forked from apluslms/a-plus
-
Notifications
You must be signed in to change notification settings - Fork 0
/
permissions.py
158 lines (124 loc) · 5.34 KB
/
permissions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
from django.http import Http404
from django.utils.translation import ugettext_lazy as _
from authorization.permissions import (
ACCESS,
Permission,
MessageMixin,
ObjectVisibleBasePermission,
FilterBackend,
)
from exercise.cache.points import CachedPoints
from userprofile.models import UserProfile
from .models import (
CourseModule,
CourseInstance,
)
class CourseVisiblePermission(ObjectVisibleBasePermission):
message = _("Permission denied by course visibility")
model = CourseInstance
obj_var = 'instance'
def is_object_visible(self, request, view, course):
"""
Find out if CourseInstance is visible to user
We expect that AccessModePermission is checked first
- Always visible to course staff
- Always hidden if not open (visible_to_students)
- Always visible if public
- If not public:
- Require authentication
- If view_access == enrolled -> visible if student of the course
- If enrollment audience external, user should be external
- If enrollment audience internal, user should be internal
"""
# NOTE: course is actually course instance
# Course is always visible to staff members
if view.is_course_staff:
return True
# Course is not visible if it's hidden
if not course.visible_to_students:
self.error_msg(_("The resource is not currently visible."))
return False
user = request.user
show_for = course.view_content_to
VA = course.VIEW_ACCESS
# FIXME: we probably should test if access_mode is ANONYMOUS (public), but that
# would break api permissiosn (requires get_access_mode)
if show_for != VA.PUBLIC:
if not user.is_authenticated():
self.error_msg(_("This course is not open for public."))
return False
# Handle enroll views separately
if getattr(view, 'access_mode', None) == ACCESS.ENROLL:
return self.enrollment_audience_check(request, course, user)
if show_for == VA.ENROLLED:
if not course.is_student(user):
self.error_msg(_("Only enrolled students shall pass."))
return False
elif show_for == VA.ENROLLMENT_AUDIENCE:
return self.enrollment_audience_check(request, course, user)
return True
def enrollment_audience_check(self, request, course, user):
audience = course.enrollment_audience
external = user.userprofile.is_external
EA = course.ENROLLMENT_AUDIENCE
if audience == EA.INTERNAL_USERS and external:
self.error_msg(_("This course is only for internal students."))
return False
elif audience == EA.EXTERNAL_USERS and not external:
self.error_msg(_("This course is only for external students."))
return False
return True
class CourseModulePermission(MessageMixin, Permission):
message = _("The module is not currently visible")
def has_permission(self, request, view):
if not view.is_course_staff:
module = view.module
return self.has_object_permission(request, view, module)
return True
def has_object_permission(self, request, view, module):
if not isinstance(module, CourseModule):
return True
if module.status == CourseModule.STATUS.HIDDEN:
return False
if not module.is_after_open():
# FIXME: use format from django settings
self.error_msg(
_("The module will open for submissions at {date}."),
format={'date': module.opening_time},
delim=' ',
)
return False
if module.requirements.count() > 0:
points = CachedPoints(module.course_instance, request.user, view.content)
return module.are_requirements_passed(points)
return True
class OnlyCourseTeacherPermission(Permission):
message = _("Only course teacher is allowed")
def has_permission(self, request, view):
return self.has_object_permission(request, view, view.instance)
def has_object_permission(self, request, view, obj):
return view.is_teacher or request.user.is_superuser
class OnlyCourseStaffPermission(Permission):
message = _("Only course staff is allowed")
def has_permission(self, request, view):
return self.has_object_permission(request, view, view.instance)
def has_object_permission(self, request, view, obj):
return view.is_course_staff or request.user.is_superuser
class IsCourseAdminOrUserObjIsSelf(OnlyCourseStaffPermission, FilterBackend):
def has_object_permission(self, request, view, obj):
if not isinstance(obj, UserProfile):
return True
user = request.user
return user and (
(user.id is not None and user.id == obj.user_id) or
super().has_object_permission(request, view, obj)
)
def filter_queryset(self, request, queryset, view):
user = request.user
if (
issubclass(queryset.model, UserProfile) and
not view.is_course_staff and
not user.is_superuser
):
queryset = queryset.filter(user_id=user.id)
return queryset