diff --git a/umiss_project/db.sqlite3 b/umiss_project/db.sqlite3 new file mode 100644 index 0000000..a5ab0fa Binary files /dev/null and b/umiss_project/db.sqlite3 differ diff --git a/umiss_project/umiss_auth/migrations/0005_auto_20170515_2101.py b/umiss_project/umiss_auth/migrations/0005_auto_20170515_2101.py new file mode 100644 index 0000000..9eee1af --- /dev/null +++ b/umiss_project/umiss_auth/migrations/0005_auto_20170515_2101.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.2 on 2017-05-15 21:01 +from __future__ import unicode_literals + +from django.conf import settings +import django.contrib.auth.models +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('umiss_auth', '0004_auto_20170422_2244'), + ] + + operations = [ + migrations.CreateModel( + name='MonitorUser', + fields=[ + ('customuser_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)), + ('android_token', models.CharField(max_length=512)), + ], + options={ + 'abstract': False, + 'verbose_name_plural': 'users', + 'verbose_name': 'user', + }, + bases=('umiss_auth.customuser',), + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.CreateModel( + name='PatientUser', + fields=[ + ('customuser_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + 'verbose_name_plural': 'users', + 'verbose_name': 'user', + }, + bases=('umiss_auth.customuser',), + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.RemoveField( + model_name='customuser', + name='monitor_users', + ), + migrations.RemoveField( + model_name='customuser', + name='user_type', + ), + migrations.AddField( + model_name='patientuser', + name='monitor_users', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='monitors', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/umiss_project/umiss_auth/models.py b/umiss_project/umiss_auth/models.py index fd2bc53..4324620 100644 --- a/umiss_project/umiss_auth/models.py +++ b/umiss_project/umiss_auth/models.py @@ -4,34 +4,37 @@ class CustomUser(AbstractUser): - type_choices = ( - ('patient', 'User Type Pacient'), - ('monitor', 'User Type Monitor'), + token = models.CharField( + max_length=512, + editable=False, + null=False ) - user_type = models.CharField( - max_length=2, - choices=type_choices, - default='monitor' - ) + def save(self, *args, **kwargs): + self.token = hashlib.sha512( + self.token.encode('utf-8') + ).hexdigest() + + super(CustomUser, self).save(*args, **kwargs) - token = models.CharField(max_length=512, editable=False) +class PatientUser(CustomUser): monitor_users = models.ForeignKey( 'umiss_auth.CustomUser', related_name='monitors', on_delete=models.SET_NULL, null=True, - limit_choices_to=models.Q(user_type='monitor') ) - def save(self, *args, **kwargs): - self.token = hashlib.sha512( - self.token.encode('utf-8') - ).hexdigest() - - super(CustomUser, self).save(*args, **kwargs) def get_monitor_tokens(self): - tokens = [monitor.token for monitor in self.monitors.all()] - return tokens + return [monitor.token for monitor in self.monitors.all()] + + +class MonitorUser(CustomUser): + android_token = models.CharField( + max_length=512, + editable=True, + null=False, + blank=False + ) diff --git a/umiss_project/umiss_auth/permissions.py b/umiss_project/umiss_auth/permissions.py new file mode 100644 index 0000000..368ab68 --- /dev/null +++ b/umiss_project/umiss_auth/permissions.py @@ -0,0 +1,34 @@ +from rest_framework import permissions + +class IsAnonCreate(permissions.BasePermission): + def has_permission(self, request, view): + print("ho") + if request.method == "POST" and not request.user.is_authenticated(): + return True + elif not request.user.is_authenticated() and request.method != "POST": + return False + elif request.method in permissions.SAFE_METHODS: + return True + + return False + + def has_object_permission(self, request, view, obj): + if not request.user.is_authenticated(): + return False + if request.method in permissions.SAFE_METHODS: + return True + + return obj.username == request.user.username + +class IsOwnerOrReadOnly(permissions.BasePermission): + """ + Custom permission to only allow owners of an object to edit it. + """ + + def has_object_permission(self, request, view, obj): + # Read permissions are allowed to any request + if request.method in permissions.SAFE_METHODS: + return True + + # Write permissions are only allowed to the owner of the snippet + return obj.owner == request.user diff --git a/umiss_project/umiss_auth/serializers.py b/umiss_project/umiss_auth/serializers.py index 80a217c..5fe506d 100644 --- a/umiss_project/umiss_auth/serializers.py +++ b/umiss_project/umiss_auth/serializers.py @@ -1,10 +1,28 @@ from rest_framework import serializers from body_sign.models import HeartBeats, BodySignal -from .models import CustomUser +from .models import CustomUser, MonitorUser, PatientUser class UserSerializer(serializers.HyperlinkedModelSerializer): - class Meta: model = CustomUser fields = ('url', 'username') + + +class MonitorUserSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = MonitorUser + fields = ('url', 'username', 'password') + + def create(self, validated_data): + user = MonitorUser.objects.create_user(**validated_data) + return user + +class PatientUserSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = PatientUser + fields = ('url', 'username', 'password') + + def create(self, validated_data): + user = PatientUser.objects.create_user(**validated_data) + return user diff --git a/umiss_project/umiss_auth/validators.py b/umiss_project/umiss_auth/validators.py new file mode 100644 index 0000000..a2e10af --- /dev/null +++ b/umiss_project/umiss_auth/validators.py @@ -0,0 +1,20 @@ +from django.core.exceptions import ValidationError +from django.utils.translation import ugettext_lazy as _ +from umiss_auth.models import CustomUser +import hashlib + + +def validate_token(token): + patients = CustomUser.objects.filter(user_type='patient') + patient_tokens = [user.token for user in patients] + hash_token = hashlib.sha512( + self.token.encode('utf-8') + ).hexdigest() + + if hash_token not in patient_tokens: + raise ValidationError( + _("The monitor must have a token from a patient." + + " The token %(token) is wrong"), + params={'token': token}, + + ) diff --git a/umiss_project/umiss_auth/views.py b/umiss_project/umiss_auth/views.py index a783a5d..995298c 100644 --- a/umiss_project/umiss_auth/views.py +++ b/umiss_project/umiss_auth/views.py @@ -1,12 +1,29 @@ from django.shortcuts import render from .models import CustomUser -from .serializers import UserSerializer +from .serializers import UserSerializer, MonitorUserSerializer, PatientUserSerializer +from .models import MonitorUser, PatientUser from rest_framework import viewsets from rest_framework import permissions +from .permissions import IsAnonCreate -class UserViewSet(viewsets.ModelViewSet): +class UserViewSet(viewsets.ReadOnlyModelViewSet): queryset = CustomUser.objects.all() serializer_class = UserSerializer + write_only_fields = ('password',) - permission_classes = (permissions.AllowAny, permissions.BasePermission) + permission_classes = (IsAnonCreate,) + +class MonitorViewSet(viewsets.ModelViewSet): + queryset = MonitorUser.objects.all() + serializer_class = MonitorUserSerializer + write_only_fields = ('password') + + permission_classes = (IsAnonCreate,) + +class PatienteViewSet(viewsets.ModelViewSet): + queryset = PatientUser.objects.all() + serializer_class = PatientUserSerializer + write_only_fields = ('password',) + + permission_classes = (IsAnonCreate,) diff --git a/umiss_project/umiss_project/urls.py b/umiss_project/umiss_project/urls.py index a77da8d..3f90204 100644 --- a/umiss_project/umiss_project/urls.py +++ b/umiss_project/umiss_project/urls.py @@ -15,7 +15,7 @@ """ from django.conf.urls import url, include from body_sign import views -from umiss_auth.views import UserViewSet +from umiss_auth.views import UserViewSet, MonitorViewSet, PatienteViewSet from rest_framework.routers import DefaultRouter from rest_framework.authtoken.views import obtain_auth_token @@ -24,6 +24,8 @@ router.register(r'galvanic_resistances', views.GalvanicResistanceViewSet) router.register(r'skin_temperatures', views.SkinTemperatureViewSet) router.register(r'users', UserViewSet) +router.register(r'monitors', MonitorViewSet) +router.register(r'patients', PatienteViewSet) # The API URLs are now determined automatically by the router. # Additionally, we include the login URLs for the browsable API.