| File: | lib/OpenAPI/Handler/Login.pm |
| Coverage: | 87.0% |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package OpenAPI; | ||||||
| 2 | |||||||
| 3 | #use Smart::Comments; | ||||||
| 4 | 22 22 22 | 174 67 176 | use strict; | ||||
| 5 | 22 22 22 | 234 74 172 | use warnings; | ||||
| 6 | 22 22 22 | 351 76 239 | use vars qw($Cache $UUID $Dumper); | ||||
| 7 | 22 22 22 | 317 85 296 | use CGI::Cookie; | ||||
| 8 | 22 22 22 | 251 64 352 | use Encode 'is_utf8'; | ||||
| 9 | |||||||
| 10 | sub GET_login_user { | ||||||
| 11 | 6 | 0 | 46 | my ($self, $bits) = @_; | |||
| 12 | 6 | 40 | my $user = $bits->[1]; | ||||
| 13 | 6 | 48 | $self->login($user); | ||||
| 14 | } | ||||||
| 15 | |||||||
| 16 | sub GET_login_user_password { | ||||||
| 17 | 22 | 0 | 189 | my ($self, $bits) = @_; | |||
| 18 | 22 | 147 | my $user = $bits->[1]; | ||||
| 19 | 22 | 120 | my $password = $bits->[2]; | ||||
| 20 | 22 | 277 | $self->login($user, { password => $password }); | ||||
| 21 | } | ||||||
| 22 | |||||||
| 23 | sub trim_sol { | ||||||
| 24 | 8 | 0 | 37 | my $s = $_[0]; | |||
| 25 | 8 | 75 | unless (is_utf8($s)) { | ||||
| 26 | 8 | 56 | $s = decode('UTF-8', $s); | ||||
| 27 | } | ||||||
| 28 | 8 | 235 | $s =~ s/\W+//g; | ||||
| 29 | 8 | 116 | $s; | ||||
| 30 | } | ||||||
| 31 | |||||||
| 32 | sub login { | ||||||
| 33 | 71 | 0 | 529 | my ($self, $user, $params) = @_; | |||
| 34 | 71 | 565 | _STRING($user) or die "Bad user name: ", $Dumper->($user), "\n"; | ||||
| 35 | 71 | 1940 | $params ||= {}; | ||||
| 36 | ### $params | ||||||
| 37 | ### caller: caller() | ||||||
| 38 | 71 | 475 | my $password = $params->{password}; | ||||
| 39 | 71 | 381 | my $captcha = $params->{captcha}; | ||||
| 40 | 71 | 218 | my $account; | ||||
| 41 | 71 | 315 | my $role = 'Admin'; | ||||
| 42 | 71 | 843 | if ($user =~ /^(\w+)\.(\w+)$/) { | ||||
| 43 | 40 | 392 | ($account, $role) = ($1, $2); | ||||
| 44 | } elsif ($user =~ /^\w+$/) { | ||||||
| 45 | 29 | 259 | $account = $&; | ||||
| 46 | } else { | ||||||
| 47 | 2 | 10 | die "Bad user name: ", $Dumper->($user), "\n"; | ||||
| 48 | } | ||||||
| 49 | 69 | 560 | _IDENT($account) or die "Bad account name: ", $Dumper->($account), "\n"; | ||||
| 50 | 69 | 514 | _IDENT($role) or die "Bad role name: ", $Dumper->($role), "\n"; | ||||
| 51 | ### $role | ||||||
| 52 | # this part is lame? | ||||||
| 53 | 69 | 474 | if (!$account) { | ||||
| 54 | 0 | 0 | die "Login required.\n"; | ||||
| 55 | } | ||||||
| 56 | 69 | 603 | if (!$self->has_user($account)) { | ||||
| 57 | ### Found user: $user | ||||||
| 58 | 0 | 0 | die "Account \"$account\" does not exist.\n"; | ||||
| 59 | } | ||||||
| 60 | 69 | 1902 | $self->set_user($account); | ||||
| 61 | |||||||
| 62 | 69 | 707 | if (!$self->has_role($role)) { | ||||
| 63 | ### Found user: $user | ||||||
| 64 | 0 | 0 | die "Role \"$role\" does not exist.\n"; | ||||
| 65 | } | ||||||
| 66 | |||||||
| 67 | ### $account | ||||||
| 68 | ### $role | ||||||
| 69 | ### $password | ||||||
| 70 | ### capture param: $captcha | ||||||
| 71 | 69 | 4921 | if (defined $captcha) { | ||||
| 72 | 12 | 153 | my ($id, $user_sol) = split /:/, $captcha, 2; | ||||
| 73 | 12 | 191 | if (!$id or !$user_sol) { | ||||
| 74 | 1 | 4 | die "Bad captcha parameter: $captcha\n"; | ||||
| 75 | } | ||||||
| 76 | 11 | 101 | my $res = $self->select("select count(*) from _roles where name = " . Q($role) . " and login = 'captcha'"); | ||||
| 77 | ### with captcha: $res | ||||||
| 78 | 11 | 8058 | if ($res->[0][0] == 0) { | ||||
| 79 | 1 | 4 | die "Cannot login as $account.$role via captchas.\n"; | ||||
| 80 | } | ||||||
| 81 | ### Captcha ID: $id | ||||||
| 82 | 10 | 122 | my $true_sol = $Cache->get($id); | ||||
| 83 | ### True sol: $true_sol | ||||||
| 84 | 10 | 682 | $Cache->remove($id); | ||||
| 85 | 10 | 1110 | if (!defined $true_sol) { | ||||
| 86 | 4 | 18 | die "Capture ID is bad or expired.\n"; | ||||
| 87 | } | ||||||
| 88 | 6 | 47 | if ($true_sol eq '1') { | ||||
| 89 | 2 | 8 | die "Captcha image never used.\n"; | ||||
| 90 | } | ||||||
| 91 | # XXX for testing purpose... | ||||||
| 92 | 4 | 127 | if ($OpenAPI::Config{'frontend.debug'} && $account eq 'peee' && $role eq 'Poster') { | ||||
| 93 | 4 | 39 | if ($true_sol =~ /[a-z]/) { | ||||
| 94 | 2 | 15 | $true_sol = 'hello world '; | ||||
| 95 | } else { | ||||||
| 96 | 2 | 33 | $true_sol = '你好世界'; | ||||
| 97 | } | ||||||
| 98 | } | ||||||
| 99 | 4 | 28 | if (trim_sol($user_sol) ne trim_sol($true_sol)) { | ||||
| 100 | 2 | 9 | die "Solution to the captcha is incorrect.\n"; | ||||
| 101 | } | ||||||
| 102 | } elsif (defined $password) { | ||||||
| 103 | 51 | 512 | my $res = $self->select("select count(*) from _roles where name = " . Q($role) . " and login = 'password' and password = " . Q($password) . ";"); | ||||
| 104 | ### with password: $res | ||||||
| 105 | 51 | 40259 | if ($res->[0][0] == 0) { | ||||
| 106 | 1 | 5 | die "Password for $account.$role is incorrect.\n"; | ||||
| 107 | } | ||||||
| 108 | } else { | ||||||
| 109 | 6 | 71 | my $res = $self->select("select count(*) from _roles where name = " . Q($role) . " and login = 'anonymous';"); | ||||
| 110 | ### no password: $res | ||||||
| 111 | ### no password (2): $res->[0][0] | ||||||
| 112 | 6 | 4930 | if ($res->[0][0] == 0) { | ||||
| 113 | ### dying... | ||||||
| 114 | 5 | 22 | die "Password for $account.$role is required.\n"; | ||||
| 115 | } | ||||||
| 116 | } | ||||||
| 117 | 53 | 584 | $self->set_role($role); | ||||
| 118 | |||||||
| 119 | 53 | 357 | my $session_from_cookie = $self->{_session_from_cookie}; | ||||
| 120 | ### Get session ID from cookie: $session_from_cookie | ||||||
| 121 | 53 | 358 | if ($session_from_cookie) { | ||||
| 122 | 29 | 287 | $OpenAPI::Cache->remove($session_from_cookie) | ||||
| 123 | } | ||||||
| 124 | |||||||
| 125 | 53 | 3475 | my $captcha_from_cookie = $self->{_captcha_from_cookie}; | ||||
| 126 | 53 | 328 | if ($captcha_from_cookie) { | ||||
| 127 | 3 | 21 | $OpenAPI::Cache->remove($captcha_from_cookie); | ||||
| 128 | } | ||||||
| 129 | |||||||
| 130 | 53 | 5167 | my $uuid = $UUID->create_str; | ||||
| 131 | 53 | 550 | if ($self->{_use_cookie}) { | ||||
| 132 | 29 | 383 | $self->{_cookie} = { session => $uuid }; | ||||
| 133 | } | ||||||
| 134 | 53 | 743 | $Cache->set($uuid => "$account.$role"); | ||||
| 135 | |||||||
| 136 | return { | ||||||
| 137 | 53 | 13035 | success => 1, | ||||
| 138 | account => $account, | ||||||
| 139 | role => $role, | ||||||
| 140 | session => $uuid, | ||||||
| 141 | }; | ||||||
| 142 | } | ||||||
| 143 | |||||||
| 144 | 1; | ||||||
| 145 | |||||||