Commit 0dec660c authored by Lincoln Smith's avatar Lincoln Smith
Browse files

Merge branch 'custom_user_model' into 'master'

Custom user model

See merge request !15
parents 68ecd261 caa01b9e
# from functools import update_wrapper
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User as UserModel
from django.contrib.contenttypes.admin import GenericTabularInline
from django.contrib.contenttypes.models import ContentType
from django.forms import Textarea
......@@ -428,10 +426,3 @@ admin.site.register(models.CourseRelatedRoleTitle, CIMSBaseModelAdmin)
admin.site.register(models.CourseRelatedRole, CIMSBaseModelAdmin)
admin.site.register(models.ReviewStatus, CIMSBaseModelAdmin)
admin.site.register(models.Annotation, admin.ModelAdmin)
admin.site.unregister(UserModel)
@admin.register(UserModel)
class CIMSUserAdmin(CIMSBaseModelAdmin, UserAdmin):
pass
from django.contrib import admin
#from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
#from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth.models import Group
from cims.auth import models
from cims.admin import CIMSBaseModelAdmin
from cims.auth.models import Role
from cims.auth.models import User as CIMSUser
#class CIMSUserCreationForm(UserCreationForm):
#
# class Meta(UserCreationForm.Meta):
# model = models.User
# fields = UserCreationForm.Meta.fields
#
#
#class CIMSUserChangeForm(UserChangeForm):
#
# class Meta(UserChangeForm.Meta):
# model = models.User
# fields = UserChangeForm.Meta.fields
class CIMSUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = CIMSUser
fields = UserCreationForm.Meta.fields
#admin.site.unregister(User)
#@admin.register(models.User)
#class UserAdmin(BaseUserAdmin):
# form = CIMSUserChangeForm
# add_form = CIMSUserCreationForm
class CIMSUserChangeForm(UserChangeForm):
class Meta(UserChangeForm.Meta):
model = CIMSUser
fields = UserChangeForm.Meta.fields
@admin.register(models.Role)
class RoleAdmin(admin.ModelAdmin):
@admin.register(CIMSUser)
class UserAdmin(BaseUserAdmin, CIMSBaseModelAdmin):
form = CIMSUserChangeForm
add_form = CIMSUserCreationForm
@admin.register(Role)
class RoleAdmin(CIMSBaseModelAdmin):
filter_horizontal = ('permissions', 'child_roles')
admin.site.unregister(Group)
# -*- coding: utf-8 -*-
# Generated by Django 1.10.5 on 2017-03-23 01:21
# Generated by Django 1.11.1 on 2017-06-07 01:57
from __future__ import unicode_literals
from django.conf import settings
import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
......@@ -12,12 +15,37 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0008_alter_user_username_max_length'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contenttypes', '0002_remove_content_type_name'),
('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')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('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(blank=True, max_length=254, verbose_name='email address')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('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,
'verbose_name': 'user',
'verbose_name_plural': 'users',
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
migrations.CreateModel(
name='Role',
fields=[
......
from django.conf import settings
from django.db import models
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.contrib.auth.models import Permission, AbstractUser
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
class User(AbstractUser):
"""Custom user model."""
pass
class RoleManager(models.Manager):
"""
The manager for the Role model.
......@@ -21,7 +26,7 @@ class RoleManager(models.Manager):
number of DB queries equal to the diameter of the resulting graph, caches
the results in a flat list as well as a list of sets, in order of
increasing distance from the user.
Currently the query doesn't prune already visited nodes, relying on set
operations to avoid duplication. Pruning could be done but would require
more bookkeeping in the loop.
......@@ -33,7 +38,7 @@ class RoleManager(models.Manager):
roles_hierarchy = []
roles = self.filter(users=user_obj)
unvisited = set(roles)
# Breadth first search of Role graph.
# Breadth first search of Role graph.
while unvisited:
roles_hierarchy.append(unvisited.difference(visited))
visited.update(roles_hierarchy[-1])
......@@ -73,7 +78,8 @@ class Role(models.Model):
verbose_name=_('permissions'),
blank=True,
)
child_roles = models.ManyToManyField('self',
child_roles = models.ManyToManyField(
'self',
symmetrical=False,
blank=True,
help_text=_(
......@@ -82,14 +88,14 @@ class Role(models.Model):
),
related_name='parent_roles',
)
class Meta:
verbose_name = _('role')
verbose_name_plural = _('roles')
def __str__(self):
return self.name
def natural_key(self):
return (self.name,)
......@@ -103,7 +109,7 @@ class Role(models.Model):
unvisited = set(roles)
while unvisited:
while unvisited:
#Add the users from each role to our set
# Add the users from each role to our set
role = unvisited.pop()
users.update(set(role.users.all()))
roles = Role.objects.filter(
......@@ -119,20 +125,6 @@ class Role(models.Model):
return self._roles_all_users
#class User(AbstractUser):
# """Custom user model."""
# roles = models.ManyToManyField(
# Role,
# blank=True,
# help_text=_(
# 'The Roles this user has direct membership in. A user gets '
# 'all permissions granted to and inherited by its roles.'
# ),
# related_name='user_set',
# related_query_name='user',
# )
#
# Below largely cut'n'paste from Django Guardian, modified to suit our
# purposes.
class BaseObjectPermission(models.Model):
......@@ -148,10 +140,10 @@ class BaseObjectPermission(models.Model):
def save(self, *args, **kwargs):
if self.content_type != self.permission.content_type:
raise ValidationError("Cannot persist permission not designed for "
"this class (permission's type is {} and object's type is "
"{})".format(self.permission.content_type, self.content_type)
)
raise ValidationError("Cannot persist permission not designed for this class "
"(permission's type is {} and object's type is "
"{})".format(self.permission.content_type, self.content_type)
)
return super().save(*args, **kwargs)
......@@ -183,7 +175,7 @@ class RoleObjectPermission(BaseObjectPermission):
unique_together = ['role', 'permission', 'content_type', 'object_id']
#setattr(Group, 'add_obj_perm',
# setattr(Group, 'add_obj_perm',
# lambda self, perm, obj: GroupObjectPermission.objects.assign_perm(perm, self, obj))
#setattr(Group, 'del_obj_perm',
# setattr(Group, 'del_obj_perm',
# lambda self, perm, obj: GroupObjectPermission.objects.remove_perm(perm, self, obj))
This diff is collapsed.
# -*- coding: utf-8 -*-
# Generated by Django 1.10.6 on 2017-04-11 05:02
from __future__ import unicode_literals
import cims.fields
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('cims', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='role',
name='courseinstance',
),
migrations.RemoveField(
model_name='role',
name='role_title',
),
migrations.RemoveField(
model_name='role',
name='user',
),
migrations.AddField(
model_name='college',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='college',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.AddField(
model_name='course',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='course',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.AddField(
model_name='courseinstance',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='courseinstance',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.AddField(
model_name='courseversion',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='courseversion',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.AddField(
model_name='deliverymode',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='deliverymode',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.AddField(
model_name='indicativeassessment',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='indicativeassessment',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.AddField(
model_name='learningoutcome',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='learningoutcome',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.AddField(
model_name='schedule',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='schedule',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.AddField(
model_name='school',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='school',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.AddField(
model_name='standardobjective',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='standardobjective',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.AddField(
model_name='standardsbody',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='standardsbody',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.AddField(
model_name='standardsframework',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='standardsframework',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.AddField(
model_name='task',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='task',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.AddField(
model_name='teachingsession',
name='created',
field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='created'),
),
migrations.AddField(
model_name='teachingsession',
name='last_modified',
field=cims.fields.AutoLastModifiedField(default=django.utils.timezone.now, editable=False, verbose_name='last modified'),
),
migrations.DeleteModel(
name='Role',
),
migrations.DeleteModel(
name='Roles',
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.10.6 on 2017-04-28 01:28
from __future__ import unicode_literals
import cims.fields
import django.core.validators
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('cims', '0002_auto_20170411_0502'),
]
operations = [
migrations.AlterField(
model_name='college',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
migrations.AlterField(
model_name='course',
name='code',
field=models.CharField(help_text='course code of format AAAA#### e.g. COMP1100.', max_length=8, unique=True, verbose_name='course code'),
),
migrations.AlterField(
model_name='course',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
migrations.AlterField(
model_name='courseinstance',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
migrations.AlterField(
model_name='courseversion',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
migrations.AlterField(
model_name='deliverymode',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
migrations.AlterField(
model_name='indicativeassessment',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
migrations.AlterField(
model_name='indicativeassessment',
name='indicative_percentage',
field=models.IntegerField(blank=True, default=0, validators=[django.core.validators.MaxValueValidator(100), django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='learningoutcome',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
migrations.AlterField(
model_name='schedule',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
migrations.AlterField(
model_name='school',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
migrations.AlterField(
model_name='standardobjective',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
migrations.AlterField(
model_name='standardsbody',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
migrations.AlterField(
model_name='standardsframework',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
migrations.AlterField(
model_name='task',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
migrations.AlterField(
model_name='teachingsession',
name='created',
field=cims.fields.AutoCreatedField(default=django.utils.timezone.now, editable=False, null=True, verbose_name='created'),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.10.6 on 2017-04-28 04:56
from __future__ import unicode_literals
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('cims', '0003_auto_20170428_0128'),
]
operations = [
migrations.AlterField(
model_name='task',
name='weighting',
field=models.IntegerField(blank=True, default=0, help_text='Fraction of final mark this task comprises.', validators=[django.core.validators.MaxValueValidator(100), django.core.validators.MinValueValidator(0)]),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.10.6 on 2017-05-03 02:48
from __future__ import unicode_literals
from django.db import migrations
import django.db.models.deletion
import mptt.fields
class Migration(migrations.Migration):
dependencies = [
('cims', '0004_auto_20170428_0456'),
]
operations = [
migrations.AlterField(
model_name='standardobjective',
name='parent',
field=mptt.fields.TreeForeignKey(blank=True, help_text='If the objectives in a framework are organised in a tree, use this field to associate this objective with its parent.', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='cims.StandardObjective'),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11.1 on 2017-05-25 04:08
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('cims', '0005_auto_20170503_1248'),
]
operations = [
migrations.RenameField(
model_name='task',
old_name='url',
new_name='task_url',
),
]