aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitch Riedstra <Mitch@riedstra.us>2017-11-02 16:03:14 -0400
committerMitch Riedstra <Mitch@riedstra.us>2017-11-02 16:03:14 -0400
commite16fa08b915562c6ab77ce7bb79a9d766b5a4036 (patch)
tree2f7d518131600f2db7bc3ac0545f11f2571c2aee
parente4d865b1a61f6a72551e70abad78c6c35b9345e7 (diff)
downloaddispatch-tracker-e16fa08b915562c6ab77ce7bb79a9d766b5a4036.tar.gz
dispatch-tracker-e16fa08b915562c6ab77ce7bb79a9d766b5a4036.tar.xz
Initial setup to use a custom User model, I still need to figure out how to use the built in Django permissions though
-rw-r--r--app/app/settings.py4
-rw-r--r--app/dispatch/migrations/0001_initial.py14
-rw-r--r--app/dispatch/migrations/0002_auto_20171024_2255.py27
-rw-r--r--app/dispatch/migrations/0002_auto_20171102_1949.py65
-rw-r--r--app/dispatch/models.py13
-rw-r--r--app/dispatch/monkey_patch.py5
-rw-r--r--app/dispatch/views.py4
-rw-r--r--app/dispatchAuth/__init__.py0
-rw-r--r--app/dispatchAuth/admin.py90
-rw-r--r--app/dispatchAuth/apps.py5
-rw-r--r--app/dispatchAuth/migrations/0001_initial.py35
-rw-r--r--app/dispatchAuth/migrations/__init__.py0
-rw-r--r--app/dispatchAuth/models.py69
-rw-r--r--app/dispatchAuth/tests.py3
-rw-r--r--app/dispatchAuth/views.py3
15 files changed, 289 insertions, 48 deletions
diff --git a/app/app/settings.py b/app/app/settings.py
index f143931..f24a6b3 100644
--- a/app/app/settings.py
+++ b/app/app/settings.py
@@ -48,6 +48,9 @@ ALLOWED_HOSTS = CONFIG['allowed_hosts']
ADMINS = CONFIG['admins']
+AUTH_USER_MODEL = 'dispatchAuth.User'
+
+
# Application definition
INSTALLED_APPS = [
@@ -58,6 +61,7 @@ INSTALLED_APPS = [
'django.contrib.messages',
'django.contrib.staticfiles',
'dispatch.apps.DispatchConfig',
+ 'dispatchAuth.apps.DispatchauthConfig',
'auditlog',
]
diff --git a/app/dispatch/migrations/0001_initial.py b/app/dispatch/migrations/0001_initial.py
index 05c6c7d..a358b07 100644
--- a/app/dispatch/migrations/0001_initial.py
+++ b/app/dispatch/migrations/0001_initial.py
@@ -1,11 +1,9 @@
# -*- coding: utf-8 -*-
-# Generated by Django 1.11.5 on 2017-10-24 22:53
+# Generated by Django 1.11.5 on 2017-11-02 19:49
from __future__ import unicode_literals
import dispatch.misc
-from django.conf import settings
from django.db import migrations, models
-import django.db.models.deletion
class Migration(migrations.Migration):
@@ -13,7 +11,6 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
@@ -37,7 +34,6 @@ class Migration(migrations.Migration):
('city', models.CharField(max_length=256)),
('state', models.CharField(max_length=256)),
('zip_code', models.CharField(max_length=256)),
- ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, unique=True)),
],
),
migrations.CreateModel(
@@ -48,9 +44,6 @@ class Migration(migrations.Migration):
('invoice_date', models.DateField()),
('due_date', models.DateField()),
('paid', models.BooleanField(default=False)),
- ('bill_to', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bill_to', to='dispatch.Identity')),
- ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='owner', to='dispatch.Identity')),
- ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
@@ -61,7 +54,6 @@ class Migration(migrations.Migration):
('description', models.CharField(max_length=256)),
('quantity', models.IntegerField()),
('amount', models.DecimalField(decimal_places=2, max_digits=19)),
- ('invoice', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dispatch.Invoice')),
],
),
migrations.CreateModel(
@@ -72,8 +64,6 @@ class Migration(migrations.Migration):
('description', models.CharField(max_length=256)),
('delivered_to', models.CharField(default='', max_length=256)),
('amount', models.DecimalField(decimal_places=2, default='0', max_digits=10)),
- ('customer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dispatch.Customer')),
- ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
@@ -82,7 +72,6 @@ class Migration(migrations.Migration):
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('description', models.CharField(max_length=256)),
('document', models.FileField(upload_to=dispatch.misc.paperwork_user_directory_path)),
- ('load', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dispatch.Load')),
],
),
migrations.CreateModel(
@@ -98,7 +87,6 @@ class Migration(migrations.Migration):
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('number', models.IntegerField(default=1200)),
- ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, unique=True)),
],
),
]
diff --git a/app/dispatch/migrations/0002_auto_20171024_2255.py b/app/dispatch/migrations/0002_auto_20171024_2255.py
deleted file mode 100644
index bbf96d4..0000000
--- a/app/dispatch/migrations/0002_auto_20171024_2255.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# -*- coding: utf-8 -*-
-# Generated by Django 1.11.5 on 2017-10-24 22:55
-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 = [
- ('dispatch', '0001_initial'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='identity',
- name='user',
- field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
- ),
- migrations.AlterField(
- model_name='userinvoicenumber',
- name='user',
- field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
- ),
- ]
diff --git a/app/dispatch/migrations/0002_auto_20171102_1949.py b/app/dispatch/migrations/0002_auto_20171102_1949.py
new file mode 100644
index 0000000..4be45e9
--- /dev/null
+++ b/app/dispatch/migrations/0002_auto_20171102_1949.py
@@ -0,0 +1,65 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2017-11-02 19:49
+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):
+
+ initial = True
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ('dispatch', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='userinvoicenumber',
+ name='user',
+ field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AddField(
+ model_name='paperwork',
+ name='load',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dispatch.Load'),
+ ),
+ migrations.AddField(
+ model_name='load',
+ name='customer',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dispatch.Customer'),
+ ),
+ migrations.AddField(
+ model_name='load',
+ name='user',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AddField(
+ model_name='invoiceitem',
+ name='invoice',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dispatch.Invoice'),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='bill_to',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bill_to', to='dispatch.Identity'),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='owner',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='owner', to='dispatch.Identity'),
+ ),
+ migrations.AddField(
+ model_name='invoice',
+ name='user',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.AddField(
+ model_name='identity',
+ name='user',
+ field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
+ ),
+ ]
diff --git a/app/dispatch/models.py b/app/dispatch/models.py
index 21c06e0..fe0cdb3 100644
--- a/app/dispatch/models.py
+++ b/app/dispatch/models.py
@@ -2,15 +2,16 @@ from django.db import models
from django.conf import settings
from auditlog.registry import auditlog
from auditlog.models import AuditlogHistoryField
-from django.contrib.auth.models import User
+# from django.contrib.auth import get_user_model
from datetime import datetime
from django.core.exceptions import ObjectDoesNotExist
from .misc import get_week_dates, paperwork_user_directory_path
-
-from . import monkey_patch
+from django.core.urlresolvers import reverse
# Create your models here.
+
+
class Customer(models.Model):
history = AuditlogHistoryField()
name = models.CharField(max_length=256)
@@ -50,7 +51,7 @@ class Paperwork(models.Model):
class Identity(models.Model):
- user = models.OneToOneField(User, on_delete=models.CASCADE)
+ user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=256)
address = models.CharField(max_length=256)
city = models.CharField(max_length=256)
@@ -81,14 +82,14 @@ class Settings(models.Model):
class UserInvoiceNumber(models.Model):
- user = models.OneToOneField(User, on_delete=models.CASCADE)
+ user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
number = models.IntegerField(default=1200)
def get_absolute_url(self):
return '/drivers/view/{:d}'.format(self.user.pk)
class Invoice(models.Model):
- user = models.ForeignKey(User, on_delete=models.CASCADE)
+ user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
owner = models.ForeignKey(Identity, on_delete=models.CASCADE, related_name="owner")
bill_to = models.ForeignKey(Identity, on_delete=models.CASCADE, related_name="bill_to")
invoice_id = models.IntegerField()
diff --git a/app/dispatch/monkey_patch.py b/app/dispatch/monkey_patch.py
index 3b87287..cc61b6e 100644
--- a/app/dispatch/monkey_patch.py
+++ b/app/dispatch/monkey_patch.py
@@ -1,6 +1,9 @@
-from django.contrib.auth.models import User
+from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse
+# This should be going away soon with the addition
+# of my custom user model
+
def get_absolute_url(self):
return reverse('driver_details', kwargs={'pk': self.pk})
diff --git a/app/dispatch/views.py b/app/dispatch/views.py
index 918cf0d..5a94775 100644
--- a/app/dispatch/views.py
+++ b/app/dispatch/views.py
@@ -15,7 +15,7 @@ from django.core.urlresolvers import reverse_lazy
from dispatch.models import Customer, Load, Paperwork, \
Invoice, UserInvoiceNumber, Identity
from dispatch.forms import AddPaperworkForm
-from django.contrib.auth.models import User
+from django.contrib.auth import get_user_model
from django.contrib.auth.mixins import UserPassesTestMixin
# from django.http import HttpResponseRedirect
from .misc import get_week_dates, split_loads_by_day
@@ -23,6 +23,8 @@ import datetime
import re
import os
+User = get_user_model()
+
def home(request):
return redirect(reverse('load_list'))
diff --git a/app/dispatchAuth/__init__.py b/app/dispatchAuth/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/dispatchAuth/__init__.py
diff --git a/app/dispatchAuth/admin.py b/app/dispatchAuth/admin.py
new file mode 100644
index 0000000..67b1170
--- /dev/null
+++ b/app/dispatchAuth/admin.py
@@ -0,0 +1,90 @@
+from django import forms
+from django.contrib import admin
+from django.contrib.auth.models import Group
+from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
+from django.contrib.auth.forms import ReadOnlyPasswordHashField
+
+# Register your models here.
+
+
+from .models import User
+
+class UserCreationForm(forms.ModelForm):
+ """A form for creating new users. Includes all the required
+ fields, plus a repeated password."""
+ password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
+ password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
+
+ class Meta:
+ model = User
+ fields = ('email', 'first_name', 'last_name')
+
+ def clean_password2(self):
+ # Check that the two password entries match
+ password1 = self.cleaned_data.get("password1")
+ password2 = self.cleaned_data.get("password2")
+ if password1 and password2 and password1 != password2:
+ raise forms.ValidationError("Passwords don't match")
+ return password2
+
+ def save(self, commit=True):
+ # Save the provided password in hashed format
+ user = super(UserCreationForm, self).save(commit=False)
+ user.set_password(self.cleaned_data["password1"])
+ if commit:
+ user.save()
+ return user
+
+
+class UserChangeForm(forms.ModelForm):
+ """A form for updating users. Includes all the fields on
+ the user, but replaces the password field with admin's
+ password hash display field.
+ """
+ password = ReadOnlyPasswordHashField()
+
+ class Meta:
+ model = User
+ fields = ('email', 'password', 'first_name', 'last_name', 'is_active',
+ 'is_superuser')
+
+ def clean_password(self):
+ # Regardless of what the user provides, return the initial value.
+ # This is done here, rather than on the field, because the
+ # field does not have access to the initial value
+ return self.initial["password"]
+
+
+class UserAdmin(BaseUserAdmin):
+ # The forms to add and change user instances
+ form = UserChangeForm
+ add_form = UserCreationForm
+
+ # The fields to be used in displaying the User model.
+ # These override the definitions on the base UserAdmin
+ # that reference specific fields on auth.User.
+ list_display = ('email', 'is_superuser')
+ list_filter = ('is_superuser',)
+ fieldsets = (
+ (None, {'fields': ('email', 'password')}),
+ ('Personal info', {'fields': ('first_name','last_name')}),
+ ('Permissions', {'fields': ('is_superuser',)}),
+ )
+ # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin
+ # overrides get_fieldsets to use this attribute when creating a user.
+ add_fieldsets = (
+ (None, {
+ 'classes': ('wide',),
+ 'fields': ('email', 'first_name', 'last_name', 'password1', 'password2')}
+ ),
+ )
+ search_fields = ('email',)
+ ordering = ('email',)
+ filter_horizontal = ()
+
+# Now register the new UserAdmin...
+admin.site.register(User, UserAdmin)
+
+# ... and, since we're not using Django's built-in permissions,
+# unregister the Group model from admin.
+# admin.site.unregister(Group)
diff --git a/app/dispatchAuth/apps.py b/app/dispatchAuth/apps.py
new file mode 100644
index 0000000..ba984ef
--- /dev/null
+++ b/app/dispatchAuth/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class DispatchauthConfig(AppConfig):
+ name = 'dispatchAuth'
diff --git a/app/dispatchAuth/migrations/0001_initial.py b/app/dispatchAuth/migrations/0001_initial.py
new file mode 100644
index 0000000..4a0f37c
--- /dev/null
+++ b/app/dispatchAuth/migrations/0001_initial.py
@@ -0,0 +1,35 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2017-11-02 19:51
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ('auth', '0008_alter_user_username_max_length'),
+ ]
+
+ 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')),
+ ('email', models.EmailField(max_length=256, unique=True)),
+ ('first_name', models.CharField(max_length=256)),
+ ('last_name', models.CharField(max_length=256)),
+ ('is_active', models.BooleanField(default=True)),
+ ('is_superuser', models.BooleanField(default=False)),
+ ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
+ ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
+ ],
+ options={
+ 'abstract': False,
+ },
+ ),
+ ]
diff --git a/app/dispatchAuth/migrations/__init__.py b/app/dispatchAuth/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/dispatchAuth/migrations/__init__.py
diff --git a/app/dispatchAuth/models.py b/app/dispatchAuth/models.py
new file mode 100644
index 0000000..6c90dd0
--- /dev/null
+++ b/app/dispatchAuth/models.py
@@ -0,0 +1,69 @@
+from django.contrib.auth.models import AbstractUser, AbstractBaseUser, PermissionsMixin, BaseUserManager
+from django.db import models
+
+# Create your models here.
+
+
+class UserManager(BaseUserManager):
+ def create_user(self, email, first_name, last_name, password=None):
+ """
+ Creates and saves a User with the given email, first name,
+ last name and password.
+ """
+ if not email:
+ raise ValueError('Users must have an email address')
+
+ user = self.model(
+ email=self.normalize_email(email),
+ first_name=first_name,
+ last_name=last_name,
+ )
+
+ user.set_password(password)
+ user.save(using=self._db)
+ return user
+
+ def create_superuser(self, email, first_name, last_name, password):
+ """
+ Creates and saves a superuser with the given email, first name,
+ last name and password.
+ """
+ user = self.create_user(
+ email=email,
+ first_name=first_name,
+ last_name=last_name,
+ password=password,
+ )
+ user.is_superuser = True
+ user.save(using=self._db)
+ return user
+
+
+class User(PermissionsMixin, AbstractBaseUser):
+ email = models.EmailField(max_length=256, unique=True)
+ first_name = models.CharField(max_length=256)
+ last_name = models.CharField(max_length=256)
+ is_active = models.BooleanField(default=True)
+ is_superuser = models.BooleanField(default=False)
+
+ USERNAME_FIELD = 'email'
+ EMAIL_FIELD = 'email'
+ REQUIRED_FIELDS = ['first_name', 'last_name']
+
+ objects = UserManager()
+
+ def get_full_name(self):
+ return "{} {}".format(self.first_name, self.last_name)
+
+ def get_short_name(self):
+ return self.first_name
+
+ def get_absolute_url(self):
+ return reverse('driver_details', kwargs={'pk': self.pk})
+
+ def __str__(self):
+ return self.email
+
+ @property
+ def is_staff(self):
+ return self.is_superuser
diff --git a/app/dispatchAuth/tests.py b/app/dispatchAuth/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/app/dispatchAuth/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/app/dispatchAuth/views.py b/app/dispatchAuth/views.py
new file mode 100644
index 0000000..91ea44a
--- /dev/null
+++ b/app/dispatchAuth/views.py
@@ -0,0 +1,3 @@
+from django.shortcuts import render
+
+# Create your views here.