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