Chris@0
|
1 /* $Id$
|
Chris@0
|
2
|
Chris@0
|
3 Part of SWI-Prolog
|
Chris@0
|
4
|
Chris@0
|
5 Author: Jan Wielemaker
|
Chris@0
|
6 E-mail: wielemak@science.uva.nl
|
Chris@0
|
7 WWW: http://www.swi-prolog.org
|
Chris@0
|
8 Copyright (C): 1985-2007, University of Amsterdam
|
Chris@0
|
9
|
Chris@0
|
10 This program is free software; you can redistribute it and/or
|
Chris@0
|
11 modify it under the terms of the GNU General Public License
|
Chris@0
|
12 as published by the Free Software Foundation; either version 2
|
Chris@0
|
13 of the License, or (at your option) any later version.
|
Chris@0
|
14
|
Chris@0
|
15 This program is distributed in the hope that it will be useful,
|
Chris@0
|
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
Chris@0
|
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Chris@0
|
18 GNU General Public License for more details.
|
Chris@0
|
19
|
Chris@0
|
20 You should have received a copy of the GNU Lesser General Public
|
Chris@0
|
21 License along with this library; if not, write to the Free Software
|
Chris@0
|
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
Chris@0
|
23
|
Chris@0
|
24 As a special exception, if you link this library with other files,
|
Chris@0
|
25 compiled with a Free Software compiler, to produce an executable, this
|
Chris@0
|
26 library does not by itself cause the resulting executable to be covered
|
Chris@0
|
27 by the GNU General Public License. This exception does not however
|
Chris@0
|
28 invalidate any other reasons why the executable file might be covered by
|
Chris@0
|
29 the GNU General Public License.
|
Chris@0
|
30 */
|
Chris@0
|
31
|
Chris@0
|
32 :- module(http_admin,
|
Chris@0
|
33 [ reload_attr/2 % +Window, -Attribute
|
Chris@0
|
34 ]).
|
Chris@0
|
35 :- use_module(user_db).
|
Chris@0
|
36 :- use_module(library('http/http_parameters')).
|
Chris@0
|
37 :- use_module(library('http/http_session')).
|
Chris@0
|
38 :- use_module(library('http/html_write')).
|
Chris@0
|
39 :- use_module(library('http/mimetype')).
|
Chris@0
|
40 :- use_module(library('http/http_dispatch')).
|
Chris@0
|
41 :- use_module(library(url)).
|
Chris@0
|
42 :- use_module(library(debug)).
|
Chris@0
|
43 :- use_module(library(lists)).
|
Chris@0
|
44 :- use_module(library(option)).
|
Chris@0
|
45 :- use_module(library(http_settings)).
|
Chris@0
|
46
|
Chris@0
|
47
|
Chris@0
|
48 :- http_handler('/admin/tasks', tasks, []).
|
Chris@0
|
49 :- http_handler('/admin/listUsers', list_users, []).
|
Chris@0
|
50 :- http_handler('/admin/form/createAdmin', create_admin, []).
|
Chris@0
|
51 :- http_handler('/admin/form/addUser', add_user_form, []).
|
Chris@0
|
52 :- http_handler('/admin/form/addOpenIDServer', add_openid_server_form, []).
|
Chris@0
|
53 :- http_handler('/admin/addUser', add_user, []).
|
Chris@0
|
54 :- http_handler('/admin/addOpenIDServer', add_openid_server, []).
|
Chris@0
|
55 :- http_handler('/admin/form/editUser', edit_user_form, []).
|
Chris@0
|
56 :- http_handler('/admin/editUser', edit_user, []).
|
Chris@0
|
57 :- http_handler('/admin/delUser', del_user, []).
|
Chris@0
|
58 :- http_handler('/admin/form/editOpenIDServer', edit_openid_server_form, []).
|
Chris@0
|
59 :- http_handler('/admin/editOpenIDServer', edit_openid_server, []).
|
Chris@0
|
60 :- http_handler('/admin/delOpenIDServer', del_openid_server, []).
|
Chris@0
|
61 :- http_handler('/admin/form/changePassword', change_password_form, []).
|
Chris@0
|
62 :- http_handler('/admin/changePassword', change_password, []).
|
Chris@0
|
63 :- http_handler('/user/form/login', login_form, []).
|
Chris@0
|
64 :- http_handler('/user/login', user_login, []).
|
Chris@0
|
65 :- http_handler('/user/logout', user_logout, []).
|
Chris@0
|
66 :- http_handler('/admin/settings', settings, []).
|
Chris@0
|
67 :- http_handler('/admin/save_settings', save_settings, []).
|
Chris@0
|
68 :- http_handler('/css/settings.css', http_reply_file(library('settings.css'), []), []).
|
Chris@0
|
69
|
Chris@0
|
70 %% tasks(+Request)
|
Chris@0
|
71 %
|
Chris@0
|
72 % Present menu with administrative tasks.
|
Chris@0
|
73
|
Chris@0
|
74 tasks(_Request) :-
|
Chris@0
|
75 reply_page('Administrative tasks',
|
Chris@0
|
76 [ \action('listUsers', 'List users')
|
Chris@0
|
77 ]).
|
Chris@0
|
78
|
Chris@0
|
79
|
Chris@0
|
80 action(URL, Label) -->
|
Chris@0
|
81 html([a([target=main, href=URL], Label), br([])]).
|
Chris@0
|
82
|
Chris@0
|
83 %% list_users(+Request)
|
Chris@0
|
84 %
|
Chris@0
|
85 % HTTP Handler listing registered users.
|
Chris@0
|
86
|
Chris@0
|
87 list_users(_Request) :-
|
Chris@0
|
88 authorized(admin(list_users)),
|
Chris@0
|
89 reply_page('Users',
|
Chris@0
|
90 [ h1('Users'),
|
Chris@0
|
91 \user_table,
|
Chris@0
|
92 p([ \action('form/addUser', 'Add user')
|
Chris@0
|
93 ]),
|
Chris@0
|
94 h1('OpenID servers'),
|
Chris@0
|
95 \openid_server_table,
|
Chris@0
|
96 p([ \action('form/addOpenIDServer', 'Add OpenID server')
|
Chris@0
|
97 ])
|
Chris@0
|
98 ]).
|
Chris@0
|
99
|
Chris@0
|
100 %% user_table//
|
Chris@0
|
101 %
|
Chris@0
|
102 % HTML DCG generating a table of registered users.
|
Chris@0
|
103
|
Chris@0
|
104 user_table -->
|
Chris@0
|
105 { setof(U, current_user(U), Users)
|
Chris@0
|
106 },
|
Chris@0
|
107 html([ table([ border(1)
|
Chris@0
|
108 ],
|
Chris@0
|
109 [ tr([ th('UserID'),
|
Chris@0
|
110 th('RealName'),
|
Chris@0
|
111 th('On since'),
|
Chris@0
|
112 th('Idle')
|
Chris@0
|
113 ])
|
Chris@0
|
114 | \list_users(Users)
|
Chris@0
|
115 ])
|
Chris@0
|
116 ]).
|
Chris@0
|
117
|
Chris@0
|
118 list_users([]) -->
|
Chris@0
|
119 [].
|
Chris@0
|
120 list_users([User|T]) -->
|
Chris@0
|
121 { user_property(User, realname(Name)),
|
Chris@0
|
122 www_form_encode(User, Encoded),
|
Chris@0
|
123 format(string(Edit), 'form/editUser?user=~w', [Encoded]),
|
Chris@0
|
124 findall(Idle-Login,
|
Chris@0
|
125 user_property(User, connection(Login, Idle)),
|
Chris@0
|
126 Pairs0),
|
Chris@0
|
127 keysort(Pairs0, Pairs),
|
Chris@0
|
128 ( Pairs == []
|
Chris@0
|
129 -> OnLine = (-)
|
Chris@0
|
130 ; length(Pairs, N),
|
Chris@0
|
131 Pairs = [Idle-Login|_],
|
Chris@0
|
132 OnLine = online(Login, Idle, N)
|
Chris@0
|
133 )
|
Chris@0
|
134 },
|
Chris@0
|
135 html(tr([ td(User),
|
Chris@0
|
136 td(Name),
|
Chris@0
|
137 td(\on_since(OnLine)),
|
Chris@0
|
138 td(\idle(OnLine)),
|
Chris@0
|
139 td(a(href(Edit), 'Edit'))
|
Chris@0
|
140 ])),
|
Chris@0
|
141 list_users(T).
|
Chris@0
|
142
|
Chris@0
|
143 on_since(online(Login, _Idle, _Connections)) --> !,
|
Chris@0
|
144 { format_time(string(Date), '%+', Login)
|
Chris@0
|
145 },
|
Chris@0
|
146 html(Date).
|
Chris@0
|
147 on_since(_) -->
|
Chris@0
|
148 html(-).
|
Chris@0
|
149
|
Chris@0
|
150 idle(online(_Login, Idle, _Connections)) -->
|
Chris@0
|
151 { mmss_duration(Idle, String)
|
Chris@0
|
152 },
|
Chris@0
|
153 html(String).
|
Chris@0
|
154 idle(_) -->
|
Chris@0
|
155 html(-).
|
Chris@0
|
156
|
Chris@0
|
157
|
Chris@0
|
158 mmss_duration(Time, String) :- % Time in seconds
|
Chris@0
|
159 Secs is round(Time),
|
Chris@0
|
160 Hour is Secs // 3600,
|
Chris@0
|
161 Min is (Secs // 60) mod 60,
|
Chris@0
|
162 Sec is Secs mod 60,
|
Chris@0
|
163 format(string(String), '~`0t~d~2|:~`0t~d~5|:~`0t~d~8|', [Hour, Min, Sec]).
|
Chris@0
|
164
|
Chris@0
|
165
|
Chris@0
|
166
|
Chris@0
|
167 /*******************************
|
Chris@0
|
168 * ADD USERS *
|
Chris@0
|
169 *******************************/
|
Chris@0
|
170
|
Chris@0
|
171 %% create_admin(+Request)
|
Chris@0
|
172 %
|
Chris@0
|
173 % Create the administrator login.
|
Chris@0
|
174
|
Chris@0
|
175 create_admin(_Request) :-
|
Chris@0
|
176 ( current_user(_)
|
Chris@0
|
177 -> throw(error(permission_error(create, user, admin),
|
Chris@0
|
178 context(_, 'Already initialized')))
|
Chris@0
|
179 ; true
|
Chris@0
|
180 ),
|
Chris@0
|
181 reply_page('Create administrator',
|
Chris@0
|
182 [ h1(align(center), 'Create administrator'),
|
Chris@0
|
183
|
Chris@0
|
184 p('No accounts are available on this server. \
|
Chris@0
|
185 This form allows for creation of an administrative \
|
Chris@0
|
186 account that can subsequently be used to create \
|
Chris@0
|
187 new users.'),
|
Chris@0
|
188
|
Chris@0
|
189 form([ action('../addUser'),
|
Chris@0
|
190 method('GET')
|
Chris@0
|
191 ],
|
Chris@0
|
192 [ \hidden(read, on),
|
Chris@0
|
193 \hidden(write, on),
|
Chris@0
|
194 \hidden(admin, on),
|
Chris@0
|
195
|
Chris@0
|
196 table([ border(1),
|
Chris@0
|
197 align(center)
|
Chris@0
|
198 ],
|
Chris@0
|
199 [ \input(user, 'Name',
|
Chris@0
|
200 [value('admin')]),
|
Chris@0
|
201 \input(realname, 'Realname',
|
Chris@0
|
202 [value('Administrator')]),
|
Chris@0
|
203 \input(pwd1, 'Password',
|
Chris@0
|
204 [type(password)]),
|
Chris@0
|
205 \input(pwd2, 'Retype',
|
Chris@0
|
206 [type(password)]),
|
Chris@0
|
207 tr(td([ colspan(2),
|
Chris@0
|
208 align(right)
|
Chris@0
|
209 ],
|
Chris@0
|
210 input([ type(submit),
|
Chris@0
|
211 value('Create')
|
Chris@0
|
212 ])))
|
Chris@0
|
213 ])
|
Chris@0
|
214 ])
|
Chris@0
|
215 ]).
|
Chris@0
|
216
|
Chris@0
|
217
|
Chris@0
|
218 %% add_user_form(+Request)
|
Chris@0
|
219 %
|
Chris@0
|
220 % Form to register a user.
|
Chris@0
|
221
|
Chris@0
|
222 add_user_form(_Request) :-
|
Chris@0
|
223 authorized(admin(add_user)),
|
Chris@0
|
224 reply_page('Add new user',
|
Chris@0
|
225 [ \new_user_form
|
Chris@0
|
226 ]).
|
Chris@0
|
227
|
Chris@0
|
228 new_user_form -->
|
Chris@0
|
229 html([ h1('Add new user'),
|
Chris@0
|
230 form([ action('../addUser'),
|
Chris@0
|
231 method('GET')
|
Chris@0
|
232 ],
|
Chris@0
|
233 table([ border(1)
|
Chris@0
|
234 ],
|
Chris@0
|
235 [ \input(user, 'Name',
|
Chris@0
|
236 []),
|
Chris@0
|
237 \input(realname, 'Realname',
|
Chris@0
|
238 []),
|
Chris@0
|
239 \input(pwd1, 'Password',
|
Chris@0
|
240 [type(password)]),
|
Chris@0
|
241 \input(pwd2, 'Retype',
|
Chris@0
|
242 [type(password)]),
|
Chris@0
|
243 \permissions(-),
|
Chris@0
|
244 tr(td([ colspan(2),
|
Chris@0
|
245 align(right)
|
Chris@0
|
246 ],
|
Chris@0
|
247 input([ type(submit),
|
Chris@0
|
248 value('Create')
|
Chris@0
|
249 ])))
|
Chris@0
|
250 ]))
|
Chris@0
|
251 ]).
|
Chris@0
|
252
|
Chris@0
|
253
|
Chris@0
|
254 input(Name, Label, Options) -->
|
Chris@0
|
255 html(tr([ td(align(right), Label),
|
Chris@0
|
256 td(input([name(Name),size(40)|Options]))
|
Chris@0
|
257 ])).
|
Chris@0
|
258
|
Chris@0
|
259 %% add_user(+Request)
|
Chris@0
|
260 %
|
Chris@0
|
261 % Register a new user.
|
Chris@0
|
262
|
Chris@0
|
263 add_user(Request) :-
|
Chris@0
|
264 ( \+ current_user(_)
|
Chris@0
|
265 -> true
|
Chris@0
|
266 ; authorized(admin(add_user))
|
Chris@0
|
267 ),
|
Chris@0
|
268 http_parameters(Request,
|
Chris@0
|
269 [ user(User, [ length > 2 ]),
|
Chris@0
|
270 realname(RealName, [ length > 2 ]),
|
Chris@0
|
271 pwd1(Password, [ length > 5 ]),
|
Chris@0
|
272 pwd2(Retype, [ length > 5 ]),
|
Chris@0
|
273 read(Read),
|
Chris@0
|
274 write(Write),
|
Chris@0
|
275 admin(Admin)
|
Chris@0
|
276 ],
|
Chris@0
|
277 [ attribute_declarations(attribute_decl)
|
Chris@0
|
278 ]),
|
Chris@0
|
279 ( current_user(User)
|
Chris@0
|
280 -> throw(error(permission_error(create, user, User),
|
Chris@0
|
281 context(_, 'Already present')))
|
Chris@0
|
282 ; true
|
Chris@0
|
283 ),
|
Chris@0
|
284 ( Password == Retype
|
Chris@0
|
285 -> true
|
Chris@0
|
286 ; throw(password_mismatch)
|
Chris@0
|
287 ),
|
Chris@0
|
288 password_hash(Password, Hash),
|
Chris@0
|
289 phrase(allow(Read, Write, Admin), Allow),
|
Chris@0
|
290 user_add(User,
|
Chris@0
|
291 [ realname(RealName),
|
Chris@0
|
292 password(Hash),
|
Chris@0
|
293 allow(Allow)
|
Chris@0
|
294 ]),
|
Chris@0
|
295 ( User == admin
|
Chris@0
|
296 -> user_add(anonymous,
|
Chris@0
|
297 [ realname('Define rights for not-logged in users'),
|
Chris@0
|
298 allow([read(_,_)])
|
Chris@0
|
299 ]),
|
Chris@0
|
300 reply_login([user(User), password(Password)])
|
Chris@0
|
301 ; list_users(Request)
|
Chris@0
|
302 ).
|
Chris@0
|
303
|
Chris@0
|
304 %% edit_user_form(+Request)
|
Chris@0
|
305 %
|
Chris@0
|
306 % Form to edit user properties
|
Chris@0
|
307
|
Chris@0
|
308 edit_user_form(Request) :-
|
Chris@0
|
309 authorized(admin(user(edit))),
|
Chris@0
|
310 http_parameters(Request,
|
Chris@0
|
311 [ user(User, [])
|
Chris@0
|
312 ]),
|
Chris@0
|
313
|
Chris@0
|
314 www_form_encode(User, Encoded),
|
Chris@0
|
315 format(string(Delete), '../delUser?user=~w', [Encoded]),
|
Chris@0
|
316
|
Chris@0
|
317 user_property(User, realname(RealName)),
|
Chris@0
|
318
|
Chris@0
|
319 reply_page('Edit user',
|
Chris@0
|
320 [ h4(['Edit user ', User, ' (', RealName, ')']),
|
Chris@0
|
321
|
Chris@0
|
322 form([ action('../editUser'),
|
Chris@0
|
323 method('GET')
|
Chris@0
|
324 ],
|
Chris@0
|
325 [ \hidden(user, User),
|
Chris@0
|
326 table([ border(1),
|
Chris@0
|
327 align(center)
|
Chris@0
|
328 ],
|
Chris@0
|
329 [ \user_property(User,
|
Chris@0
|
330 realname,
|
Chris@0
|
331 'Realname',
|
Chris@0
|
332 []),
|
Chris@0
|
333 \permissions(User),
|
Chris@0
|
334 tr(td([ colspan(2),
|
Chris@0
|
335 align(right)
|
Chris@0
|
336 ],
|
Chris@0
|
337 input([ type(submit),
|
Chris@0
|
338 value('Modify')
|
Chris@0
|
339 ])))
|
Chris@0
|
340 ])
|
Chris@0
|
341 ]),
|
Chris@0
|
342
|
Chris@0
|
343 p([ \action(Delete, [ 'Delete ',
|
Chris@0
|
344 b(User),
|
Chris@0
|
345 ' (', b(RealName), ')'
|
Chris@0
|
346 ])
|
Chris@0
|
347 ])
|
Chris@0
|
348 ]).
|
Chris@0
|
349
|
Chris@0
|
350 user_property(User, Name, Label, Options) -->
|
Chris@0
|
351 { Term =.. [Name, Value],
|
Chris@0
|
352 user_property(User, Term)
|
Chris@0
|
353 -> O2 = [value(Value)|Options]
|
Chris@0
|
354 ; O2 = Options
|
Chris@0
|
355 },
|
Chris@0
|
356 html(tr([ td(align(right), Label),
|
Chris@0
|
357 td(input([name(Name),size(40)|O2]))
|
Chris@0
|
358 ])).
|
Chris@0
|
359
|
Chris@0
|
360 permissions(User) -->
|
Chris@0
|
361 html(tr([ td(align(right), 'Permissions'),
|
Chris@0
|
362 td([ \permission_checkbox(User, read, 'Read'),
|
Chris@0
|
363 \permission_checkbox(User, write, 'Write'),
|
Chris@0
|
364 \permission_checkbox(User, admin, 'Admin')
|
Chris@0
|
365 ])
|
Chris@0
|
366 ])).
|
Chris@0
|
367
|
Chris@0
|
368 permission_checkbox(User, Name, Label) -->
|
Chris@0
|
369 { ( User \== (-),
|
Chris@0
|
370 ( user_property(User, allow(Actions))
|
Chris@0
|
371 -> true
|
Chris@0
|
372 ; openid_server_property(User, allow(Actions))
|
Chris@0
|
373 ),
|
Chris@0
|
374 pterm(Name, Action),
|
Chris@0
|
375 memberchk(Action, Actions)
|
Chris@0
|
376 -> Opts = [checked]
|
Chris@0
|
377 ; Opts = []
|
Chris@0
|
378 )
|
Chris@0
|
379 },
|
Chris@0
|
380 html([ input([ type(checkbox),
|
Chris@0
|
381 name(Name)
|
Chris@0
|
382 | Opts
|
Chris@0
|
383 ]),
|
Chris@0
|
384 Label
|
Chris@0
|
385 ]).
|
Chris@0
|
386
|
Chris@0
|
387 %% edit_user(Request)
|
Chris@0
|
388 %
|
Chris@0
|
389 % Handle reply from edit user form.
|
Chris@0
|
390
|
Chris@0
|
391 edit_user(Request) :-
|
Chris@0
|
392 authorized(admin(user(edit))),
|
Chris@0
|
393 http_parameters(Request,
|
Chris@0
|
394 [ user(User, []),
|
Chris@0
|
395 realname(RealName,
|
Chris@0
|
396 [ optional(true),
|
Chris@0
|
397 length > 2
|
Chris@0
|
398 ]),
|
Chris@0
|
399 read(Read),
|
Chris@0
|
400 write(Write),
|
Chris@0
|
401 admin(Admin)
|
Chris@0
|
402 ],
|
Chris@0
|
403 [ attribute_declarations(attribute_decl)
|
Chris@0
|
404 ]),
|
Chris@0
|
405 modify_user(User, realname(RealName)),
|
Chris@0
|
406 modify_permissions(User, Read, Write, Admin),
|
Chris@0
|
407 list_users(Request).
|
Chris@0
|
408
|
Chris@0
|
409
|
Chris@0
|
410 modify_user(User, Property) :-
|
Chris@0
|
411 Property =.. [_Name|Value],
|
Chris@0
|
412 ( ( var(Value)
|
Chris@0
|
413 ; Value == ''
|
Chris@0
|
414 )
|
Chris@0
|
415 -> true
|
Chris@0
|
416 ; set_user_property(User, Property)
|
Chris@0
|
417 ).
|
Chris@0
|
418
|
Chris@0
|
419 modify_permissions(User, Read, Write, Admin) :-
|
Chris@0
|
420 phrase(allow(Read, Write, Admin), Allow),
|
Chris@0
|
421 set_user_property(User, allow(Allow)).
|
Chris@0
|
422
|
Chris@0
|
423 allow(Read, Write, Admin) -->
|
Chris@0
|
424 allow(read, Read),
|
Chris@0
|
425 allow(write, Write),
|
Chris@0
|
426 allow(admin, Admin).
|
Chris@0
|
427
|
Chris@0
|
428 allow(Access, on) -->
|
Chris@0
|
429 { pterm(Access, Allow)
|
Chris@0
|
430 }, !,
|
Chris@0
|
431 [ Allow
|
Chris@0
|
432 ].
|
Chris@0
|
433 allow(_Access, off) --> !,
|
Chris@0
|
434 [].
|
Chris@0
|
435
|
Chris@0
|
436 pterm(read, read(_Repositiory, _Action)).
|
Chris@0
|
437 pterm(write, write(_Repositiory, _Action)).
|
Chris@0
|
438 pterm(admin, admin(_Action)).
|
Chris@0
|
439
|
Chris@0
|
440
|
Chris@0
|
441 %% del_user(+Request)
|
Chris@0
|
442 %
|
Chris@0
|
443 % Delete a user
|
Chris@0
|
444
|
Chris@0
|
445 del_user(Request) :- !,
|
Chris@0
|
446 authorized(admin(del_user)),
|
Chris@0
|
447 http_parameters(Request,
|
Chris@0
|
448 [ user(User, [])
|
Chris@0
|
449 ]),
|
Chris@0
|
450 ( User == admin
|
Chris@0
|
451 -> throw(error(permission_error(delete, user, User), _))
|
Chris@0
|
452 ; true
|
Chris@0
|
453 ),
|
Chris@0
|
454 user_del(User),
|
Chris@0
|
455 list_users(Request).
|
Chris@0
|
456
|
Chris@0
|
457
|
Chris@0
|
458 %% change_password_form(+Request)
|
Chris@0
|
459 %
|
Chris@0
|
460 % Allow user to change the password
|
Chris@0
|
461
|
Chris@0
|
462 change_password_form(_Request) :-
|
Chris@0
|
463 logged_on(User),
|
Chris@0
|
464 user_property(User, realname(RealName)),
|
Chris@0
|
465 reply_page('Change password',
|
Chris@0
|
466 [ h4(['Change password for ', User, ' (', RealName, ')']),
|
Chris@0
|
467
|
Chris@0
|
468 form([ action('../changePassword'),
|
Chris@0
|
469 method('GET')
|
Chris@0
|
470 ],
|
Chris@0
|
471 [ table([ border(1),
|
Chris@0
|
472 align(center)
|
Chris@0
|
473 ],
|
Chris@0
|
474 [ \user_or_old(User),
|
Chris@0
|
475 \input(pwd1, 'New Password',
|
Chris@0
|
476 [type(password)]),
|
Chris@0
|
477 \input(pwd2, 'Retype',
|
Chris@0
|
478 [type(password)]),
|
Chris@0
|
479 tr(td([ align(right),
|
Chris@0
|
480 colspan(2)
|
Chris@0
|
481 ],
|
Chris@0
|
482 input([ type(submit),
|
Chris@0
|
483 value('Change password')
|
Chris@0
|
484 ])))
|
Chris@0
|
485 ])
|
Chris@0
|
486 ])
|
Chris@0
|
487 ]).
|
Chris@0
|
488
|
Chris@0
|
489 user_or_old(admin) --> !,
|
Chris@0
|
490 input(user, 'User', []).
|
Chris@0
|
491 user_or_old(_) -->
|
Chris@0
|
492 input(pwd0, 'Old password', [type(password)]).
|
Chris@0
|
493
|
Chris@0
|
494
|
Chris@0
|
495 %% change_password(+Request)
|
Chris@0
|
496 %
|
Chris@0
|
497 % Actually change the password. The user must be logged on.
|
Chris@0
|
498
|
Chris@0
|
499 change_password(Request) :-
|
Chris@0
|
500 logged_on(Login),
|
Chris@0
|
501 http_parameters(Request,
|
Chris@0
|
502 [ user(User, [ optional(true) ]),
|
Chris@0
|
503 pwd0(Password, [ optional(true) ]),
|
Chris@0
|
504 pwd1(New, [ length > 5 ]),
|
Chris@0
|
505 pwd2(Retype, [ length > 5 ])
|
Chris@0
|
506 ]),
|
Chris@0
|
507 ( Login == admin
|
Chris@0
|
508 -> ( current_user(User)
|
Chris@0
|
509 -> true
|
Chris@0
|
510 ; throw(error(existence_error(user, User), _))
|
Chris@0
|
511 )
|
Chris@0
|
512 ; Login = User,
|
Chris@0
|
513 validate_password(User, Password)
|
Chris@0
|
514 ),
|
Chris@0
|
515 ( New == Retype
|
Chris@0
|
516 -> true
|
Chris@0
|
517 ; throw(password_mismatch)
|
Chris@0
|
518 ),
|
Chris@0
|
519 password_hash(New, Hash),
|
Chris@0
|
520 set_user_property(User, password(Hash)),
|
Chris@0
|
521 reply_page('Password changed',
|
Chris@0
|
522 [ h1(align(center), 'Password changed'),
|
Chris@0
|
523 p([ 'Your password has been changed successfully' ])
|
Chris@0
|
524 ]).
|
Chris@0
|
525
|
Chris@0
|
526
|
Chris@0
|
527 /*******************************
|
Chris@0
|
528 * LOGIN *
|
Chris@0
|
529 *******************************/
|
Chris@0
|
530
|
Chris@0
|
531 %% login_form(+Request)
|
Chris@0
|
532 %
|
Chris@0
|
533 % HTTP handler that presents a form to login.
|
Chris@0
|
534
|
Chris@0
|
535 login_form(_Request) :-
|
Chris@0
|
536 reply_page('Login',
|
Chris@0
|
537 [ h1(align(center), 'Login'),
|
Chris@0
|
538 form([ action('../login'),
|
Chris@0
|
539 method('GET')
|
Chris@0
|
540 ],
|
Chris@0
|
541 table([ tr([ th(align(right), 'User:'),
|
Chris@0
|
542 td(input([ name(user),
|
Chris@0
|
543 size(40)
|
Chris@0
|
544 ]))
|
Chris@0
|
545 ]),
|
Chris@0
|
546 tr([ th(align(right), 'Password:'),
|
Chris@0
|
547 td(input([ type(password),
|
Chris@0
|
548 name(password),
|
Chris@0
|
549 size(40)
|
Chris@0
|
550 ]))
|
Chris@0
|
551 ]),
|
Chris@0
|
552 tr([ td([ align(right), colspan(2) ],
|
Chris@0
|
553 input([ type(submit),
|
Chris@0
|
554 value('Login')
|
Chris@0
|
555 ]))
|
Chris@0
|
556 ])
|
Chris@0
|
557 ])
|
Chris@0
|
558 )
|
Chris@0
|
559 ]).
|
Chris@0
|
560
|
Chris@0
|
561 %% user_login(+Request)
|
Chris@0
|
562 %
|
Chris@0
|
563 % Handle =user= and =password=. If there is a parameter
|
Chris@0
|
564 % =return_to= or =|openid.return_to|=, reply using a redirect to
|
Chris@0
|
565 % the given URL. Otherwise display a welcome page.
|
Chris@0
|
566
|
Chris@0
|
567 user_login(Request) :- !,
|
Chris@0
|
568 http_parameters(Request,
|
Chris@0
|
569 [ user(User, []),
|
Chris@0
|
570 password(Password, []),
|
Chris@0
|
571 'openid.return_to'(ReturnTo, [optional(true)]),
|
Chris@0
|
572 'return_to'(ReturnTo, [optional(true)])
|
Chris@0
|
573 ]),
|
Chris@0
|
574 ( var(ReturnTo)
|
Chris@0
|
575 -> Extra = []
|
Chris@0
|
576 ; Extra = [ return_to(ReturnTo) ]
|
Chris@0
|
577 ),
|
Chris@0
|
578 reply_login([ user(User),
|
Chris@0
|
579 password(Password)
|
Chris@0
|
580 | Extra
|
Chris@0
|
581 ]).
|
Chris@0
|
582
|
Chris@0
|
583
|
Chris@0
|
584 reply_login(Options) :-
|
Chris@0
|
585 option(user(User), Options),
|
Chris@0
|
586 option(password(Password), Options),
|
Chris@0
|
587 validate_password(User, Password), !,
|
Chris@0
|
588 login(User),
|
Chris@0
|
589 ( option(return_to(ReturnTo), Options)
|
Chris@0
|
590 -> throw(http_reply(moved_temporary(ReturnTo)))
|
Chris@0
|
591 ; reload_attr(sidebar, OnLoad),
|
Chris@0
|
592 reply_page('Login ok',
|
Chris@0
|
593 body([ OnLoad
|
Chris@0
|
594 ],
|
Chris@0
|
595 [ h1(align(center), ['Welcome ', User])
|
Chris@0
|
596 ]))
|
Chris@0
|
597 ).
|
Chris@0
|
598 reply_login(_) :-
|
Chris@0
|
599 reply_page('Login failed',
|
Chris@0
|
600 [ h1(align(center), 'Login failed'),
|
Chris@0
|
601 p(['Password incorrect'])
|
Chris@0
|
602 ]).
|
Chris@0
|
603
|
Chris@0
|
604 %% user_logout(+Request)
|
Chris@0
|
605 %
|
Chris@0
|
606 % Logout the current user
|
Chris@0
|
607
|
Chris@0
|
608 user_logout(_Request) :-
|
Chris@0
|
609 logged_on(User),
|
Chris@0
|
610 logout(User),
|
Chris@0
|
611 reload_attr(sidebar, OnLoad),
|
Chris@0
|
612 reply_page('Logout',
|
Chris@0
|
613 body([ OnLoad
|
Chris@0
|
614 ],
|
Chris@0
|
615 [ h1(align(center), ['Logged out ', User])
|
Chris@0
|
616 ])).
|
Chris@0
|
617
|
Chris@0
|
618 reload_attr(Frame, onLoad(Script)) :-
|
Chris@0
|
619 concat_atom([ 'top.frames[\'', Frame, '\'].location=top.frames[\'',
|
Chris@0
|
620 Frame, '\'].location.href'
|
Chris@0
|
621 ], Script).
|
Chris@0
|
622
|
Chris@0
|
623
|
Chris@0
|
624 attribute_decl(read, Options) :- bool(off, Options).
|
Chris@0
|
625 attribute_decl(write, Options) :- bool(off, Options).
|
Chris@0
|
626 attribute_decl(admin, Options) :- bool(off, Options).
|
Chris@0
|
627
|
Chris@0
|
628 bool(Def,
|
Chris@0
|
629 [ default(Def),
|
Chris@0
|
630 type(oneof([on, off]))
|
Chris@0
|
631 ]).
|
Chris@0
|
632
|
Chris@0
|
633
|
Chris@0
|
634 /*******************************
|
Chris@0
|
635 * OPENID ADMIN *
|
Chris@0
|
636 *******************************/
|
Chris@0
|
637
|
Chris@0
|
638 %% add_openid_server_form(+Request)
|
Chris@0
|
639 %
|
Chris@0
|
640 % Register an OpenID server
|
Chris@0
|
641
|
Chris@0
|
642 add_openid_server_form(_Request) :-
|
Chris@0
|
643 authorized(admin(add_openid_server)),
|
Chris@0
|
644 reply_page('Add OpenID server',
|
Chris@0
|
645 [ \new_openid_form
|
Chris@0
|
646 ]).
|
Chris@0
|
647
|
Chris@0
|
648
|
Chris@0
|
649 %% new_openid_form// is det.
|
Chris@0
|
650 %
|
Chris@0
|
651 % Present form to add a new OpenID provider.
|
Chris@0
|
652
|
Chris@0
|
653 new_openid_form -->
|
Chris@0
|
654 html([ h1('Add new OpenID server'),
|
Chris@0
|
655 form([ action('../addOpenIDServer'),
|
Chris@0
|
656 method('GET')
|
Chris@0
|
657 ],
|
Chris@0
|
658 table([ border(1)
|
Chris@0
|
659 ],
|
Chris@0
|
660 [ \input(openid_server, 'Server homepage', []),
|
Chris@0
|
661 \input(openid_description, 'Server description',
|
Chris@0
|
662 []),
|
Chris@0
|
663 \permissions(-),
|
Chris@0
|
664 tr(td([ colspan(2),
|
Chris@0
|
665 align(right)
|
Chris@0
|
666 ],
|
Chris@0
|
667 input([ type(submit),
|
Chris@0
|
668 value('Create')
|
Chris@0
|
669 ])))
|
Chris@0
|
670 ])),
|
Chris@0
|
671 p([ 'Use this form to define access rights for users of an ',
|
Chris@0
|
672 a(href('http://www.openid.net'), 'OpenID'), ' server.',
|
Chris@0
|
673 'The special server', code(*), ' specifies access for all OpenID servers.',
|
Chris@0
|
674 'Here are some examples of servers:'
|
Chris@0
|
675 ]),
|
Chris@0
|
676 ul([ li(code('http://myopenid.com')),
|
Chris@0
|
677 li(code('http://videntity.org'))
|
Chris@0
|
678 ])
|
Chris@0
|
679 ]).
|
Chris@0
|
680
|
Chris@0
|
681
|
Chris@0
|
682 %% add_openid_server(+Request)
|
Chris@0
|
683 %
|
Chris@0
|
684 % Allow access from an OpenID server
|
Chris@0
|
685
|
Chris@0
|
686 add_openid_server(Request) :-
|
Chris@0
|
687 authorized(admin(add_openid_server)),
|
Chris@0
|
688 http_parameters(Request,
|
Chris@0
|
689 [ openid_server(Server0, []),
|
Chris@0
|
690 openid_description(Description, [ optional(true) ]),
|
Chris@0
|
691 read(Read),
|
Chris@0
|
692 write(Write)
|
Chris@0
|
693 ],
|
Chris@0
|
694 [ attribute_declarations(attribute_decl)
|
Chris@0
|
695 ]),
|
Chris@0
|
696 phrase(allow(Read, Write, off), Allow),
|
Chris@0
|
697 canonical_url(Server0, Server),
|
Chris@0
|
698 Options = [ description(Description),
|
Chris@0
|
699 allow(Allow)
|
Chris@0
|
700 ],
|
Chris@0
|
701 remove_optional(Options, Properties),
|
Chris@0
|
702 openid_add_server(Server, Properties),
|
Chris@0
|
703 list_users(Request).
|
Chris@0
|
704
|
Chris@0
|
705 remove_optional([], []).
|
Chris@0
|
706 remove_optional([H|T0], [H|T]) :-
|
Chris@0
|
707 arg(1, H, A),
|
Chris@0
|
708 nonvar(A), !,
|
Chris@0
|
709 remove_optional(T0, T).
|
Chris@0
|
710 remove_optional([_|T0], T) :-
|
Chris@0
|
711 remove_optional(T0, T).
|
Chris@0
|
712
|
Chris@0
|
713
|
Chris@0
|
714 canonical_url(Var, Var) :-
|
Chris@0
|
715 var(Var), !.
|
Chris@0
|
716 canonical_url(*, *) :- !.
|
Chris@0
|
717 canonical_url(URL0, URL) :-
|
Chris@0
|
718 parse_url(URL0, Parts),
|
Chris@0
|
719 parse_url(URL, Parts).
|
Chris@0
|
720
|
Chris@0
|
721
|
Chris@0
|
722 %% edit_openid_server_form(+Request)
|
Chris@0
|
723 %
|
Chris@0
|
724 % Form to edit user properties
|
Chris@0
|
725
|
Chris@0
|
726 edit_openid_server_form(Request) :-
|
Chris@0
|
727 authorized(admin(openid(edit))),
|
Chris@0
|
728 http_parameters(Request,
|
Chris@0
|
729 [ openid_server(Server, [])
|
Chris@0
|
730 ]),
|
Chris@0
|
731
|
Chris@0
|
732 www_form_encode(Server, Encoded),
|
Chris@0
|
733 format(string(Delete),
|
Chris@0
|
734 '../delOpenIDServer?openid_server=~w', [Encoded]),
|
Chris@0
|
735
|
Chris@0
|
736 reply_page('Edit OpenID server',
|
Chris@0
|
737 [ h4(['Edit OpenID server ', Server]),
|
Chris@0
|
738
|
Chris@0
|
739 form([ action('../editOpenIDServer'),
|
Chris@0
|
740 method('GET')
|
Chris@0
|
741 ],
|
Chris@0
|
742 [ \hidden(openid_server, Server),
|
Chris@0
|
743 table([ border(1)
|
Chris@0
|
744 ],
|
Chris@0
|
745 [ \openid_property(Server, description, 'Description', []),
|
Chris@0
|
746 \permissions(Server),
|
Chris@0
|
747 tr(td([ colspan(2),
|
Chris@0
|
748 align(right)
|
Chris@0
|
749 ],
|
Chris@0
|
750 input([ type(submit),
|
Chris@0
|
751 value('Modify')
|
Chris@0
|
752 ])))
|
Chris@0
|
753 ])
|
Chris@0
|
754 ]),
|
Chris@0
|
755
|
Chris@0
|
756 p([ \action(Delete, [ 'Delete ', b(Server) ]) ])
|
Chris@0
|
757 ]).
|
Chris@0
|
758
|
Chris@0
|
759
|
Chris@0
|
760 openid_property(Server, Name, Label, Options) -->
|
Chris@0
|
761 { Term =.. [Name, Value],
|
Chris@0
|
762 openid_server_property(Server, Term)
|
Chris@0
|
763 -> O2 = [value(Value)|Options]
|
Chris@0
|
764 ; O2 = Options
|
Chris@0
|
765 },
|
Chris@0
|
766 html(tr([ td(align(right), Label),
|
Chris@0
|
767 td(input([name(Name),size(40)|O2]))
|
Chris@0
|
768 ])).
|
Chris@0
|
769
|
Chris@0
|
770
|
Chris@0
|
771 %% openid_server_table//
|
Chris@0
|
772 %
|
Chris@0
|
773 % List registered openid servers
|
Chris@0
|
774
|
Chris@0
|
775 openid_server_table -->
|
Chris@0
|
776 { setof(S, openid_current_server(S), Servers), !
|
Chris@0
|
777 },
|
Chris@0
|
778 html([ table([ border(1)
|
Chris@0
|
779 ],
|
Chris@0
|
780 [ tr([ th('Server'),
|
Chris@0
|
781 th('Description')
|
Chris@0
|
782 ])
|
Chris@0
|
783 | \openid_list_servers(Servers)
|
Chris@0
|
784 ])
|
Chris@0
|
785 ]).
|
Chris@0
|
786 openid_server_table -->
|
Chris@0
|
787 [].
|
Chris@0
|
788
|
Chris@0
|
789 openid_list_servers([]) -->
|
Chris@0
|
790 [].
|
Chris@0
|
791 openid_list_servers([H|T]) -->
|
Chris@0
|
792 openid_list_server(H),
|
Chris@0
|
793 openid_list_servers(T).
|
Chris@0
|
794
|
Chris@0
|
795 openid_list_server(Server) -->
|
Chris@0
|
796 { www_form_encode(Server, Encoded),
|
Chris@0
|
797 format(string(Edit), 'form/editOpenIDServer?openid_server=~w', [Encoded])
|
Chris@0
|
798 },
|
Chris@0
|
799 html(tr([td(\openid_server(Server)),
|
Chris@0
|
800 td(\openid_field(Server, description)),
|
Chris@0
|
801 td(a(href(Edit), 'Edit'))
|
Chris@0
|
802 ])).
|
Chris@0
|
803
|
Chris@0
|
804 openid_server(*) --> !,
|
Chris@0
|
805 html(*).
|
Chris@0
|
806 openid_server(Server) -->
|
Chris@0
|
807 html(a(href(Server), Server)).
|
Chris@0
|
808
|
Chris@0
|
809 openid_field(Server, Field) -->
|
Chris@0
|
810 { Term =.. [Field, Value],
|
Chris@0
|
811 openid_server_property(Server, Term)
|
Chris@0
|
812 }, !,
|
Chris@0
|
813 html(Value).
|
Chris@0
|
814 openid_field(_, _) -->
|
Chris@0
|
815 [].
|
Chris@0
|
816
|
Chris@0
|
817
|
Chris@0
|
818 %% edit_openid_server(Request)
|
Chris@0
|
819 %
|
Chris@0
|
820 % Handle reply from OpenID server form.
|
Chris@0
|
821
|
Chris@0
|
822 edit_openid_server(Request) :-
|
Chris@0
|
823 authorized(admin(openid(edit))),
|
Chris@0
|
824 http_parameters(Request,
|
Chris@0
|
825 [ openid_server(Server, []),
|
Chris@0
|
826 description(Description,
|
Chris@0
|
827 [ optional(true),
|
Chris@0
|
828 length > 2
|
Chris@0
|
829 ]),
|
Chris@0
|
830 read(Read),
|
Chris@0
|
831 write(Write),
|
Chris@0
|
832 admin(Admin)
|
Chris@0
|
833 ],
|
Chris@0
|
834 [ attribute_declarations(attribute_decl)
|
Chris@0
|
835 ]),
|
Chris@0
|
836 modify_openid(Server, description(Description)),
|
Chris@0
|
837 openid_modify_permissions(Server, Read, Write, Admin),
|
Chris@0
|
838 list_users(Request).
|
Chris@0
|
839
|
Chris@0
|
840
|
Chris@0
|
841 modify_openid(User, Property) :-
|
Chris@0
|
842 Property =.. [_Name|Value],
|
Chris@0
|
843 ( ( var(Value)
|
Chris@0
|
844 ; Value == ''
|
Chris@0
|
845 )
|
Chris@0
|
846 -> true
|
Chris@0
|
847 ; openid_set_property(User, Property)
|
Chris@0
|
848 ).
|
Chris@0
|
849
|
Chris@0
|
850
|
Chris@0
|
851 openid_modify_permissions(Server, Read, Write, Admin) :-
|
Chris@0
|
852 phrase(allow(Read, Write, Admin), Allow),
|
Chris@0
|
853 openid_set_property(Server, allow(Allow)).
|
Chris@0
|
854
|
Chris@0
|
855
|
Chris@0
|
856 %% del_openid_server(+Request)
|
Chris@0
|
857 %
|
Chris@0
|
858 % Delete an OpenID Server
|
Chris@0
|
859
|
Chris@0
|
860 del_openid_server(Request) :- !,
|
Chris@0
|
861 authorized(admin(openid(delete))),
|
Chris@0
|
862 http_parameters(Request,
|
Chris@0
|
863 [ openid_server(Server, [])
|
Chris@0
|
864 ]),
|
Chris@0
|
865 openid_del_server(Server),
|
Chris@0
|
866 list_users(Request).
|
Chris@0
|
867
|
Chris@0
|
868
|
Chris@0
|
869 /*******************************
|
Chris@0
|
870 * SETTINGS *
|
Chris@0
|
871 *******************************/
|
Chris@0
|
872
|
Chris@0
|
873 %% settings(+Request)
|
Chris@0
|
874 %
|
Chris@0
|
875 % Show current settings. Is user is =admin=, allow editing the
|
Chris@0
|
876 % settings.
|
Chris@0
|
877
|
Chris@0
|
878 settings(_Request) :-
|
Chris@0
|
879 ( catch(authorized(admin(edit_settings)), _, fail)
|
Chris@0
|
880 -> Edit = true
|
Chris@0
|
881 ; authorized(read(admin, settings)),
|
Chris@0
|
882 Edit = false
|
Chris@0
|
883 ),
|
Chris@0
|
884 phrase(page([ title('Settings'),
|
Chris@0
|
885 link([ rel(stylesheet),
|
Chris@0
|
886 type('text/css'),
|
Chris@0
|
887 href('../css/settings.css')
|
Chris@0
|
888 ])
|
Chris@0
|
889 ],
|
Chris@0
|
890 [ \http_show_settings([ edit(Edit),
|
Chris@0
|
891 hide_module(false),
|
Chris@0
|
892 action('save_settings')
|
Chris@0
|
893 ])
|
Chris@0
|
894 ]), HTML),
|
Chris@0
|
895 format('Content-type: text/html~n~n'),
|
Chris@0
|
896 print_html(HTML).
|
Chris@0
|
897
|
Chris@0
|
898 %% save_settings(+Request)
|
Chris@0
|
899 %
|
Chris@0
|
900 % Save modified settings.
|
Chris@0
|
901
|
Chris@0
|
902 save_settings(Request) :-
|
Chris@0
|
903 authorized(admin(edit_settings)),
|
Chris@0
|
904 phrase(page([ title('Save settings'),
|
Chris@0
|
905 link([ rel(stylesheet),
|
Chris@0
|
906 type('text/css'),
|
Chris@0
|
907 href('../css/settings.css')
|
Chris@0
|
908 ])
|
Chris@0
|
909 ],
|
Chris@0
|
910 [ \http_apply_settings(Request, [save(true)])
|
Chris@0
|
911 ]), HTML),
|
Chris@0
|
912 format('Content-type: text/html~n~n'),
|
Chris@0
|
913 print_html(HTML).
|
Chris@0
|
914
|
Chris@0
|
915
|
Chris@0
|
916 /*******************************
|
Chris@0
|
917 * EMIT *
|
Chris@0
|
918 *******************************/
|
Chris@0
|
919
|
Chris@0
|
920 %% hidden(+Name, +Value)
|
Chris@0
|
921 %
|
Chris@0
|
922 % Create a hidden input field with given name and value
|
Chris@0
|
923
|
Chris@0
|
924 hidden(Name, Value) -->
|
Chris@0
|
925 html(input([ type(hidden),
|
Chris@0
|
926 name(Name),
|
Chris@0
|
927 value(Value)
|
Chris@0
|
928 ])).
|
Chris@0
|
929
|
Chris@0
|
930
|
Chris@0
|
931 reply_page(Title, Content) :-
|
Chris@0
|
932 phrase(page(title(Title), Content), HTML),
|
Chris@0
|
933 format('Content-type: text/html~n~n'),
|
Chris@0
|
934 print_html(HTML).
|
Chris@0
|
935
|
Chris@0
|
936 % Support Cross-Referencer and PceEmacs.
|
Chris@0
|
937
|
Chris@0
|
938 :- multifile
|
Chris@0
|
939 emacs_prolog_colours:goal_colours/2,
|
Chris@0
|
940 prolog:called_by/2.
|
Chris@0
|
941
|
Chris@0
|
942
|
Chris@0
|
943 emacs_prolog_colours:goal_colours(reply_page(_, HTML),
|
Chris@0
|
944 built_in-[classify, Colours]) :-
|
Chris@0
|
945 catch(html_write:html_colours(HTML, Colours), _, fail).
|
Chris@0
|
946 prolog:called_by(reply_page(_, HTML), Called) :-
|
Chris@0
|
947 catch(phrase(html_write:called_by(HTML), Called), _, fail).
|