#---------- default callbacks ----------
-sub _def_is_logout ($$) {
- my ($c,$r) = @_;
- foreach my $pn (@{ $r->{S}{logout_param_names} }) {
+sub has_a_param ($$) {
+ my ($c,$cn) = @_;
+ foreach my $pn (@{ $r->{S}{$cn} }) {
return 1 if $r->_cm('get_param')($pn);
}
return 0;
login_timeout => 86400, # seconds
assoc_param_name => 'cah_associd',
password_param_name => 'password',
- logout_param_names => [qw(logout)],
+ logout_param_names => [qw(cah_logout)],
+ loggedout_param_names => [qw(cah_loggedout)],
promise_check_mutate => 0,
get_param => sub { $_[0]->param($_[2]) },
get_cah_cookie => sub { $_[0]->cookie($s->{S}{cookie_name}) },
get_method => sub { $_[0]->request_method() },
is_login => sub { defined $_[1]->_rp('password_param_name') },
login_ok => sub { die },
- is_logout => \&_def_is_logout,
+ is_logout => sub { $_[1]->has_a_param('logout_param_names') },
+ is_loggedout => sub { $_[1]->has_a_param('loggedout_param_names') },
is_page => sub { return 1 },
},
Dbh => undef,
# u update of information by JS, mutating
# i login
# o logout
-
+# O "you have just logged out" page load
# in cook and par,
# a, aN anything including -
# any - POST nrmuoi bug or attack, fail
# any - GET rmuoi bug or attack, fail
# any any GET muoi bug or attack, fail
- # any t any nrmuo bug or attack, fail
+ # any t any nrmu bug or attack, fail
+ #
+ # - - GET O "just logged out" page
+ # (any other) O bug or attack, fail
#
# a1 a2 POST o logout
# if a1 is valid, revoke it
# (which contains link to login form)
#
# - t POST i complain about cookies being disabled
+ # (with link to login form)
#
# any n POST i complain about stale login form
# show new login form
#
# x1 t2 POST i login (or switch user)
- # revoke x1 if it was valid and !=t2
- # upgrade t2 to y2 in our db (setting username)
- # set cookie to t2
- # redirect to GET of remaining params
+ # if bad
+ # show new login form
+ # if good
+ # revoke x1 if it was valid and !=t2
+ # upgrade t2 to y2 in our db (setting username)
+ # set cookie to t2
+ # redirect to GET of remaining params
#
# t1 a2 ANY nrmu treat as - a2 ANY
#
# -/n n GET rmu user not logged in
# fail
#
- # -/n n POST nrmu user not logged in
+ # -/n n POST n m user not logged in
+ # show login form
+ #
+ # -/n n POST r u user not logged in
# fail
sub check_divert ($) {
my ($r) = @_;
+ my $meth = $r->_ch('get_method');
my $cookv = $r->_ch('get_cah_cookie');
my $parmv = $r->_rp('assoc_param_name');
$r->_db_perhaps_revoke($cookv);
$r->_db_perhaps_revoke($parmv);
$r->_queue_set_cookie('');
- return 'REDIRECT-LOGGEDOUT';
+ return 'REDIRECT-LOGGEDOUT'
+ }
+ if ($r->_ch('is_loggedout')) {
+ die unless $meth eq 'GET';
+ die unless $cookt;
+ die unless $parmt;
+ return ('SMALLPAGE-LOGGEDOUT', "You have been logged out.");
}
if ($r->_ch('is_login')) {
- return 'NOCOOKIE' if !$cookt && $parmt eq 't';
- return 'LOGIN-STALE' if $parmt eq 'n';
+ $r->_must_be_post();
+ return ('LOGIN-STALE',
+ "This session was stale and you need to log in again.")
+ if $parmt eq 'n';
+ die unless $parmt eq 't' || $parmt eq 'y';
+ $r->_queue_preserve_params();
+ return ('SMALLPAGE-NOCOOKIE',
+ "You do not seem to have cookies enabled. ".
+ "You must enable cookies as we use them for login.")
+ if !$cookt && $parmt eq 't';
+ return ('LOGIN-BAD',
+ "Incorrect username/password.")
+ unless defined $username && length $username;
$r->_db_perhaps_revoke($cookv)
if defined $cookv && !(defined $parmv && $cookv eq $parmv);
$r->_queue_set_cookie($parmv);
my $username = $r->_ch('login_ok');
- return 'LOGIN-BAD' unless defined $username && length $username;
$r->_db_record_login_ok($parmv,$username);
return 'REDIRECT-LOGGEDIN';
}
if (!$r->{S}{promise_check_mutate}) {
- something with method get, check parameter, etc.
- return 'FRONTPAGE';
+ if ($meth ne 'POST') {
+ return 'MAINPAGEONLY';
+ # NB caller must then ignore params & path!
+ # if this is too hard they can spit out a small form
+ # with a "click to continue"
+ }
+ }
+ if ($cookt eq 't') {
+ $cookt = undef;
}
-
+ die if $parmt eq 't';
+
+ if ($cookt eq 'y' && $parmt eq 'y' && $cookv ne $parmv) {
+ $r->_db_perhaps_revoke($parmv) if $meth eq 'POST';
+ $parmt = 'n';
+ }
+
+ if ($cookt ne 'y') {
+ die unless !$cookt || $cookt eq 'n';
+ die unless !$parmt || $parmt eq 'n' || $parmt eq 'y';
+ if ($meth eq 'GET') {
+ $r->_queue_preserve_params();
+ return ('LOGIN-INCOMINGLINK',
+ "You need to log in again.");
+ } else {
+ return ('LOGIN-FRESH',
+ "You need to log in again.");
+ }
+ }
+
+ die unless $cookt eq 'y';
+ die unless $parmt eq 'y';
+ die unless $cookv eq $parmv;
+ return '';
+}
UP TO HERE