1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#!/usr/bin/perl
package IkiWiki::Plugin::loginselector;
use warnings;
use strict;
use IkiWiki 3.00;
# Plugins that provide login methods can register themselves here.
# Note that the template and js file also have be be modifed to add a new
# login method.
our %login_plugins;
sub register_login_plugin ($$$$) {
# Same as the name of the plugin that is registering itself as a
# login plugin. eg, "openid"
my $plugin_name=shift;
# This sub is passed a cgi object and a template object which it
# can manipulate. It should return true if the plugin can be used
# (it might load necessary modules for auth checking, for example).
my $plugin_setup=shift;
# This sub is passed a cgi object, and should return true
# if it looks like the user is logging in using the plugin.
my $plugin_check_input=shift;
# This sub is passed a cgi object, a session object, and an error
# display callback, and should handle the actual authentication.
# It can either exit w/o returning, if it is able to handle
# auth, or it can pass an error message to the error display
# callback to make the openid selector form be re-disiplayed with
# an error message on it.
my $plugin_auth=shift;
$login_plugins{$plugin_name}={
setup => $plugin_setup,
check_input => $plugin_check_input,
auth => $plugin_auth,
};
}
sub login_selector {
my $real_cgi_signin=shift;
my $otherform_label=shift;
my $q=shift;
my $session=shift;
my $template=IkiWiki::template("login-selector.tmpl");
foreach my $plugin (keys %login_plugins) {
if (! $login_plugins{$plugin}->{setup}->($template)) {
delete $login_plugins{$plugin};
}
else {
$template->param("login_selector_$plugin", 1);
}
}
foreach my $plugin (keys %login_plugins) {
if ($login_plugins{$plugin}->{check_input}->($q)) {
$login_plugins{$plugin}->{auth}->($q, $session, sub {
$template->param(login_error => shift());
});
last;
}
}
$template->param(
cgiurl => IkiWiki::cgiurl(),
($real_cgi_signin ? (otherform => $real_cgi_signin->($q, $session, 1)) : ()),
otherform_label => $otherform_label,
);
IkiWiki::printheader($session);
print IkiWiki::cgitemplate($q, "signin", $template->output);
exit;
}
sub import {
add_underlay("login-selector");
add_underlay("jquery");
hook(type => "getsetup", id => "loginselector", call => \&getsetup);
hook(type => "checkconfig", id => "loginselector", call => \&checkconfig);
}
sub checkconfig () {
if ($config{cgi}) {
# Intercept normal signin form, so the login selector
# can be displayed.
#
# When other auth hooks are registered, give the selector
# a reference to the normal signin form.
require IkiWiki::CGI;
my $real_cgi_signin;
my $otherform_label=gettext("Other");
if (keys %{$IkiWiki::hooks{auth}} > 1) {
$real_cgi_signin=\&IkiWiki::cgi_signin;
my %h=%{$IkiWiki::hooks{auth}};
foreach my $p (keys %login_plugins) {
delete $h{$p};
}
# Special case to avoid labeling password auth as
# "Other" when it's the only auth plugin not
# integrated with the loginselector.
if (keys %h == 1 && exists $h{passwordauth}) {
$otherform_label=gettext("Password");
}
}
inject(name => "IkiWiki::cgi_signin", call => sub ($$) {
login_selector($real_cgi_signin, $otherform_label, @_);
});
}
}
sub getsetup () {
return
plugin => {
# this plugin is safe but only makes sense as a
# dependency
safe => 0,
rebuild => 0,
},
}
1
|