Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce change_user_status admin interface #458

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion lib/pause_2017/PAUSE/Web/Config.pm
Original file line number Diff line number Diff line change
Expand Up @@ -537,11 +537,25 @@ our %Actions = (
cat => "01usr/01look",
desc => "Admins can look where email should go",
},
change_user_status => {
x_mojo_to => "admin#change_user_status",
verb => "Change user status",
priv => "admin",
cat => "01usr/03",
desc => "Admins can change the ustatus of a user",
x_csrf_protection => 1,
x_form => {
HIDDENNAME => {form_type => "hidden_field"},
pause99_change_user_status_user => {form_type => "text_field"},
pause99_change_user_status_new_ustatus => {form_type => "select_field"},
pause99_change_user_status_sub => {form_type => "submit_button"},
},
},
select_user => {
x_mojo_to => "admin#select_user",
verb => "Select User/Action",
priv => "admin",
cat => "01usr/03",
cat => "01usr/04",
desc => "Admins can access PAUSE as-if they were somebody else. Here they select a user/action pair.",
method => 'POST',
x_form => {
Expand Down
44 changes: 44 additions & 0 deletions lib/pause_2017/PAUSE/Web/Controller/Admin.pm
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,50 @@ sub edit_ml {
}
}

sub change_user_status {
my $c = shift;
my $pause = $c->stash(".pause");
my $mgr = $c->app->pause;
my $req = $c->req;
my $u = $c->active_user_record;

my %valid_status = map {$_ => 1} qw(active nologin);

my $user = $req->param("pause99_change_user_status_user");
my $new_ustatus = $req->param("pause99_change_user_status_new_ustatus");
if ($user) {
$pause->{user} = uc $user;
my $dbh = $mgr->connect;
my $sql = qq{SELECT ustatus FROM users WHERE userid = ?};
my $row = $dbh->selectrow_arrayref($sql, undef, uc $user);
if ($row) {
$pause->{ustatus} = $row->[0];
} else {
$pause->{user_not_found} = 1;
return;
}

if ($new_ustatus && $valid_status{$new_ustatus} && $new_ustatus ne $pause->{ustatus}) {
my $sql = qq{UPDATE users SET ustatus = ?, changed = ?, changedby = ? WHERE userid = ?};
my $sth = $dbh->prepare($sql);
my $ret = $sth->execute($new_ustatus, time, $u->{userid}, uc $user);
$sth->finish;
if ($ret) {
$pause->{changed} = 1;
$pause->{new_ustatus} = $new_ustatus;
my $mailblurb = $c->render_to_string("email/admin/change_user_status", format => "email");
my @to = ($u->{secretemail}||$u->{email}, $mgr->config->mailto_admins);
warn "sending to[@to]";
warn "mailblurb[$mailblurb]";
my $header = {
Subject => "User status update for $user"
};
$mgr->send_mail_multi(\@to, $header, $mailblurb);
}
}
}
}

sub select_user {
my $c = shift;
my $pause = $c->stash(".pause");
Expand Down
19 changes: 19 additions & 0 deletions lib/pause_2017/templates/admin/change_user_status.html.ep
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
% layout 'layout';
% my $pause = stash(".pause") || {};

<input type="hidden" name="HIDDENNAME" value="<%= $pause->{HiddenUser}{userid} %>">

% if ($pause->{user_not_found}) {
<div class="messagebox error">
<p>User <%= $pause->{user} %> is not found.</p>
</div>
% } elsif ($pause->{changed}) {
<div class="messagebox info">
<p><%= $pause->{user} %>'s status has changed from <%= $pause->{ustatus} %> to <%= $pause->{new_ustatus} %>.</p>
</div>
% }

%= csrf_field
%= text_field "pause99_change_user_status_user" => $pause->{user};
%= select_field "pause99_change_user_status_new_ustatus" => ['nologin', 'active'];
%= submit_button "Change", name => "pause99_change_user_status_sub";
13 changes: 13 additions & 0 deletions lib/pause_2017/templates/email/admin/change_user_status.email.ep
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
% my $pause = stash(".pause") || {};
%
%#------------------------------------------------------------------
%
Record update in the PAUSE users database:

The ustatus of <%= $pause->{user} %> has changed from <%= $pause->{ustatus} %> to <%= $pause->{new_ustatus} %>.

Data entered by <%= $pause->{User}{fullname} %>.

Thanks,
--
The PAUSE Team
98 changes: 98 additions & 0 deletions t/pause_2017/action/change_user_status.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use Mojo::Base -strict;
use FindBin;
use lib "$FindBin::Bin/../lib";
use Test::PAUSE::Web;

my $default = {
pause99_change_user_status_user => "TESTUSER",
pause99_change_user_status_new_ustatus => "nologin",
pause99_change_user_status_sub => 1,
};

Test::PAUSE::Web->setup;

subtest 'get' => sub {
for my $test (Test::PAUSE::Web->tests_for('admin')) {
my ($path, $user) = @$test;
my $t = Test::PAUSE::Web->new(user => $user);
$t->get_ok("$path?ACTION=change_user_status");
# note $t->content;
}
};

subtest 'post: basic' => sub {
Test::PAUSE::Web->setup;
for my $test (Test::PAUSE::Web->tests_for('admin')) {
my ($path, $user) = @$test;
my %form = %$default;
my $t = Test::PAUSE::Web->new(user => $user);
my $res = $t->post("$path?ACTION=change_user_status", \%form);
ok !$res->is_success && $res->code == 403, "Forbidden";
like $res->content => qr/Failed CSRF check/;
# note $t->content;
}
};

subtest 'post_with_token: basic' => sub {
Test::PAUSE::Web->setup;
for my $test (Test::PAUSE::Web->tests_for('admin')) {
my ($path, $user) = @$test;
my %form = %$default;
my $t = Test::PAUSE::Web->new(user => $user);
$t->post_with_token_ok("$path?ACTION=change_user_status", \%form)
->text_like("div.messagebox p", qr/status has changed from \w+ to nologin/);
is $t->deliveries => 2, "two deliveries for admin";
# note $t->content;
}
};

subtest 'post_with_token: user not found' => sub {
Test::PAUSE::Web->setup;
for my $test (Test::PAUSE::Web->tests_for('admin')) {
my ($path, $user) = @$test;
my %form = (
%$default,
pause99_change_user_status_user => 'UNKNOWN',
);
my $t = Test::PAUSE::Web->new(user => $user);
$t->post_with_token_ok("$path?ACTION=change_user_status", \%form)
->text_like("div.messagebox p", qr/User UNKNOWN is not found/);
is $t->deliveries => 0, "no deliveries for admin";
# note $t->content;
}
};

subtest 'post_with_token: ustatus not changed' => sub {
Test::PAUSE::Web->setup;
for my $test (Test::PAUSE::Web->tests_for('admin')) {
my ($path, $user) = @$test;
my %form = %$default;
my $t = Test::PAUSE::Web->new(user => $user);
$t->post_with_token_ok("$path?ACTION=change_user_status", \%form)
->text_like("div.messagebox p", qr/status has changed from \w+ to nologin/);
is $t->deliveries => 2, "two deliveries for admin";
# note $t->content;

# nologin to nologin
$t->post_with_token_ok("$path?ACTION=change_user_status", \%form)
->dom_not_found("div.messagebox p");
is $t->deliveries => 0, "no deliveries for admin";
}
};

subtest 'post_with_token: unknown ustatus' => sub {
Test::PAUSE::Web->setup;
for my $test (Test::PAUSE::Web->tests_for('admin')) {
my ($path, $user) = @$test;
my %form = (
%$default,
pause99_change_user_status_new_ustatus => 'unknown',
);
my $t = Test::PAUSE::Web->new(user => $user);
$t->post_with_token_ok("$path?ACTION=change_user_status", \%form)
->dom_not_found("div.messagebox p");
is $t->deliveries => 0, "no deliveries for admin";
}
};

done_testing;
11 changes: 11 additions & 0 deletions t/pause_2017/lib/Test/PAUSE/Web.pm
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,17 @@ sub text_unlike {
$self;
}

sub dom_not_found {
my ($self, $selector) = @_;
my $at = $self->dom->at($selector);
if ($at) {
fail "'$selector' is found";
} else {
pass "'$selector' is not found";
}
$self;
}

sub title_is_ok {
my ($self, $url) = @_;
return if $self->dom->at('p.error_message'); # ignore if error
Expand Down
Loading