Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-notes-api
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-notes-api
Commits
4310403b
Commit
4310403b
authored
Feb 08, 2016
by
ehtesham
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[TNL-4029] user can't add more than maximum number of allowed annotations
parent
05dba592
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
100 additions
and
4 deletions
+100
-4
notesapi/v1/tests/test_views.py
+68
-1
notesapi/v1/views.py
+26
-3
notesserver/settings/common.py
+3
-0
notesserver/settings/test.py
+3
-0
No files found.
notesapi/v1/tests/test_views.py
View file @
4310403b
...
@@ -18,6 +18,7 @@ from rest_framework.test import APITestCase
...
@@ -18,6 +18,7 @@ from rest_framework.test import APITestCase
from
.helpers
import
get_id_token
from
.helpers
import
get_id_token
TEST_USER
=
"test_user_id"
TEST_USER
=
"test_user_id"
TEST_OTHER_USER
=
"test_other_user_id"
if
not
settings
.
ES_DISABLED
:
if
not
settings
.
ES_DISABLED
:
import
haystack
import
haystack
...
@@ -65,6 +66,16 @@ class BaseAnnotationViewTests(APITestCase):
...
@@ -65,6 +66,16 @@ class BaseAnnotationViewTests(APITestCase):
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_201_CREATED
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_201_CREATED
)
return
response
.
data
.
copy
()
return
response
.
data
.
copy
()
def
_create_annotation_without_assert
(
self
,
**
kwargs
):
"""
Create annotation but do not check for 201
"""
opts
=
self
.
payload
.
copy
()
opts
.
update
(
kwargs
)
url
=
reverse
(
'api:v1:annotations'
)
response
=
self
.
client
.
post
(
url
,
opts
,
format
=
'json'
)
return
response
def
_do_annotation_update
(
self
,
data
,
updated_fields
):
def
_do_annotation_update
(
self
,
data
,
updated_fields
):
"""
"""
Helper method for updating an annotation.
Helper method for updating an annotation.
...
@@ -98,7 +109,7 @@ class BaseAnnotationViewTests(APITestCase):
...
@@ -98,7 +109,7 @@ class BaseAnnotationViewTests(APITestCase):
result
=
self
.
client
.
get
(
url
,
data
=
data
)
result
=
self
.
client
.
get
(
url
,
data
=
data
)
return
result
.
data
return
result
.
data
@ddt.ddt
class
AnnotationListViewTests
(
BaseAnnotationViewTests
):
class
AnnotationListViewTests
(
BaseAnnotationViewTests
):
"""
"""
Test annotation creation and listing by user and course
Test annotation creation and listing by user and course
...
@@ -222,6 +233,62 @@ class AnnotationListViewTests(BaseAnnotationViewTests):
...
@@ -222,6 +233,62 @@ class AnnotationListViewTests(BaseAnnotationViewTests):
del
annotation
[
'created'
]
del
annotation
[
'created'
]
self
.
assertEqual
(
annotation
,
note
)
self
.
assertEqual
(
annotation
,
note
)
@ddt.data
(
(
6
,
False
),
(
4
,
True
)
)
@ddt.unpack
def
test_create_maximum_allowed
(
self
,
num_notes
,
should_create
):
"""
Tests user can not create more than allowed notes/annotations per course
"""
for
i
in
xrange
(
num_notes
-
1
):
kwargs
=
{
'text'
:
'Foo_{}'
.
format
(
i
)}
self
.
_create_annotation
(
**
kwargs
)
# Creating more notes should result in 400 error
kwargs
=
{
'text'
:
'Foo_{}'
.
format
(
num_notes
)}
response
=
self
.
_create_annotation_without_assert
(
**
kwargs
)
if
not
should_create
:
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_400_BAD_REQUEST
,
'Creating more than allowed notes'
)
self
.
assertEqual
(
response
.
data
[
'error_msg'
],
u'You can create up to {0} notes.'
u' You must remove some notes before you can add new ones.'
.
format
(
settings
.
MAX_ANNOTATIONS_PER_COURSE
)
)
else
:
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_201_CREATED
)
def
test_create_maximum_allowed_other
(
self
):
# if user tries to create notes in another course it should succeed
for
i
in
xrange
(
5
):
kwargs
=
{
'text'
:
'Foo_{}'
.
format
(
i
)}
self
.
_create_annotation
(
**
kwargs
)
# Creating more notes should result in 400 error
kwargs
=
{
'text'
:
'Foo_{}'
.
format
(
6
)}
response
=
self
.
_create_annotation_without_assert
(
**
kwargs
)
self
.
assertEqual
(
response
.
status_code
,
status
.
HTTP_400_BAD_REQUEST
,
'Creating more than allowed notes'
)
self
.
assertEqual
(
response
.
data
[
'error_msg'
],
u'You can create up to {0} notes.'
u' You must remove some notes before you can add new ones.'
.
format
(
settings
.
MAX_ANNOTATIONS_PER_COURSE
)
)
# if user tries to create note in a different course it should succeed
kwargs
=
{
'course_id'
:
'test-course-id-2'
}
response
=
self
.
_create_annotation
(
**
kwargs
)
self
.
assertFalse
(
hasattr
(
response
,
'data'
))
# if another user to tries to create note in first course it should succeed
token
=
get_id_token
(
TEST_OTHER_USER
)
self
.
client
.
credentials
(
HTTP_X_ANNOTATOR_AUTH_TOKEN
=
token
)
self
.
headers
=
{
'user'
:
TEST_OTHER_USER
}
kwargs
=
{
'user'
:
TEST_OTHER_USER
}
response
=
self
.
_create_annotation
(
**
kwargs
)
self
.
assertFalse
(
hasattr
(
response
,
'data'
))
def
test_read_all_no_annotations
(
self
):
def
test_read_all_no_annotations
(
self
):
"""
"""
Tests list all annotations endpoint when no annotations are present in database.
Tests list all annotations endpoint when no annotations are present in database.
...
...
notesapi/v1/views.py
View file @
4310403b
...
@@ -5,6 +5,7 @@ from django.conf import settings
...
@@ -5,6 +5,7 @@ from django.conf import settings
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
from
django.core.exceptions
import
ValidationError
from
django.core.exceptions
import
ValidationError
from
django.db.models
import
Q
from
django.db.models
import
Q
from
django.utils.translation
import
ugettext_noop
from
rest_framework
import
status
from
rest_framework
import
status
from
rest_framework.response
import
Response
from
rest_framework.response
import
Response
...
@@ -20,6 +21,13 @@ if not settings.ES_DISABLED:
...
@@ -20,6 +21,13 @@ if not settings.ES_DISABLED:
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
class
AnnotationsLimitReachedError
(
Exception
):
"""
Exception when trying to create more than allowed annotations
"""
pass
class
AnnotationSearchView
(
APIView
):
class
AnnotationSearchView
(
APIView
):
"""
"""
Search annotations.
Search annotations.
...
@@ -117,20 +125,35 @@ class AnnotationListView(APIView):
...
@@ -117,20 +125,35 @@ class AnnotationListView(APIView):
Returns 400 request if bad payload is sent or it was empty object.
Returns 400 request if bad payload is sent or it was empty object.
"""
"""
if
'id'
in
self
.
request
.
data
:
if
not
self
.
request
.
data
or
'id'
in
self
.
request
.
data
:
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
)
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
)
try
:
try
:
if
Note
.
objects
.
filter
(
user_id
=
self
.
request
.
data
[
'user'
],
course_id
=
self
.
request
.
data
[
'course_id'
]
)
.
count
()
>=
settings
.
MAX_ANNOTATIONS_PER_COURSE
:
raise
AnnotationsLimitReachedError
note
=
Note
.
create
(
self
.
request
.
data
)
note
=
Note
.
create
(
self
.
request
.
data
)
note
.
full_clean
()
note
.
full_clean
()
except
ValidationError
as
error
:
except
ValidationError
as
error
:
log
.
debug
(
error
,
exc_info
=
True
)
log
.
debug
(
error
,
exc_info
=
True
)
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
)
return
Response
(
status
=
status
.
HTTP_400_BAD_REQUEST
)
except
AnnotationsLimitReachedError
:
error_message
=
ugettext_noop
(
u'You can create up to {max_num_annotations_per_course} notes.'
u' You must remove some notes before you can add new ones.'
)
.
format
(
max_num_annotations_per_course
=
settings
.
MAX_ANNOTATIONS_PER_COURSE
)
log
.
info
(
u'Attempted to create more than
%
s annotations'
,
settings
.
MAX_ANNOTATIONS_PER_COURSE
)
return
Response
({
'error_msg'
:
error_message
},
status
=
status
.
HTTP_400_BAD_REQUEST
)
note
.
save
()
note
.
save
()
location
=
reverse
(
'api:v1:annotations_detail'
,
kwargs
=
{
'annotation_id'
:
note
.
id
})
location
=
reverse
(
'api:v1:annotations_detail'
,
kwargs
=
{
'annotation_id'
:
note
.
id
})
return
Response
(
note
.
as_dict
(),
status
=
status
.
HTTP_201_CREATED
,
headers
=
{
'Location'
:
location
})
return
Response
(
note
.
as_dict
(),
status
=
status
.
HTTP_201_CREATED
,
headers
=
{
'Location'
:
location
})
...
...
notesserver/settings/common.py
View file @
4310403b
...
@@ -80,3 +80,6 @@ CORS_ALLOW_HEADERS = (
...
@@ -80,3 +80,6 @@ CORS_ALLOW_HEADERS = (
TEMPLATE_DIRS
=
(
TEMPLATE_DIRS
=
(
'templates'
,
'templates'
,
)
)
### Maximum number of allowed notes per course ###
MAX_ANNOTATIONS_PER_COURSE
=
500
notesserver/settings/test.py
View file @
4310403b
...
@@ -42,3 +42,6 @@ LOGGING = {
...
@@ -42,3 +42,6 @@ LOGGING = {
}
}
},
},
}
}
### Maximum number of allowed notes per course ###
MAX_ANNOTATIONS_PER_COURSE
=
5
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