Skip to content

Commit 2a9c342

Browse files
pstaabpdrdrew42drgrice1
authored
Redo roles and permissions (#95)
Peter Staab: This pull request does a number of things with roles and permissions: - all roles and permissions are defined in `permissions.dist.yml` - admins can copy this file over and change permissions/add roles, etc. - there is a role called `course_admin`, which can have additional permissions that instructors don't have. - there are both server-side permissions and ui permissions. - there is a script `bin/update_perms.pl` which loads both the roles and permissions in the `permissions.yml` file into the database. - on the server side, the permissions are checked by querying the database. - on the UI side, after login, the permissions are loaded in the store to be able to be queried whenever. - every route is now checked that the user has permission to visit that route. Glenn Rice: Make a Boolean InflateColumn package that works for the boolean data type. K. Andrew Parker: Track authentication expiry in session store. Co-authored-by: K. Andrew Parker <[email protected]> Co-authored-by: Glenn Rice <[email protected]>
1 parent c3fe843 commit 2a9c342

File tree

85 files changed

+3746
-1692
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+3746
-1692
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ are assuming terminal/shell commands.
4646

4747
1. Clone the webwork3 code with `git clone https://github.com/openwebwork/webwork3.git`
4848
2. Change directory to the webwork3 directory: `cd webwork3`
49-
3. Copy conf/webwork3.yml.dist to conf/webwork3.yml and modify it appropriately if needed.
49+
3. Copy `conf/webwork3.dist.yml` to `conf/webwork3.yml` and modify it appropriately if needed.
5050

5151
### Download Quasar
5252

@@ -163,7 +163,7 @@ sudo systemctl start webwork3
163163
10. Set up permissions for the renderer with the following commands executed from the renderer directory.
164164

165165
```sh
166-
sudo chown -R youruser:www-data logs
166+
sudo chown -R youruser:www-data logs
167167
sudo chmod g+rw logs/standalone_results.log
168168
sudo chmod -R g+rw lib/WeBWorK/tmp/* lib/WeBWorK/htdocs/tmp/*
169169
```

bin/import_ww2_db.pl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,12 @@ BEGIN
100100

101101
my $dbh = DBI->connect($db_dsn, $db_user, $db_pass, { RaiseError => 1, AutoCommit => 0 });
102102

103-
my $schema = DB::Schema->connect($config->{database_dsn}, $config->{database_user}, $config->{database_password});
103+
my $schema = DB::Schema->connect(
104+
$config->{database_dsn},
105+
$config->{database_user},
106+
$config->{database_password},
107+
{ quote_names => 1 }
108+
);
104109

105110
my $course_rs = $schema->resultset('Course');
106111
my $user_rs = $schema->resultset('User');

bin/update_perms.pl

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#!/usr/bin/env perl
2+
3+
=head1 NAME
4+
5+
update_perms.pl - Load the roles and permissions in conf/permissions.yml into the database
6+
7+
=head1 SYNOPSIS
8+
9+
update_perms.p [options]
10+
11+
Options:
12+
-h|--help Show full help
13+
14+
=head1 DESCRIPTION
15+
16+
All of the roles and permissions for webwork3 are defined in conf/permissions.yml (or it's
17+
default file permissions.dist.yml). This script checks for consistancy of that file and
18+
then loads the roles and permissions into the database.
19+
20+
=cut
21+
22+
use warnings;
23+
use strict;
24+
25+
require Exporter;
26+
use base qw(Exporter);
27+
our @EXPORT_OK = qw/updatePermissions/;
28+
29+
BEGIN {
30+
use File::Basename qw/dirname/;
31+
use Cwd qw/abs_path/;
32+
$main::webwork3_dir = dirname(dirname(abs_path(__FILE__)));
33+
}
34+
35+
use lib "$main::webwork3_dir/lib";
36+
37+
use Getopt::Long qw(:config bundling);
38+
use Pod::Usage;
39+
use DB::Schema;
40+
41+
use DB::Utils qw/updatePermissions/;
42+
43+
my $showHelp;
44+
GetOptions('h|help' => \$showHelp);
45+
pod2usage({ -verbose => 2, -exitval => 0 }) if $showHelp;
46+
47+
# Load the configuration to obtain the database settings.
48+
my $ww3_conf = "$main::webwork3_dir/conf/webwork3.yml";
49+
$ww3_conf = "$main::webwork3_dir/conf/webwork3.dist.yml" unless -r $ww3_conf;
50+
51+
my $role_perm_file = "$main::webwork3_dir/conf/permissions.yml";
52+
# if it doesn't exist, load the default one:
53+
$role_perm_file = "$main::webwork3_dir/conf/permissions.dist.yml" unless -r $role_perm_file;
54+
55+
updatePermissions($ww3_conf, $role_perm_file);
56+
57+
1;

conf/permissions.dist.yml

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
---
2+
# This file defines the default roles and permissions for webwork 3. If you wish to add or
3+
# change any roles, copy this file to conf/permissions.yml and make changes.
4+
# Whether or not you have made changes, run /bin/update_role_db.pl to load all roles
5+
# in the database.
6+
7+
roles:
8+
- course_admin
9+
- instructor
10+
- ta
11+
- student
12+
13+
# This defines the permisions for each role for the backend/database.
14+
#
15+
# This hash has each of the Controllers (Logger, Permission, Course, ...) as a field
16+
# and each action as a subfield. For each Controller/action, there are three possibilities
17+
#
18+
# - authenticated: true this route can be accessed by any user who has been authenticated.
19+
# - admin_required: true this route can only be accessed by a user with admin flag (no course role)
20+
# - allow_self_access: true this route can be accessed by a user matching the user_id
21+
# - allowed_roles: Array this route can be accessed by a user with a role in the given array.
22+
# and '*' can be used for all roles.
23+
24+
db_permissions:
25+
Logger:
26+
clientLog:
27+
authenticated: true
28+
Permission:
29+
getRoles:
30+
authenticated: true
31+
getUIRoutePermissions:
32+
authenticated: true
33+
checkPermission:
34+
authenticated: true
35+
36+
Course:
37+
getCourses:
38+
allowed_roles: ['*']
39+
getCourse:
40+
allowed_roles: ['*']
41+
updateCourse:
42+
admin_required: true
43+
addCourse:
44+
admin_required: true
45+
deleteCourse:
46+
admin_required: true
47+
User:
48+
getGlobalUsers:
49+
admin_required: true
50+
getGlobalUser:
51+
admin_required: true
52+
checkGlobalUser:
53+
allowed_roles: ['course_admin', 'instructor']
54+
updateGlobalUser:
55+
admin_required: true
56+
addGlobalUser:
57+
admin_required: true
58+
deleteGlobalUser:
59+
admin_required: true
60+
# The following actions are needed for instructors to handle global users
61+
getGlobalUsersFromCourse:
62+
allowed_roles: ['course_admin', 'instructor']
63+
getGlobalUserFromCourse:
64+
allowed_roles: ['course_admin', 'instructor']
65+
getUserCoursesFromCourse:
66+
allowed_roles: ['course_admin', 'instructor']
67+
updateGlobalUserFromCourse:
68+
allowed_roles: ['course_admin', 'instructor']
69+
addGlobalUserFromCourse:
70+
allowed_roles: ['course_admin', 'instructor']
71+
deleteGlobalUserFromCourse:
72+
allowed_roles: ['course_admin', 'instructor']
73+
getCourseUsers:
74+
allowed_roles: ['course_admin', 'instructor']
75+
getUserCourses:
76+
allow_self_access: true
77+
allowed_roles: ['course_admin', 'instructor']
78+
getGlobalCourseUsers:
79+
allowed_roles: ['course_admin', 'instructor']
80+
getCourseUser:
81+
allowed_roles: ['course_admin', 'instructor']
82+
addCourseUser:
83+
allowed_roles: ['course_admin', 'instructor']
84+
updateCourseUser:
85+
allowed_roles: ['course_admin', 'instructor']
86+
deleteCourseUser:
87+
allowed_roles: ['course_admin', 'instructor']
88+
ProblemSet:
89+
getProblemSets:
90+
allowed_roles: ['course_admin', 'instructor', 'student']
91+
getProblemSet:
92+
allowed_roles: ['course_admin', 'instructor']
93+
addProblemSet:
94+
allowed_roles: ['course_admin', 'instructor']
95+
updateProblemSet:
96+
allowed_roles: ['course_admin', 'instructor']
97+
deleteProblemSet:
98+
allowed_roles: ['course_admin', 'instructor']
99+
getAllUserSets:
100+
allowed_roles: ['course_admin', 'instructor']
101+
getUserSets:
102+
allowed_roles: ['course_admin', 'instructor']
103+
addUserSet:
104+
allowed_roles: ['course_admin', 'instructor']
105+
updateUserSet:
106+
allowed_roles: ['course_admin', 'instructor']
107+
deleteUserSet:
108+
allowed_roles: ['course_admin', 'instructor']
109+
Problem:
110+
getAllProblems:
111+
allowed_roles: ['course_admin', 'instructor', 'student']
112+
getProblem:
113+
allowed_roles: ['course_admin', 'instructor', 'student']
114+
addProblem:
115+
allowed_roles: ['course_admin', 'instructor']
116+
updateProblem:
117+
allowed_roles: ['course_admin', 'instructor']
118+
deleteProblem:
119+
allowed_roles: ['course_admin', 'instructor']
120+
121+
# UserProblem Routes
122+
123+
getUserProblemsForSet:
124+
allowed_roles: ['course_admin', 'instructor']
125+
getUserProblemsForUser:
126+
allowed_roles: ['course_admin', 'instructor']
127+
allow_self_access: true
128+
getUserProblem:
129+
allowed_roles: ['course_admin', 'instructor']
130+
allow_self_access: true
131+
addUserProblem:
132+
allowed_roles: ['course_admin', 'instructor']
133+
updateUserProblem:
134+
allowed_roles: ['course_admin', 'instructor']
135+
allow_self_access: true
136+
deleteUserProblem:
137+
allowed_roles: ['course_admin', 'instructor']
138+
139+
# ProblemPool routes
140+
getProblemPools:
141+
allowed_roles: ['course_admin', 'instructor']
142+
getProblemPool:
143+
allowed_roles: ['course_admin', 'instructor']
144+
addProblemPool:
145+
allowed_roles: ['course_admin', 'instructor']
146+
updateProblemPool:
147+
allowed_roles: ['course_admin', 'instructor']
148+
deleteProblemPool:
149+
allowed_roles: ['course_admin', 'instructor']
150+
151+
# PoolProblem routes
152+
getPoolProblems:
153+
allowed_roles: ['course_admin', 'instructor']
154+
getPoolProblem:
155+
allowed_roles: ['course_admin', 'instructor']
156+
addProblemToPool:
157+
allowed_roles: ['course_admin', 'instructor']
158+
updatePoolProblem:
159+
allowed_roles: ['course_admin', 'instructor']
160+
removePoolProblem:
161+
allowed_roles: ['course_admin', 'instructor']
162+
Settings:
163+
getDefaultCourseSettings:
164+
allowed_roles: ['*']
165+
getCourseSettings:
166+
allowed_roles: ['*']
167+
updateCourseSettings:
168+
allowed_roles: ['course_admin', 'instructor']
169+
170+
# This defines the permisions for each role for the frontend/UI layer.
171+
172+
# This object is a list of routes, followed by an array of roles allowed.
173+
174+
ui_permissions:
175+
/login:
176+
allowed_roles: ['*']
177+
/users/*/courses:
178+
allowed_roles: ['instructor', 'course_admin']
179+
allow_self_access: true
180+
/courses/*/instructor:
181+
allowed_roles: ['instructor', 'course_admin']
182+
/courses/*/student:
183+
allowed_roles: ['student', 'instructor', 'course_admin']
184+
/admin:
185+
admin_required: true

conf/permissions.yaml

Lines changed: 0 additions & 35 deletions
This file was deleted.

conf/webwork3-test.dist.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,18 @@ webwork3_home: .
1313
# For the sqlite database
1414
database_dsn: dbi:SQLite:./t/db/sample_db.sqlite
1515
# For mysql or mariadb
16-
#database_dsn: dbi:mysql:dbname=webwork3_test
16+
# database_dsn: dbi:mysql:dbname=webwork3_test
1717
# For postgres
1818
#database_dsn: dbi:Pg:dbname=webwork3_test;host=localhost
1919

2020
# Database credentials for mysql, mariadb, or postgres.
2121
# These are ignored if the 'sqlite' database is used.
2222
database_user: webworkWrite
2323
database_password: password
24+
25+
# Cookie control settings
26+
# cookie_samesite: None
27+
# disable this for testing.
28+
cookie_secure: 0
29+
cookie_lifetime: 3600
30+

lib/DB/Exception.pm

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ use warnings;
33
use strict;
44

55
use Exception::Class (
6+
'DB::Exception::RouteWithoutPermission' => {
7+
fields => [ 'route', 'message' ]
8+
},
69
'DB::Exception::UndefinedCourseField' => {
710
fields => ['message'],
811
description => 'There is an undefined course setting field'
@@ -100,6 +103,10 @@ use Exception::Class (
100103
'DB::Exception::UserProblemNotFound' => {
101104
fields => [ 'course_name', 'problem_number', 'problem_version', 'username', 'set_name' ],
102105
description => 'The requested user problem is not found.'
106+
},
107+
'DB::Exception::UserRoleUndefined' => {
108+
fields => ['role_name'],
109+
description => 'The role name is not defined.'
103110
}
104111
);
105112

@@ -108,7 +115,7 @@ DB::Exception::UndefinedCourseField->Trace(1);
108115
DB::Exception::InvalidCourseField->Trace(1);
109116
DB::Exception::UserSetNotInCourse->Trace(1);
110117
DB::Exception::SetNotInCourse->Trace(1);
111-
# DB::Exception::UserNotInCourse->Trace(1);
118+
DB::Exception::UserNotInCourse->Trace(1);
112119
DB::Exception::UserNotFound->Trace(1);
113120
DB::Exception::CourseAlreadyExists->Trace(1);
114121
DB::Exception::InvalidParameter->Trace(1);
@@ -120,4 +127,5 @@ DB::Exception::UserSetExists->Trace(1);
120127
DB::Exception::ImproperDateOrder->Trace(1);
121128
DB::Exception::SetAlreadyExists->Trace(1);
122129
DB::Exception::UserProblemNotFound->Trace(1);
130+
DB::Exception::UserRoleUndefined->Trace(1);
123131
1;

lib/DB/Schema/Result/Course.pm

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ our $REQUIRED_PARAMS = { _ALL_ => ['visible'] };
4040

4141
__PACKAGE__->table('course');
4242

43-
__PACKAGE__->load_components('InflateColumn::Serializer', 'Core');
43+
__PACKAGE__->load_components(qw/InflateColumn::Serializer InflateColumn::Boolean Core/);
4444

4545
__PACKAGE__->add_columns(
4646
course_id => {
@@ -68,14 +68,6 @@ __PACKAGE__->add_columns(
6868
}
6969
);
7070

71-
__PACKAGE__->inflate_column(
72-
'visible',
73-
{
74-
inflate => sub { return shift ? true : false; },
75-
deflate => sub { return shift; }
76-
}
77-
);
78-
7971
__PACKAGE__->set_primary_key('course_id');
8072

8173
# set up the many-to-many relationship to users

0 commit comments

Comments
 (0)