Commit 6c0af6ad authored by freetux's avatar freetux

add custom user model, user permissions, doctors now can add drugs and rxs and...

add custom user model, user permissions, doctors now can add drugs and rxs and patients can retrive own rxs
parent 13cdff99
from django.contrib import admin
from weights.models import Weight
from body.models import Weight
class WeightAdmin(admin.ModelAdmin):
......
......@@ -3,5 +3,5 @@ from __future__ import unicode_literals
from django.apps import AppConfig
class WeightsConfig(AppConfig):
name = 'weights'
class BodyConfig(AppConfig):
name = 'body'
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2018-05-11 22:19
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('body', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Drug',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('name', models.CharField(max_length=255)),
('description', models.CharField(max_length=255)),
],
),
migrations.CreateModel(
name='Rx',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date Created')),
('drugs', models.ManyToManyField(related_name='rxs', to='body.Drug')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Rx',
'verbose_name_plural': 'Rxs',
},
),
]
from __future__ import unicode_literals
from django.conf import settings
from rest_framework.authtoken.models import Token
#from rest_framework.authtoken.models import Token
from django.db import models
from django.utils.encoding import smart_text as smart_unicode
from django.utils.translation import ugettext_lazy as _
......@@ -21,8 +21,33 @@ class Weight(models.Model):
def __unicode__(self):
return smart_unicode(self.text)
# def bmi(self):
# return self.weight / (self.height/100) ** 2
class Drug(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255)
description = models.CharField(max_length=255)
class Rx(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
drugs = models.ManyToManyField(Drug, related_name="rxs")
date_created = models.DateTimeField(_("Date Created"), auto_now_add=True)
class Meta:
verbose_name = _("Rx")
verbose_name_plural = _("Rxs")
def __unicode__(self):
return "{}-{}-{}-{}".format(self.id, self.user, self.date_created, self.drugs)
# def bmi(self):
# return self.weight / (self.height/100) ** 2
#TODO:add BMI calculator
#TODO:add BMR calculator
......
from rest_framework import permissions
class UserIsOwnerWeight(permissions.BasePermission):
def has_object_permission(self, request, view, weight):
return request.user.id == weight.user.id
class IsOwnerOrAdmin(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method in permissions.SAFE_METHODS:
return True
return obj.owner == request.user or request.user.is_admin
\ No newline at end of file
from django.contrib.auth.models import User
from rest_framework import serializers
from weights.models import Weight
from body.models import Weight, Drug, Rx
......@@ -17,4 +17,15 @@ class WeightSerializer(serializers.ModelSerializer):
class Meta:
model = Weight
fields = ("id", "user", "text", "weight", "height", "date_created")
\ No newline at end of file
class DrugSerializer(serializers.ModelSerializer):
class Meta:
model = Drug
fields = ("id", "name", "description")
class RxSerializer(serializers.ModelSerializer):
user = WeightUserSerializer(read_only=True)
class Meta:
model = Rx
fields = ("id", "user", "drugs", "date_created")
\ No newline at end of file
......@@ -4,8 +4,8 @@ from django.core.urlresolvers import reverse
from rest_framework.authtoken.models import Token
from rest_framework.test import APITestCase
from weights.models import Weight
from weights.serializers import WeightSerializer
from body.models import Weight
from body.serializers import WeightSerializer
class WeightListCreateAPIViewTestCase(APITestCase):
......
from django.conf.urls import url
from body.views import WeightListCreateAPIView, WeightDetailAPIView, DrugListCreateAPIView, RxListCreateAPIView, RxDetailAPIView, DrugDetailAPIView
urlpatterns = [
url(r'^weight/$', WeightListCreateAPIView.as_view(), name="list"),
url(r'^weight/(?P<pk>[0-9]+)/$', WeightDetailAPIView.as_view(), name="detail"),
url(r'^drug/$', DrugListCreateAPIView.as_view(), name="list"),
url(r'^drug/(?P<pk>[0-9]+)/$', DrugDetailAPIView.as_view(), name="detail"),
url(r'^rx/$', RxListCreateAPIView.as_view(), name="list"),
url(r'^rx/(?P<pk>[0-9]+)/$', RxDetailAPIView.as_view(), name="detail"),
]
\ No newline at end of file
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
from rest_framework.permissions import IsAuthenticated
from weights.models import Weight
from weights.permissions import UserIsOwnerWeight
from weights.serializers import WeightSerializer
from body.models import Weight, Drug, Rx
from body.permissions import UserIsOwnerWeight, IsOwnerOrAdmin
from rest_framework.permissions import IsAdminUser
from body.serializers import WeightSerializer, DrugSerializer, RxSerializer
class WeightListCreateAPIView(ListCreateAPIView):
......@@ -20,6 +21,47 @@ class WeightDetailAPIView(RetrieveUpdateDestroyAPIView):
serializer_class = WeightSerializer
queryset = Weight.objects.all()
permission_classes = (IsAuthenticated, UserIsOwnerWeight)
class DrugListCreateAPIView(ListCreateAPIView):
serializer_class = DrugSerializer
permission_classes = (IsAdminUser,)
def get_queryset(self):
return Drug.objects.all()
def perform_create(self, serializer):
serializer.save()
class DrugDetailAPIView(RetrieveUpdateDestroyAPIView):
serializer_class = DrugSerializer
queryset = Drug.objects.all()
permission_classes = (IsAdminUser)
class RxListCreateAPIView(ListCreateAPIView):
serializer_class = RxSerializer
permission_classes = (IsAdminUser,)
def get_queryset(self):
return Rx.objects.all()
def perform_create(self, serializer):
serializer.save()
class RxDetailAPIView(RetrieveUpdateDestroyAPIView):
serializer_class = RxSerializer
queryset = Rx.objects.all()
permission_classes = (IsOwnerOrAdmin)
class UserRxtDetailAPIView(RetrieveUpdateDestroyAPIView):
serializer_class = RxSerializer
queryset = Rx.objects.all()
permission_classes = (IsAuthenticated, UserIsOwnerWeight)
# def bmi(self, height, weight):
# data = Weight.objects.latest('date_added')
......
......@@ -29,6 +29,8 @@ ALLOWED_HOSTS = []
APPEND_SLASH=False
AUTH_USER_MODEL = 'users.User'
# Application definition
INSTALLED_APPS = [
......@@ -43,7 +45,7 @@ INSTALLED_APPS = [
'rest_framework.authtoken',
'corsheaders',
'users',
'weights',
'body',
'django_nose'
]
......
......@@ -2,7 +2,7 @@ from django.conf.urls import url, include
from django.contrib import admin
api_urls = [
url(r'^weights/', include('weights.urls', namespace='weights')),
url(r'^body/', include('body.urls', namespace='body')),
url(r'^users/', include('users.urls', namespace='users')),
]
......
from django.contrib import admin
from .models import User
# Register your models here.
@admin.register(User)
class UserList(admin.ModelAdmin):
list_display = ('get_full_name','email', 'is_staff')
list_filter = ('is_staff', 'is_superuser', 'is_active', 'groups')
search_fields = ('first_name', 'last_name', 'email')
ordering = ('last_name',)
filter_horizontal = ('groups', 'user_permissions',)
# -*- coding: utf-8 -*-
# Generated by Django 1.9.4 on 2018-05-11 23:04
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0007_alter_validators_add_error_messages'),
]
operations = [
migrations.CreateModel(
name='User',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')),
('email', models.EmailField(max_length=255, unique=True, verbose_name='email_address')),
('photo', models.ImageField(blank=True, null=True, upload_to='images/users/')),
('is_active', models.BooleanField(default=True, help_text='Disable this instead of deleting a user', verbose_name='active')),
('is_staff', models.BooleanField(default=False, help_text='Allow the user access to the admin site', verbose_name='staff status')),
('is_superuser', models.BooleanField(default=False, help_text='User has all permissions', verbose_name='superuser status')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('groups', models.ManyToManyField(blank=True, help_text='Groups a user belongs to and inherits permissions from', to='auth.Group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Permissions for this user', to='auth.Permission', verbose_name='user permissions')),
],
options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
},
),
]
from __future__ import unicode_literals
from django.db import models
from django.core.mail import send_mail
from django.contrib import auth
from django.contrib.auth.models import (
AbstractBaseUser,
BaseUserManager,
Group,
Permission,
_user_get_all_permissions,
_user_has_perm,
_user_has_module_perms,
)
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
class UserManager(BaseUserManager):
def create_user(self, email, password=None, **kw):
"""
Creates a user with a given email address and password
"""
if not email:
raise ValueError('The given email address must be set')
now = timezone.now()
u = self.model(
email=UserManager.normalize_email(email),
last_login=now,
**kw
)
u.set_password(password)
u.save(using=self._db)
return u
def create_superuser(self, email, password, **kw):
"""
Creates a superuser with a given email address and password
"""
u = self.create_user(email, password, **kw)
u.is_staff = True
u.is_active = True
u.is_superuser = True
u.save(using=self._db)
return u
"""
Model for users across the site
"""
class User(AbstractBaseUser):
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
email = models.EmailField(_('email_address'), max_length=255, unique=True)
photo = models.ImageField(upload_to='images/users/', null=True, blank=True)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_('Disable this instead of deleting a user')
)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_('Allow the user access to the admin site')
)
is_superuser = models.BooleanField(
_('superuser status'),
default=False,
help_text=_('User has all permissions')
)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
groups = models.ManyToManyField(
Group,
verbose_name=_('groups'),
blank=True,
help_text=_('Groups a user belongs to and inherits permissions from')
)
user_permissions = models.ManyToManyField(
Permission,
verbose_name=_('user permissions'),
blank=True,
help_text=_('Permissions for this user')
)
objects = UserManager()
USERNAME_FIELD = 'email'
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
def get_full_name(self):
"""
Return the first name and last name
"""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"""
Since the user is identified by their email address return that
"""
if self.first_name :
return self.first_name
else:
return self.email
def get_group_permissions(self, obj=None):
"""
Returns a list of permissions that this user has through their groups
"""
permissions = set()
for backend in auth.get_backends():
if hasattr(backend, 'get_group_permissions'):
if obj is not None:
permissions.update(backend.get_group_permissions(
self, obj
))
else:
permissions.update(backend.get_group_permissions(self))
return permissions
def get_all_permissions(self, obj=None):
return _user_get_all_permissions(self, obj)
def has_perm(self, perm, obj=None):
"""
Returns True if the user has the given permission
"""
if self.is_active and self.is_superuser:
return True
return _user_has_perm(self, perm, obj)
def has_perms(self, perm_list, obj=None):
"""
Returns True if the user has each of the permissions in the give list
"""
for perm in perm_list:
if not self.has_perm(perm, obj):
return False
return True
def has_module_perms(self, app_label):
"""
Returns True if the user has any permissions in the give app label
"""
if self.is_active and self.is_superuser:
return True
return _user_has_module_perms(self, app_label)
# Create your models here.
def email_user(self, subject, message, from_email=None):
"""
Sends an email to the user
"""
send_mail(subject, message, from_email, [self.email])
def __unicode__(self):
return self.get_full_name
\ No newline at end of file
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib.auth import authenticate
from django.contrib.auth.models import User
# from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from rest_framework.authtoken.models import Token
from .models import User
from .validators import validate_username
class UserRegistrationSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('email', 'username', 'password')
extra_kwargs = {'password': {'write_only': True}}
class UserLoginSerializer(serializers.Serializer):
email = serializers.EmailField()
password = serializers.CharField()
def create(self, validated_data):
user = User(
email=validated_data['email'],
username=validated_data['username']
)
user.set_password(validated_data['password'])
user.save()
return user
def validate(self, attrs):
user = authenticate(username=attrs['email'], password=attrs['password'])
if not user:
raise serializers.ValidationError('Incorrect email or password.')
class UserLoginSerializer(serializers.Serializer):
username = serializers.CharField(required=True)
password = serializers.CharField(required=True)
if not user.is_active:
raise serializers.ValidationError('User is disabled.')
default_error_messages = {
'inactive_account': _('User account is disabled.'),
'invalid_credentials': _('Unable to login with provided credentials.')
}
return {'user': user}
def __init__(self, *args, **kwargs):
super(UserLoginSerializer, self).__init__(*args, **kwargs)
self.user = None
def validate(self, attrs):
self.user = authenticate(username=attrs.get("username"), password=attrs.get('password'))
if self.user:
if not self.user.is_active:
raise serializers.ValidationError(self.error_messages['inactive_account'])
return attrs
else:
raise serializers.ValidationError(self.error_messages['invalid_credentials'])
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = (
'id',
'last_login',
'email',
'first_name',
'last_name',
'is_active',
'date_joined',
'password'
)
read_only_fields = ('last_login', 'is_active', 'date_joined')
extra_kwargs = {
'password': {'required': True, 'write_only': True},
'first_name': {'required': True},
'last_name': {'required': True}
}
@staticmethod
def validate_email(value):
return validate_username(value)
def create(self, validated_data):
return User.objects.create_user(
validated_data.pop('email'),
validated_data.pop('password'),
**validated_data
)
from django.core.exceptions import ValidationError
from .models import User
def validate_username(username):
if User.objects.filter(**{'{}__iexact'.format(User.USERNAME_FIELD): username}).exists():