aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet
diff options
context:
space:
mode:
Diffstat (limited to 'perllib/FixMyStreet')
-rw-r--r--perllib/FixMyStreet/App/Controller/Admin.pm72
-rw-r--r--perllib/FixMyStreet/App/Controller/Auth.pm2
-rw-r--r--perllib/FixMyStreet/Cobrand/Default.pm16
-rw-r--r--perllib/FixMyStreet/Cobrand/SeeSomething.pm5
-rw-r--r--perllib/FixMyStreet/Cobrand/UKCouncils.pm7
-rw-r--r--perllib/FixMyStreet/Cobrand/Zurich.pm6
-rw-r--r--perllib/FixMyStreet/DB/Result/User.pm16
-rw-r--r--perllib/FixMyStreet/Script/CreateSuperuser.pm25
-rw-r--r--perllib/FixMyStreet/TestMech.pm7
9 files changed, 120 insertions, 36 deletions
diff --git a/perllib/FixMyStreet/App/Controller/Admin.pm b/perllib/FixMyStreet/App/Controller/Admin.pm
index bcf66f36f..35af9a1a6 100644
--- a/perllib/FixMyStreet/App/Controller/Admin.pm
+++ b/perllib/FixMyStreet/App/Controller/Admin.pm
@@ -32,10 +32,12 @@ sub begin : Private {
$c->uri_disposition('relative');
- if ( $c->cobrand->moniker eq 'zurich' || $c->cobrand->moniker eq 'seesomething' ) {
- $c->detach( '/auth/redirect' ) unless $c->user_exists;
- $c->detach( '/auth/redirect' ) unless $c->user->from_body;
+ # User must be logged in to see cobrand, and meet whatever checks the
+ # cobrand specifies. Default cobrand just requires superuser flag to be set.
+ unless ( $c->user_exists && $c->cobrand->admin_allow_user($c->user) ) {
+ $c->detach( '/auth/redirect' );
}
+
if ( $c->cobrand->moniker eq 'zurich' ) {
$c->cobrand->admin_type();
}
@@ -73,7 +75,7 @@ sub index : Path : Args(0) {
$c->forward('stats_by_state');
- my @unsent = $c->model('DB::Problem')->search( {
+ my @unsent = $c->cobrand->problems->search( {
state => [ 'confirmed' ],
whensent => undef,
bodies_str => { '!=', undef },
@@ -242,13 +244,15 @@ sub bodies : Path('bodies') : Args(0) {
$c->forward('/auth/check_csrf_token');
my $params = $c->forward('body_params');
- my $body = $c->model('DB::Body')->create( $params );
- my @area_ids = $c->get_param_list('area_ids');
- foreach (@area_ids) {
- $c->model('DB::BodyArea')->create( { body => $body, area_id => $_ } );
- }
+ unless ( keys $c->stash->{body_errors} ) {
+ my $body = $c->model('DB::Body')->create( $params );
+ my @area_ids = $c->get_param_list('area_ids');
+ foreach (@area_ids) {
+ $c->model('DB::BodyArea')->create( { body => $body, area_id => $_ } );
+ }
- $c->stash->{updated} = _('New body added');
+ $c->stash->{updated} = _('New body added');
+ }
}
$c->forward( 'fetch_all_bodies' );
@@ -313,8 +317,13 @@ sub body : Path('body') : Args(1) {
sub check_for_super_user : Private {
my ( $self, $c ) = @_;
- if ( $c->cobrand->moniker eq 'zurich' && $c->stash->{admin_type} ne 'super' ) {
- $c->detach('/page_error_404_not_found', []);
+
+ my $superuser = $c->user->is_superuser;
+ # Zurich currently has its own way of defining superusers
+ $superuser ||= $c->cobrand->moniker eq 'zurich' && $c->stash->{admin_type} eq 'super';
+
+ unless ( $superuser ) {
+ $c->detach('/page_error_403_access_denied', []);
}
}
@@ -403,18 +412,20 @@ sub update_contacts : Private {
$c->forward('/auth/check_csrf_token');
my $params = $c->forward( 'body_params' );
- $c->stash->{body}->update( $params );
- my @current = $c->stash->{body}->body_areas->all;
- my %current = map { $_->area_id => 1 } @current;
- my @area_ids = $c->get_param_list('area_ids');
- foreach (@area_ids) {
- $c->model('DB::BodyArea')->find_or_create( { body => $c->stash->{body}, area_id => $_ } );
- delete $current{$_};
- }
- # Remove any others
- $c->stash->{body}->body_areas->search( { area_id => [ keys %current ] } )->delete;
+ unless ( keys $c->stash->{body_errors} ) {
+ $c->stash->{body}->update( $params );
+ my @current = $c->stash->{body}->body_areas->all;
+ my %current = map { $_->area_id => 1 } @current;
+ my @area_ids = $c->get_param_list('area_ids');
+ foreach (@area_ids) {
+ $c->model('DB::BodyArea')->find_or_create( { body => $c->stash->{body}, area_id => $_ } );
+ delete $current{$_};
+ }
+ # Remove any others
+ $c->stash->{body}->body_areas->search( { area_id => [ keys %current ] } )->delete;
- $c->stash->{updated} = _('Values updated');
+ $c->stash->{updated} = _('Values updated');
+ }
}
}
@@ -433,9 +444,20 @@ sub body_params : Private {
deleted => 0,
);
my %params = map { $_ => $c->get_param($_) || $defaults{$_} } keys %defaults;
+ $c->forward('check_body_params', [ \%params ]);
return \%params;
}
+sub check_body_params : Private {
+ my ( $self, $c, $params ) = @_;
+
+ $c->stash->{body_errors} ||= {};
+
+ unless ($params->{name}) {
+ $c->stash->{body_errors}->{name} = _('Please enter a name for this body');
+ }
+}
+
sub display_contacts : Private {
my ( $self, $c ) = @_;
@@ -1072,6 +1094,8 @@ sub user_add : Path('user_edit') : Args(0) {
phone => $c->get_param('phone') || undef,
from_body => $c->get_param('body') || undef,
flagged => $c->get_param('flagged') || 0,
+ # Only superusers can create superusers
+ is_superuser => ( $c->user->is_superuser && $c->get_param('is_superuser') ) || 0,
}, {
key => 'users_email_key'
} );
@@ -1114,6 +1138,8 @@ sub user_edit : Path('user_edit') : Args(1) {
$user->phone( $c->get_param('phone') ) if $c->get_param('phone');
$user->from_body( $c->get_param('body') || undef );
$user->flagged( $c->get_param('flagged') || 0 );
+ # Only superusers can grant superuser status
+ $user->is_superuser( ( $c->user->is_superuser && $c->get_param('is_superuser') ) || 0 );
unless ($user->email) {
$c->stash->{field_errors}->{email} = _('Please enter a valid email');
diff --git a/perllib/FixMyStreet/App/Controller/Auth.pm b/perllib/FixMyStreet/App/Controller/Auth.pm
index ca4a2fc80..40cd163cf 100644
--- a/perllib/FixMyStreet/App/Controller/Auth.pm
+++ b/perllib/FixMyStreet/App/Controller/Auth.pm
@@ -414,8 +414,8 @@ Used after signing in to take the person back to where they were.
sub redirect_on_signin : Private {
my ( $self, $c, $redirect ) = @_;
$redirect = 'my' unless $redirect;
+ $redirect = 'my' if $redirect =~ /^admin/ && !$c->user->is_superuser;
if ( $c->cobrand->moniker eq 'zurich' ) {
- $redirect = 'my' if $redirect eq 'admin';
$redirect = 'admin' if $c->user->from_body;
}
$c->res->redirect( $c->uri_for( "/$redirect" ) );
diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm
index 36313cf63..e5ec0c13a 100644
--- a/perllib/FixMyStreet/Cobrand/Default.pm
+++ b/perllib/FixMyStreet/Cobrand/Default.pm
@@ -369,8 +369,8 @@ sub uri {
{
no warnings 'once';
- (my $map_class = $FixMyStreet::Map::map_class) =~ s/^FixMyStreet::Map:://;
- return $uri unless $map_class =~ /OSM|FMS/;
+ my $map_class = $FixMyStreet::Map::map_class;
+ return $uri unless $map_class && $map_class =~ /FixMyStreet::Map::(OSM|FMS)/;
}
$uri->query_param( zoom => 3 )
@@ -622,6 +622,18 @@ Show the problem creation graph in the admin interface
sub admin_show_creation_graph { 1 }
+=head2 admin_allow_user
+
+Perform checks on whether this user can access admin. By default only superusers
+are allowed.
+
+=cut
+
+sub admin_allow_user {
+ my ( $self, $user ) = @_;
+ return 1 if $user->is_superuser;
+}
+
=head2 area_types
The MaPit types this site handles
diff --git a/perllib/FixMyStreet/Cobrand/SeeSomething.pm b/perllib/FixMyStreet/Cobrand/SeeSomething.pm
index 22750aafa..4d4dd000e 100644
--- a/perllib/FixMyStreet/Cobrand/SeeSomething.pm
+++ b/perllib/FixMyStreet/Cobrand/SeeSomething.pm
@@ -60,6 +60,11 @@ sub allow_anonymous_reports { 1; }
sub anonymous_account { return { name => 'Anonymous Submission', email => FixMyStreet->config('DO_NOT_REPLY_EMAIL') }; }
+sub admin_allow_user {
+ my ( $self, $user ) = @_;
+ return 1 if ( $user->from_body || $user->is_superuser );
+}
+
sub admin_pages {
my $self = shift;
diff --git a/perllib/FixMyStreet/Cobrand/UKCouncils.pm b/perllib/FixMyStreet/Cobrand/UKCouncils.pm
index 6e98f4ae0..43f10130a 100644
--- a/perllib/FixMyStreet/Cobrand/UKCouncils.pm
+++ b/perllib/FixMyStreet/Cobrand/UKCouncils.pm
@@ -150,4 +150,11 @@ sub base_url_for_report {
}
}
+sub admin_allow_user {
+ my ( $self, $user ) = @_;
+ return 1 if $user->is_superuser;
+ return undef unless defined $user->from_body;
+ return $user->from_body->id == $self->council_id;
+}
+
1;
diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm
index d13408321..1bf9cb9a5 100644
--- a/perllib/FixMyStreet/Cobrand/Zurich.pm
+++ b/perllib/FixMyStreet/Cobrand/Zurich.pm
@@ -371,6 +371,12 @@ sub update_admin_log {
$c->forward( 'log_edit', [ $problem->id, 'problem', $text, $time_spent ] );
}
+# Any user with from_body set can view admin
+sub admin_allow_user {
+ my ( $self, $user ) = @_;
+ return 1 if $user->from_body;
+}
+
# Specific administrative displays
sub admin_pages {
diff --git a/perllib/FixMyStreet/DB/Result/User.pm b/perllib/FixMyStreet/DB/Result/User.pm
index 7356969d1..65dd1dab1 100644
--- a/perllib/FixMyStreet/DB/Result/User.pm
+++ b/perllib/FixMyStreet/DB/Result/User.pm
@@ -26,16 +26,18 @@ __PACKAGE__->add_columns(
{ data_type => "text", is_nullable => 1 },
"password",
{ data_type => "text", default_value => "", is_nullable => 0 },
- "from_body",
- { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
"flagged",
{ data_type => "boolean", default_value => \"false", is_nullable => 0 },
+ "from_body",
+ { data_type => "integer", is_foreign_key => 1, is_nullable => 1 },
"title",
{ data_type => "text", is_nullable => 1 },
- "twitter_id",
- { data_type => "bigint", is_nullable => 1 },
"facebook_id",
{ data_type => "bigint", is_nullable => 1 },
+ "twitter_id",
+ { data_type => "bigint", is_nullable => 1 },
+ "is_superuser",
+ { data_type => "boolean", default_value => \"false", is_nullable => 0 },
);
__PACKAGE__->set_primary_key("id");
__PACKAGE__->add_unique_constraint("users_email_key", ["email"]);
@@ -90,8 +92,8 @@ __PACKAGE__->has_many(
);
-# Created by DBIx::Class::Schema::Loader v0.07035 @ 2015-12-09 16:02:08
-# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:hCq6ZDZfV/6iiu3HFhPPOg
+# Created by DBIx::Class::Schema::Loader v0.07035 @ 2016-07-11 12:49:31
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:SG86iN6Fr4/JIq7U2zYkug
__PACKAGE__->add_columns(
"password" => {
@@ -230,6 +232,8 @@ sub split_name {
sub has_permission_to {
my ($self, $permission_type, $body_id) = @_;
+ return 1 if $self->is_superuser;
+
return unless $self->belongs_to_body($body_id);
my $permission = $self->user_body_permissions->find({
diff --git a/perllib/FixMyStreet/Script/CreateSuperuser.pm b/perllib/FixMyStreet/Script/CreateSuperuser.pm
new file mode 100644
index 000000000..69d165abb
--- /dev/null
+++ b/perllib/FixMyStreet/Script/CreateSuperuser.pm
@@ -0,0 +1,25 @@
+package FixMyStreet::Script::CreateSuperuser;
+
+use strict;
+use warnings;
+
+use FixMyStreet;
+use FixMyStreet::DB;
+
+sub createsuperuser {
+ die "Specify a single email address and optionally password to create a superuser or grant superuser status to." if (@ARGV < 1 || @ARGV > 2);
+
+ my $user = FixMyStreet::DB->resultset('User')->find_or_new({ email => $ARGV[0] });
+ if ( !$user->in_storage ) {
+ die "Specify a password for this new user." if (@ARGV < 2);
+ $user->password($ARGV[1]);
+ $user->is_superuser(1);
+ $user->insert;
+ } else {
+ $user->update({ is_superuser => 1 });
+ }
+ print $user->email . " is now a superuser.\n";
+}
+
+
+1; \ No newline at end of file
diff --git a/perllib/FixMyStreet/TestMech.pm b/perllib/FixMyStreet/TestMech.pm
index 2ad820d1f..937780a31 100644
--- a/perllib/FixMyStreet/TestMech.pm
+++ b/perllib/FixMyStreet/TestMech.pm
@@ -63,11 +63,10 @@ Create a test user (or find it and return if it already exists).
sub create_user_ok {
my $self = shift;
- my ($email) = @_;
+ my ( $email, %extra ) = @_;
- my $user =
- FixMyStreet::DB->resultset('User')
- ->find_or_create( { email => $email } );
+ my $params = { email => $email, %extra };
+ my $user = FixMyStreet::DB->resultset('User')->find_or_create($params);
ok $user, "found/created user for $email";
return $user;