Add account management page

This commit is contained in:
Citlali del Rey 2022-10-15 13:45:04 -07:00
parent 01ad8acd9a
commit 30902a0912
Signed by: nullobsi
GPG Key ID: 933A1F44222C2634
7 changed files with 258 additions and 0 deletions

View File

@ -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;

View File

@ -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;

View File

@ -132,6 +132,7 @@ textarea {
margin: auto 0 auto auto;
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
#nav a {

View File

@ -0,0 +1,66 @@
% title 'UNIX.dog Account';
% layout 'default';
<% if (my $err = stash 'err') { %>
<p class="error">
<%= $err %>
</p>
<% if (my $failed = stash 'failed' and my $v = stash 'v') { %>
<ul class="error">
<% foreach my $fn (@{$failed}) { %>
<% my ($check, $result, @args) = @{$v->error($fn)}; %>
<li><%= $fn %>: <%= $check %> <%= join "-", @args %></li>
<% } %>
</ul>
<% } %>
<% } %>
<p>
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. :)
</p>
<p>
Here is your current information:
</p>
%= form_for account => (method => 'POST') => begin
<p>
%= label_for gecos => 'GECOS field:'
%= text_field gecos => $gecos, id => 'gecos'
</p>
<p>
%= label_for givenName => 'First name:'
%= text_field givenName => $givenName, id => 'givenName'
</p>
<p>
%= label_for surname => 'Last name:'
%= text_field surname => $surname, id => 'surname'
</p>
<p>
%= label_for loginShell => 'Login shell:'
%= text_field loginShell => $loginShell, id => 'loginShell'
</p>
<p>
%= label_for roomNumber => 'Room number:'
%= text_field roomNumber => $roomNumber, id => 'roomNumber'
</p>
<p>
%= label_for telNum => 'Telephone number:'
%= text_field telNum => $telNum, id => 'telNum'
</p>
<p>
%= label_for sshKeys => 'SSH keys:'
<br>
%= text_area sshKeys => $sshKeys, id => 'sshKeys'
</p>
<p>
Leave this blank if you don't want to change your password.
<br>
%= label_for newPasswd => 'New password:'
%= password_field 'newPasswd', id => 'newPasswd'
</p>
<p>
%= label_for curPasswd => 'Current password:'
%= password_field 'curPasswd', id => 'curPasswd'
</p>
<input type="text" name="username" hidden="true" value="<%= $username %>">
%= submit_button 'Update!'
% end

View File

@ -0,0 +1,26 @@
% title 'UNIX.dog Account Management';
% layout 'default';
<h1>Account</h1>
<% if (my $err = stash 'err') { %>
<p class="error">
<%= $err %>
</p>
<% } %>
<p>
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.
</p>
<p>
You can also use LDAP tools to connect to
ldap.unix.dog and manage your account information
that way.
</p>
%= form_for account => begin
<p>
%= label_for username => 'Enter your username to get started:'
%= text_field 'username', id => 'username'
</p>
%= submit_button
% end

View File

@ -0,0 +1,4 @@
% title 'UNIX.dog Account Management';
% layout 'default';
<h1>Success</h1>
<p>Your account was updated successfully.</p>

View File

@ -19,6 +19,7 @@
<img src="favicon.ico" width="32" height="32" alt="UNIX.dog"/>
<h1><a href="/">UNIX.dog</a></h1>
<div id="nav">
<a href="/account">Account</a>
<a href="/services">Services</a>
<a href="/register">Register</a>
</div>