Skip to content

Commit

Permalink
feat: Admin power for custom levels (#1371)
Browse files Browse the repository at this point in the history
* feat: Admin power for custom levels

* fix command

* Install common too

* Revert ci

* Update and fix test
  • Loading branch information
faucomte97 authored Oct 6, 2022
1 parent b6ea0f3 commit 22b34e6
Show file tree
Hide file tree
Showing 13 changed files with 432 additions and 273 deletions.
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pytest = "==7.*"
pytest-xdist = "*"
pytest-order = "*"
codeforlife-portal = "*"
importlib-metadata = "<5" # Using version 5 causes an issue when trying to run pytest. Not sure why, linked to: https://stackoverflow.com/questions/73929564/entrypoints-object-has-no-attribute-get-digital-ocean

[requires]
python_version = "3.7"
78 changes: 39 additions & 39 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 17 additions & 37 deletions game/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ def _get_userprofile_school(userprofile):
elif hasattr(userprofile, "student"):
return userprofile.student.class_field.teacher.school
else:
LOGGER.error(
f"Userprofile ID {userprofile.id} has no teacher or student attribute"
)
LOGGER.error(f"Userprofile ID {userprofile.id} has no teacher or student attribute")
return None


Expand All @@ -37,6 +35,7 @@ def can_save_workspace(user, workspace):
def can_delete_workspace(user, workspace):
return not user.is_anonymous and workspace.owner == user.userprofile


#####################
# Level permissions #
#####################
Expand All @@ -50,10 +49,7 @@ def can_play_or_delete_level(user, level):
# If the teacher is an admin, they can play any student's level in the school, otherwise only student levels
# from their own classes
if user.userprofile.teacher.is_admin and hasattr(level.owner, "student"):
return (
user.userprofile.teacher.school
== level.owner.student.class_field.teacher.school
)
return user.userprofile.teacher.school == level.owner.student.class_field.teacher.school
else:
return user.userprofile.teacher.teaches(level.owner)

Expand Down Expand Up @@ -87,9 +83,7 @@ def can_load_level(user, level):
owner_school = _get_userprofile_school(level.owner)
return user_school is not None and user_school == owner_school
else:
return hasattr(
user.userprofile, "teacher"
) and user.userprofile.teacher.teaches(level.owner)
return hasattr(user.userprofile, "teacher") and user.userprofile.teacher.teaches(level.owner)


def can_save_level(user, level):
Expand Down Expand Up @@ -125,32 +119,25 @@ def has_permission(self, request, view):
def has_object_permission(self, request, view, obj):
if request.user.is_anonymous:
return False
elif (
hasattr(request.user.userprofile, "student")
and request.user.userprofile.student.is_independent()
):
elif hasattr(request.user.userprofile, "student") and request.user.userprofile.student.is_independent():
return False
# if the user is a teacher and the level is shared with them
elif (
hasattr(request.user.userprofile, "teacher")
and obj.shared_with.filter(id=request.user.id).exists()
):
elif hasattr(request.user.userprofile, "teacher") and obj.shared_with.filter(id=request.user.id).exists():
return True
else:
return obj.owner == request.user.userprofile


class CanShareLevelWith(permissions.BasePermission):
"""
Used to verify that an the user who is requesting to share their level is
authorised to share the level with a specific recipient.
Used to verify that the user who is requesting to share their level is authorised to share the level with a specific
recipient.
The user is authorised if:
- neither they nor the recipient are anonymous,
- neither they nor the recipient are independent students,
- they are a student and the recipient is a student in the same class, or their
teacher
- they are a teacher and the recipient is a teacher in the same school, or their
student
- they are a student and the recipient is a student in the same class, or their teacher
- they are a teacher and the recipient is a teacher in the same school, or their student
- they are an admin teacher and the recipient is a student in the same school
"""

def has_permission(self, request, view):
Expand All @@ -174,25 +161,18 @@ def can_share_level_with(self, recipient, sharer):
and not (recipient_profile.student.is_independent())
):
# Are they in the same class?
return (
sharer_profile.student.class_field
== recipient_profile.student.class_field
)
elif hasattr(sharer_profile, "teacher") and sharer_profile.teacher.teaches(
recipient_profile
):
return sharer_profile.student.class_field == recipient_profile.student.class_field
elif hasattr(sharer_profile, "teacher") and sharer_profile.teacher.teaches(recipient_profile):
# Is the recipient taught by the sharer?
return True
elif hasattr(
recipient_profile, "teacher"
) and recipient_profile.teacher.teaches(sharer_profile):
elif hasattr(recipient_profile, "teacher") and recipient_profile.teacher.teaches(sharer_profile):
# Is the sharer taught by the recipient?
return True
elif hasattr(sharer_profile, "teacher") and hasattr(
recipient_profile, "teacher"
):
elif hasattr(sharer_profile, "teacher") and hasattr(recipient_profile, "teacher"):
# Are they in the same organisation?
return recipient_profile.teacher.school == sharer_profile.teacher.school
elif hasattr(sharer_profile, "teacher") and sharer_profile.teacher.is_admin:
return recipient_profile.student.class_field.teacher.school == sharer_profile.teacher.school
else:
return False

Expand Down
11 changes: 6 additions & 5 deletions game/static/game/css/level_share.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
}

#share_type_select {
width: 180px;
width: 250px;
margin-bottom: 0px;
margin-left: 35px;
margin-left: 15px;
}

#class_select {
width: 180px;
width: 250px;
margin-bottom: 0px;
margin-left: 70px;
margin-left: 50px;
}

#classes_radio {
Expand All @@ -34,6 +34,7 @@ tr[status='unshared'] .share_cell {
color: red;
}

tr[status='pending'] .share_cell {
tr[status="admin"] .share_name,
tr[status="admin"] .share_cell {
color: gray;
}
Loading

0 comments on commit 22b34e6

Please sign in to comment.