Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-proctoring
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-proctoring
Commits
a9aeb462
Unverified
Commit
a9aeb462
authored
Nov 10, 2017
by
Rabia Iftikhar
Committed by
GitHub
Nov 10, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #391 from edx/ri/EDUCATOR-1648
EDUCATOR-1648 give proctored exams access to course staff
parents
580c32ad
4ca93ade
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
24 additions
and
36 deletions
+24
-36
edx_proctoring/api.py
+2
-2
edx_proctoring/models.py
+3
-13
edx_proctoring/tests/test_api.py
+1
-1
edx_proctoring/tests/test_views.py
+13
-10
edx_proctoring/views.py
+5
-10
No files found.
edx_proctoring/api.py
View file @
a9aeb462
...
@@ -353,12 +353,12 @@ def add_allowance_for_user(exam_id, user_info, key, value):
...
@@ -353,12 +353,12 @@ def add_allowance_for_user(exam_id, user_info, key, value):
emit_event
(
exam
,
'allowance.{action}'
.
format
(
action
=
action
),
override_data
=
data
)
emit_event
(
exam
,
'allowance.{action}'
.
format
(
action
=
action
),
override_data
=
data
)
def
get_allowances_for_course
(
course_id
,
timed_exams_only
=
False
):
def
get_allowances_for_course
(
course_id
):
"""
"""
Get all the allowances for the course.
Get all the allowances for the course.
"""
"""
student_allowances
=
ProctoredExamStudentAllowance
.
get_allowances_for_course
(
student_allowances
=
ProctoredExamStudentAllowance
.
get_allowances_for_course
(
course_id
,
timed_exams_only
=
timed_exams_only
course_id
)
)
return
[
ProctoredExamStudentAllowanceSerializer
(
allowance
)
.
data
for
allowance
in
student_allowances
]
return
[
ProctoredExamStudentAllowanceSerializer
(
allowance
)
.
data
for
allowance
in
student_allowances
]
...
...
edx_proctoring/models.py
View file @
a9aeb462
...
@@ -394,27 +394,20 @@ class ProctoredExamStudentAttemptManager(models.Manager):
...
@@ -394,27 +394,20 @@ class ProctoredExamStudentAttemptManager(models.Manager):
exam_attempt_obj
=
None
exam_attempt_obj
=
None
return
exam_attempt_obj
return
exam_attempt_obj
def
get_all_exam_attempts
(
self
,
course_id
,
timed_exams_only
=
False
):
def
get_all_exam_attempts
(
self
,
course_id
):
"""
"""
Returns the Student Exam Attempts for the given course_id.
Returns the Student Exam Attempts for the given course_id.
"""
"""
filtered_query
=
Q
(
proctored_exam__course_id
=
course_id
)
filtered_query
=
Q
(
proctored_exam__course_id
=
course_id
)
if
timed_exams_only
:
filtered_query
=
filtered_query
&
Q
(
proctored_exam__is_proctored
=
False
)
return
self
.
filter
(
filtered_query
)
.
order_by
(
'-created'
)
return
self
.
filter
(
filtered_query
)
.
order_by
(
'-created'
)
def
get_filtered_exam_attempts
(
self
,
course_id
,
search_by
,
timed_exams_only
=
False
):
def
get_filtered_exam_attempts
(
self
,
course_id
,
search_by
):
"""
"""
Returns the Student Exam Attempts for the given course_id filtered by search_by.
Returns the Student Exam Attempts for the given course_id filtered by search_by.
"""
"""
filtered_query
=
Q
(
proctored_exam__course_id
=
course_id
)
&
(
filtered_query
=
Q
(
proctored_exam__course_id
=
course_id
)
&
(
Q
(
user__username__contains
=
search_by
)
|
Q
(
user__email__contains
=
search_by
)
Q
(
user__username__contains
=
search_by
)
|
Q
(
user__email__contains
=
search_by
)
)
)
if
timed_exams_only
:
filtered_query
=
filtered_query
&
Q
(
proctored_exam__is_proctored
=
False
)
return
self
.
filter
(
filtered_query
)
.
order_by
(
'-created'
)
# pylint: disable=no-member
return
self
.
filter
(
filtered_query
)
.
order_by
(
'-created'
)
# pylint: disable=no-member
def
get_proctored_exam_attempts
(
self
,
course_id
,
username
):
def
get_proctored_exam_attempts
(
self
,
course_id
,
username
):
...
@@ -720,14 +713,11 @@ class ProctoredExamStudentAllowance(TimeStampedModel):
...
@@ -720,14 +713,11 @@ class ProctoredExamStudentAllowance(TimeStampedModel):
verbose_name
=
'proctored allowance'
verbose_name
=
'proctored allowance'
@classmethod
@classmethod
def
get_allowances_for_course
(
cls
,
course_id
,
timed_exams_only
=
False
):
def
get_allowances_for_course
(
cls
,
course_id
):
"""
"""
Returns all the allowances for a course.
Returns all the allowances for a course.
"""
"""
filtered_query
=
Q
(
proctored_exam__course_id
=
course_id
)
filtered_query
=
Q
(
proctored_exam__course_id
=
course_id
)
if
timed_exams_only
:
filtered_query
=
filtered_query
&
Q
(
proctored_exam__is_proctored
=
False
)
return
cls
.
objects
.
filter
(
filtered_query
)
return
cls
.
objects
.
filter
(
filtered_query
)
@classmethod
@classmethod
...
...
edx_proctoring/tests/test_api.py
View file @
a9aeb462
...
@@ -409,7 +409,7 @@ class ProctoredExamApiTests(ProctoredExamTestCase):
...
@@ -409,7 +409,7 @@ class ProctoredExamApiTests(ProctoredExamTestCase):
Test to get all the allowances for a course.
Test to get all the allowances for a course.
"""
"""
allowance
=
self
.
_add_allowance_for_user
()
allowance
=
self
.
_add_allowance_for_user
()
course_allowances
=
get_allowances_for_course
(
self
.
course_id
,
False
)
course_allowances
=
get_allowances_for_course
(
self
.
course_id
)
self
.
assertEqual
(
len
(
course_allowances
),
1
)
self
.
assertEqual
(
len
(
course_allowances
),
1
)
self
.
assertEqual
(
course_allowances
[
0
][
'proctored_exam'
][
'course_id'
],
allowance
.
proctored_exam
.
course_id
)
self
.
assertEqual
(
course_allowances
[
0
][
'proctored_exam'
][
'course_id'
],
allowance
.
proctored_exam
.
course_id
)
...
...
edx_proctoring/tests/test_views.py
View file @
a9aeb462
...
@@ -1190,11 +1190,10 @@ class TestStudentProctoredExamAttempt(LoggedInTestCase):
...
@@ -1190,11 +1190,10 @@ class TestStudentProctoredExamAttempt(LoggedInTestCase):
response_data
=
json
.
loads
(
response
.
content
)
response_data
=
json
.
loads
(
response
.
content
)
self
.
assertEqual
(
len
(
response_data
[
'proctored_exam_attempts'
]),
1
)
self
.
assertEqual
(
len
(
response_data
[
'proctored_exam_attempts'
]),
1
)
def
test_exam_attempts_not_staff
(
self
):
def
test_exam_attempts_not_
global_
staff
(
self
):
"""
"""
Test to get the exam attempts in a course as a not
Test to get both timed and proctored exam attempts
staff user but still we get the timed exams attempts
in a course as a course staff
but not the proctored exam attempts
"""
"""
# Create an timed_exam.
# Create an timed_exam.
timed_exam
=
ProctoredExam
.
objects
.
create
(
timed_exam
=
ProctoredExam
.
objects
.
create
(
...
@@ -1241,11 +1240,15 @@ class TestStudentProctoredExamAttempt(LoggedInTestCase):
...
@@ -1241,11 +1240,15 @@ class TestStudentProctoredExamAttempt(LoggedInTestCase):
response
=
self
.
client
.
get
(
url
)
response
=
self
.
client
.
get
(
url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
status_code
,
200
)
response_data
=
json
.
loads
(
response
.
content
)
response_data
=
json
.
loads
(
response
.
content
)
#
we should only get the timed exam attempt in this case
#
assert that both timed and proctored exam attempts are in response data
# so the len should be
1
# so the len should be
2
self
.
assertEqual
(
len
(
response_data
[
'proctored_exam_attempts'
]),
1
)
self
.
assertEqual
(
len
(
response_data
[
'proctored_exam_attempts'
]),
2
)
self
.
assertEqual
(
self
.
assertEqual
(
response_data
[
'proctored_exam_attempts'
][
0
][
'proctored_exam'
][
'is_proctored'
],
response_data
[
'proctored_exam_attempts'
][
0
][
'proctored_exam'
][
'is_proctored'
],
proctored_exam
.
is_proctored
)
self
.
assertEqual
(
response_data
[
'proctored_exam_attempts'
][
1
][
'proctored_exam'
][
'is_proctored'
],
timed_exam
.
is_proctored
timed_exam
.
is_proctored
)
)
...
@@ -2317,9 +2320,9 @@ class TestExamAllowanceView(LoggedInTestCase):
...
@@ -2317,9 +2320,9 @@ class TestExamAllowanceView(LoggedInTestCase):
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
status_code
,
200
)
response_data
=
json
.
loads
(
response
.
content
)
response_data
=
json
.
loads
(
response
.
content
)
#
we should only get the timed exam allowance
#
assert that both timed and proctored exams allowance are in response data
#
We are not logged in as a global user
#
so the len should be 2
self
.
assertEqual
(
len
(
response_data
),
1
)
self
.
assertEqual
(
len
(
response_data
),
2
)
self
.
assertEqual
(
response_data
[
0
][
'proctored_exam'
][
'course_id'
],
timed_exam
.
course_id
)
self
.
assertEqual
(
response_data
[
0
][
'proctored_exam'
][
'course_id'
],
timed_exam
.
course_id
)
self
.
assertEqual
(
response_data
[
0
][
'proctored_exam'
][
'content_id'
],
timed_exam
.
content_id
)
self
.
assertEqual
(
response_data
[
0
][
'proctored_exam'
][
'content_id'
],
timed_exam
.
content_id
)
self
.
assertEqual
(
response_data
[
0
][
'key'
],
allowance_data
[
'key'
])
self
.
assertEqual
(
response_data
[
0
][
'key'
],
allowance_data
[
'key'
])
...
...
edx_proctoring/views.py
View file @
a9aeb462
...
@@ -611,18 +611,16 @@ class StudentProctoredExamAttemptsByCourse(AuthenticatedAPIView):
...
@@ -611,18 +611,16 @@ class StudentProctoredExamAttemptsByCourse(AuthenticatedAPIView):
def
get
(
self
,
request
,
course_id
,
search_by
=
None
):
# pylint: disable=unused-argument
def
get
(
self
,
request
,
course_id
,
search_by
=
None
):
# pylint: disable=unused-argument
"""
"""
HTTP GET Handler. Returns the status of the exam attempt.
HTTP GET Handler. Returns the status of the exam attempt.
Course and Global staff can view both timed and proctored exam attempts.
"""
"""
# course staff only views attempts of timed exams. edx staff can view both timed and proctored attempts.
time_exams_only
=
not
request
.
user
.
is_staff
if
search_by
is
not
None
:
if
search_by
is
not
None
:
exam_attempts
=
ProctoredExamStudentAttempt
.
objects
.
get_filtered_exam_attempts
(
exam_attempts
=
ProctoredExamStudentAttempt
.
objects
.
get_filtered_exam_attempts
(
course_id
,
search_by
,
time_exams_only
course_id
,
search_by
)
)
attempt_url
=
reverse
(
'edx_proctoring.proctored_exam.attempts.search'
,
args
=
[
course_id
,
search_by
])
attempt_url
=
reverse
(
'edx_proctoring.proctored_exam.attempts.search'
,
args
=
[
course_id
,
search_by
])
else
:
else
:
exam_attempts
=
ProctoredExamStudentAttempt
.
objects
.
get_all_exam_attempts
(
exam_attempts
=
ProctoredExamStudentAttempt
.
objects
.
get_all_exam_attempts
(
course_id
,
time_exams_only
course_id
)
)
attempt_url
=
reverse
(
'edx_proctoring.proctored_exam.attempts.course'
,
args
=
[
course_id
])
attempt_url
=
reverse
(
'edx_proctoring.proctored_exam.attempts.course'
,
args
=
[
course_id
])
...
@@ -701,13 +699,10 @@ class ExamAllowanceView(AuthenticatedAPIView):
...
@@ -701,13 +699,10 @@ class ExamAllowanceView(AuthenticatedAPIView):
def
get
(
self
,
request
,
course_id
):
# pylint: disable=unused-argument
def
get
(
self
,
request
,
course_id
):
# pylint: disable=unused-argument
"""
"""
HTTP GET handler. Get all allowances for a course.
HTTP GET handler. Get all allowances for a course.
Course and Global staff can view both timed and proctored exam allowances.
"""
"""
# course staff only views attempts of timed exams. edx staff can view both timed and proctored attempts.
time_exams_only
=
not
request
.
user
.
is_staff
result_set
=
get_allowances_for_course
(
result_set
=
get_allowances_for_course
(
course_id
=
course_id
,
course_id
=
course_id
timed_exams_only
=
time_exams_only
)
)
return
Response
(
result_set
)
return
Response
(
result_set
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment