-
Notifications
You must be signed in to change notification settings - Fork 2
/
security.py
182 lines (146 loc) · 5.51 KB
/
security.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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
from functools import wraps
from django.shortcuts import reverse, redirect, get_object_or_404, Http404
from django.core.exceptions import PermissionDenied
from django.contrib import messages
from plugins.typesetting import models, plugin_settings
from security.decorators import base_check, deny_access
from submission import models as submission_models
from core import models as core_models
def proofreader_for_article_required(func):
"""
Checks that the current user is the proofreader for the current task.
:param func: the function to callback from the decorator
:return: either the function call or raises an PermissionDenied
"""
def wrapper(request, *args, **kwargs):
if not base_check(request):
return redirect(
'{0}?next={1}'.format(
reverse('core_login'),
request.path,
)
)
elif request.user.is_editor(request) or request.user.is_staff or request.user.is_production(request):
return func(request, *args, **kwargs)
# User is Assigned as proofreader, regardless of role
elif models.GalleyProofing.objects.filter(
pk=kwargs['assignment_id'],
proofreader=request.user,
cancelled=False,
completed__isnull=True,
round__article__journal=request.journal,
).exists():
return func(request, *args, **kwargs)
else:
deny_access(request)
return wrapper
def can_preview_typesetting_article(func):
""" Checks if the user should be allowed to preview articles files
The user should either be an editor/production manager, a proofreader
for the article or a typesetter for the article
:param func: the function to callback from the decorator
:return: either the function call or raises an PermissionDenied
"""
def wrapper(request, *args, **kwargs):
assignment_id = kwargs.get('assignment_id')
if not base_check(request):
return redirect(
'{0}?next={1}'.format(
reverse('core_login'),
request.path,
)
)
elif request.user.is_editor(request) or request.user.is_staff or request.user.is_production(request):
return func(request, *args, **kwargs)
# User is Assigned as proofreader, regardless of role
elif assignment_id and models.GalleyProofing.objects.filter(
pk=assignment_id,
proofreader=request.user,
cancelled=False,
completed__isnull=True,
round__article__journal=request.journal,
).exists():
return func(request, *args, **kwargs)
# User is Assigned as typesetter, regardless of role
elif assignment_id and models.TypesettingAssignment.objects.filter(
pk=assignment_id,
typesetter=request.user,
cancelled__isnull=True,
round__article__journal=request.journal,
).exists():
return func(request, *args, **kwargs)
else:
deny_access(request)
return wrapper
def require_not_notified(object_model):
"""
Decorator that checks if an object's notified boolean attribute is True
and redirects
"""
def decorator(func):
@wraps(func)
def inner(request, *args, **kwargs):
assignment_id = kwargs.get('assignment_id')
if not assignment_id:
raise Http404
object_to_check = get_object_or_404(
object_model,
pk=assignment_id,
)
if object_to_check.notified:
raise PermissionDenied(
"Notification for this assignment has already been sent.",
)
return func(request, *args, **kwargs)
return inner
return decorator
def user_can_manage_file(func):
"""
A decorator for checking if the current user can manage a file.
"""
def wrapper(request, *args, **kwargs):
file_object_id = kwargs.get('file_id', None)
if not file_object_id:
raise Http404
file_object = get_object_or_404(
core_models.File,
pk=file_object_id,
)
if can_manage_file(request, file_object):
return func(request, *args, **kwargs)
return deny_access(request)
return wrapper
def can_manage_file(request, file_object):
"""
Determines if a user can view and download a file in the Typesetting Plugin.
"""
if request.user.is_anonymous:
return redirect(
'{0}?next={1}'.format(
reverse('core_login'),
request.path
)
)
if (
request.user.is_staff or
request.user.is_editor(request)
):
return True
if file_object.article_id:
# Check if there is a workflow log entry for the typesetting plugin.
if not core_models.WorkflowLog.objects.filter(
article__pk=file_object.article_id,
article__journal=request.journal,
element__element_name=plugin_settings.PLUGIN_NAME,
).exists():
return False
else:
# Files without article ids should not be downloadable here.
return False
if (
request.user.is_production(request) or
file_object.owner == request.user
):
return True
# deny access to all others
return False