summaryrefslogtreecommitdiff
path: root/lib/VNWeb/User/Login.pm
blob: 0aaa1aba8cc3afe0eaf100858ae821cdc27a3fdf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package VNWeb::User::Login;

use VNWeb::Prelude;


TUWF::get '/u/login' => sub {
    return tuwf->resRedirect('/', 'temp') if auth;

    my $ref = tuwf->reqGet('ref');
    $ref = '/' if !$ref || $ref !~ /^\//;

    framework_ title => 'Login', sub {
        elm_ 'User.Login' => tuwf->compile({}), $ref;
    };
};


elm_api UserLogin => undef, {
    username => { username => 1 },
    password => { password => 1 }
}, sub {
    my $data = shift;

    my $ip = norm_ip tuwf->reqIP;
    my $tm = tuwf->dbVali(
        'SELECT', sql_totime('greatest(timeout, now())'), 'FROM login_throttle WHERE ip =', \$ip
    ) || time;
    return elm_LoginThrottle if $tm-time() > config->{login_throttle}[1];

    my $insecure = is_insecurepass $data->{password};
    if(auth->login($data->{username}, $data->{password}, $insecure)) {
        auth->audit(auth->uid, 'login') if !$insecure;
        return $insecure ? elm_InsecurePass : elm_Success
    }

    # Failed login, log and update throttle.
    auth->audit(tuwf->dbVali('SELECT id FROM users WHERE lower(username) = lower(', \$data->{username}, ')'), 'bad password', 'failed login attempt');
    my $upd = {
        ip      => \$ip,
        timeout => sql_fromtime $tm + config->{login_throttle}[0]
    };
    tuwf->dbExeci('INSERT INTO login_throttle', $upd, 'ON CONFLICT (ip) DO UPDATE SET', $upd);
    elm_BadLogin
};


elm_api UserChangePass => undef, {
    username => { username => 1 },
    oldpass  => { password => 1 },
    newpass  => { password => 1 },
}, sub {
    my $data = shift;
    my $uid = tuwf->dbVali('SELECT id FROM users WHERE lower(username) = lower(', \$data->{username}, ')');
    die if !$uid;
    return elm_InsecurePass if is_insecurepass $data->{newpass};
    auth->audit($uid, 'password change', 'after login with an insecure password');
    die if !auth->setpass($uid, undef, $data->{oldpass}, $data->{newpass}); # oldpass should already have been verified.
    elm_Success
};


TUWF::post qr{/$RE{uid}/logout}, sub {
    return tuwf->resNotFound if !auth || auth->uid ne tuwf->capture('id') || (tuwf->reqPost('csrf')||'') ne auth->csrftoken;
    auth->logout;
    tuwf->resRedirect('/', 'post');
};

1;