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
e5a025df
Commit
e5a025df
authored
Jul 28, 2014
by
Zia Fazal
Committed by
Jonathan Piacenti
Aug 20, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added has_organizations filter to users api
parent
f384d6e3
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
69 additions
and
4 deletions
+69
-4
lms/djangoapps/api_manager/permissions.py
+20
-0
lms/djangoapps/api_manager/users/serializers.py
+1
-1
lms/djangoapps/api_manager/users/tests.py
+38
-0
lms/djangoapps/api_manager/users/views.py
+10
-3
No files found.
lms/djangoapps/api_manager/permissions.py
View file @
e5a025df
...
@@ -7,6 +7,8 @@ from api_manager.utils import get_client_ip_address, address_exists_in_network
...
@@ -7,6 +7,8 @@ from api_manager.utils import get_client_ip_address, address_exists_in_network
from
rest_framework
import
permissions
,
generics
,
filters
,
pagination
,
serializers
from
rest_framework
import
permissions
,
generics
,
filters
,
pagination
,
serializers
from
rest_framework.views
import
APIView
from
rest_framework.views
import
APIView
from
api_manager.utils
import
str2bool
from
api_manager.models
import
APIUser
as
User
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -97,6 +99,24 @@ class IdsInFilterBackend(filters.BaseFilterBackend):
...
@@ -97,6 +99,24 @@ class IdsInFilterBackend(filters.BaseFilterBackend):
return
queryset
return
queryset
class
HasOrgsFilterBackend
(
filters
.
BaseFilterBackend
):
"""
This backend support filtering users with and organization association or not
"""
def
filter_queryset
(
self
,
request
,
queryset
,
view
):
"""
Parse querystring base on has_organizations query param
"""
has_orgs
=
request
.
QUERY_PARAMS
.
get
(
'has_organizations'
,
None
)
if
has_orgs
:
if
str2bool
(
has_orgs
):
queryset
=
queryset
.
filter
(
organizations__id__gt
=
0
)
else
:
queryset
=
queryset
.
exclude
(
id__in
=
User
.
objects
.
filter
(
organizations__id__gt
=
0
)
.
values_list
(
'id'
,
flat
=
True
))
return
queryset
.
distinct
()
class
CustomPaginationSerializer
(
pagination
.
PaginationSerializer
):
class
CustomPaginationSerializer
(
pagination
.
PaginationSerializer
):
"""
"""
Custom PaginationSerializer to include num_pages field
Custom PaginationSerializer to include num_pages field
...
...
lms/djangoapps/api_manager/users/serializers.py
View file @
e5a025df
...
@@ -13,7 +13,7 @@ class UserSerializer(serializers.ModelSerializer):
...
@@ -13,7 +13,7 @@ class UserSerializer(serializers.ModelSerializer):
class
Meta
:
class
Meta
:
""" Serializer/field specification """
""" Serializer/field specification """
model
=
APIUser
model
=
APIUser
fields
=
(
"id"
,
"email"
,
"username"
,
"first_name"
,
"last_name"
,
"created"
,
"organizations"
)
fields
=
(
"id"
,
"email"
,
"username"
,
"first_name"
,
"last_name"
,
"created"
,
"
is_active"
,
"
organizations"
)
read_only_fields
=
(
"id"
,
"email"
,
"username"
)
read_only_fields
=
(
"id"
,
"email"
,
"username"
)
...
...
lms/djangoapps/api_manager/users/tests.py
View file @
e5a025df
...
@@ -197,6 +197,44 @@ class UsersApiTests(ModuleStoreTestCase):
...
@@ -197,6 +197,44 @@ class UsersApiTests(ModuleStoreTestCase):
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
len
(
response
.
data
[
'results'
]),
0
)
self
.
assertEqual
(
len
(
response
.
data
[
'results'
]),
0
)
def
test_user_list_get_with_org_filter
(
self
):
test_uri
=
'/api/users'
users
=
[]
# create a 7 new users
for
i
in
xrange
(
1
,
8
):
data
=
{
'email'
:
'test{}@example.com'
.
format
(
i
),
'username'
:
'test_user{}'
.
format
(
i
),
'password'
:
'test_pass'
,
'first_name'
:
'John{}'
.
format
(
i
),
'last_name'
:
'Doe{}'
.
format
(
i
)
}
response
=
self
.
do_post
(
test_uri
,
data
)
self
.
assertEqual
(
response
.
status_code
,
201
)
users
.
append
(
response
.
data
[
'id'
])
# create organizations and add users to them
total_orgs
=
4
for
i
in
xrange
(
1
,
total_orgs
):
data
=
{
'name'
:
'{} {}'
.
format
(
'Org'
,
i
),
'display_name'
:
'{} {}'
.
format
(
'Org display name'
,
i
),
'users'
:
users
[:
i
]
}
response
=
self
.
do_post
(
self
.
org_base_uri
,
data
)
self
.
assertEqual
(
response
.
status_code
,
201
)
# fetch users without any organization association
response
=
self
.
do_get
(
'{}?has_organizations=true'
.
format
(
test_uri
))
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
len
(
response
.
data
[
'results'
]),
3
)
self
.
assertIsNotNone
(
response
.
data
[
'results'
][
0
][
'is_active'
])
response
=
self
.
do_get
(
'{}?has_organizations=false'
.
format
(
test_uri
))
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertGreaterEqual
(
len
(
response
.
data
[
'results'
]),
4
)
def
test_user_list_post
(
self
):
def
test_user_list_post
(
self
):
test_uri
=
'/api/users'
test_uri
=
'/api/users'
local_username
=
self
.
test_username
+
str
(
randint
(
11
,
99
))
local_username
=
self
.
test_username
+
str
(
randint
(
11
,
99
))
...
...
lms/djangoapps/api_manager/users/views.py
View file @
e5a025df
...
@@ -12,11 +12,12 @@ from django.conf import settings
...
@@ -12,11 +12,12 @@ from django.conf import settings
from
django.http
import
Http404
from
django.http
import
Http404
from
django.utils.translation
import
get_language
,
ugettext_lazy
as
_
from
django.utils.translation
import
get_language
,
ugettext_lazy
as
_
from
rest_framework
import
status
from
rest_framework
import
status
from
rest_framework
import
filters
from
rest_framework.response
import
Response
from
rest_framework.response
import
Response
from
api_manager.courseware_access
import
get_course
,
get_course_child
,
get_course_total_score
from
api_manager.courseware_access
import
get_course
,
get_course_child
,
get_course_total_score
from
api_manager.permissions
import
SecureAPIView
,
SecureListAPIView
from
api_manager.permissions
import
SecureAPIView
,
SecureListAPIView
,
IdsInFilterBackend
,
HasOrgsFilterBackend
from
api_manager.models
import
GroupProfile
,
APIUser
as
User
from
api_manager.models
import
GroupProfile
,
APIUser
as
User
from
api_manager.organizations.serializers
import
OrganizationSerializer
from
api_manager.organizations.serializers
import
OrganizationSerializer
from
api_manager.courses.serializers
import
CourseModuleCompletionSerializer
from
api_manager.courses.serializers
import
CourseModuleCompletionSerializer
...
@@ -102,7 +103,7 @@ class UsersList(SecureListAPIView):
...
@@ -102,7 +103,7 @@ class UsersList(SecureListAPIView):
"""
"""
### The UsersList view allows clients to retrieve/append a list of User entities
### The UsersList view allows clients to retrieve/append a list of User entities
- URI: ```/api/users/```
- URI: ```/api/users/```
- GET: Provides paginated list of users, it supports email, username and id filters
- GET: Provides paginated list of users, it supports email, username
, has_organizations
and id filters
Possible use cases
Possible use cases
GET /api/users?ids=23
GET /api/users?ids=23
GET /api/users?ids=11,12,13&page=2
GET /api/users?ids=11,12,13&page=2
...
@@ -110,6 +111,10 @@ class UsersList(SecureListAPIView):
...
@@ -110,6 +111,10 @@ class UsersList(SecureListAPIView):
GET /api/users?username={john}
GET /api/users?username={john}
* email: string, filters user set by email address
* email: string, filters user set by email address
* username: string, filters user set by username
* username: string, filters user set by username
GET /api/users?has_organizations={true}
* has_organizations: boolean, filters user set with organization association
GET /api/users?has_organizations={false}
* has_organizations: boolean, filters user set with no organization association
Example JSON output {'count': '25', 'next': 'https://testserver/api/users?page=2', num_pages='3',
Example JSON output {'count': '25', 'next': 'https://testserver/api/users?page=2', num_pages='3',
'previous': None, 'results':[]}
'previous': None, 'results':[]}
...
@@ -155,6 +160,7 @@ class UsersList(SecureListAPIView):
...
@@ -155,6 +160,7 @@ class UsersList(SecureListAPIView):
"""
"""
queryset
=
User
.
objects
.
all
()
queryset
=
User
.
objects
.
all
()
serializer_class
=
UserSerializer
serializer_class
=
UserSerializer
filter_backends
=
(
filters
.
DjangoFilterBackend
,
IdsInFilterBackend
,
HasOrgsFilterBackend
)
filter_fields
=
(
'email'
,
'username'
,
)
filter_fields
=
(
'email'
,
'username'
,
)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
...
@@ -164,7 +170,8 @@ class UsersList(SecureListAPIView):
...
@@ -164,7 +170,8 @@ class UsersList(SecureListAPIView):
email
=
request
.
QUERY_PARAMS
.
get
(
'email'
,
None
)
email
=
request
.
QUERY_PARAMS
.
get
(
'email'
,
None
)
username
=
request
.
QUERY_PARAMS
.
get
(
'username'
,
None
)
username
=
request
.
QUERY_PARAMS
.
get
(
'username'
,
None
)
ids
=
request
.
QUERY_PARAMS
.
get
(
'ids'
,
None
)
ids
=
request
.
QUERY_PARAMS
.
get
(
'ids'
,
None
)
if
email
or
username
or
ids
:
has_orgs
=
request
.
QUERY_PARAMS
.
get
(
'has_organizations'
,
None
)
if
email
or
username
or
ids
or
has_orgs
:
return
self
.
list
(
request
,
*
args
,
**
kwargs
)
return
self
.
list
(
request
,
*
args
,
**
kwargs
)
else
:
else
:
return
Response
({
'message'
:
_
(
'Unfiltered request is not allowed.'
)},
status
=
status
.
HTTP_400_BAD_REQUEST
)
return
Response
({
'message'
:
_
(
'Unfiltered request is not allowed.'
)},
status
=
status
.
HTTP_400_BAD_REQUEST
)
...
...
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