Repository: DDMAL/CantusDB

Issue:
Allow superusers access to all edit forms
When trying to compare my local changes to the edit forms to the production version, I got a '403 Permission Denied" error when trying to access the edit form, despite the fact that I am set as a superuser in the admin, and can actually edit everything anyway. 

It would be useful if superusers could also access all the edit forms by default. 

I think this could be done pretty easily -- add: 

```
if user.is_superuser:
    return True
```

To these functions:

https://github.com/DDMAL/CantusDB/blob/develop/django/cantusdb_project/main_app/permissions.py

Does that sound reasonable? 



Discussion:
What edit form was this? I think this makes sense, but as far as I know, "project managers" should be able to do this... you, for example, have the exact same permissions as Debra, Anna, and others currently, so I'm worried if there are things you are getting a 403 on?
I assigned myself that as a workaround. :-D 
Phew! This seems fine to me then

Resolving patch:
diff --git a/django/cantusdb_project/main_app/permissions.py b/django/cantusdb_project/main_app/permissions.py
--- a/django/cantusdb_project/main_app/permissions.py
+++ b/django/cantusdb_project/main_app/permissions.py
@@ -14,11 +14,14 @@ def user_can_edit_chants_in_source(user: User, source: Optional[Source]) -> bool
     Used in ChantDetail, ChantList, ChantCreate, ChantDelete, ChantEdit,
     ChantEditSyllabification, and SourceDetail views.
     """
-    if user.is_anonymous or (source is None):
+    if user.is_superuser:
+        return True
+
+    if user.is_anonymous or source is None:
         return False
 
     source_id = source.id
-    user_is_assigned_to_source: bool = user.sources_user_can_edit.filter(
+    user_is_assigned_to_source: bool = user.sources_user_can_edit.filter(  # noqa
         id=source_id
     ).exists()
 
@@ -27,7 +30,7 @@ def user_can_edit_chants_in_source(user: User, source: Optional[Source]) -> bool
     user_is_contributor: bool = user.groups.filter(name="contributor").exists()
 
     return (
-        (user_is_project_manager)
+        user_is_project_manager
         or (user_is_editor and user_is_assigned_to_source)
         or (user_is_editor and source.created_by == user)
         or (user_is_contributor and user_is_assigned_to_source)
@@ -40,17 +43,21 @@ def user_can_proofread_chant(user: User, chant: Chant) -> bool:
     Checks if the user can access the proofreading page of a given Source.
     Used in SourceEditChantsView.
     """
-    source_id = chant.source.id
+    if user.is_superuser:
+        return True
+
     if user.is_anonymous:
         return False
-    user_is_assigned_to_source: bool = user.sources_user_can_edit.filter(
+
+    source_id = chant.source.id
+    user_is_assigned_to_source: bool = user.sources_user_can_edit.filter(  # noqa
         id=source_id
     ).exists()
 
     user_is_project_manager: bool = user.groups.filter(name="project manager").exists()
     user_is_editor: bool = user.groups.filter(name="editor").exists()
 
-    return (user_is_project_manager) or (user_is_editor and user_is_assigned_to_source)
+    return user_is_project_manager or (user_is_editor and user_is_assigned_to_source)
 
 
 def user_can_view_source(user: User, source: Source) -> bool:
@@ -58,8 +65,7 @@ def user_can_view_source(user: User, source: Source) -> bool:
     Checks if the user can view an unpublished Source on the site.
     Used in ChantDetail, SequenceDetail, and SourceDetail views.
     """
-    user_is_authenticated: bool = user.is_authenticated
-    return (source.published) or (user_is_authenticated)
+    return source.published or user.is_authenticated
 
 
 def user_can_view_chant(user: User, chant: Chant) -> bool:
@@ -68,8 +74,7 @@ def user_can_view_chant(user: User, chant: Chant) -> bool:
     Used in ChantDetail, SequenceDetail, and SourceDetail views.
     """
     source = chant.source
-    user_is_authenticated: bool = user.is_authenticated
-    return (source is not None) and ((source.published) or (user_is_authenticated))
+    return (source is not None) and (source.published or user.is_authenticated)
 
 
 def user_can_view_sequence(user: User, sequence: Sequence) -> bool:
@@ -78,8 +83,7 @@ def user_can_view_sequence(user: User, sequence: Sequence) -> bool:
     Used in ChantDetail, SequenceDetail, and SourceDetail views.
     """
     source = sequence.source
-    user_is_authenticated: bool = user.is_authenticated
-    return (source is not None) and ((source.published) or (user_is_authenticated))
+    return (source is not None) and (source.published or user.is_authenticated)
 
 
 def user_can_edit_sequences(user: User, sequence: Sequence) -> bool:
@@ -87,12 +91,15 @@ def user_can_edit_sequences(user: User, sequence: Sequence) -> bool:
     Checks if the user has permission to edit a Sequence object.
     Used in SequenceDetail and SequenceEdit views.
     """
+    if user.is_superuser:
+        return True
+
     source = sequence.source
-    if user.is_anonymous or (source is None):
+    if user.is_anonymous or source is None:
         return False
 
     source_id = source.id
-    user_is_assigned_to_source: bool = user.sources_user_can_edit.filter(
+    user_is_assigned_to_source: bool = user.sources_user_can_edit.filter(  # noqa
         id=source_id
     ).exists()
 
@@ -101,7 +108,7 @@ def user_can_edit_sequences(user: User, sequence: Sequence) -> bool:
     user_is_contributor: bool = user.groups.filter(name="contributor").exists()
 
     return (
-        (user_is_project_manager)
+        user_is_project_manager
         or (user_is_editor and user_is_assigned_to_source)
         or (user_is_editor and source.created_by == user)
         or (user_is_contributor and user_is_assigned_to_source)
@@ -128,14 +135,14 @@ def user_can_edit_source(user: User, source: Source) -> bool:
     if user.is_anonymous:
         return False
     source_id = source.id
-    assigned_to_source = user.sources_user_can_edit.filter(id=source_id)
+    assigned_to_source = user.sources_user_can_edit.filter(id=source_id)  # noqa
 
     is_project_manager: bool = user.groups.filter(name="project manager").exists()
     is_editor: bool = user.groups.filter(name="editor").exists()
     is_contributor: bool = user.groups.filter(name="contributor").exists()
 
     return (
-        (is_project_manager)
+        is_project_manager
         or (is_editor and assigned_to_source)
         or (is_editor and source.created_by == user)
         or (is_contributor and source.created_by == user)
@@ -155,4 +162,4 @@ def user_can_manage_source_editors(user: User) -> bool:
     Checks if the user has permission to change the editors assigned to a Source.
     Used in SourceDetailView.
     """
-    return user.is_staff or user.groups.filter(name="project manager").exists()
+    return user.is_superuser or user.is_staff or user.groups.filter(name="project manager").exists()


Test patch: