34
35:- module(user_profile,
36 [ profile_open_db/1, 37
38 profile_create/2, 39 current_profile/1, 40 current_profile/2, 41 profile_property/2, 42 set_profile/2, 43 set_profile/3, 44 profile_remove/2, 45 profile_remove/1, 46
47 profile_add_session/3, 48 profile_remove_session/2, 49 profile_session/2, 50 profile_refresh_session/2, 51
52 profile_canonical_value/3 53 ]). 54:- use_module(library(uuid)). 55:- use_module(library(error)). 56:- use_module(library(apply)). 57:- use_module(library(option)). 58:- use_module(library(settings)). 59:- use_module(library(uri)). 60:- use_module(library(lists)). 61
88
89:- multifile
90 attribute/3. 91
92:- setting(backend, atom, user_profile_prolog,
93 "Backend to use (name of the module"). 94:- setting(session_timeout, number, 900,
95 "Default timeout for session based logins"). 96:- setting(session_persistency, boolean, false,
97 "Default session persistency handling"). 98
99
100 103
109
110profile_open_db(Options) :-
111 setting(backend, Backend),
112 Backend:impl_profile_open_db(Options).
113
114
115 118
124
125profile_create(ProfileID, Attributes) :-
126 instantiate_profile_id(ProfileID),
127 maplist(typecheck_attribute, Attributes, CanAttributes),
128 ( current_profile(ProfileID)
129 -> permission_error(redefine, user_profile, ProfileID)
130 ; true
131 ),
132 setting(backend, Backend),
133 Backend:impl_profile_create(ProfileID, CanAttributes).
134
135instantiate_profile_id(ProfileID) :-
136 var(ProfileID), !,
137 uuid(ProfileID).
138instantiate_profile_id(ProfileID) :-
139 must_be(atom, ProfileID).
140
141typecheck_attribute(Term, Canonical) :-
142 attribute_nv(Term, Name, Value0),
143 profile_canonical_value(Name, Value0, Value),
144 Canonical =.. [Name,Value].
145
154
155profile_canonical_value(Name, Value0, Value) :-
156 ( attribute(Name, Type, _)
157 -> must_be(ground, Type),
158 ( convert_attribute_value(Type, Value0, Value)
159 -> true
160 ; Value = Value0,
161 must_be(Type, Value)
162 )
163 ; existence_error(profile_attribute, Name)
164 ).
165
169
170convert_attribute_value(Type, Text, String) :-
171 string_value(Type),
172 text(Text), !,
173 atom_string(Text, String).
174convert_attribute_value(float, Int, Float) :-
175 integer(Int),
176 Float is float(Int).
177convert_attribute_value(string, ip(A,B,C,D), String) :-
178 format(string(String), '~w.~w.~w.~w', [A,B,C,D]).
179convert_attribute_value(oneof(Values), Text, Value) :-
180 member(Value, Values),
181 string_value(Text, Value), !.
182
183string_value(string).
184string_value(url).
185string_value(url(_Scheme)).
186string_value(email).
187
188string_value(Value, Value) :- !.
189string_value(String, Value) :-
190 atom(Value),
191 atom_string(Value, String), !.
192string_value(String, Value) :-
193 number(Value),
194 number_string(String, Value1),
195 Value1 =:= Value.
196
197text(T) :- atom(T), !.
198text(T) :- string(T), !.
199
200attribute_nv(Term, _Name, _Value) :-
201 var(Term), !,
202 instantiation_error(Term).
203attribute_nv(Term, Name, Value) :-
204 compound(Term),
205 compound_name_arguments(Term, Name, [Value]), !.
206attribute_nv(Name = Value, Name, Value) :- !,
207 must_be(atom, Name).
208attribute_nv(Name - Value, Name, Value) :- !,
209 must_be(atom, Name).
210attribute_nv(Term, _Name, _Value) :-
211 type_error(name_value, Term).
212
213
214 217
221
222current_profile(ProfileID) :-
223 setting(backend, Backend),
224 Backend:impl_current_profile(ProfileID).
225
230
231current_profile(ProfileID, Attributes) :-
232 setting(backend, Backend),
233 Backend:impl_current_profile(ProfileID, Attributes0),
234 add_defaults(Attributes0, Attributes).
235
236add_defaults(Attributes0, Attributes) :-
237 findall(Name-Value, default_attribute(Name, Value), Pairs),
238 Pairs \== [], !,
239 dict_pairs(Defaults, user_profile, Pairs),
240 Attributes = Defaults.put(Attributes0).
241add_defaults(Attributes, Attributes).
242
243default_attribute(Name, Value) :-
244 attribute(Name, _Type, Options),
245 memberchk(default(Value), Options).
246
247
252
253profile_property(ProfileID, Property) :-
254 nonvar(ProfileID),
255 nonvar(Property), !,
256 attribute_nv(Property, Name, Value),
257 setting(backend, Backend),
258 ( VarP =.. [Name,Value0],
259 Backend:impl_profile_property(ProfileID, VarP)
260 -> Value = Value0
261 ; default_attribute(Name, Value)
262 ).
263profile_property(ProfileID, Property) :-
264 setting(backend, Backend),
265 Backend:impl_profile_property(ProfileID, Property).
266
267
268 271
280
281set_profile(ProfileID, Attribute) :-
282 set_profile(ProfileID, Attribute, _).
283
284set_profile(ProfileID, Attribute, Modified) :-
285 must_be(atom, ProfileID),
286 typecheck_attribute(Attribute, CanAttribute),
287 setting(backend, Backend),
288 Backend:impl_set_profile(ProfileID, CanAttribute, Modified).
289
293
294profile_remove(ProfileID) :-
295 must_be(atom, ProfileID),
296 setting(backend, Backend),
297 Backend:impl_profile_remove(ProfileID).
298
302
303profile_remove(ProfileID, Attribute) :-
304 must_be(atom, ProfileID),
305 must_be(atom, Attribute),
306 setting(backend, Backend),
307 Backend:impl_profile_remove(ProfileID, Attribute).
308
309
310 313
323
324profile_add_session(ProfileID, SessionID, Options) :-
325 must_be(atom, ProfileID),
326 must_be(atom, SessionID),
327 setting(session_timeout, DefTimeOut),
328 setting(session_persistency, DefPresistency),
329 option(timeout(TimeOut), Options, DefTimeOut),
330 option(persistent(Persistent), Options, DefPresistency),
331 local_add_session(ProfileID, SessionID,
332 [ timeout(TimeOut),
333 persistent(Persistent)
334 ]).
335
339
340profile_refresh_session(ProfileID, SessionID) :-
341 must_be(atom, ProfileID),
342 must_be(atom, SessionID),
343 local_refresh_session(ProfileID, SessionID).
344
348
349profile_remove_session(ProfileID, SessionID) :-
350 must_be(atom, ProfileID),
351 must_be(atom, SessionID),
352 local_remove_session(ProfileID, SessionID).
353
357
358profile_session(ProfileID, SessionID) :-
359 local_session(ProfileID, SessionID).
360
361
362 365
366:- dynamic
367 tmp_session/3, 368 session_last_usage/2. 369:- volatile
370 tmp_session/3,
371 session_last_usage/2. 372
373local_add_session(ProfileID, SessionID, Options) :-
374 option(persistent(false), Options), !,
375 option(timeout(Timeout), Options),
376 get_time(Now),
377 asserta(tmp_session(ProfileID, SessionID, Timeout)),
378 asserta(session_last_usage(SessionID, Now)).
379local_add_session(ProfileID, SessionID, Options) :-
380 setting(backend, Backend),
381 Backend:impl_profile_add_session(ProfileID, SessionID, Options).
382
383local_refresh_session(ProfileID, SessionID) :-
384 tmp_session(ProfileID, SessionID, _Timeout), !,
385 get_time(Now),
386 retractall(session_last_usage(SessionID, _)),
387 asserta(session_last_usage(SessionID, Now)).
388local_refresh_session(ProfileID, SessionID) :-
389 setting(backend, Backend),
390 Backend:impl_profile_refresh_session(ProfileID, SessionID).
391
392local_remove_session(ProfileID, SessionID) :-
393 retract(tmp_session(ProfileID, SessionID, _)), !.
394local_remove_session(ProfileID, SessionID) :-
395 setting(backend, Backend),
396 Backend:impl_profile_remove_session(ProfileID, SessionID).
397
398local_session(ProfileID, SessionID) :-
399 var(ProfileID), var(SessionID), !,
400 ( tmp_session(_, SessionID, _),
401 local_session(ProfileID, SessionID)
402 ; setting(backend, Backend),
403 Backend:impl_profile_session(ProfileID, SessionID)
404 ).
405local_session(ProfileID, SessionID) :-
406 tmp_session(ProfileID, SessionID, TimeOut), !,
407 session_last_usage(SessionID, LastUsage),
408 get_time(Now),
409 ( LastUsage+TimeOut < Now
410 -> true
411 ; retractall(tmp_session(ProfileID, SessionID, _)),
412 retractall(session_last_usage(SessionID, _)),
413 fail
414 ).
415local_session(ProfileID, SessionID) :-
416 setting(backend, Backend),
417 Backend:impl_profile_session(ProfileID, SessionID).
418
419
420 423
424:- multifile error:has_type/2. 425
433
434error:has_type(url(http), URI) :-
435 string(URI),
436 uri_components(URI, Components),
437 valid_http_scheme(Components),
438 valid_authority(Components).
439error:has_type(email, Email) :-
440 string(Email),
441 split_string(Email, "@", "", [_,_]).
442error:has_type(time_stamp(_Format), Stamp) :-
443 number(Stamp).
444
445valid_http_scheme(Components) :-
446 uri_data(scheme, Components, Scheme),
447 nonvar(Scheme),
448 http_scheme(Scheme).
449
450http_scheme(http).
451http_scheme(https).
452
453valid_authority(Components) :-
454 uri_data(authority, Components, Authority),
455 nonvar(Authority).
456
457
458 461