package OpenResty::Handler::Login; #use Smart::Comments '####'; use strict; use warnings; use CGI::Simple::Cookie; use OpenResty::Util; use Params::Util qw( _STRING ); use OpenResty::Handler::Logout; use OpenResty::QuasiQuote::SQL; use base 'OpenResty::Handler::Base'; __PACKAGE__->register('login'); sub requires_acl { undef } sub level2name { qw< login login_user login_user_password >[$_[-1]] } sub login_per_request { my ($class, $openresty, $bits) = @_; my ($account, $role); # XXX this part is lame... # XXX param user is now deprecated; use _user instead my $session = $openresty->get_session; my $user = $openresty->builtin_param('_user'); #warn "_user = $user\n"; if (defined $user) { #$OpenResty::Cache->remove($uuid); my $captcha = $openresty->builtin_param('_captcha'); ### URL param capture: $captcha #require OpenResty::Handler::Login; my $res = OpenResty::Handler::Login->login($openresty, $user, { password => $openresty->builtin_param('_password'), captcha => $captcha, }); $account = $res->{account}; $role = $res->{role}; # XXX login as $account.$role... # XXX if account is anonymous, then create a session # XXX else check password, if correct, create a session } else { if ($session) { my $user = $OpenResty::Cache->get($session); #### User from cache: $user if ($user) { ($account, $role) = split /\./, $user, 2; } #### $account ### $role } } my $call_level = $openresty->{_call_level}; if ($call_level == 0) { # this part is lame? if (!$account) { die "Login required.\n"; } if (!$openresty->has_user($account)) { ### Found user: $user die "Account \"$account\" does not exist.\n"; } } else { if (!$account) { $account = $openresty->{_parent_account}; } else { if (!$openresty->has_user($account)) { ### Found user: $user die "Account \"$account\" does not exist.\n"; } } } #warn "Setting user: $account ", join ('/', @$bits), "\n"; $openresty->set_user($account); $role ||= 'Admin'; if (!$openresty->has_role($role)) { ### Found user: $user die "Role \"$role\" does not exist.\n"; } $openresty->set_role($role); } #*login = \&login_by_sql; *login = \&login_by_perl; sub GET_login_user { my ($self, $openresty, $bits) = @_; my $user = $bits->[1]; $self->login($openresty, $user); } sub GET_login_user_password { my ($self, $openresty, $bits) = @_; my $user = $bits->[1]; my $password = $bits->[2]; $self->login($openresty, $user, { password => $password }); } sub login_by_perl { my ($self, $openresty, $user, $params) = @_; _STRING($user) or die "Bad user name: ", $OpenResty::Dumper->($user), "\n"; $params ||= {}; ### $params ### caller: caller() my $password = $params->{password}; my $captcha = $params->{captcha}; my $account; my $role = 'Admin'; if ($user =~ /^(\w+)\.(\w+)$/) { ($account, $role) = ($1, $2); } elsif ($user =~ /^\w+$/) { $account = $&; } else { die "Bad user name: ", $OpenResty::Dumper->($user), "\n"; } _IDENT($account) or die "Bad account name: ", $OpenResty::Dumper->($account), "\n"; _IDENT($role) or die "Bad role name: ", $OpenResty::Dumper->($role), "\n"; ### $role # this part is lame? if (!$account) { die "Login required.\n"; } if (!$openresty->has_user($account)) { ### Found user: $user die "Account \"$account\" does not exist.\n"; } $openresty->set_user($account); $openresty->set_unlimited($OpenResty::UnlimitedAccounts{$account}); my $login_meth = $openresty->has_role($role); if (!$login_meth) { ### Found user: $user die "Role \"$role\" does not exist.\n"; } ### $account ### $role ### $password ### capture param: $captcha #warn "!!!!!!!!!!!!!!!!!!! Captcha Value: $captcha\n"; if (defined $captcha && defined $password) { my ($id, $user_sol) = split /:/, $captcha, 2; if (!$id or !$user_sol) { die "Bad captcha parameter: $captcha\n"; } if ($login_meth ne 'captcha+password') { die "Cannot login as $account.$role via captchas and password.\n"; } my ($rc, $err) = OpenResty::Handler::Captcha::validate_captcha($openresty,$id,$user_sol); if (!$rc) { die $err."\n"; } my $res = $openresty->select([:sql| select id from _roles where name = $role and password = $password limit 1; |]); if (! @$res) { die "Password for $account.$role is incorrect.\n"; } } elsif (defined $captcha) { #warn "!!!!!!!!!!!!!!!!!!! Captcha Value: $captcha\n"; my ($id, $user_sol) = split /:/, $captcha, 2; if (!$id or !$user_sol) { die "Bad captcha parameter: $captcha\n"; } #warn "!!! $login_meth !!!\n"; if ($login_meth ne 'captcha') { die "Cannot login as $account.$role via captchas.\n"; } my ($rc, $err) = OpenResty::Handler::Captcha::validate_captcha($openresty,$id,$user_sol); if (!$rc) { die $err."\n"; } } elsif (defined $password) { #warn "Login meth: $login_meth\n"; if ($login_meth ne 'password') { # short-cut #warn "HERE!!!"; die "Password for $account.$role is incorrect.\n"; } my $res = $openresty->select([:sql| select id from _roles where name = $role and password = $password limit 1; |]); #### with password: $res if (! @$res) { die "Password for $account.$role is incorrect.\n"; } } else { if ($role eq 'Admin') { die "$account.$role is not anonymous.\n"; } if ($role ne 'Public' && $login_meth ne 'anonymous') { die "$account.$role is not anonymous.\n"; } } $openresty->set_role($role); my $session_from_cookie = $openresty->{_session_from_cookie}; ### Get session ID from cookie: $session_from_cookie if ($session_from_cookie) { $OpenResty::Cache->remove($session_from_cookie) } #my $captcha_from_cookie = $openresty->{_captcha_from_cookie}; #if ($captcha_from_cookie) { #$OpenResty::Cache->remove($captcha_from_cookie); #} my $uuid = $OpenResty::UUID->create_str; if ($openresty->{_use_cookie}) { $openresty->{_cookie} = { session => $uuid }; } $OpenResty::Cache->set($uuid => "$account.$role", 48 * 3600); # expire in 8 h return { success => 1, account => $account, role => $role, session => $uuid, }; } sub login_by_sql { my ($self, $openresty, $user, $params) = @_; _STRING($user) or die "Bad user name: ", $OpenResty::Dumper->($user), "\n"; $params ||= {}; ### $params ### caller: caller() my $password = $params->{password}; my $captcha = $params->{captcha}; my $account; my $role = 'Admin'; if ($user =~ /^(\w+)\.(\w+)$/) { ($account, $role) = ($1, $2); } elsif ($user =~ /^\w+$/) { $account = $&; } else { die "Bad user name: ", $OpenResty::Dumper->($user), "\n"; } _IDENT($account) or die "Bad account name: ", $OpenResty::Dumper->($account), "\n"; _IDENT($role) or die "Bad role name: ", $OpenResty::Dumper->($role), "\n"; ### $role # this part is lame? if (!$account) { die "Login required.\n"; } ### True sol: $true_sol $openresty->set_user($account); $OpenResty::Backend->login($account, $role, $captcha, $password); if (defined $captcha) { my ($id, $user_sol) = split /:/, $captcha, 2; my ($rc,$err)=OpenResty::Handler::Captcha::validate_captcha($openresty,$id,$user_sol); if (!$rc) { die $err."\n"; } } $openresty->set_role($role); my $session_from_cookie = $openresty->{_session_from_cookie}; ### Get session ID from cookie: $session_from_cookie if ($session_from_cookie) { $OpenResty::Cache->remove($session_from_cookie) } #my $captcha_from_cookie = $openresty->{_captcha_from_cookie}; #if ($captcha_from_cookie) { #$OpenResty::Cache->remove($captcha_from_cookie); #} my $uuid = $OpenResty::UUID->create_str; if ($openresty->{_use_cookie}) { $openresty->{_cookie} = { session => $uuid }; } $OpenResty::Cache->set($uuid => "$account.$role", 48 * 3600); # expire in 8 h return { success => 1, account => $account, role => $role, session => $uuid, }; } 1; __END__ =head1 NAME OpenResty::Handler::Login - The login handler for OpenResty =head1 SYNOPSIS =head1 DESCRIPTION This OpenResty handler class implements the Login API, i.e., the C stuff. =head1 METHODS =head1 AUTHOR Agent Zhang (agentzh) C<< >> =head1 SEE ALSO L, L, L, L, L, L, L, L.