Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
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-platform
Commits
44c78c60
Commit
44c78c60
authored
Mar 20, 2015
by
Daniel Friedman
Committed by
Andy Armstrong
Apr 17, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add logging to image uploads/deletes.
Conflicts: openedx/core/djangoapps/profile_images/views.py
parent
c898e413
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
62 additions
and
19 deletions
+62
-19
openedx/core/djangoapps/profile_images/tests/test_views.py
+42
-17
openedx/core/djangoapps/profile_images/views.py
+20
-2
No files found.
openedx/core/djangoapps/profile_images/tests/test_views.py
View file @
44c78c60
...
...
@@ -4,7 +4,6 @@ Test cases for the HTTP endpoints of the profile image api.
from
contextlib
import
closing
import
unittest
import
ddt
from
django.conf
import
settings
from
django.core.urlresolvers
import
reverse
import
mock
...
...
@@ -21,6 +20,7 @@ from ...user_api.accounts.image_helpers import (
get_profile_image_storage
)
from
..images
import
create_profile_images
,
ImageValidationError
from
..views
import
LOG_MESSAGE_CREATE
,
LOG_MESSAGE_DELETE
from
.helpers
import
make_image_file
TEST_PASSWORD
=
"test"
...
...
@@ -94,15 +94,15 @@ class ProfileImageEndpointTestCase(APITestCase):
self
.
assertEqual
(
profile
.
has_profile_image
,
has_profile_image
)
@ddt.ddt
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Profile Image API is only supported in LMS'
)
@mock.patch
(
'openedx.core.djangoapps.profile_images.views.log'
)
class
ProfileImageUploadTestCase
(
ProfileImageEndpointTestCase
):
"""
Tests for the profile_image upload endpoint.
"""
_view_name
=
"profile_image_upload"
def
test_unsupported_methods
(
self
):
def
test_unsupported_methods
(
self
,
mock_log
):
"""
Test that GET, PUT, PATCH, and DELETE are not supported.
"""
...
...
@@ -110,16 +110,18 @@ class ProfileImageUploadTestCase(ProfileImageEndpointTestCase):
self
.
assertEqual
(
405
,
self
.
client
.
put
(
self
.
url
)
.
status_code
)
self
.
assertEqual
(
405
,
self
.
client
.
patch
(
self
.
url
)
.
status_code
)
self
.
assertEqual
(
405
,
self
.
client
.
delete
(
self
.
url
)
.
status_code
)
self
.
assertFalse
(
mock_log
.
info
.
called
)
def
test_anonymous_access
(
self
):
def
test_anonymous_access
(
self
,
mock_log
):
"""
Test that an anonymous client (not logged in) cannot POST.
"""
anonymous_client
=
APIClient
()
response
=
anonymous_client
.
post
(
self
.
url
)
self
.
assertEqual
(
401
,
response
.
status_code
)
self
.
assertFalse
(
mock_log
.
info
.
called
)
def
test_upload_self
(
self
):
def
test_upload_self
(
self
,
mock_log
):
"""
Test that an authenticated user can POST to their own upload endpoint.
"""
...
...
@@ -128,8 +130,12 @@ class ProfileImageUploadTestCase(ProfileImageEndpointTestCase):
self
.
check_response
(
response
,
204
)
self
.
check_images
()
self
.
check_has_profile_image
()
mock_log
.
info
.
assert_called_once_with
(
LOG_MESSAGE_CREATE
,
{
'image_names'
:
get_profile_image_names
(
self
.
user
.
username
)
.
values
(),
'user_id'
:
self
.
user
.
id
}
)
def
test_upload_other
(
self
):
def
test_upload_other
(
self
,
mock_log
):
"""
Test that an authenticated user cannot POST to another user's upload endpoint.
"""
...
...
@@ -141,8 +147,9 @@ class ProfileImageUploadTestCase(ProfileImageEndpointTestCase):
self
.
check_response
(
response
,
404
)
self
.
check_images
(
False
)
self
.
check_has_profile_image
(
False
)
self
.
assertFalse
(
mock_log
.
info
.
called
)
def
test_upload_staff
(
self
):
def
test_upload_staff
(
self
,
mock_log
):
"""
Test that an authenticated staff cannot POST to another user's upload endpoint.
"""
...
...
@@ -154,8 +161,9 @@ class ProfileImageUploadTestCase(ProfileImageEndpointTestCase):
self
.
check_response
(
response
,
403
)
self
.
check_images
(
False
)
self
.
check_has_profile_image
(
False
)
self
.
assertFalse
(
mock_log
.
info
.
called
)
def
test_upload_missing_file
(
self
):
def
test_upload_missing_file
(
self
,
mock_log
):
"""
Test that omitting the file entirely from the POST results in HTTP 400.
"""
...
...
@@ -167,8 +175,9 @@ class ProfileImageUploadTestCase(ProfileImageEndpointTestCase):
)
self
.
check_images
(
False
)
self
.
check_has_profile_image
(
False
)
self
.
assertFalse
(
mock_log
.
info
.
called
)
def
test_upload_not_a_file
(
self
):
def
test_upload_not_a_file
(
self
,
mock_log
):
"""
Test that sending unexpected data that isn't a file results in HTTP
400.
...
...
@@ -181,8 +190,9 @@ class ProfileImageUploadTestCase(ProfileImageEndpointTestCase):
)
self
.
check_images
(
False
)
self
.
check_has_profile_image
(
False
)
self
.
assertFalse
(
mock_log
.
info
.
called
)
def
test_upload_validation
(
self
):
def
test_upload_validation
(
self
,
mock_log
):
"""
Test that when upload validation fails, the proper HTTP response and
messages are returned.
...
...
@@ -200,9 +210,10 @@ class ProfileImageUploadTestCase(ProfileImageEndpointTestCase):
)
self
.
check_images
(
False
)
self
.
check_has_profile_image
(
False
)
self
.
assertFalse
(
mock_log
.
info
.
called
)
@patch
(
'PIL.Image.open'
)
def
test_upload_failure
(
self
,
image_open
):
def
test_upload_failure
(
self
,
image_open
,
mock_log
):
"""
Test that when upload validation fails, the proper HTTP response and
messages are returned.
...
...
@@ -217,9 +228,11 @@ class ProfileImageUploadTestCase(ProfileImageEndpointTestCase):
)
self
.
check_images
(
False
)
self
.
check_has_profile_image
(
False
)
self
.
assertFalse
(
mock_log
.
info
.
called
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Profile Image API is only supported in LMS'
)
@mock.patch
(
'openedx.core.djangoapps.profile_images.views.log'
)
class
ProfileImageRemoveTestCase
(
ProfileImageEndpointTestCase
):
"""
Tests for the profile_image remove endpoint.
...
...
@@ -233,7 +246,7 @@ class ProfileImageRemoveTestCase(ProfileImageEndpointTestCase):
self
.
check_images
()
set_has_profile_image
(
self
.
user
.
username
,
True
)
def
test_unsupported_methods
(
self
):
def
test_unsupported_methods
(
self
,
mock_log
):
"""
Test that GET, PUT, PATCH, and DELETE are not supported.
"""
...
...
@@ -241,8 +254,9 @@ class ProfileImageRemoveTestCase(ProfileImageEndpointTestCase):
self
.
assertEqual
(
405
,
self
.
client
.
put
(
self
.
url
)
.
status_code
)
self
.
assertEqual
(
405
,
self
.
client
.
patch
(
self
.
url
)
.
status_code
)
self
.
assertEqual
(
405
,
self
.
client
.
delete
(
self
.
url
)
.
status_code
)
self
.
assertFalse
(
mock_log
.
info
.
called
)
def
test_anonymous_access
(
self
):
def
test_anonymous_access
(
self
,
mock_log
):
"""
Test that an anonymous client (not logged in) cannot call GET or POST.
"""
...
...
@@ -250,8 +264,9 @@ class ProfileImageRemoveTestCase(ProfileImageEndpointTestCase):
for
request
in
(
anonymous_client
.
get
,
anonymous_client
.
post
):
response
=
request
(
self
.
url
)
self
.
assertEqual
(
401
,
response
.
status_code
)
self
.
assertFalse
(
mock_log
.
info
.
called
)
def
test_remove_self
(
self
):
def
test_remove_self
(
self
,
mock_log
):
"""
Test that an authenticated user can POST to remove their own profile
images.
...
...
@@ -260,8 +275,12 @@ class ProfileImageRemoveTestCase(ProfileImageEndpointTestCase):
self
.
check_response
(
response
,
204
)
self
.
check_images
(
False
)
self
.
check_has_profile_image
(
False
)
mock_log
.
info
.
assert_called_once_with
(
LOG_MESSAGE_DELETE
,
{
'image_names'
:
get_profile_image_names
(
self
.
user
.
username
)
.
values
(),
'user_id'
:
self
.
user
.
id
}
)
def
test_remove_other
(
self
):
def
test_remove_other
(
self
,
mock_log
):
"""
Test that an authenticated user cannot POST to remove another user's
profile images.
...
...
@@ -273,8 +292,9 @@ class ProfileImageRemoveTestCase(ProfileImageEndpointTestCase):
self
.
check_response
(
response
,
404
)
self
.
check_images
(
True
)
# thumbnails should remain intact.
self
.
check_has_profile_image
(
True
)
self
.
assertFalse
(
mock_log
.
info
.
called
)
def
test_remove_staff
(
self
):
def
test_remove_staff
(
self
,
mock_log
):
"""
Test that an authenticated staff user can POST to remove another user's
profile images.
...
...
@@ -286,9 +306,13 @@ class ProfileImageRemoveTestCase(ProfileImageEndpointTestCase):
self
.
check_response
(
response
,
204
)
self
.
check_images
(
False
)
self
.
check_has_profile_image
(
False
)
mock_log
.
info
.
assert_called_once_with
(
LOG_MESSAGE_DELETE
,
{
'image_names'
:
get_profile_image_names
(
self
.
user
.
username
)
.
values
(),
'user_id'
:
self
.
user
.
id
}
)
@patch
(
'student.models.UserProfile.save'
)
def
test_remove_failure
(
self
,
user_profile_save
):
def
test_remove_failure
(
self
,
user_profile_save
,
mock_log
):
"""
Test that when upload validation fails, the proper HTTP response and
messages are returned.
...
...
@@ -302,3 +326,4 @@ class ProfileImageRemoveTestCase(ProfileImageEndpointTestCase):
)
self
.
check_images
(
True
)
# thumbnails should remain intact.
self
.
check_has_profile_image
(
True
)
self
.
assertFalse
(
mock_log
.
info
.
called
)
openedx/core/djangoapps/profile_images/views.py
View file @
44c78c60
...
...
@@ -2,6 +2,7 @@
This module implements the upload and remove endpoints of the profile image api.
"""
from
contextlib
import
closing
import
logging
from
django.utils.translation
import
ugettext
as
_
from
rest_framework
import
permissions
,
status
...
...
@@ -18,6 +19,11 @@ from openedx.core.lib.api.permissions import IsUserInUrl, IsUserInUrlOrStaff
from
openedx.core.djangoapps.user_api.accounts.image_helpers
import
set_has_profile_image
,
get_profile_image_names
from
.images
import
validate_uploaded_image
,
create_profile_images
,
remove_profile_images
,
ImageValidationError
log
=
logging
.
getLogger
(
__name__
)
LOG_MESSAGE_CREATE
=
'Generated and uploaded images
%(image_names)
s for user
%(user_id)
s'
LOG_MESSAGE_DELETE
=
'Deleted images
%(image_names)
s for user
%(user_id)
s'
class
ProfileImageUploadView
(
APIView
):
"""
...
...
@@ -82,10 +88,16 @@ class ProfileImageUploadView(APIView):
)
# generate profile pic and thumbnails and store them
create_profile_images
(
uploaded_file
,
get_profile_image_names
(
username
))
profile_image_names
=
get_profile_image_names
(
username
)
create_profile_images
(
uploaded_file
,
profile_image_names
)
# update the user account to reflect that a profile image is available.
set_has_profile_image
(
username
,
True
)
log
.
info
(
LOG_MESSAGE_CREATE
,
{
'image_names'
:
profile_image_names
.
values
(),
'user_id'
:
request
.
user
.
id
}
)
except
Exception
as
error
:
return
Response
(
{
...
...
@@ -135,7 +147,13 @@ class ProfileImageRemoveView(APIView):
set_has_profile_image
(
username
,
False
)
# remove physical files from storage.
remove_profile_images
(
get_profile_image_names
(
username
))
profile_image_names
=
get_profile_image_names
(
username
)
remove_profile_images
(
profile_image_names
)
log
.
info
(
LOG_MESSAGE_DELETE
,
{
'image_names'
:
profile_image_names
.
values
(),
'user_id'
:
request
.
user
.
id
}
)
except
UserNotFound
:
return
Response
(
status
=
status
.
HTTP_404_NOT_FOUND
)
except
Exception
as
error
:
...
...
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