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

Editor object permissions in a multisite #565

Merged
merged 246 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
246 commits
Select commit Hold shift + click to select a range
83176a9
add editor field to Role model in accounts
MyPyDavid Jan 16, 2023
288a967
move view_questionset_object from projects to questions
MyPyDavid Jan 16, 2023
3aee9b3
add rules for editor under questions
MyPyDavid Jan 16, 2023
c81ef3a
add HasObjectPermission to Viewsets
MyPyDavid Jan 16, 2023
856a401
add site editor test objects to fixtures
MyPyDavid Jan 16, 2023
5d07b7f
add tests for catalogs and site editor
MyPyDavid Jan 17, 2023
f42f616
update fixtures for site editors
MyPyDavid Jan 17, 2023
6fff6f6
rm is_multisite_editor from Role model
MyPyDavid Jan 17, 2023
db3d9c2
update questions rules
MyPyDavid Jan 17, 2023
beae814
add multisite_editor property to Role model
MyPyDavid Jan 18, 2023
716e2e1
Revert "add multisite_editor property to Role model"
MyPyDavid Jan 18, 2023
077deb0
add is_multisite_editor to Role model
MyPyDavid Jan 18, 2023
370ae92
update questions.rules
MyPyDavid Jan 18, 2023
9927505
revert test_viewset_catalog to original
MyPyDavid Jan 18, 2023
91cecac
add user group "api" to is_multisite_editor
MyPyDavid Jan 18, 2023
5a0dfdb
add "add_element_object" to rules
MyPyDavid Jan 18, 2023
aa72f90
add questions/tests for site editors
MyPyDavid Jan 18, 2023
a283ae8
fix testcases with filter for DEFAULT_URI_PREFIX
MyPyDavid Jan 18, 2023
3f2574b
update account viewsets test with editors
MyPyDavid Jan 18, 2023
4f7fea8
revert validator_tests to original
MyPyDavid Jan 20, 2023
06d66bd
rename multisite tests
MyPyDavid Jan 20, 2023
22753f0
rm test fixture question_multisite
MyPyDavid Jan 20, 2023
431886b
remove comment
MyPyDavid Jan 20, 2023
c429b2e
fix fitures with updated value for "order"
MyPyDavid Jan 20, 2023
50d4aa2
add sites and edited_by to models
MyPyDavid Jan 20, 2023
ea6a12b
add type hints to rules
MyPyDavid Jan 23, 2023
770cbd1
add ElementSitePermissionsMixin, clean questions catalog model fields
MyPyDavid Jan 24, 2023
3cef80b
update questions.rules
MyPyDavid Jan 24, 2023
3f553ef
add editors to catalog viewset and v1 serializer
MyPyDavid Jan 24, 2023
32582af
make test user site editor for example.com
MyPyDavid Jan 26, 2023
28056fc
add user site to editors group
MyPyDavid Jan 26, 2023
344957d
add editor to catalogs in questions fixture
MyPyDavid Jan 26, 2023
7fffc36
make test_multisite_viewset_catalog pass all test
MyPyDavid Jan 26, 2023
26905ce
add user site to _views tests
MyPyDavid Jan 26, 2023
2b69411
update rules
MyPyDavid Jan 30, 2023
bc1e177
add test_multisite_models questions
MyPyDavid Jan 30, 2023
b3c10ef
revert Role model, rm propery multisite_editor
MyPyDavid Feb 6, 2023
7160105
fix questions fixture, unicode character
MyPyDavid Feb 6, 2023
4712069
revert project rules to original
MyPyDavid Feb 6, 2023
e0e27fb
clean up questions rules, leave is_element_editor predicate
MyPyDavid Feb 6, 2023
7b5d16f
move view_questionset_object perm to projects/rules
MyPyDavid Feb 8, 2023
c3052ba
revert core/models to original
MyPyDavid Feb 8, 2023
27dbdd2
update catalog model and migration
MyPyDavid Feb 8, 2023
6b12f24
fix test questions model
MyPyDavid Feb 8, 2023
557117d
add multisite user and accounts test fixtures, foo and bar
MyPyDavid Feb 8, 2023
d539d02
fix test, users from other sites
MyPyDavid Feb 8, 2023
634a4e2
add model name check to project/rules
MyPyDavid Feb 9, 2023
dec945e
add model perms to questions/rules
MyPyDavid Feb 9, 2023
a065a7d
keep HasObjPerm only for CatalogViewSet
MyPyDavid Feb 9, 2023
607fb54
update test
MyPyDavid Feb 9, 2023
a79ebc7
add user check to is_multisite_editor
MyPyDavid Feb 10, 2023
b20f4b7
add editors tab to modal form catalog
MyPyDavid Feb 13, 2023
d69671b
add user.is_authenticated check to is_element_editor
MyPyDavid Feb 13, 2023
d09ab10
add editors fields to questions models
MyPyDavid Feb 13, 2023
0f4d81a
remove GROUPS
MyPyDavid Feb 13, 2023
447e1ab
add rules to management app
MyPyDavid Feb 13, 2023
553ac0a
rename pred to is_an_editor
MyPyDavid Feb 13, 2023
30dc0cd
update questions.rules for editor
MyPyDavid Feb 13, 2023
be4c287
add editors field to models
MyPyDavid Feb 13, 2023
1013657
update permission classes
MyPyDavid Feb 13, 2023
65ed72d
remove groups from fixture
MyPyDavid Feb 13, 2023
a59e5fb
remove group users from tests
MyPyDavid Feb 13, 2023
12c6443
rm groups from conditions tests
MyPyDavid Feb 14, 2023
7971b08
rm groups from domain tests
MyPyDavid Feb 14, 2023
4c42e65
rm group users from management tests
MyPyDavid Feb 14, 2023
7b96653
add editor to test users
MyPyDavid Feb 14, 2023
a5f94d8
add editor to test users
MyPyDavid Feb 14, 2023
2441889
add editor to test users
MyPyDavid Feb 14, 2023
46d02fe
add editor to test users
MyPyDavid Feb 14, 2023
dc6db7a
add perms for tasks and views to management rules
MyPyDavid Feb 14, 2023
8bb86cd
update options tests
MyPyDavid Feb 14, 2023
26df8b1
rm groups from editor and reviewer
MyPyDavid Feb 14, 2023
4f946da
revert groups reviewer and api
MyPyDavid Feb 14, 2023
ff29808
revert test users
MyPyDavid Feb 14, 2023
db69db3
revert test users
MyPyDavid Feb 14, 2023
d7f17df
add groups to reviewer test user
MyPyDavid Feb 14, 2023
4daa1d4
add editor roles to api test user
MyPyDavid Feb 14, 2023
e703fe2
add nested to status map
MyPyDavid Feb 14, 2023
25edc72
add newlines
MyPyDavid Feb 14, 2023
242d8ad
add 'Editors for this catalog' to catalogs template
MyPyDavid Feb 16, 2023
99f04b1
update is_site_manager query
MyPyDavid Feb 17, 2023
a7b40a7
add reviewer to account migrations
MyPyDavid Feb 17, 2023
77b80ea
add reviewer to Role
MyPyDavid Feb 17, 2023
f1b6140
update display of RoleAdmin fields
MyPyDavid Feb 17, 2023
cf449f2
add reviewer to management rules
MyPyDavid Feb 17, 2023
ec4a7f7
add is_element_reviewer to view_questionset_object
MyPyDavid Feb 17, 2023
e46bde8
add reviewer role to questions rules
MyPyDavid Feb 17, 2023
5b9cb48
rm reviewer from settings groups
MyPyDavid Feb 17, 2023
5c6248a
add reviewer role and more test users
MyPyDavid Feb 17, 2023
90ebeb8
rm groups and add test users
MyPyDavid Feb 17, 2023
fed09d4
fix test user foo-reviewer
MyPyDavid Feb 17, 2023
1d7b340
add member roles to api test user
MyPyDavid Feb 17, 2023
238b38b
update is_site_manager query
MyPyDavid Feb 17, 2023
9e42730
update accounts tests
MyPyDavid Feb 17, 2023
b64b170
fix project test_handlers
MyPyDavid Feb 20, 2023
a9409f9
fix test_multisite_viewset_catalog
MyPyDavid Feb 20, 2023
6a7a3ce
fix question viewset tests for reviewer
MyPyDavid Feb 21, 2023
d45ccca
add is_multisite_reviewer
MyPyDavid Feb 21, 2023
9a9d75c
add questions modal alert message
MyPyDavid Feb 21, 2023
ebc63c3
add editors to questions modal forms
MyPyDavid Feb 21, 2023
932d4d6
update formatting
MyPyDavid Feb 21, 2023
80cdc38
add editors field to domain/attribute
MyPyDavid Feb 21, 2023
fc97c98
add editors to domain attribute modal form
MyPyDavid Feb 21, 2023
0536930
add multisite tests for attributes
MyPyDavid Feb 21, 2023
1076786
add object perms, mv preds to management
MyPyDavid Feb 24, 2023
ed9eeff
fix domain obj perms and test
MyPyDavid Feb 24, 2023
c2038d9
mv preds to management
MyPyDavid Feb 24, 2023
fc1d24b
add editors to options app
MyPyDavid Feb 24, 2023
19ae76b
add "Editors for this Option Set"
MyPyDavid Feb 24, 2023
992e45e
add editors to conditions app
MyPyDavid Feb 24, 2023
d6c44cc
add editors to tasks app
MyPyDavid Feb 24, 2023
bc954b3
add editors to views app
MyPyDavid Feb 24, 2023
7b99d8f
add editors to element import
MyPyDavid Feb 27, 2023
c704351
fix domain multisite tests
MyPyDavid Feb 27, 2023
c7e9bc5
add editors to prefetch domain
MyPyDavid Feb 27, 2023
4b547f7
refactor rules preds
MyPyDavid Feb 27, 2023
7dd4327
add EditableElementQuerySetMixin to core managers
MyPyDavid Feb 27, 2023
01b58bf
add editable element manager to domain app
MyPyDavid Feb 27, 2023
58929aa
refactor questions tests
MyPyDavid Feb 27, 2023
8070cf4
add EditableElementQuerySet to catalog
MyPyDavid Feb 27, 2023
b2f9a19
refactor options tests
MyPyDavid Feb 27, 2023
cd9aadc
ignore .vscode
MyPyDavid Mar 8, 2023
e8d2a05
update query filter_related_to_user_role
MyPyDavid Mar 8, 2023
58fcd4d
add questions__editors to prefetch
MyPyDavid Mar 8, 2023
0b9f724
fix nested test
MyPyDavid Mar 8, 2023
bc04532
fix base_navigation for anonymous user
MyPyDavid Mar 9, 2023
279bbd4
add LoginRequiredMixin to ModelPermissionMixin to handle AnonymousUser
MyPyDavid Mar 9, 2023
89ed60f
rm view_questionset_object under project rules
MyPyDavid Mar 9, 2023
3b551d3
fix ProjectQuestionPermission for projects.view_questionset_object
MyPyDavid Mar 9, 2023
553f4dc
clean up rules predicates, check attr in try-except block
MyPyDavid Mar 10, 2023
fe325ce
add questions.view_questionset_object to questions rules
MyPyDavid Mar 10, 2023
3d1d1e9
remove filter_user from Catalog get_queryset
MyPyDavid Mar 10, 2023
ed972e0
fix QuestionSetNestedSerializer with many=True
MyPyDavid Mar 10, 2023
2bd56bb
rename uris https to http
MyPyDavid Mar 10, 2023
40796f4
revert queryset mixins and object managers
MyPyDavid Mar 16, 2023
5567ff6
fix tests for object permissions
MyPyDavid Mar 16, 2023
43e9cd6
add editor and reviewer to RoleSerializer
MyPyDavid Mar 17, 2023
c5d847c
fix and refactor RoleAdmin
MyPyDavid Mar 17, 2023
ab4b59a
add editor and reviewer to UserViewSetMixin
MyPyDavid Mar 17, 2023
40faf85
refactor questions rules
MyPyDavid Mar 17, 2023
170a887
refactor test fixtures for accounts and users
MyPyDavid Mar 17, 2023
78f33c6
add can_edit field and indicators to questions front-end
MyPyDavid Mar 20, 2023
73ed0e4
add can_edit to questions backend
MyPyDavid Mar 20, 2023
b8fa110
refactor and tidy up questions front-end
MyPyDavid Mar 20, 2023
cd3f962
add can_edit to conditions back-end
MyPyDavid Mar 20, 2023
f8cf0b9
add can_edit to conditions templates
MyPyDavid Mar 20, 2023
8b7af1d
add CanEditObjectSerializerMixin to core
MyPyDavid Mar 20, 2023
d470fb4
add can_edit to domain back-end
MyPyDavid Mar 20, 2023
e7d3225
add can_edit to domain templates
MyPyDavid Mar 20, 2023
919a609
rename domain tests
MyPyDavid Mar 20, 2023
e137552
add can_edit to options back-end
MyPyDavid Mar 20, 2023
574483e
add can_edit to options templates
MyPyDavid Mar 20, 2023
a88938b
add can_edit to tasks back-end
MyPyDavid Mar 20, 2023
4431326
add can_edit to tasks templates
MyPyDavid Mar 20, 2023
ccdd38a
add can_edit to views back-end
MyPyDavid Mar 20, 2023
91db7f8
add can_edit to views templates
MyPyDavid Mar 20, 2023
11e287b
fix pass for example-user
MyPyDavid Mar 21, 2023
d934528
add example-user to tests
MyPyDavid Mar 21, 2023
c96f94a
fix context kwargs for questionset serializer
MyPyDavid Mar 21, 2023
1d1b4b5
add tests for questions models
MyPyDavid Mar 21, 2023
5b66aff
remove comments from test
MyPyDavid Mar 21, 2023
c68a83e
fix typo bug in tasks modal form
MyPyDavid Mar 21, 2023
0d953ba
fix help_text on questions models
MyPyDavid Mar 21, 2023
eb91d09
rename can_edit to read_only, in serializers and templates
MyPyDavid Mar 22, 2023
f2ce916
rename can_edit to read_only and refactor CanEditObjectSerializerMixin
MyPyDavid Mar 22, 2023
4b594c4
rename class CanEditObjectSerializerMixin to ReadOnlyObjectPermission…
MyPyDavid Mar 27, 2023
36e93a1
rename serializer mixin to ReadOnlyObjectPermissionsSerializerMixin
MyPyDavid Mar 27, 2023
a7c20e9
fix testing fixtures users.json
MyPyDavid Mar 28, 2023
60211fc
add tests for RoleAdmin in accounts
MyPyDavid Mar 28, 2023
3c3168a
fix formatting
MyPyDavid Mar 28, 2023
7b9958b
refactor ReadOnlyMixin methods
MyPyDavid Mar 28, 2023
60dfcd1
fix formatting
MyPyDavid Mar 29, 2023
a94da72
add member role to test_admin
MyPyDavid Mar 29, 2023
504b41b
add tests for rules in accounts
MyPyDavid Mar 29, 2023
56cce83
Merge branch 'dev-1.10.0' into 'feature/490-editor-permissions-multis…
MyPyDavid Apr 14, 2023
dd22102
revert gitignore to original
MyPyDavid Apr 17, 2023
b48cff4
revert models copy functions, editors and sites
MyPyDavid Jun 2, 2023
c69adff
revert models copy functions, editors and sites
MyPyDavid Jun 2, 2023
4b56a00
remove copy editors related tests
MyPyDavid Jun 2, 2023
7c7765d
change viewset permissions from AND to OR
MyPyDavid Jun 2, 2023
c963534
update drf version to 3.14.0 for permissions implementation
MyPyDavid Jun 6, 2023
56cf5c3
add HasObjectPerms to conditions viewset
MyPyDavid Jun 6, 2023
b666455
fix object perms in conditions viewset tests
MyPyDavid Jun 6, 2023
9eeb55b
rename management rule to is_editor, is_reviewer
MyPyDavid Jun 6, 2023
2a687ee
consolidate has_perm checks to single can_view_management check
MyPyDavid Jun 6, 2023
bf3c666
add HasObjectPermission to CopyModelMixin
MyPyDavid Jun 6, 2023
fabb12b
remove an_editor_or_reviewer_can_see_themselves from accounts rules
MyPyDavid Jun 6, 2023
73dd34c
add add_project_object rule and fix preds for swagger
MyPyDavid Jun 6, 2023
7c351c7
change permission to HasProjectQuestionPermission for get_continue
MyPyDavid Jun 6, 2023
3aee5b4
rename rules to is_editor, remove try-blocks, leave only view and add…
MyPyDavid Jun 6, 2023
42081d9
move rules from questions to management
MyPyDavid Jun 6, 2023
95560b1
add HasObjectPermission to questions viewsets
MyPyDavid Jun 6, 2023
fabce7a
change return value for list or create from True to super().has_perms
MyPyDavid Jun 6, 2023
abf2eac
Merge branch 'feature/490-editor-permissions-multisite' of github.com…
MyPyDavid Jun 6, 2023
19ec88e
fix duplicate line for groups.set
MyPyDavid Jun 6, 2023
d36d178
remove an_editor_or_reviewer_can_see_themselves from tests
MyPyDavid Jun 6, 2023
9512b14
revert project rules
MyPyDavid Jun 6, 2023
f096a28
revert requirement drf to 3.12.4
MyPyDavid Jun 6, 2023
b268e25
revert core permissions to original
MyPyDavid Jun 6, 2023
b9949bd
remove an_editor_or_reviewer_can_see_themselves from accounts viewset…
MyPyDavid Jun 6, 2023
ffcc848
Refactor rules and object permissions
jochenklar Jun 7, 2023
ab3d3ac
fix AttributeError for HasProjectPermission in swagger api/v1
MyPyDavid Jun 12, 2023
5ef6a58
fix test status codes for accounts/viewsets, change to 403
MyPyDavid Jun 12, 2023
f8d2f8a
add rule is_site_manager_for_current_site for projects in templates
MyPyDavid Jun 12, 2023
c08961e
fix tests in test_viewset_catalog_multisite
MyPyDavid Jun 12, 2023
38a0446
fix tests domain test_viewset_attribute_multisite
MyPyDavid Jun 12, 2023
c8da3ee
fix tests for options viewsets
MyPyDavid Jun 12, 2023
7857b3b
fix tests for tasks viewset
MyPyDavid Jun 12, 2023
301d28b
fix tests for views viewset
MyPyDavid Jun 12, 2023
ee484a0
fix tests domain viewset
MyPyDavid Jun 12, 2023
a11792e
delete accounts rules
MyPyDavid Jun 12, 2023
4a95bcb
rename projects rule to can_view_all_projects
MyPyDavid Jun 12, 2023
4203fec
Merge branch 'dev-2.0.0' of github.com:rdmorganiser/rdmo into feature…
MyPyDavid Jun 12, 2023
78c7fa4
delete rules from accounts apps.py
MyPyDavid Jun 12, 2023
bcc1207
fix test formatting test_view_project
MyPyDavid Jun 12, 2023
ee4e9f4
remove unused exception ObjectDoesNotExist
MyPyDavid Jun 12, 2023
a48548b
fix tests accounts viewsets
MyPyDavid Jun 13, 2023
f0a5ee8
fix tests questions viewsets
MyPyDavid Jun 13, 2023
96e62d8
Merge branch 'dev-2.0.0' into feature/490-editor-permissions-multisite
jochenklar Jun 23, 2023
a1bb01c
Fix base_navigation.html
jochenklar Jun 23, 2023
9695820
Fix migrations and add editors to Page
jochenklar Jun 23, 2023
8149bfa
rename HasProjectQuestionPermission into HasProjectPagePermission
MyPyDavid Jun 26, 2023
f24b95e
add rules for page
MyPyDavid Jun 26, 2023
fe630e9
update test_rule can_view_management
MyPyDavid Jun 26, 2023
7115437
add read_only to options serializers
MyPyDavid Jun 26, 2023
63f1f59
add read_only to questions serializers
MyPyDavid Jun 26, 2023
b7c5ed7
remove redundant permission_classes from actions of element viewsets
MyPyDavid Jun 26, 2023
61334a8
remove redundant permission_classes from CopyModelMixin
MyPyDavid Jun 26, 2023
3106b9f
add editors to prefetch_related in questions viewsets
MyPyDavid Jun 26, 2023
076cad1
add editors and foo- elements to testing fixtures
MyPyDavid Jun 26, 2023
ad69824
fix tests in test_viewset_catalog_multisite
MyPyDavid Jun 26, 2023
1790bab
Add editors to edit components in management interface
jochenklar Jun 26, 2023
3c4bf57
Add editors to serializers
jochenklar Jun 27, 2023
a16c3e6
Add superuser check to base_navigation.html
jochenklar Jun 27, 2023
41e6fe6
Add read_only mode to management interface
jochenklar Jun 27, 2023
189452f
Fix fetch errors
jochenklar Jun 27, 2023
7e92401
Update admin interface
jochenklar Jun 27, 2023
78d081d
add testing fixtures for site bar.com
MyPyDavid Jun 27, 2023
6ce4b2b
fix and refactor tests for multisite
MyPyDavid Jun 27, 2023
a4dd7f6
fix test_detail_export
MyPyDavid Jun 28, 2023
f9438b7
fix failing tests, rename key with uri_path
MyPyDavid Jun 28, 2023
e01c33b
fix tests for tasks and views
MyPyDavid Jun 28, 2023
90e9725
fix tests for viewset page
MyPyDavid Jun 28, 2023
e99e74f
refactor string formatting in ReadOnlyObjectPermissionsSerializerMixin
MyPyDavid Jun 28, 2023
9feb620
fix test_viewset_question, remove nested
MyPyDavid Jun 28, 2023
c21bea5
refactor tests for multisite viewsets of elements
MyPyDavid Jun 28, 2023
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
31 changes: 30 additions & 1 deletion rdmo/accounts/admin.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from django.contrib import admin
from django.contrib.sites.models import Site
from django.db.models import Count, Value

from .models import AdditionalField, AdditionalFieldValue, ConsentFieldValue, Role

Expand All @@ -20,7 +22,34 @@ def has_add_permission(self, request, obj=None):

class RoleAdmin(admin.ModelAdmin):
search_fields = ('user__username', 'user__email')
list_filter = ('member', 'manager')
list_filter = ('member', 'manager', 'editor', 'reviewer')

list_display = ('user', 'members', 'managers', 'editors', 'reviewers')

def get_queryset(self, request):
return Role.objects.prefetch_related(
'member', 'manager', 'editor', 'reviewer').annotate(
Count('member'), Count('manager'), Count('editor'), Count('reviewer'),
sites_count=Value(Site.objects.count())
)

@staticmethod
def render_all_sites_or_join(obj, field_name: str) -> str:
if getattr(obj, f'{field_name}__count', 0) == obj.sites_count:
return 'all Sites'
return ', '.join([site.domain for site in getattr(obj, field_name).all()])

def members(self, obj):
return self.render_all_sites_or_join(obj, 'member')

def managers(self, obj):
return self.render_all_sites_or_join(obj, 'manager')

def editors(self, obj):
return self.render_all_sites_or_join(obj, 'editor')

def reviewers(self, obj):
return self.render_all_sites_or_join(obj, 'reviewer')


admin.site.register(AdditionalField, AdditionalFieldAdmin)
Expand Down
3 changes: 0 additions & 3 deletions rdmo/accounts/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,3 @@
class AccountsConfig(AppConfig):
name = 'rdmo.accounts'
verbose_name = _('Accounts')

def ready(self):
from . import rules
24 changes: 24 additions & 0 deletions rdmo/accounts/migrations/0020_add_role_editor_and_reviewer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 3.2.16 on 2023-02-17 14:25

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('sites', '0002_alter_domain_unique'),
('accounts', '0019_delete_proxyuser'),
]

operations = [
migrations.AddField(
model_name='role',
name='editor',
field=models.ManyToManyField(blank=True, help_text='The sites for which this user is an editor.', related_name='editors', to='sites.Site', verbose_name='Editor'),
),
migrations.AddField(
model_name='role',
name='reviewer',
field=models.ManyToManyField(blank=True, help_text='The sites for which this user is a reviewer.', related_name='reviewers', to='sites.Site', verbose_name='Reviewer'),
),
]
10 changes: 10 additions & 0 deletions rdmo/accounts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ class Role(models.Model):
verbose_name=_('Manager'),
help_text=_('The sites for which this user is manager.')
)
editor = models.ManyToManyField(
Site, related_name='editors', blank=True,
verbose_name=_('Editor'),
help_text=_('The sites for which this user is an editor.')
)
reviewer = models.ManyToManyField(
Site, related_name='reviewers', blank=True,
verbose_name=_('Reviewer'),
help_text=_('The sites for which this user is a reviewer.')
)

class Meta:
ordering = ('user', )
Expand Down
16 changes: 0 additions & 16 deletions rdmo/accounts/rules.py

This file was deleted.

6 changes: 5 additions & 1 deletion rdmo/accounts/serializers/v1.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@ class RoleSerializer(serializers.ModelSerializer):

member = SiteSerializer(many=True)
manager = SiteSerializer(many=True)
editor = SiteSerializer(many=True)
reviewer = SiteSerializer(many=True)

class Meta:
model = Role
fields = (
'id',
'member',
'manager'
'manager',
'editor',
'reviewer'
)


Expand Down
13 changes: 13 additions & 0 deletions rdmo/accounts/tests/test_admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import pytest

from django.urls import reverse


roles = ('member', 'manager', 'editor', 'reviewer')


@pytest.mark.parametrize('role', roles)
def test_admin_accounts_role(admin_client, role):
url = reverse('admin:accounts_role_changelist') + f'?q={role}'
response = admin_client.get(url)
assert response.status_code == 200
14 changes: 14 additions & 0 deletions rdmo/accounts/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,24 @@
('editor', 'editor'),
('reviewer', 'reviewer'),
('user', 'user'),
('site', 'site'),
('api', 'api'),
('anonymous', None),
)

other_site_users = (
'foo-user',
'foo-manager',
'foo-editor',
'foo-reviewer',
'bar-user',
'bar-manager',
'bar-editor',
'bar-reviewer',
)

users += tuple(zip(other_site_users, other_site_users)) # add (other site users and passwords)

boolean_toggle = (True, False)


Expand Down
51 changes: 36 additions & 15 deletions rdmo/accounts/tests/test_viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,49 @@
from django.urls import reverse

users = (
('site', 'site'),
('api', 'api'),
('site', 'site'), # site manager for all sites
('editor', 'editor'), # editor for all sites
('reviewer', 'reviewer'), # reviewer for all sites
('api', 'api'), # has all roles for all sites, same as superuser
('admin', 'admin'), # superuser
('user', 'user'),
('anonymous', None),
('anonymous', None)
)

more_example_users = (
'example-user',
'example-manager',
'example-editor',
'example-reviewer'
)

members_from_other_sites = (
'other',
'foo-user',
'foo-manager',
'foo-editor',
'foo-reviewer',
'bar-user',
'bar-manager',
'bar-editor',
'bar-reviewer',
)

status_map = {
'list': {
'site': 200, 'api': 200, 'user': 200, 'anonymous': 401
'editor': 403, 'reviewer': 403, 'site': 403, 'api': 403, 'user': 403, 'anonymous': 401, 'admin' : 200
},
'detail': {
'site': 200, 'api': 200, 'user': 404, 'anonymous': 401
'editor': 404, 'reviewer': 404, 'site': 404, 'api': 404, 'user': 404, 'anonymous': 401, 'admin' : 200
},
'create': {
'site': 405, 'api': 405, 'user': 405, 'anonymous': 401
'editor': 403, 'reviewer': 403, 'site': 403, 'api': 403, 'user': 403, 'anonymous': 401, 'admin' : 405
},
'update': {
'site': 405, 'api': 405, 'user': 405, 'anonymous': 401
'editor': 405, 'reviewer': 405, 'site': 405, 'api': 405, 'user': 405, 'anonymous': 401, 'admin' : 405
},
'delete': {
'site': 405, 'api': 405, 'user': 405, 'anonymous': 401
'editor': 405, 'reviewer': 405, 'site': 405, 'api': 405, 'user': 405, 'anonymous': 401, 'admin' : 405
}
}

Expand All @@ -41,11 +63,11 @@ def test_list(db, client, username, password):
response = client.get(url)
assert response.status_code == status_map['list'][username], response.json()
if response.status_code == 200:
if username == 'api':
assert len(response.json()) == 11
if username == 'api' or username == 'admin':
assert len(response.json()) == get_user_model().objects.count()
elif username == 'site':
# the site admin must not see the user 'other'
assert len(response.json()) == 10
# the site manager for example.com must see only the members of example.com
assert len(response.json()) == get_user_model().objects.count() - len(members_from_other_sites)
else:
assert len(response.json()) == 0

Expand All @@ -54,12 +76,11 @@ def test_list(db, client, username, password):
def test_detail(db, client, username, password):
client.login(username=username, password=password)
instances = get_user_model().objects.all()

for instance in instances:
url = reverse(urlnames['detail'], args=[instance.pk])
response = client.get(url)
if username == 'site' and instance.username == 'other':
# the site admin must not see the user 'other'
if username == 'site' and not instance.role.member.filter(domain__contains='example.com').exists():
# the site manager for example.com must see only the members of example.com
assert response.status_code == 404, response.json()
else:
assert response.status_code == status_map['detail'][username], response.json()
Expand Down
11 changes: 7 additions & 4 deletions rdmo/accounts/viewsets.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.viewsets import ReadOnlyModelViewSet

from rdmo.core.permissions import HasModelPermission, HasObjectPermission
from rdmo.management.rules import is_editor, is_reviewer

from .models import Role
from .serializers.v1 import UserSerializer
from .utils import is_site_manager

Expand All @@ -16,8 +17,7 @@ def get_users_for_user(self, user):
if user.has_perm('auth.view_user'):
return get_user_model().objects.all()
elif is_site_manager(user):
current_site = Site.objects.get_current()
return get_user_model().objects.filter(role__member=current_site)
return get_user_model().objects.filter(role__member__id__in=user.role.manager.all()).distinct()
return get_user_model().objects.none()


Expand All @@ -36,4 +36,7 @@ class UserViewSet(UserViewSetMixin, ReadOnlyModelViewSet):

def get_queryset(self):
return self.get_users_for_user(self.request.user) \
.prefetch_related('groups', 'role__member', 'role__manager', 'memberships')
.prefetch_related('groups',
'role__member', 'role__manager',
'role__editor', 'role__reviewer',
'memberships')
1 change: 1 addition & 0 deletions rdmo/conditions/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class ConditionAdmin(admin.ModelAdmin):
list_display = ('uri', 'source', 'relation', 'target_text', 'target_option')
readonly_fields = ('uri', )
list_filter = ('relation', )
filter_horizontal = ('editors', )


admin.site.register(Condition, ConditionAdmin)
3 changes: 3 additions & 0 deletions rdmo/conditions/imports.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import logging

from django.contrib.sites.models import Site

from rdmo.core.imports import (set_common_fields, set_foreign_field,
validate_instance)

Expand Down Expand Up @@ -34,5 +36,6 @@ def import_condition(element, save=False):
logger.info('Condition created with uri %s.', element.get('uri'))

condition.save()
condition.editors.add(Site.objects.get_current())

return condition
19 changes: 19 additions & 0 deletions rdmo/conditions/migrations/0023_condition_editors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 3.2.16 on 2023-02-24 14:14

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('sites', '0002_alter_domain_unique'),
('conditions', '0022_condition_locked'),
]

operations = [
migrations.AddField(
model_name='condition',
name='editors',
field=models.ManyToManyField(blank=True, help_text='The sites that can edit this condition (in a multi site setup).', related_name='condition_editors', to='sites.Site', verbose_name='Editors'),
),
]
8 changes: 7 additions & 1 deletion rdmo/conditions/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.conf import settings
from django.contrib.sites.models import Site
from django.db import models
from django.utils.translation import gettext_lazy as _

Expand Down Expand Up @@ -54,6 +55,11 @@ class Condition(models.Model):
verbose_name=_('Locked'),
help_text=_('Designates whether this condition can be changed.')
)
editors = models.ManyToManyField(
Site, related_name='%(class)s_editors', blank=True,
verbose_name=_('Editors'),
help_text=_('The sites that can edit this condition (in a multi site setup).')
)
source = models.ForeignKey(
Attribute, db_constraint=False, blank=True, null=True, on_delete=models.SET_NULL, related_name='conditions',
verbose_name=_('Source'),
Expand Down Expand Up @@ -89,7 +95,7 @@ def save(self, *args, **kwargs):

def copy(self, uri_prefix, key):
condition = copy_model(self, uri_prefix=uri_prefix, key=key, source=self.source, target_option=self.target_option)

return condition

@property
Expand Down
10 changes: 8 additions & 2 deletions rdmo/conditions/serializers/v1.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from rest_framework import serializers

from rdmo.core.serializers import (ElementExportSerializerMixin,
ElementModelSerializerMixin)
ElementModelSerializerMixin,
ReadOnlyObjectPermissionsSerializerMixin)
from rdmo.domain.models import Attribute
from rdmo.options.models import OptionSet
from rdmo.questions.models import Page, Question, QuestionSet
Expand All @@ -11,7 +12,8 @@
from ..validators import ConditionLockedValidator, ConditionUniqueURIValidator


class ConditionSerializer(ElementModelSerializerMixin, serializers.ModelSerializer):
class ConditionSerializer(ElementModelSerializerMixin, ReadOnlyObjectPermissionsSerializerMixin,
serializers.ModelSerializer):

model = serializers.SerializerMethodField()
key = serializers.SlugField(required=True)
Expand All @@ -23,6 +25,8 @@ class ConditionSerializer(ElementModelSerializerMixin, serializers.ModelSerializ
questions = serializers.PrimaryKeyRelatedField(queryset=Question.objects.all(), required=False, many=True)
tasks = serializers.PrimaryKeyRelatedField(queryset=Task.objects.all(), required=False, many=True)

read_only = serializers.SerializerMethodField()

class Meta:
model = Condition
fields = (
Expand All @@ -33,6 +37,8 @@ class Meta:
'key',
'comment',
'locked',
'read_only',
'editors',
'source',
'relation',
'target_text',
Expand Down
Loading