aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoey Hess <joeyh@joeyh.name>2015-05-13 18:37:24 -0400
committerJoey Hess <joeyh@joeyh.name>2015-05-13 18:50:29 -0400
commit5b459737a50d83ff94490d86d1b9a4438d4b50a1 (patch)
treebbef22e5ca5f1288f226c2044cbfb46565e4bcb6
parentf8add0adb327a6514bbfc1773e1fc9577c98fa32 (diff)
downloadikiwiki-5b459737a50d83ff94490d86d1b9a4438d4b50a1.tar
ikiwiki-5b459737a50d83ff94490d86d1b9a4438d4b50a1.tar.gz
Converted openid-selector into a more generic loginselector helper plugin.
-rw-r--r--IkiWiki/Plugin/loginselector.pm121
-rw-r--r--IkiWiki/Plugin/openid.pm85
-rw-r--r--debian/changelog2
-rw-r--r--doc/plugins/write.mdwn3
-rw-r--r--templates/login-selector.tmpl28
5 files changed, 169 insertions, 70 deletions
diff --git a/IkiWiki/Plugin/loginselector.pm b/IkiWiki/Plugin/loginselector.pm
new file mode 100644
index 000000000..b5e2056a4
--- /dev/null
+++ b/IkiWiki/Plugin/loginselector.pm
@@ -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
diff --git a/IkiWiki/Plugin/openid.pm b/IkiWiki/Plugin/openid.pm
index a12c83b8c..67b8cd387 100644
--- a/IkiWiki/Plugin/openid.pm
+++ b/IkiWiki/Plugin/openid.pm
@@ -7,38 +7,17 @@ use strict;
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);
-}
-
-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 () {
@@ -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 (@) {
diff --git a/debian/changelog b/debian/changelog
index 4d8b589cf..30b358ca6 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -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.
+ * Converted openid-selector into a more generic loginselector helper
+ plugin.
-- Joey Hess <id@joeyh.name> Tue, 28 Apr 2015 12:24:08 -0400
diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn
index c3f531b66..95f4a39df 100644
--- a/doc/plugins/write.mdwn
+++ b/doc/plugins/write.mdwn
@@ -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.
+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);
diff --git a/templates/login-selector.tmpl b/templates/login-selector.tmpl
index e3a91fef2..9b68838dc 100644
--- a/templates/login-selector.tmpl
+++ b/templates/login-selector.tmpl
@@ -6,7 +6,7 @@ $(document).ready(function() {
'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>'
@@ -27,23 +27,23 @@ $(document).ready(function() {
</div>
<div id="login_input_area">
- <div>
- <h3>OpenId login:</h3>
<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>
- </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>
- </div>
<TMPL_IF LOGIN_ERROR>
<div class="error"><TMPL_VAR LOGIN_ERROR></div>