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
a24cf993
Commit
a24cf993
authored
Jul 09, 2015
by
Chris Dodge
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Switch to use User object rather than integer. Also add new field for allowed_time_limit_mins
parent
ac0115f7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
31 additions
and
162 deletions
+31
-162
edx_proctoring/api.py
+7
-1
edx_proctoring/migrations/0001_initial.py
+0
-0
edx_proctoring/migrations/0002_auto__add_field_proctoredexamstudentattempt_taking_as_proctored.py
+0
-73
edx_proctoring/migrations/0003_auto__add_field_proctoredexamstudentattempt_student_name.py
+0
-74
edx_proctoring/models.py
+12
-6
edx_proctoring/serializers.py
+3
-2
edx_proctoring/tests/test_api.py
+4
-2
edx_proctoring/tests/test_models.py
+2
-2
edx_proctoring/tests/test_views.py
+2
-1
edx_proctoring/views.py
+1
-1
No files found.
edx_proctoring/api.py
View file @
a24cf993
...
...
@@ -167,10 +167,16 @@ def create_exam_attempt(exam_id, user_id, external_id):
raise
StudentExamAttemptAlreadyExistsException
(
err_msg
)
# for now the student is allowed the exam default
exam
=
get_exam_by_id
(
exam_id
)
allowed_time_limit_mins
=
exam
[
'time_limit_mins'
]
attempt
=
ProctoredExamStudentAttempt
.
create_exam_attempt
(
exam_id
,
user_id
,
''
,
# student name is TBD
allowed_time_limit_mins
,
external_id
)
return
attempt
.
id
...
...
@@ -312,7 +318,7 @@ def get_student_view(user_id, course_id, content_id, context):
has_started_exam
=
attempt
and
attempt
.
get
(
'started_at'
)
if
has_started_exam
:
now_utc
=
datetime
.
now
(
pytz
.
UTC
)
expires_at
=
attempt
[
'started_at'
]
+
timedelta
(
minutes
=
context
[
'default
_time_limit_mins'
])
expires_at
=
attempt
[
'started_at'
]
+
timedelta
(
minutes
=
attempt
[
'allowed
_time_limit_mins'
])
has_time_expired
=
now_utc
>
expires_at
if
not
has_started_exam
:
...
...
edx_proctoring/migrations/0001_initial.py
View file @
a24cf993
This diff is collapsed.
Click to expand it.
edx_proctoring/migrations/0002_auto__add_field_proctoredexamstudentattempt_taking_as_proctored.py
deleted
100644 → 0
View file @
ac0115f7
# -*- coding: utf-8 -*-
from
south.utils
import
datetime_utils
as
datetime
from
south.db
import
db
from
south.v2
import
SchemaMigration
from
django.db
import
models
class
Migration
(
SchemaMigration
):
def
forwards
(
self
,
orm
):
# Adding field 'ProctoredExamStudentAttempt.taking_as_proctored'
db
.
add_column
(
'proctoring_proctoredexamstudentattempt'
,
'taking_as_proctored'
,
self
.
gf
(
'django.db.models.fields.BooleanField'
)(
default
=
False
),
keep_default
=
False
)
def
backwards
(
self
,
orm
):
# Deleting field 'ProctoredExamStudentAttempt.taking_as_proctored'
db
.
delete_column
(
'proctoring_proctoredexamstudentattempt'
,
'taking_as_proctored'
)
models
=
{
'edx_proctoring.proctoredexam'
:
{
'Meta'
:
{
'unique_together'
:
"(('course_id', 'content_id'),)"
,
'object_name'
:
'ProctoredExam'
,
'db_table'
:
"'proctoring_proctoredexam'"
},
'content_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'course_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'created'
:
(
'model_utils.fields.AutoCreatedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'exam_name'
:
(
'django.db.models.fields.TextField'
,
[],
{}),
'external_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'null'
:
'True'
,
'db_index'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'is_active'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'is_proctored'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'modified'
:
(
'model_utils.fields.AutoLastModifiedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'time_limit_mins'
:
(
'django.db.models.fields.IntegerField'
,
[],
{})
},
'edx_proctoring.proctoredexamstudentallowance'
:
{
'Meta'
:
{
'unique_together'
:
"(('user_id', 'proctored_exam', 'key'),)"
,
'object_name'
:
'ProctoredExamStudentAllowance'
,
'db_table'
:
"'proctoring_proctoredexamstudentallowance'"
},
'created'
:
(
'model_utils.fields.AutoCreatedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'key'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
}),
'modified'
:
(
'model_utils.fields.AutoLastModifiedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'proctored_exam'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['edx_proctoring.ProctoredExam']"
}),
'user_id'
:
(
'django.db.models.fields.IntegerField'
,
[],
{}),
'value'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
})
},
'edx_proctoring.proctoredexamstudentallowancehistory'
:
{
'Meta'
:
{
'object_name'
:
'ProctoredExamStudentAllowanceHistory'
,
'db_table'
:
"'proctoring_proctoredexamstudentallowancehistory'"
},
'allowance_id'
:
(
'django.db.models.fields.IntegerField'
,
[],
{}),
'created'
:
(
'model_utils.fields.AutoCreatedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'key'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
}),
'modified'
:
(
'model_utils.fields.AutoLastModifiedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'proctored_exam'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['edx_proctoring.ProctoredExam']"
}),
'user_id'
:
(
'django.db.models.fields.IntegerField'
,
[],
{}),
'value'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
})
},
'edx_proctoring.proctoredexamstudentattempt'
:
{
'Meta'
:
{
'object_name'
:
'ProctoredExamStudentAttempt'
,
'db_table'
:
"'proctoring_proctoredexamstudentattempt'"
},
'completed_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'null'
:
'True'
}),
'created'
:
(
'model_utils.fields.AutoCreatedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'external_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'null'
:
'True'
,
'db_index'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'modified'
:
(
'model_utils.fields.AutoLastModifiedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'proctored_exam'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['edx_proctoring.ProctoredExam']"
}),
'started_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'null'
:
'True'
}),
'status'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'64'
}),
'taking_as_proctored'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'user_id'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'db_index'
:
'True'
})
}
}
complete_apps
=
[
'edx_proctoring'
]
\ No newline at end of file
edx_proctoring/migrations/0003_auto__add_field_proctoredexamstudentattempt_student_name.py
deleted
100644 → 0
View file @
ac0115f7
# -*- coding: utf-8 -*-
from
south.utils
import
datetime_utils
as
datetime
from
south.db
import
db
from
south.v2
import
SchemaMigration
from
django.db
import
models
class
Migration
(
SchemaMigration
):
def
forwards
(
self
,
orm
):
# Adding field 'ProctoredExamStudentAttempt.student_name'
db
.
add_column
(
'proctoring_proctoredexamstudentattempt'
,
'student_name'
,
self
.
gf
(
'django.db.models.fields.CharField'
)(
max_length
=
255
,
null
=
True
),
keep_default
=
False
)
def
backwards
(
self
,
orm
):
# Deleting field 'ProctoredExamStudentAttempt.student_name'
db
.
delete_column
(
'proctoring_proctoredexamstudentattempt'
,
'student_name'
)
models
=
{
'edx_proctoring.proctoredexam'
:
{
'Meta'
:
{
'unique_together'
:
"(('course_id', 'content_id'),)"
,
'object_name'
:
'ProctoredExam'
,
'db_table'
:
"'proctoring_proctoredexam'"
},
'content_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'course_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'db_index'
:
'True'
}),
'created'
:
(
'model_utils.fields.AutoCreatedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'exam_name'
:
(
'django.db.models.fields.TextField'
,
[],
{}),
'external_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'null'
:
'True'
,
'db_index'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'is_active'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'is_proctored'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'modified'
:
(
'model_utils.fields.AutoLastModifiedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'time_limit_mins'
:
(
'django.db.models.fields.IntegerField'
,
[],
{})
},
'edx_proctoring.proctoredexamstudentallowance'
:
{
'Meta'
:
{
'unique_together'
:
"(('user_id', 'proctored_exam', 'key'),)"
,
'object_name'
:
'ProctoredExamStudentAllowance'
,
'db_table'
:
"'proctoring_proctoredexamstudentallowance'"
},
'created'
:
(
'model_utils.fields.AutoCreatedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'key'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
}),
'modified'
:
(
'model_utils.fields.AutoLastModifiedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'proctored_exam'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['edx_proctoring.ProctoredExam']"
}),
'user_id'
:
(
'django.db.models.fields.IntegerField'
,
[],
{}),
'value'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
})
},
'edx_proctoring.proctoredexamstudentallowancehistory'
:
{
'Meta'
:
{
'object_name'
:
'ProctoredExamStudentAllowanceHistory'
,
'db_table'
:
"'proctoring_proctoredexamstudentallowancehistory'"
},
'allowance_id'
:
(
'django.db.models.fields.IntegerField'
,
[],
{}),
'created'
:
(
'model_utils.fields.AutoCreatedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'key'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
}),
'modified'
:
(
'model_utils.fields.AutoLastModifiedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'proctored_exam'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['edx_proctoring.ProctoredExam']"
}),
'user_id'
:
(
'django.db.models.fields.IntegerField'
,
[],
{}),
'value'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
})
},
'edx_proctoring.proctoredexamstudentattempt'
:
{
'Meta'
:
{
'object_name'
:
'ProctoredExamStudentAttempt'
,
'db_table'
:
"'proctoring_proctoredexamstudentattempt'"
},
'completed_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'null'
:
'True'
}),
'created'
:
(
'model_utils.fields.AutoCreatedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'external_id'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'null'
:
'True'
,
'db_index'
:
'True'
}),
'id'
:
(
'django.db.models.fields.AutoField'
,
[],
{
'primary_key'
:
'True'
}),
'modified'
:
(
'model_utils.fields.AutoLastModifiedField'
,
[],
{
'default'
:
'datetime.datetime.now'
}),
'proctored_exam'
:
(
'django.db.models.fields.related.ForeignKey'
,
[],
{
'to'
:
"orm['edx_proctoring.ProctoredExam']"
}),
'started_at'
:
(
'django.db.models.fields.DateTimeField'
,
[],
{
'null'
:
'True'
}),
'status'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'64'
}),
'student_name'
:
(
'django.db.models.fields.CharField'
,
[],
{
'max_length'
:
'255'
,
'null'
:
'True'
}),
'taking_as_proctored'
:
(
'django.db.models.fields.BooleanField'
,
[],
{
'default'
:
'False'
}),
'user_id'
:
(
'django.db.models.fields.IntegerField'
,
[],
{
'db_index'
:
'True'
})
}
}
complete_apps
=
[
'edx_proctoring'
]
\ No newline at end of file
edx_proctoring/models.py
View file @
a24cf993
...
...
@@ -9,6 +9,8 @@ from django.db.models.signals import post_save, pre_delete
from
django.dispatch
import
receiver
from
model_utils.models
import
TimeStampedModel
from
django.contrib.auth.models
import
User
class
ProctoredExam
(
TimeStampedModel
):
"""
...
...
@@ -78,7 +80,7 @@ class ProctoredExamStudentAttempt(TimeStampedModel):
Information about the Student Attempt on a
Proctored Exam.
"""
user
_id
=
models
.
IntegerField
(
db_index
=
True
)
user
=
models
.
ForeignKey
(
User
,
db_index
=
True
)
proctored_exam
=
models
.
ForeignKey
(
ProctoredExam
,
db_index
=
True
)
...
...
@@ -89,6 +91,9 @@ class ProctoredExamStudentAttempt(TimeStampedModel):
# This will be a integration specific ID - say to SoftwareSecure.
external_id
=
models
.
CharField
(
max_length
=
255
,
null
=
True
,
db_index
=
True
)
# this is the time limit allowed to the student
allowed_time_limit_mins
=
models
.
IntegerField
()
# what is the status of this attempt
status
=
models
.
CharField
(
max_length
=
64
)
...
...
@@ -109,7 +114,7 @@ class ProctoredExamStudentAttempt(TimeStampedModel):
return
self
.
started_at
and
not
self
.
completed_at
@classmethod
def
create_exam_attempt
(
cls
,
exam_id
,
user_id
,
student_name
,
external_id
):
def
create_exam_attempt
(
cls
,
exam_id
,
user_id
,
student_name
,
allowed_time_limit_mins
,
external_id
):
"""
Create a new exam attempt entry for a given exam_id and
user_id.
...
...
@@ -119,6 +124,7 @@ class ProctoredExamStudentAttempt(TimeStampedModel):
proctored_exam_id
=
exam_id
,
user_id
=
user_id
,
student_name
=
student_name
,
allowed_time_limit_mins
=
allowed_time_limit_mins
,
external_id
=
external_id
)
...
...
@@ -180,7 +186,7 @@ class ProctoredExamStudentAllowance(TimeStampedModel):
objects
=
ProctoredExamStudentAllowanceManager
()
user
_id
=
models
.
IntegerField
(
)
user
=
models
.
ForeignKey
(
User
)
proctored_exam
=
models
.
ForeignKey
(
ProctoredExam
)
...
...
@@ -190,7 +196,7 @@ class ProctoredExamStudentAllowance(TimeStampedModel):
class
Meta
:
""" Meta class for this Django model """
unique_together
=
((
'user
_id
'
,
'proctored_exam'
,
'key'
),)
unique_together
=
((
'user'
,
'proctored_exam'
,
'key'
),)
db_table
=
'proctoring_proctoredexamstudentallowance'
verbose_name
=
'proctored allowance'
...
...
@@ -234,7 +240,7 @@ class ProctoredExamStudentAllowanceHistory(TimeStampedModel):
# what was the original id of the allowance
allowance_id
=
models
.
IntegerField
()
user
_id
=
models
.
IntegerField
(
)
user
=
models
.
ForeignKey
(
User
)
proctored_exam
=
models
.
ForeignKey
(
ProctoredExam
)
...
...
@@ -276,7 +282,7 @@ def _make_archive_copy(item):
archive_object
=
ProctoredExamStudentAllowanceHistory
(
allowance_id
=
item
.
id
,
user
_id
=
item
.
user_id
,
user
=
item
.
user
,
proctored_exam
=
item
.
proctored_exam
,
key
=
item
.
key
,
value
=
item
.
value
...
...
edx_proctoring/serializers.py
View file @
a24cf993
...
...
@@ -47,6 +47,7 @@ class ProctoredExamStudentAttemptSerializer(serializers.ModelSerializer):
Serializer for the ProctoredExamStudentAttempt Model.
"""
proctored_exam_id
=
serializers
.
IntegerField
(
source
=
"proctored_exam_id"
)
user_id
=
serializers
.
IntegerField
(
source
=
'user_id'
)
class
Meta
:
"""
...
...
@@ -56,7 +57,7 @@ class ProctoredExamStudentAttemptSerializer(serializers.ModelSerializer):
fields
=
(
"id"
,
"created"
,
"modified"
,
"user_id"
,
"started_at"
,
"completed_at"
,
"external_id"
,
"status"
,
"proctored_exam_id"
"external_id"
,
"status"
,
"proctored_exam_id"
,
"allowed_time_limit_mins"
)
...
...
@@ -70,5 +71,5 @@ class ProctoredExamStudentAllowanceSerializer(serializers.ModelSerializer):
"""
model
=
ProctoredExamStudentAllowance
fields
=
(
"id"
,
"created"
,
"modified"
,
"user
_id
"
,
"key"
,
"value"
"id"
,
"created"
,
"modified"
,
"user"
,
"key"
,
"value"
)
edx_proctoring/tests/test_api.py
View file @
a24cf993
...
...
@@ -94,7 +94,8 @@ class ProctoredExamApiTests(LoggedInTestCase):
return
ProctoredExamStudentAttempt
.
objects
.
create
(
proctored_exam_id
=
self
.
proctored_exam_id
,
user_id
=
self
.
user_id
,
external_id
=
self
.
external_id
external_id
=
self
.
external_id
,
allowed_time_limit_mins
=
10
)
def
_create_started_exam_attempt
(
self
,
started_at
=
None
):
...
...
@@ -105,7 +106,8 @@ class ProctoredExamApiTests(LoggedInTestCase):
proctored_exam_id
=
self
.
proctored_exam_id
,
user_id
=
self
.
user_id
,
external_id
=
self
.
external_id
,
started_at
=
started_at
if
started_at
else
datetime
.
now
(
pytz
.
UTC
)
started_at
=
started_at
if
started_at
else
datetime
.
now
(
pytz
.
UTC
),
allowed_time_limit_mins
=
10
)
def
_add_allowance_for_user
(
self
):
...
...
edx_proctoring/tests/test_models.py
View file @
a24cf993
...
...
@@ -47,7 +47,7 @@ class ProctoredExamModelTests(LoggedInTestCase):
user_id
=
1
,
proctored_exam
=
proctored_exam
,
)
.
update
(
user
_id
=
1
,
user
=
1
,
proctored_exam
=
proctored_exam
,
key
=
'allowance_key update 1'
,
value
=
'10 minutes'
...
...
@@ -57,7 +57,7 @@ class ProctoredExamModelTests(LoggedInTestCase):
user_id
=
1
,
proctored_exam
=
proctored_exam
,
)
.
update
(
user
_id
=
1
,
user
=
1
,
proctored_exam
=
proctored_exam
,
key
=
'allowance_key update 2'
,
value
=
'5 minutes'
...
...
edx_proctoring/tests/test_views.py
View file @
a24cf993
...
...
@@ -639,7 +639,8 @@ class TestActiveExamsForUserView(LoggedInTestCase):
proctored_exam_id
=
proctored_exam
.
id
,
user_id
=
self
.
student_taking_exam
.
id
,
external_id
=
'123aXqe3'
,
started_at
=
datetime
.
now
(
pytz
.
UTC
)
started_at
=
datetime
.
now
(
pytz
.
UTC
),
allowed_time_limit_mins
=
90
)
ProctoredExamStudentAllowance
.
objects
.
create
(
...
...
edx_proctoring/views.py
View file @
a24cf993
...
...
@@ -248,7 +248,7 @@ class StudentProctoredExamAttempt(AuthenticatedAPIView):
exam
=
exams
[
0
]
# need to adjust for allowances
expires_at
=
exam
[
'attempt'
][
'started_at'
]
+
timedelta
(
minutes
=
exam
[
'
exam'
][
'
time_limit_mins'
])
expires_at
=
exam
[
'attempt'
][
'started_at'
]
+
timedelta
(
minutes
=
exam
[
'
attempt'
][
'allowed_
time_limit_mins'
])
now_utc
=
datetime
.
now
(
pytz
.
UTC
)
if
expires_at
>
now_utc
:
...
...
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