blob: 4ee567d76a42a7994684f4761f7c9354ead3aa58 [file] [log] [blame]
Mitja Nikolaus6a679132018-08-30 14:35:29 +02001"""Authorization permission classes for accessing the API."""
Mitja Nikolause1389bd2018-08-30 17:09:04 +02002import logging
Mitja Nikolaus6a679132018-08-30 14:35:29 +02003
Mitja Nikolausff2d1802018-09-13 11:15:18 +02004from django.core.exceptions import ObjectDoesNotExist
Dirk Vogtc9e10ab2016-10-12 13:58:15 +02005from rest_framework.permissions import BasePermission
Mitja Nikolausbcaf5022018-08-30 16:40:38 +02006from crashreports.models import Device
Mitja Nikolaus78e3a052018-09-05 12:18:35 +02007from hiccup.allauth_adapters import FP_STAFF_GROUP_NAME
Dirk Vogtc9e10ab2016-10-12 13:58:15 +02008
9
Dirk Vogt7160b5e2016-10-12 17:04:40 +020010def user_owns_uuid(user, uuid):
Mitja Nikolaus6a679132018-08-30 14:35:29 +020011 """Determine whether a user is owning the device with the given UUID.
12
13 Args:
14 user: The user making the request.
15 uuid: The UUID of the device to be manipulated.
16
17 Returns: True if the user owns the device.
18
19 """
Dirk Vogt7160b5e2016-10-12 17:04:40 +020020 try:
21 device = Device.objects.get(user=user)
Mitja Nikolausff2d1802018-09-13 11:15:18 +020022 except (ObjectDoesNotExist, TypeError):
23 # If the device does not exist or type of the given user is not
24 # correct, False is returned.
25 return False
Mitja Nikolause1389bd2018-08-30 17:09:04 +020026 except Exception as exception: # pylint: disable=broad-except
Mitja Nikolausff2d1802018-09-13 11:15:18 +020027 # All other exceptions are logged and False is returned.
Mitja Nikolause1389bd2018-08-30 17:09:04 +020028 logging.exception(exception)
Dirk Vogt7160b5e2016-10-12 17:04:40 +020029 return False
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020030 if uuid == device.uuid:
Dirk Vogt7160b5e2016-10-12 17:04:40 +020031 return True
32 return False
33
34
35def user_is_hiccup_staff(user):
Mitja Nikolaus6a679132018-08-30 14:35:29 +020036 """Determine whether a user is part of the Hiccup staff.
37
38 Returns true if either the user is part of the group
39 "FairphoneSoftwareTeam", or he/she has all permissions for manipulating
40 crashreports, heartbeats and logfiles.
41
42 Args:
43 user: The user making the request.
44
45 Returns: True if user is part of the Hiccup staff.
46
47 """
Mitja Nikolaus78e3a052018-09-05 12:18:35 +020048 if user.groups.filter(name=FP_STAFF_GROUP_NAME).exists():
Borjan Tchakalofffa134bd2018-04-09 16:16:11 +020049 return True
Mitja Nikolausb4e3bec2018-08-30 17:16:21 +020050 return user.has_perms(
51 [
52 # Crashreports
53 "crashreports.add_crashreport",
54 "crashreports.change_crashreport",
55 "crashreports.del_crashreport",
56 # Heartbeats
57 "heartbeat.add_crashreport",
58 "heartbeat.change_crashreport",
59 "heartbeat.del_crashreport",
60 # Logfiles
61 "heartbeat.add_logfile",
62 "heartbeat.change_logfile",
63 "heartbeat.del_logfile",
64 ]
65 )
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020066
Dirk Vogt7160b5e2016-10-12 17:04:40 +020067
Borjan Tchakalofffa134bd2018-04-09 16:16:11 +020068class HasStatsAccess(BasePermission):
Mitja Nikolaus6a679132018-08-30 14:35:29 +020069 """Authorization requires to be part of the Hiccup staff."""
70
Borjan Tchakalofffa134bd2018-04-09 16:16:11 +020071 def has_permission(self, request, view):
Mitja Nikolaus6a679132018-08-30 14:35:29 +020072 """Check if user is part of the Hiccup staff."""
Borjan Tchakalofffa134bd2018-04-09 16:16:11 +020073 return user_is_hiccup_staff(request.user)
Dirk Vogt7160b5e2016-10-12 17:04:40 +020074
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020075
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020076class HasRightsOrIsDeviceOwnerDeviceCreation(BasePermission):
Mitja Nikolaus6a679132018-08-30 14:35:29 +020077 """Authorization requires to be part of Hiccup staff or device owner."""
78
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020079 def has_permission(self, request, view):
Mitja Nikolaus6a679132018-08-30 14:35:29 +020080 """Return true if user is part of Hiccp staff or device owner."""
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020081 if user_is_hiccup_staff(request.user):
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020082 return True
Dirk Vogt57a615d2017-05-04 22:29:54 +020083
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020084 # special case:
85 # user is the owner of a device. in this case creations are allowed.
86 # we have to check if the device with the supplied uuid indeed
87 # belongs to the user
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020088 if request.method == "POST":
89 if "uuid" not in request.data:
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020090 return False
Dirk Vogt7160b5e2016-10-12 17:04:40 +020091 return user_owns_uuid(request.user, request.data["uuid"])
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020092 return False
Mitja Nikolaus4d759da2018-08-28 15:31:29 +020093
94
95# Security requirements for swagger documentation
96SWAGGER_SECURITY_REQUIREMENTS_OAUTH = [{"Google OAuth": []}]
Mitja Nikolaus78e3a052018-09-05 12:18:35 +020097SWAGGER_SECURITY_REQUIREMENTS_DEVICE_TOKEN = [
98 {"Device token authentication": []}
99]
Mitja Nikolaus4d759da2018-08-28 15:31:29 +0200100SWAGGER_SECURITY_REQUIREMENTS_ALL = (
101 SWAGGER_SECURITY_REQUIREMENTS_OAUTH
102 + SWAGGER_SECURITY_REQUIREMENTS_DEVICE_TOKEN
103)