From 30902a09129a4d0ecba4a9053f33c686e684707d Mon Sep 17 00:00:00 2001 From: Kayden Tebau Date: Sat, 15 Oct 2022 13:45:04 -0700 Subject: [PATCH] Add account management page --- lib/unix_dog.pm | 3 + lib/unix_dog/Controller/Account.pm | 157 ++++++++++++++++++++++++ public/css/main.css | 1 + templates/account/accountManage.html.ep | 66 ++++++++++ templates/account/accountPage.html.ep | 26 ++++ templates/account/success.html.ep | 4 + templates/layouts/default.html.ep | 1 + 7 files changed, 258 insertions(+) create mode 100644 lib/unix_dog/Controller/Account.pm create mode 100644 templates/account/accountManage.html.ep create mode 100644 templates/account/accountPage.html.ep create mode 100644 templates/account/success.html.ep diff --git a/lib/unix_dog.pm b/lib/unix_dog.pm index d15fadb..6c175fe 100644 --- a/lib/unix_dog.pm +++ b/lib/unix_dog.pm @@ -23,6 +23,9 @@ sub startup ($self) { $r->get('/register')->to('Register#registration'); $r->post('/register')->to('Register#register'); + + $r->get('/account')->to('Account#account'); + $r->post('/account')->to('Account#update_account'); } 1; diff --git a/lib/unix_dog/Controller/Account.pm b/lib/unix_dog/Controller/Account.pm new file mode 100644 index 0000000..01e7ed8 --- /dev/null +++ b/lib/unix_dog/Controller/Account.pm @@ -0,0 +1,157 @@ +package unix_dog::Controller::Account; +use Mojo::Base 'Mojolicious::Controller', -signatures; +use Net::LDAPS; +use Net::LDAP::Extension::SetPassword; + +sub update_account($self) { + my $v = $self->validation; + $v->optional('gecos'); + $v->optional('givenName'); + $v->optional('surname'); + $v->required('loginShell')->size(1,64); + $v->optional('roomNumber'); + $v->optional('telNum'); + $v->required('sshKeys')->size(1,4096); + + $v->optional('newPasswd'); + $v->required('curPasswd')->size(1,512); + + $v->required('username', 'trim')->size(1,32)->like(qr/^([a-z_][a-z0-9_-]*[\$]?)$/); + + my $gecos = $self->param('gecos'); + my $givenName = $self->param('givenName'); + my $surname = $self->param('surname'); + my $loginShell = $self->param('loginShell'); + my $roomNumber = $self->param('roomNumber'); + my $telNum = $self->param('telNum'); + my @sshKeys = split "\n", $self->param('sshKeys'); + + my $curPasswd = $self->param('curPasswd'); + my $newPasswd = $self->param('newPasswd'); + + my $username = $self->param('username'); + + $self->stash( + gecos => $gecos, + givenName => $givenName, + surname => $surname, + loginShell => $loginShell, + roomNumber => $roomNumber, + telNum => $telNum, + sshKeys => join("\n", @sshKeys), + username => $username, + ); + + if ($v->has_error) { + my $err = "Your input was invalid. Please try again."; + my @failed = $v->failed; + $self->stash(err => $err); + $self->stash(failed => @failed); + $self->stash(v => $v); + + return $self->render('account/accountManage'); + } + + + my $config = $self->config; + my $connStr = $config->{'ldap'}->{'uri'}; + my $userDN ='CN='.$username.',OU=Dogs,DC=unix,DC=dog'; + + return Mojo::IOLoop->subprocess->run_p(sub { + my $ldap = Net::LDAPS->new($connStr, verify=>'none', version=>3) or die "$@"; + my $mesg = $ldap->bind($userDN, password=>$curPasswd); + $mesg->code and die $mesg->error; + + + $mesg = $ldap->modify( + $userDN, + replace => { + gecos => $gecos || [], + givenName => $givenName || [], + sn => $surname || [], + loginShell => $loginShell, + roomNumber => $roomNumber || [], + telephoneNumber => $telNum || [], + sshPublicKey => @sshKeys, + } + ); + $mesg->code and die $mesg->error; + + if (defined $newPasswd and $newPasswd) { + $mesg = $ldap->set_password( + user => $userDN, + oldpasswd => $curPasswd, + newpasswd => $newPasswd + ); + $mesg->code and die $mesg->error; + } + })->then(sub (@results) { + return $self->render('account/success'); + })->catch(sub ($err) { + $self->stash(err => $err); + return $self->render('account/accountManage'); + }); + + +} + +sub account($self) { + + my $v = $self->validation; + + $v->optional('username', 'trim')->size(1,32)->like(qr/^([a-z_][a-z0-9_-]*[\$]?)$/); + + if ($v->has_error) { + $self->stash(err => 'Username is invalid.'); + return $self->render('account/accountPage'); + } + + if ($v->has_data) { + my $username = $self->param('username'); + my $config = $self->config; + my $connStr = $config->{'ldap'}->{'uri'}; + return Mojo::IOLoop->subprocess->run_p(sub { + my $ldap = Net::LDAPS->new($connStr, verify=>'none', version=>3) or die "$@"; + my $mesg = $ldap->bind(); + $mesg->code and die $mesg->error; + + $mesg = $ldap->search( + base => 'OU=Dogs,DC=unix,DC=dog', + filter => '(uid='.$username.')', + ); + $mesg->code and die $mesg->error; + + my $userEntry = $mesg->first_entry; + $userEntry or die 'User not found'; + + my $gecos = $userEntry->get_value('gecos'); + my $givenName = $userEntry->get_value('givenname'); + my $surname = $userEntry->get_value('sn'); + my $loginShell = $userEntry->get_value('loginshell'); + my $roomNumber = $userEntry->get_value('roomnumber'); + my $telNum = $userEntry->get_value('telephonenumber'); + my @sshKeys = $userEntry->get_value('sshPublicKey'); + + return ( + gecos => $gecos, + givenName => $givenName, + surname => $surname, + loginShell => $loginShell, + roomNumber => $roomNumber, + telNum => $telNum, + sshKeys => join("\n", @sshKeys), + username => $username, + ) + })->then(sub (@results) { + $self->stash(@results); + $self->render('account/accountManage'); + })->catch(sub ($err) { + $self->stash(err => $err); + $self->render('account/accountPage'); + }); + } + + return $self->render('account/accountPage'); +} + +1; diff --git a/public/css/main.css b/public/css/main.css index 8e9218c..0cd9af1 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -132,6 +132,7 @@ textarea { margin: auto 0 auto auto; display: flex; flex-direction: row; + flex-wrap: wrap; } #nav a { diff --git a/templates/account/accountManage.html.ep b/templates/account/accountManage.html.ep new file mode 100644 index 0000000..e828d3c --- /dev/null +++ b/templates/account/accountManage.html.ep @@ -0,0 +1,66 @@ +% title 'UNIX.dog Account'; +% layout 'default'; +<% if (my $err = stash 'err') { %> +

+ <%= $err %> +

+ <% if (my $failed = stash 'failed' and my $v = stash 'v') { %> + + <% } %> +<% } %> +

+ Please note that this information is public. We don't recommend + that you publish your actual phone number or actual name, but + it's fun for some jokes. :) +

+

+ Here is your current information: +

+%= form_for account => (method => 'POST') => begin +

+ %= label_for gecos => 'GECOS field:' + %= text_field gecos => $gecos, id => 'gecos' +

+

+ %= label_for givenName => 'First name:' + %= text_field givenName => $givenName, id => 'givenName' +

+

+ %= label_for surname => 'Last name:' + %= text_field surname => $surname, id => 'surname' +

+

+ %= label_for loginShell => 'Login shell:' + %= text_field loginShell => $loginShell, id => 'loginShell' +

+

+ %= label_for roomNumber => 'Room number:' + %= text_field roomNumber => $roomNumber, id => 'roomNumber' +

+

+ %= label_for telNum => 'Telephone number:' + %= text_field telNum => $telNum, id => 'telNum' +

+

+ %= label_for sshKeys => 'SSH keys:' +
+ %= text_area sshKeys => $sshKeys, id => 'sshKeys' +

+

+ Leave this blank if you don't want to change your password. +
+ %= label_for newPasswd => 'New password:' + %= password_field 'newPasswd', id => 'newPasswd' +

+

+ %= label_for curPasswd => 'Current password:' + %= password_field 'curPasswd', id => 'curPasswd' +

+ + %= submit_button 'Update!' +% end diff --git a/templates/account/accountPage.html.ep b/templates/account/accountPage.html.ep new file mode 100644 index 0000000..a3b895f --- /dev/null +++ b/templates/account/accountPage.html.ep @@ -0,0 +1,26 @@ +% title 'UNIX.dog Account Management'; +% layout 'default'; +

Account

+<% if (my $err = stash 'err') { %> +

+ <%= $err %> +

+<% } %> +

+ Here you can change your password or SSH keys + used to log into the server. Please note that + SSH keys must be stored in LDAP, and the + .authorized_keys file does not work. +

+

+ You can also use LDAP tools to connect to + ldap.unix.dog and manage your account information + that way. +

+%= form_for account => begin +

+ %= label_for username => 'Enter your username to get started:' + %= text_field 'username', id => 'username' +

+%= submit_button +% end diff --git a/templates/account/success.html.ep b/templates/account/success.html.ep new file mode 100644 index 0000000..762ee3e --- /dev/null +++ b/templates/account/success.html.ep @@ -0,0 +1,4 @@ +% title 'UNIX.dog Account Management'; +% layout 'default'; +

Success

+

Your account was updated successfully.

diff --git a/templates/layouts/default.html.ep b/templates/layouts/default.html.ep index 2457fba..dedeefc 100644 --- a/templates/layouts/default.html.ep +++ b/templates/layouts/default.html.ep @@ -19,6 +19,7 @@ UNIX.dog

UNIX.dog