35
36:- module(swish_login,
37 [ login_button//1, 38 login_continue_button//0,
39 reply_logged_in/1, 40 reply_logged_in_page/1, 41 reply_logged_out/1, 42 reply_logged_out_page/1, 43 current_user_info/2 44 ]). 45:- use_module(library(http/http_dispatch)). 46:- use_module(library(http/http_parameters)). 47:- use_module(library(http/http_json)). 48:- use_module(library(http/html_write)). 49:- use_module(library(http/js_write)). 50:- use_module(library(option)). 51:- use_module(library(apply)). 52:- use_module(library(broadcast)). 53
54:- use_module('../config', []). 55
56:- multifile
57 swish_config:login/2,
58 swish_config:login_item/2,
59 swish_config:li_login_button//1, 60 swish_config:reply_logged_in/1, 61 swish_config:reply_logged_out/1, 62 swish_config:user_info/3, 63 swish_config:user_profile/2. 64
75
76:- http_handler(swish(login), swish_login, [id(login)]). 77:- http_handler(swish(user_info), user_info, [id(user_info)]). 78
79
80 83
87
88swish_config:li_login_button(Options) -->
89 html(li(\login_button(Options))).
90
95
96login_button(_Options) -->
97 { findall(Item, login_item(Item), Items0),
98 Items0 \== [],
99 sort(Items0, Items),
100 http_link_to_id(login, [], Login)
101 },
102 !,
103 html(a([ href(Login), id(login), class(login) ],
104 [ span(class(login),
105 \login_items(Items)),
106 span([ class(logout)
107 ],
108 [ span(class(value), 'Logout')
109 ])
110 ])).
111login_button(_Options) --> 112 html(a([ id(login), class([login, 'no-logout']) ],
113 [ span([ class(logout)
114 ],
115 [ span(class(value), [])
116 ])
117 ])).
118
119login_item(item(Tag, Server, Item)) :-
120 swish_config:login_item(Server, Item0),
121 ( Item0 = Tag-Item
122 -> true
123 ; Item = Item0,
124 Tag = 0
125 ).
126
131
132login_items([item(_Tag, Server, Item)]) -->
133 !,
134 { findall(Attr, login_attr(Item, Attr), Attrs)
135 },
136 html(span(['data-server'(Server)|Attrs],
137 [ span(class([glyphicon, 'glyphicon-log-in']), []),
138 span(class(value), 'Login')
139 ])).
140login_items(Items) -->
141 { maplist(arg(3), Items, HTML) },
142 html([ span(class(value), HTML)
143 ]).
144
145login_attr(Item, 'data-frame'(Frame)) :-
146 sub_term('data-frame'(Frame), Item).
147
148
149
150
173
174reply_logged_in(Options) :-
175 swish_config:reply_logged_in(Options),
176 !.
177reply_logged_in(Options) :-
178 reply_logged_in_page(Options).
179
180reply_logged_in_page(Options) :-
181 reply_html_page(
182 title('Logged in'),
183 [ h4('Welcome'),
184 p([ 'You have been identified ',
185 \identity_provider(Options),
186 ' as ',
187 \user(Options)
188 ]),
189 \login_continue_button
190 ]).
191
192identity_provider(Options) -->
193 { option(identity_provider(Provider), Options) },
194 !,
195 html(['by ', Provider]).
196identity_provider(_) --> [].
197
198user(Options) -->
199 { option(user(User), Options) },
200 !,
201 html(User),
202 ( { option(name(Name), Options) }
203 -> html([' (', Name, ')' ])
204 ; []
205 ).
206user(Options) -->
207 { option(name(Name), Options) },
208 !,
209 html(Name).
210user(_) -->
211 html(unknown).
212
218
219login_continue_button -->
220 html(style(\[ 'div.login-continue { text-align: center; margin-top: 2em; }'
221 ])),
222
223 js_script({|javascript||
224function inIframe() {
225 try {
226 return window.self !== window.top;
227 } catch (e) {
228 return true;
229 }
230}
231
232function append( elString, parent ) {
233 var div = document.createElement( "div" );
234 div.innerHTML = elString;
235 document.querySelector( parent || "body" ).appendChild( div.firstChild );
236}
237
238if ( !inIframe() ) {
239 append('<div class="login-continue">\n'+
240 ' <button onclick="window.close()">\n'+
241 ' Continue\n'+
242 ' </button>\n'+
243 '</div>');
244}
245 |}).
246
247
248
252
253reply_logged_out(Options) :-
254 swish_config:reply_logged_out(Options),
255 !.
256reply_logged_out(Options) :-
257 reply_logged_out_page(Options).
258
259reply_logged_out_page(Options) :-
260 option(reply(Format), Options, json),
261 ( Format == json
262 -> reply_json_dict(true)
263 ; true
264 ).
265
266
267 270
276
277swish_login(Request) :-
278 http_parameters(Request,
279 [ server(Server, [default(default)])
280 ]),
281 swish_config:login(Server, Request).
282
288
289user_info(Request) :-
290 http_parameters(Request,
291 [ reason(Reason, [optional(true)])
292 ]),
293 ( current_user_info(Request, Info)
294 -> reply_json_dict(Info)
295 ; ( Reason == logout_by_http
296 -> broadcast(swish(logout(http)))
297 ; true
298 ),
299 reply_json_dict(null)
300 ).
301
306
307current_user_info(Request, Info) :-
308 swish_config:user_info(Request, _Server, UserInfo),
309 ( swish_config:user_profile(Request, Profile)
310 -> copy_fields([identity_provider, auth_method, logout_url],
311 UserInfo, Profile, Info)
312 ; Info = UserInfo
313 ).
314
315copy_fields([], _From, Dict, Dict).
316copy_fields([H|T], From, Dict0, Dict) :-
317 ( V = From.get(H)
318 -> copy_fields(T, From, Dict0.put(H,V), Dict)
319 ; copy_fields(T, From, Dict0, Dict)
320 )