]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/commitdiff
Converted openid-selector into a more generic loginselector helper plugin.
authorJoey Hess <joeyh@joeyh.name>
Wed, 13 May 2015 22:37:24 +0000 (18:37 -0400)
committerJoey Hess <joeyh@joeyh.name>
Wed, 13 May 2015 22:50:29 +0000 (18:50 -0400)
IkiWiki/Plugin/loginselector.pm [new file with mode: 0644]
IkiWiki/Plugin/openid.pm
debian/changelog
doc/plugins/write.mdwn
templates/login-selector.tmpl

diff --git a/IkiWiki/Plugin/loginselector.pm b/IkiWiki/Plugin/loginselector.pm
new file mode 100644 (file)
index 0000000..b5e2056
--- /dev/null
@@ -0,0 +1,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
index a12c83b8cada4547ed31c27e5fa86490454f6bac..67b8cd387a947a201463a5bf6254eddf26be1808 100644 (file)
@@ -7,38 +7,17 @@ use strict;
 use IkiWiki 3.00;
 
 sub import {
 use IkiWiki 3.00;
 
 sub import {
-       add_underlay("login-selector");
-       add_underlay("jquery");
-       hook(type => "checkconfig", id => "openid", call => \&checkconfig);
        hook(type => "getsetup", id => "openid", call => \&getsetup);
        hook(type => "auth", id => "openid", call => \&auth);
        hook(type => "formbuilder_setup", id => "openid",
                call => \&formbuilder_setup, last => 1);
        hook(type => "getsetup", id => "openid", call => \&getsetup);
        hook(type => "auth", id => "openid", call => \&auth);
        hook(type => "formbuilder_setup", id => "openid",
                call => \&formbuilder_setup, last => 1);
-}
-
-sub checkconfig () {
-       if ($config{cgi}) {
-               # Intercept normal signin form, so the openid 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}};
-                       delete $h{openid};
-                       delete $h{emailauth};
-                       if (keys %h == 1 && exists $h{passwordauth}) {
-                               $otherform_label=gettext("Password");
-                       }
-               }
-               inject(name => "IkiWiki::cgi_signin", call => sub ($$) {
-                       openid_selector($real_cgi_signin, $otherform_label, @_);
-               });
-       }
+       IkiWiki::loadplugin("loginselector");
+       IkiWiki::Plugin::loginselector::register_login_plugin(
+               "openid",
+               \&openid_setup,
+               \&openid_check_input,
+               \&openid_auth,
+       );
 }
 
 sub getsetup () {
 }
 
 sub getsetup () {
@@ -62,40 +41,34 @@ sub getsetup () {
                },
 }
 
                },
 }
 
-sub openid_selector {
-       my $real_cgi_signin=shift;
-       my $otherform_label=shift;
-        my $q=shift;
-        my $session=shift;
-
-       my $template=IkiWiki::template("login-selector.tmpl");
-       my $openid_url=$q->param('openid_identifier');
+sub openid_setup ($$) {
+       my $q=shift;
+       my $template=shift;
 
 
-       if (load_openid_module()) {
-               if ($real_cgi_signin) {
-                       $real_cgi_signin->($q, $session);
-                       exit;
+       if (load_openid_module()) {
+               my $openid_url=$q->param('openid_identifier');
+               if (defined $openid_url) {
+                       $template->param(openid_url => $openid_url);
                }
                }
-               error(sprintf(gettext("failed to load openid module: "), @_));
+               return 1;
        }
        }
-       elsif (defined $q->param("action") && $q->param("action") eq "verify" && defined $openid_url && length $openid_url) {
-               validate($q, $session, $openid_url, sub {
-                       $template->param(login_error => shift())
-               });
+       else {
+               return 0;
        }
        }
+}
 
 
-       $template->param(
-               cgiurl => IkiWiki::cgiurl(),
-               (defined $openid_url ? (openid_url => $openid_url) : ()),
-               ($real_cgi_signin ? (otherform => $real_cgi_signin->($q, $session, 1)) : ()),
-               otherform_label => $otherform_label,
-               login_selector_openid => 1,
-               login_selector_email => 1,
-       );
+sub openid_check_input ($) {
+       my $q=shift;
+       my $openid_url=$q->param('openid_identifier');
+       defined $q->param("action") && $q->param("action") eq "verify" && defined $openid_url && length $openid_url;
+}
 
 
-       IkiWiki::printheader($session);
-       print IkiWiki::cgitemplate($q, "signin", $template->output);
-       exit;
+sub openid_auth ($$$) {
+       my $q=shift;
+       my $session=shift;
+       my $errordisplayer=shift;
+       my $openid_url=$q->param('openid_identifier');
+       validate($q, $session, $openid_url, $errordisplayer);
 }
 
 sub formbuilder_setup (@) {
 }
 
 sub formbuilder_setup (@) {
index 4d8b589cf6f3e113d39fbab309ab2792b56813cc..30b358ca67d5c7bde56794f32f74d247ae08e517 100644 (file)
@@ -5,6 +5,8 @@ ikiwiki (3.20150330) UNRELEASED; urgency=medium
   * When openid and passwordauth are the only enabled auth plugins,
     make the openid selector display "Password" instead of "Other",
     so users are more likely to click on it when they don't have an openid.
   * When openid and passwordauth are the only enabled auth plugins,
     make the openid selector display "Password" instead of "Other",
     so users are more likely to click on it when they don't have an openid.
+  * Converted openid-selector into a more generic loginselector helper
+    plugin.
 
  -- Joey Hess <id@joeyh.name>  Tue, 28 Apr 2015 12:24:08 -0400
 
 
  -- Joey Hess <id@joeyh.name>  Tue, 28 Apr 2015 12:24:08 -0400
 
index c3f531b66aa706f7b44eb4a0b52250f16d4ca732..95f4a39dfb9f3f0e24de672419f62cb043835422 100644 (file)
@@ -458,6 +458,9 @@ object's "name" parameter to the authenticated user's name. Note that
 if the name is set to the name of a user who is not registered,
 a basic registration of the user will be automatically performed.
 
 if the name is set to the name of a user who is not registered,
 a basic registration of the user will be automatically performed.
 
+Auth plugins can use the loginselector helper plugin to let the user
+select which authentication method to use.
+
 ### <a name="sessioncgi">sessioncgi</a>
 
        hook(type => "sessioncgi", id => "foo", call => \&sessioncgi);
 ### <a name="sessioncgi">sessioncgi</a>
 
        hook(type => "sessioncgi", id => "foo", call => \&sessioncgi);
index e3a91fef2c85b9d2ff9c45e8d7bf86b7364bcfd4..9b68838dc3984dec75e7daa35f0195c44adfce1f 100644 (file)
@@ -6,7 +6,7 @@ $(document).ready(function() {
                'openid_identifier',
                {
                        <TMPL_IF LOGIN_SELECTOR_OPENID>'openid': 1,</TMPL_IF>
                'openid_identifier',
                {
                        <TMPL_IF LOGIN_SELECTOR_OPENID>'openid': 1,</TMPL_IF>
-                       <TMPL_IF LOGIN_SELECTOR_EMAIL>'email': 1,</TMPL_IF>
+                       <TMPL_IF LOGIN_SELECTOR_EMAILAUTH>'email': 1,</TMPL_IF>
                },
                '<TMPL_IF OTHERFORM>otherform</TMPL_IF>',
                '<TMPL_VAR OTHERFORM_LABEL>'
                },
                '<TMPL_IF OTHERFORM>otherform</TMPL_IF>',
                '<TMPL_VAR OTHERFORM_LABEL>'
@@ -27,23 +27,23 @@ $(document).ready(function() {
                </div>
 
                <div id="login_input_area">
                </div>
 
                <div id="login_input_area">
-               <div>
-               <h3>OpenId login:</h3>
                <TMPL_IF LOGIN_SELECTOR_OPENID>
                <TMPL_IF LOGIN_SELECTOR_OPENID>
-                       <label for="openid_identifier" class="block">Enter your OpenID:</label>
-                       <input id="openid_identifier" name="openid_identifier" type="text" value="<TMPL_VAR ESCAPE=HTML OPENID_URL>"/>
-                       <input id="openid_submit" type="submit" value="Login"/>
+                       <div>
+                               <h3>OpenId login:</h3>
+                               <label for="openid_identifier" class="block">Enter your OpenID:</label>
+                               <input id="openid_identifier" name="openid_identifier" type="text" value="<TMPL_VAR ESCAPE=HTML OPENID_URL>"/>
+                               <input id="openid_submit" type="submit" value="Login"/>
+                       </div>
                </TMPL_IF>
                </TMPL_IF>
-               </div>
-               <div>
-               <h3>Email login:</h3>
-               <TMPL_IF LOGIN_SELECTOR_EMAIL>
-                       <label for="email_address" class="block">Enter your email address:</label>
-                       <input id="email_address" name="Email_entry" type="text" value="<TMPL_VAR ESCAPE=HTML EMAIL_ADDRESS>"/>
-                       <input id="email_submit" type="submit" value="Login"/>
+               <TMPL_IF LOGIN_SELECTOR_EMAILAUTH>
+                       <div>
+                               <h3>Email login:</h3>
+                               <label for="email_address" class="block">Enter your email address:</label>
+                               <input id="email_address" name="Email_entry" type="text" value="<TMPL_VAR ESCAPE=HTML EMAIL_ADDRESS>"/>
+                               <input id="email_submit" type="submit" value="Login"/>
+                       </div>
                </TMPL_IF>
                </div>
                </TMPL_IF>
                </div>
-               </div>
 
                <TMPL_IF LOGIN_ERROR>
                <div class="error"><TMPL_VAR LOGIN_ERROR></div>
 
                <TMPL_IF LOGIN_ERROR>
                <div class="error"><TMPL_VAR LOGIN_ERROR></div>