Skip to content

Commit 08ecbb8

Browse files
authored
Merge pull request #1998 from rtibbles/superuser_or_superluser
Remove DeviceOwner and implement superuser flags for FacilityUsers
2 parents c5ac39f + 7d25ccb commit 08ecbb8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+815
-649
lines changed

CHANGELOG.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Changes are ordered reverse-chronologically.
1010

1111
- Add support for RTL languages
1212
- Add support for frontend translation outside of Vue components
13+
- Delete DeviceOwner model, and replace with a superuser flag on FacilityUsers
1314

1415

1516
0.5
@@ -39,16 +40,16 @@ Changes are ordered reverse-chronologically.
3940

4041

4142
0.4.2
42-
-----
43+
-----
4344

44-
- Fixes for morango database migrations
45+
- Fixes for morango database migrations
4546

4647

4748
0.4.1
4849
-----
4950

50-
- Makes usernames for login case insensitive #1733
51-
- Fixes various issues with exercise rendering #1757
51+
- Makes usernames for login case insensitive #1733
52+
- Fixes various issues with exercise rendering #1757
5253
- Removes wrong CLI usage instructions #1742
5354

5455

kolibri/auth/api.py

Lines changed: 25 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@
99

1010
from .constants import collection_kinds
1111
from .filters import HierarchyRelationsFilter
12-
from .models import Classroom, DeviceOwner, Facility, FacilityDataset, FacilityUser, LearnerGroup, Membership, Role
12+
from .models import Classroom, Facility, FacilityDataset, FacilityUser, LearnerGroup, Membership, Role
1313
from .serializers import (
14-
ClassroomSerializer, DeviceOwnerSerializer, FacilityDatasetSerializer, FacilitySerializer, FacilityUsernameSerializer, FacilityUserSerializer,
15-
LearnerGroupSerializer, MembershipSerializer, RoleSerializer
14+
ClassroomSerializer, FacilityDatasetSerializer, FacilitySerializer, FacilityUsernameSerializer, FacilityUserSerializer, LearnerGroupSerializer,
15+
MembershipSerializer, RoleSerializer
1616
)
1717

1818

@@ -111,13 +111,6 @@ class FacilityUsernameViewSet(viewsets.ReadOnlyModelViewSet):
111111
search_fields = ('^username', )
112112

113113

114-
class DeviceOwnerViewSet(viewsets.ModelViewSet):
115-
permission_classes = (KolibriAuthPermissions,)
116-
filter_backends = (KolibriAuthPermissionsFilter,)
117-
queryset = DeviceOwner.objects.all()
118-
serializer_class = DeviceOwnerSerializer
119-
120-
121114
class MembershipViewSet(viewsets.ModelViewSet):
122115
permission_classes = (KolibriAuthPermissions,)
123116
filter_backends = (KolibriAuthPermissionsFilter, filters.DjangoFilterBackend)
@@ -143,9 +136,7 @@ class FacilityViewSet(viewsets.ModelViewSet):
143136
class CurrentFacilityViewSet(viewsets.ViewSet):
144137
def list(self, request):
145138
logged_in_user = get_user(request)
146-
if type(logged_in_user) is DeviceOwner:
147-
return Response(Facility.objects.all().values_list('id', flat=True))
148-
elif type(logged_in_user) is AnonymousUser:
139+
if type(logged_in_user) is AnonymousUser:
149140
return Response(Facility.objects.all().values_list('id', flat=True))
150141
else:
151142
return Response([logged_in_user.facility_id])
@@ -206,8 +197,7 @@ def create(self, request):
206197
login(request, user)
207198
# Success!
208199
return Response(self.get_session(request))
209-
elif not password and (FacilityUser.objects.filter(username=username, facility=facility_id).exists() or
210-
DeviceOwner.objects.filter(username=username).exists()):
200+
elif not password and FacilityUser.objects.filter(username=username, facility=facility_id).exists():
211201
# Password was missing, but username is valid, prompt to give password
212202
return Response({
213203
"message": "Please provide password for user",
@@ -238,28 +228,25 @@ def get_session(self, request):
238228
session = {'id': 'current',
239229
'username': user.username,
240230
'full_name': user.full_name,
241-
'user_id': user.id}
242-
if isinstance(user, DeviceOwner):
243-
session.update({'facility_id': getattr(Facility.get_default_facility(), 'id', None),
244-
'kind': ['superuser'],
231+
'user_id': user.id,
232+
'can_manage_content': user.can_manage_content}
233+
roles = Role.objects.filter(user_id=user.id)
234+
if len(roles) is not 0 or user.is_superuser:
235+
session.update({'facility_id': user.facility_id,
236+
'kind': [],
245237
'error': '200'})
246-
return session
238+
if user.is_superuser:
239+
session['kind'].append('superuser')
240+
for role in roles:
241+
if role.kind == 'admin':
242+
session['kind'].append('admin')
243+
else:
244+
session['kind'].append('coach')
247245
else:
248-
roles = Role.objects.filter(user_id=user.id)
249-
if len(roles) is not 0:
250-
session.update({'facility_id': user.facility_id,
251-
'kind': [],
252-
'error': '200'})
253-
for role in roles:
254-
if role.kind == 'admin':
255-
session['kind'].append('admin')
256-
else:
257-
session['kind'].append('coach')
258-
else:
259-
session.update({'facility_id': user.facility_id,
260-
'kind': ['learner'],
261-
'error': '200'})
262-
263-
UserSessionLog.update_log(user)
264-
265-
return session
246+
session.update({'facility_id': user.facility_id,
247+
'kind': ['learner'],
248+
'error': '200'})
249+
250+
UserSessionLog.update_log(user)
251+
252+
return session

kolibri/auth/api_urls.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
from rest_framework import routers
22

33
from .api import (
4-
ClassroomViewSet, CurrentFacilityViewSet, DeviceOwnerViewSet, FacilityDatasetViewSet, FacilityUsernameViewSet, FacilityUserViewSet, FacilityViewSet,
5-
LearnerGroupViewSet, MembershipViewSet, RoleViewSet, SessionViewSet, SignUpViewSet
4+
ClassroomViewSet, CurrentFacilityViewSet, FacilityDatasetViewSet, FacilityUsernameViewSet, FacilityUserViewSet, FacilityViewSet, LearnerGroupViewSet,
5+
MembershipViewSet, RoleViewSet, SessionViewSet, SignUpViewSet
66
)
77

88
router = routers.SimpleRouter()
99

1010
router.register(r'facilitydataset', FacilityDatasetViewSet, base_name='facilitydataset')
1111
router.register(r'facilityuser', FacilityUserViewSet, base_name='facilityuser')
1212
router.register(r'facilityusername', FacilityUsernameViewSet, base_name='facilityusername')
13-
router.register(r'deviceowner', DeviceOwnerViewSet, base_name='deviceowner')
1413
router.register(r'membership', MembershipViewSet, base_name='membership')
1514
router.register(r'role', RoleViewSet, base_name='role')
1615
router.register(r'facility', FacilityViewSet, base_name='facility')

kolibri/auth/backends.py

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
"""
2-
Implements custom auth backends as described in the Django docs, for our custom user classes -- FacilityUser and
3-
DeviceOwner. The appropriate classes should be listed in the AUTHENTICATION_BACKENDS. Note that authentication
2+
Implements custom auth backends as described in the Django docs, for our custom user class -- FacilityUser.
3+
The appropriate classes should be listed in the AUTHENTICATION_BACKENDS. Note that authentication
44
backends are checked in the order they're listed.
55
"""
66

7-
from kolibri.auth.models import DeviceOwner, FacilityUser
7+
from kolibri.auth.models import FacilityUser
88

99

1010
class FacilityUserBackend(object):
@@ -44,38 +44,3 @@ def get_user(self, user_id):
4444
return FacilityUser.objects.get(pk=user_id)
4545
except FacilityUser.DoesNotExist:
4646
return None
47-
48-
49-
class DeviceOwnerBackend(object):
50-
"""
51-
A class that implements authentication for DeviceOwners.
52-
"""
53-
54-
def authenticate(self, username=None, password=None, **kwargs):
55-
"""
56-
Authenticates the user if the credentials correspond to a DeviceOwner.
57-
58-
:param username: a string
59-
:param password: a string
60-
:return: A DeviceOwner instance if successful, or None if authentication failed.
61-
"""
62-
try:
63-
user = DeviceOwner.objects.get(username=username)
64-
if user.check_password(password):
65-
return user
66-
else:
67-
return None
68-
except DeviceOwner.DoesNotExist:
69-
return None
70-
71-
def get_user(self, user_id):
72-
"""
73-
Gets a user. Auth backends are required to implement this.
74-
75-
:param user_id: A BaseUser pk
76-
:return: A DeviceOwner instance if a BaseUser with that pk is found, else None.
77-
"""
78-
try:
79-
return DeviceOwner.objects.get(pk=user_id)
80-
except DeviceOwner.DoesNotExist:
81-
return None
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# -*- coding: utf-8 -*-
2+
# Generated by Django 1.9.7 on 2017-08-16 23:07
3+
from __future__ import unicode_literals
4+
5+
import django.core.validators
6+
from django.db import migrations, models
7+
8+
9+
def device_owner_to_super_user(apps, schema_editor):
10+
DeviceOwner = apps.get_model('kolibriauth', 'DeviceOwner')
11+
FacilityUser = apps.get_model('kolibriauth', 'FacilityUser')
12+
Facility = apps.get_model('kolibriauth', 'Facility')
13+
default_facility = Facility.objects.all().first()
14+
DevicePermissions = apps.get_model('device', 'DevicePermissions')
15+
DeviceSettings = apps.get_model('device', 'DeviceSettings')
16+
# Can't do much if no facilities exist, as no facility to FK the users onto
17+
if default_facility:
18+
for device_owner in DeviceOwner.objects.all():
19+
superuser = FacilityUser.objects.create(
20+
username=device_owner.username,
21+
password=device_owner.password,
22+
facility=default_facility,
23+
full_name=device_owner.full_name,
24+
date_joined=device_owner.date_joined,
25+
)
26+
DevicePermissions.objects.create(user=superuser, is_superuser=True)
27+
# Finally, set the is_provisioned flag
28+
settings, created = DeviceSettings.get_or_create(is_provisioned=True)
29+
30+
31+
class Migration(migrations.Migration):
32+
33+
dependencies = [
34+
('kolibriauth', '0003_auto_20170621_0958'),
35+
('device', '0001_initial')
36+
]
37+
38+
operations = [
39+
migrations.RunPython(device_owner_to_super_user, migrations.RunPython.noop),
40+
migrations.DeleteModel(
41+
name='DeviceOwner',
42+
),
43+
]

0 commit comments

Comments
 (0)