Also, don't use the flash anymore for going back to the referer.
LSZLZHJYGXZTCNH4JUXU7W23MW5PBVM4OBMWRRVNEDROMIBUVQNAC
F7S2EGV2SLCAPGKAL5QHXS5KDOIRVAXVXYAIMSNYW27VM6J3X5TAC
6ED5NSYT67X4LXDMIYBEIV64JUOWRY7EW2QE4FW2HZGQS2ME4BTAC
CB33YUQLKC3CH2DKRAAUAES6DK475AKZARGGHXWK35QTBVURWRBQC
QIW2WZKWE3ULO4O4QB6EQWUKZY2UFNN7WA464FMIZOAHP3UHFGSAC
K22TMPH534XFKE6MWYRZSOCRWB7MCBKTMUBIBDF36FJR5DF5UE3AC
WYMEG4VPYR4AE54S5KJYL6WDILJ4GDVJA23AHKUZDLTFFZOPAIBAC
EVZTBKEFHKIT6LIDRNAYFNELPYS7L2YQBLPQUB3LHLYSP3UM4OCQC
XJRJ4J7M6BC433TBLWHHKX7UYYCFX6M7ZQLUEYYTREPCSM6M3RDQC
BKOIYITRBRVU4D7XFAZPV5QHAPCBMIO3SBNHYJ6TVT43WR32CTHQC
PCKLFRT5IZVLG47GQQ23GBSROKUR4CUEZW4PRVGREHNDFTCZ7VBAC
SZYDW2DG5Z7BR3ICKWDXVUNSMCDSXMYZUB6FQ4W2B2FVZJD6PULQC
ZWCTAZGLJZQNTYWTC2XQUKMILJF6JGDL5IND6QNYWK4FIGMLRFXAC
SMCOU72FKTPFNCDXFJAILVUWFE4DY33CJJE4436H5POKENFFDFFAC
QT4FO2HPUPOS72Y5UTILN5AOV7S47AGG7V32CT24NA7TOVP76NAQC
JARRBLZDQ2JZWY7IUVPTOT7WJMBPMLFLF2MGLVGOYROAAISYGLSAC
6KJXJB7NZ5XJ3WGUWKFNT6LMBNYJN3IPHZ7B7H654D5B6LPOL5QAC
I2WEO2VSDAYTRCHV7UJP2YPDUEJ6RM3N7JJV24P6A5WZSZG73X3AC
IK2KI6KZEJCPWJDOCWWMXYCARUSMRDK73QMUTCOROUHWJ22VXDAQC
3PNG7NIBQQURUUPRVQXYL342OT7JUUYOMY2JJNP6YDX7SYJDZMYAC
PALLP4UYHQRWZB5HIZN7QCUA43WMQRCWMBETAQX5A4R77QACVFKQC
5D327YA3JUHPTGZVF5UVAECNM34OYWQARYGHSHXCJMC6A46X3E5AC
SN2KFKSW3CQXK2T3P23AXEOV2BRGHDHLPKUG5P77GNCLNROLTGSQC
NYC3LZKHWRIP2VJDCO3UVPR6TR7JURVX5NBS4H2AOOOG3ZG5G6FAC
SMM4HQTPAY45254O7GQOJVLHP5LZ6BXDKGNE7IKUJHB5XKH244ZAC
J5UVLXOK6EDIL5I7VKWH4V2QDS4DPD7FHRK6XBWSXFRQS4JKXFZQC
AFEKITYDRS6BTHHBUAELN2GSHP4VDZPVH2FVA23NF3IURVDHJY7AC
XE6HD7BPU2TGDFSXCLBQTVBBCJBPCRP7ENRE3RWQRK5SWUMTITPQC
MVB7RRLTOLZALMUVUNSCMXDB76QLICJAV2GYQQZO7E6S327LHMSQC
CS7T2XFIISZ7TPQ6FFRIDYPR6BDCQHURP4JE4YKLI4OYSNWKZCHAC
7DWCXNC72OO3M4YGNVV4KM775CUSPBHEFFNMRIA2XAZTQCXYHBRQC
LBNVQXUBEZ45SOTGVXK5UEZXIAIZTJLWZNUYFI4JZ6J65N3KPDVQC
5NO7NCKTMM5ZW7JYOETUFOSWK2ACTXWDZGJAFXZN6L3OF6BFTNOQC
A52HEFHQNVNF2OUSWDSUYVVXLYR2UFCGOORPCN27CJJYA4UDJA3AC
FPK5LF53CFUEKFYJ3IYXT4UTVC6IITWJOCFATMC4PLHEUP5SIEAAC
D5QIOJGPKQJIYBUCSC3MFJ3TXLPNZ2XMI37GXMFRVRFWWR2VMTFAC
UICHT2PSN2QOCHP6MGY5QQJUDU4IF6FBIOJLBA55QBJDK6ST566AC
QL55ECJ6KMMBUOWQ6LKSOVN7L43CH4S6SPE2AQ3VX3KSGC32RP4AC
KA45EBF5GVBBFQ2E6GSMDJ5ORSOJ7YP5EHAHLUZB226F7WNO6KYQC
AJKTRRDJA6N5NZ7ZZNN6RQCLIJKOHQ5OF3QQFQMGKOM5MNIHEYPQC
7YBYT2LQML2PKEO6UO4444AGSASS664UCDXW2YO3ALB7THQHCEBQC
WQXF2T3DFC2K72OVX46TUQ4IMZNJ5BSBQ7L7AVI7QL54DXCBEKLQC
HX4QYOYAKKFKK4KF6SZ6FQCM5ZF7ZFDTQUR4GS5WPPTYZASYZZUAC
SBKX3YH2EOCYY2IDACGOTXHJZSYSRHD5EC7FB6WGPKHLFYOF6SAAC
3RL7VFKEVVQBVKLKM7ZS3M67BOGGJ3OWPARHG64AOUTZTPPYCHLQC
HE3GX5IPS6XA7KLNP5WZY2YU27WQS663WSKAL5FHWBSJ5GMM633AC
}
sub updateUser {
my ($c, $user) = @_;
my $username = trim $c->request->params->{"username"};
my $fullname = trim $c->request->params->{"fullname"};
my $emailaddress = trim $c->request->params->{"emailaddress"};
my $emailonerror = trim $c->request->params->{"emailonerror"};
my $roles = $c->request->params->{"roles"} ;
$user->update(
{ fullname => $fullname
, emailaddress => $emailaddress
, emailonerror => $emailonerror
});
$user->userroles->delete_all;
if(ref($roles) eq 'ARRAY') {
for my $s (@$roles) {
$user->userroles->create({ role => $s}) ;
}
} else {
$user->userroles->create({ role => $roles}) if defined $roles ;
}
}
sub create_user : Chained('admin') PathPart('create-user') Args(0) {
my ($self, $c) = @_;
requireAdmin($c);
$c->stash->{template} = 'user.tt';
$c->stash->{edit} = 1;
$c->stash->{create} = 1;
txn_do($c->model('DB')->schema, sub {
my $user = $c->model('DB::Users')->create(
{username => $username, emailaddress => "", password => ""});
updateUser($c, $user);
});
$c->res->redirect("/admin/users");
}
sub user : Chained('admin') PathPart('user') CaptureArgs(1) {
my ($self, $c, $username) = @_;
requireAdmin($c);
my $user = $c->model('DB::Users')->find($username)
or notFound($c, "User $username doesn't exist.");
$c->stash->{user} = $user;
}
sub user_edit : Chained('user') PathPart('edit') Args(0) {
my ($self, $c) = @_;
$c->stash->{template} = 'user.tt';
$c->stash->{edit} = 1;
}
sub user_edit_submit : Chained('user') PathPart('submit') Args(0) {
my ($self, $c) = @_;
requirePost($c);
txn_do($c->model('DB')->schema, sub {
if (($c->request->params->{submit} || "") eq "delete") {
$c->stash->{user}->delete;
} else {
updateUser($c, $c->stash->{user});
}
});
$c->res->redirect("/admin/users");
}
sub sendemail {
my ($to, $subject, $body) = @_;
my $url = hostname_long;
my $sender = ($ENV{'USER'} || "hydra") . "@" . $url;
my $email = Email::Simple->create(
header => [
To => $to,
From => "Hydra <$sender>",
Subject => $subject
],
body => $body
);
sendmail($email);
}
sub reset_password : Chained('user') PathPart('reset-password') Args(0) {
my ($self, $c) = @_;
# generate password
my $password = Crypt::RandPasswd->word(8,10);
# calculate hash
my $hashed = sha1_hex($password);
$c->stash->{user}-> update({ password => $hashed}) ;
# send email
sendemail(
$c->stash->{user}->emailaddress,
"New password for Hydra",
"Hi,\n\n".
"Your password has been reset. Your new password is '$password'.\n".
"You can change your password at " . $c->config()->{'base_uri'} . "/change-password .\n".
"With regards, Hydra\n"
);
$c->res->redirect("/admin/users");
}
sub change_password : Path('change-password') :Args(0) {
my ($self, $c) = @_;
requireLogin($c) if !$c->user_exists;
$c->stash->{template} = 'change-password.tt';
}
sub change_password_submit : Path('change-password/submit') : Args(0) {
my ($self, $c) = @_;
requireLogin($c) if !$c->user_exists;
my $password = $c->request->params->{"password"};
my $password_check = $c->request->params->{"password_check"};
print STDERR "$password \n";
print STDERR "$password_check \n";
error($c, "Passwords did not match, go back and try again!") if $password ne $password_check;
my $hashed = sha1_hex($password);
$c->user->update({ password => $hashed}) ;
$c->res->redirect("/");
}
if ($c->authenticate({username => $username, password => $password})) {
$c->response->redirect($c->flash->{referer} || $c->uri_for('/'));
$c->flash->{referer} = undef;
return;
}
backToReferer($c) if $c->authenticate({username => $username, password => $password});
$c->authenticate({username => $userName, password => $password})
or error($c, "Unable to authenticate the new user!");
unless ($c->user_exists) {
$c->authenticate({username => $userName, password => $password})
or error($c, "Unable to authenticate the new user!");
}
$c->response->redirect($c->flash->{referer} || $c->uri_for('/'));
backToReferer($c);
}
sub user :Chained('/') PathPart('user') CaptureArgs(1) {
my ($self, $c, $userName) = @_;
requireLogin($c) if !$c->user_exists;
error($c, "You do not have permission to edit other users.")
if $userName ne $c->user->username && !isAdmin($c);
$c->stash->{user} = $c->model('DB::Users')->find($userName)
or notFound($c, "User $userName doesn't exist.");
sub preferences :Local Args(0) {
sub deleteUser {
my ($self, $c, $user) = @_;
my ($project) = $c->model('DB::Projects')->search({ owner => $user->username });
error($c, "User " . $user->username . " is still owner of project " . $project->name . ".")
if defined $project;
$c->logout() if $user->username eq $c->user->username;
$user->delete;
}
sub edit :Chained('user') Args(0) {
error($c, "Not implemented.");
my $user = $c->stash->{user};
$c->stash->{template} = 'user.tt';
$c->session->{referer} = $c->request->referer if !defined $c->session->{referer};
if ($c->request->method ne "POST") {
$c->stash->{fullname} = $user->fullname;
$c->stash->{emailonerror} = $user->emailonerror;
return;
}
if (($c->request->params->{submit} // "") eq "delete") {
deleteUser($self, $c, $user);
backToReferer($c);
}
if (($c->request->params->{submit} // "") eq "reset-password") {
$c->stash->{json} = {};
error($c, "No email address is set for this user.")
unless $user->emailaddress;
my $password = Crypt::RandPasswd->word(8,10);
setPassword($user, $password);
sendEmail($c,
$user->emailaddress,
"Hydra password reset",
"Hi,\n\n".
"Your password has been reset. Your new password is '$password'.\n\n".
"You can change your password at " . $c->uri_for($self->action_for('edit'), [$user->username]) . ".\n\n".
"With regards,\n\nHydra.\n"
);
return;
}
my $fullName = trim $c->req->params->{fullname};
txn_do($c->model('DB')->schema, sub {
error($c, "Your must specify your full name.") if $fullName eq "";
$user->update(
{ fullname => $fullName
, emailonerror => $c->request->params->{"emailonerror"} ? 1 : 0
});
my $password = $c->req->params->{password} // "";
if ($password ne "") {
error($c, "You must specify a password of at least 6 characters.")
unless isValidPassword($password);
error($c, "The passwords you specified did not match.")
if $password ne trim $c->req->params->{password2};
setPassword($user, $password);
}
if (isAdmin($c)) {
$user->userroles->delete_all;
$user->userroles->create({ role => $_})
foreach paramToList($c, "roles");
}
});
backToReferer($c);
my $email = Email::Simple->create(
header => [
To => $to,
From => "Hydra <$sender>",
Subject => $subject
],
body => $body
);
print STDERR "Sending email:\n", $email->as_string if $ENV{'HYDRA_MAIL_TEST'};
sendmail($email);
}
# Catalyst request parameters can be an array or a scalar or
# undefined, making them annoying to handle. So this utility function
# always returns a request parameter as a list.
sub paramToList {
my ($c, $name) = @_;
my $x = $c->request->params->{$name};
return () unless defined $x;
return @$x if ref($x) eq 'ARRAY';
return ($x);
}
[% WRAPPER layout.tt title="Change password" %]
[% PROCESS common.tt %]
<form action="[% c.uri_for('/change-password/submit') %]" method="post">
<h2>Change password</h2>
<tr>
<th>Enter password:</th>
<td><input type="password" class="string" id="password" name="password" /></td>
</tr>
<tr>
<th>Enter password again:</th>
<td><input type="password" class="string" id="password_check" name="password_check" /></td>
</tr>
</table>
<p><button type="submit"><img src="/static/images/success.gif" />Change</button></p>
</form>
[% END %]
<table class="info-table">
<input type="checkbox" name="enabled" [% IF 1; 'checked="checked"'; END %]></input>Receive evaluation error notifications
<input type="checkbox" name="emailonerror" [% IF emailonerror; 'checked="checked"'; END %]></input>Receive evaluation error notifications
[% IF !create && c.check_user_roles('admin') %]
<button id="reset-password" type="submit" class="btn btn-warning" name="submit" value="reset-password">
<i class="icon-trash icon-white"></i>
Reset password
</button>
<script type="text/javascript">
$("#reset-password").click(function() {
bootbox.confirm(
'Are you sure you want to reset the password for this user?',
function(c) {
if (!c) return;
$.post("[% c.uri_for(c.controller('User').action_for('edit'), [user.username]) %]", { submit: 'reset-password' })
.done(function(data) {
if (data.error)
bootbox.alert("Unable to reset password: " + data.error);
else
bootbox.alert("An email containing the new password has been sent to the user.");
})
.fail(function() { bootbox.alert("Server request failed!"); });
});
return false;
});
</script>
[% END %]
<td><a class="row-link" href="[% c.uri_for(c.controller('Admin').action_for('user_edit'), [u.username]) %]">[% u.username %]</a></td>
<td><a class="row-link" href="[% c.uri_for(c.controller('User').action_for('edit'), [u.username]) %]">[% u.username %]</a></td>