diff options
author | Yorhel <git@yorhel.nl> | 2019-09-30 18:05:28 +0200 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2019-09-30 18:05:41 +0200 |
commit | 2d7e855cfb37f35cb2cd0f8f39754002c20c8a7c (patch) | |
tree | b1ff536adee289c3b6e1a56c1f1a71acd1da6c87 /lib/VNWeb/User | |
parent | 24e08e0f2caf8dede4a0c8a77b8ede1e13899785 (diff) |
v2rw: Convert login, logout & insecure-password-change forms
The insecure-password-change flow is now slightly more friendly. The
logout functionality has been hardened to use POST and require CSRF.
Diffstat (limited to 'lib/VNWeb/User')
-rw-r--r-- | lib/VNWeb/User/Login.pm | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/lib/VNWeb/User/Login.pm b/lib/VNWeb/User/Login.pm new file mode 100644 index 00000000..bd8f75ab --- /dev/null +++ b/lib/VNWeb/User/Login.pm @@ -0,0 +1,69 @@ +package VNWeb::User::Login; + +use VNWeb::Prelude; + + +my $LOGIN = form_compile in => { + username => { username => 1 }, + password => { password => 1 } +}; + +elm_form UserLogin => $LOGIN, $LOGIN; + + +TUWF::get '/u/login' => sub { + return tuwf->resRedirect('/', 'temp') if auth; + + my $ref = tuwf->reqGet('ref'); + $ref = '/' if !$ref || $ref !~ /^\//; + + framework_ title => 'Login', index => 0, sub { + elm_ 'User.Login' => tuwf->compile({}), $ref; + }; +}; + + +json_api '/u/login', $LOGIN, 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}; + return $insecure ? elm_InsecurePass : elm_Success + if auth->login($data->{username}, $data->{password}, $insecure); + + # Failed login, update throttle. + 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 +}; + + +json_api '/u/changepass', { + username => { username => 1 }, + oldpass => { password => 1 }, + newpass => { password => 1 }, +}, sub { + my $data = shift; + my $uid = tuwf->dbVali('SELECT id FROM users WHERE username =', \$data->{username}); + die if !$uid; + return elm_InsecurePass if is_insecurepass $data->{newpass}; + 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 != tuwf->capture('id') || (tuwf->reqPost('csrf')||'') ne auth->csrftoken; + auth->logout; + tuwf->resRedirect('/', 'post'); +}; + +1; |