Added SchoolRole models from Helloclass

This commit is contained in:
Daniel Egger 2018-10-04 16:00:21 +02:00
parent ba18946736
commit 6a57b35251
8 changed files with 330 additions and 10 deletions

View File

@ -12,6 +12,7 @@ from wagtail.core.models import Page
from books.factories import BookFactory, TopicFactory, ModuleFactory, ChapterFactory, ContentBlockFactory from books.factories import BookFactory, TopicFactory, ModuleFactory, ChapterFactory, ContentBlockFactory
from core.factories import UserFactory from core.factories import UserFactory
from objectives.factories import ObjectiveGroupFactory, ObjectiveFactory from objectives.factories import ObjectiveGroupFactory, ObjectiveFactory
from user.services import create_school_with_users
data = [ data = [
{ {
@ -695,8 +696,7 @@ class Command(BaseCommand):
is_superuser=True is_superuser=True
) )
for i in range(0, 4): create_school_with_users('skillbox')
UserFactory(username='user{}'.format(i))
for book_idx, book_data in enumerate(data): for book_idx, book_data in enumerate(data):
book = BookFactory.create(parent=site.root_page, **self.filter_data(book_data, 'topics')) book = BookFactory.create(parent=site.root_page, **self.filter_data(book_data, 'topics'))

View File

@ -10,7 +10,6 @@ from wagtail.core.models import Site
from rooms.factories import RoomFactory, RoomEntryFactory from rooms.factories import RoomFactory, RoomEntryFactory
from rooms.models import Room from rooms.models import Room
from user.factories import UserGroupFactory from user.factories import UserGroupFactory
from user.models import UserGroup
data = [ data = [
{ {
@ -200,17 +199,13 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
Room.objects.all().delete() Room.objects.all().delete()
UserGroup.objects.all().delete()
root_page = Site.objects.get(is_default_site=True).root_page root_page = Site.objects.get(is_default_site=True).root_page
for i in range(0, 6):
UserGroupFactory(users=(random.choices(get_user_model().objects.all(), k=3)))
for room_idx, room_data in enumerate(data): for room_idx, room_data in enumerate(data):
room = RoomFactory.create(**self.filter_data(room_data, ['entries'])) room = RoomFactory.create(**self.filter_data(room_data, ['entries']))
default_room_entries = [{} for i in range(0, random.randint(5, 8))] default_room_entries = [{} for _ in range(0, random.randint(5, 8))]
room_entries = room_data.get('entries', default_room_entries) room_entries = room_data.get('entries', default_room_entries)
for room_entry_idx, room_entry_data in enumerate(room_entries): for room_entry_idx, room_entry_data in enumerate(room_entries):

View File

@ -1,7 +1,7 @@
from django.contrib import admin from django.contrib import admin
from django.contrib.auth.admin import UserAdmin from django.contrib.auth.admin import UserAdmin
from .models import User, UserGroup from .models import User, UserGroup, School, SchoolRole, UserSchoolRole
admin.site.register(User, UserAdmin) admin.site.register(User, UserAdmin)
@ -10,3 +10,25 @@ admin.site.register(User, UserAdmin)
class UserGroupAdmin(admin.ModelAdmin): class UserGroupAdmin(admin.ModelAdmin):
list_display = ('id', 'name', 'year') list_display = ('id', 'name', 'year')
list_filter = ('year',) list_filter = ('year',)
@admin.register(School)
class SchoolAdmin(admin.ModelAdmin):
list_display = ('name',)
list_filter = ('name',)
readonly_fields = []
@admin.register(SchoolRole)
class SchoolRoleAdmin(admin.ModelAdmin):
list_display = ('school', 'name')
list_filter = ('school', 'name')
readonly_fields = ('school', )
@admin.register(UserSchoolRole)
class UserSchoolRoleAdmin(admin.ModelAdmin):
list_display = ('user', 'school_role')
list_filter = ('school_role__school',)
readonly_fields = []
#search_fields = ('user__email', 'user__username')

View File

@ -0,0 +1,53 @@
# Generated by Django 2.0.6 on 2018-10-04 12:46
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import user.models
class Migration(migrations.Migration):
dependencies = [
('auth', '0009_alter_user_last_name_max_length'),
('user', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='School',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, verbose_name='Name')),
('old_id', models.IntegerField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='SchoolRole',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('key', models.CharField(max_length=100, verbose_name='Key')),
('name', models.CharField(max_length=100, verbose_name='Name')),
('role_permission', models.ManyToManyField(blank=True, related_name='role_set', related_query_name='role', to='auth.Permission', verbose_name='Role permission')),
('school', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='user.School')),
],
options={
'permissions': (('can_create_contentblocks', 'Can create new contentblocks'),),
},
managers=[
('objects', user.models.SchoolRoleManager()),
],
),
migrations.CreateModel(
name='UserSchoolRole',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('school_role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='user.SchoolRole')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.AlterUniqueTogether(
name='schoolrole',
unique_together={('key', 'school')},
),
]

View File

@ -0,0 +1,17 @@
# Generated by Django 2.0.6 on 2018-10-04 13:13
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('user', '0002_auto_20181004_1246'),
]
operations = [
migrations.RemoveField(
model_name='school',
name='old_id',
),
]

View File

@ -0,0 +1,20 @@
# Generated by Django 2.0.6 on 2018-10-04 13:47
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('user', '0003_remove_school_old_id'),
]
operations = [
migrations.AddField(
model_name='usergroup',
name='school',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='user.School'),
preserve_default=False,
),
]

View File

@ -1,18 +1,214 @@
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser, Permission
from django.contrib.contenttypes.models import ContentType
from django.core.validators import MinValueValidator, MaxValueValidator from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models from django.db import models
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
class User(AbstractUser): class User(AbstractUser):
pass pass
class School(models.Model):
name = models.CharField(_(u'Name'), max_length=100, null=False, blank=False)
@classmethod
def create_school(cls, name):
school = School(name=name)
school.save()
# Label.create_labels_for_school(school)
SchoolRole.objects.create_default_roles_for_school(school)
return school
def __str__(self):
return self.name
class UserGroup(models.Model): class UserGroup(models.Model):
name = models.CharField(max_length=100, blank=False, null=False) name = models.CharField(max_length=100, blank=False, null=False)
year = models.PositiveIntegerField(blank=False, null=False, validators=[MinValueValidator(1900), MaxValueValidator(2200)]) year = models.PositiveIntegerField(blank=False, null=False, validators=[MinValueValidator(1900), MaxValueValidator(2200)])
is_deleted = models.BooleanField(blank=False, null=False, default=False) is_deleted = models.BooleanField(blank=False, null=False, default=False)
users = models.ManyToManyField(get_user_model()) users = models.ManyToManyField(get_user_model())
school = models.ForeignKey('School', null=False, on_delete=models.CASCADE)
def __str__(self): def __str__(self):
return 'UserGroup {}-{}-{}'.format(self.id, self.name, self.year) return 'UserGroup {}-{}-{}'.format(self.id, self.name, self.year)
class SchoolRoleManager(models.Manager):
use_in_migrations = True
TEACHER_KEY = 'teacher'
STUDENT_KEY = 'student'
PARENT_KEY = 'parent'
SCHOOL_ADMIN_KEY = 'school_admin'
DEFAULT_ROLES = {
TEACHER_KEY: _(u'Lehrperson'),
STUDENT_KEY: _(u'Schüler'),
# PARENT_KEY: _(u'Aufsichtsperson'),
# SCHOOL_ADMIN_KEY: _(u'Schuladministrator')
}
READONLY_ROLES = [SCHOOL_ADMIN_KEY]
DEFAULT_ROLE_KEYS = DEFAULT_ROLES.keys()
def is_key_in_defaults(self, key):
return key in self.DEFAULT_ROLE_KEYS
def is_key_readonly(self, key):
return key in self.READONLY_ROLES
def get_school_roles_for_user(self, hc_user):
return self.model.objects.filter(userschoolrole__user=hc_user)
def create_default_roles_for_school(self, school):
for key, value in self.DEFAULT_ROLES.items():
role = self.create(name=value, school=school, key=key)
role.save()
can_create_contentblocks, = self._create_default_permissions()
if key == "teacher":
role.role_permission.add(can_create_contentblocks.id)
# elif key == "school_admin":
# role.role_permission.add()
#
# elif key == "student":
# role.role_permission.add()
def get_default_admin_role_for_school(self, school):
return self._get_default_role_for_school(school, self.SCHOOL_ADMIN_KEY)
def get_default_teacher_role_for_school(self, school):
return self._get_default_role_for_school(school, self.TEACHER_KEY)
def get_default_student_role_for_school(self, school):
return self._get_default_role_for_school(school, self.STUDENT_KEY)
def get_default_parent_for_school(self, school):
return self._get_default_role_for_school(school, self.PARENT_KEY)
def _get_default_role_for_school(self, school, key):
try:
return self.get(school=school, name=self.DEFAULT_ROLES[key])
except self.model.DoesNotExist:
return None
def _create_default_permissions(self):
content_type = ContentType.objects.get_for_model(self.model)
#edit_events = Permission.objects.get(content_type=content_type, codename="can_edit_events")
#edit_own_comments = Permission.objects.get(content_type=content_type, codename="can_edit_own_comments")
#delete_comments = Permission.objects.get(content_type=content_type, codename="can_delete_comments")
#admin_school = Permission.objects.get(content_type=content_type, codename="can_admin_school")
can_create_contentblocks = Permission.objects.get(content_type=content_type, codename='can_create_contentblocks')
return can_create_contentblocks,
class SchoolRole(models.Model):
key = models.CharField(_('Key'), max_length=100, blank=False, null=False)
name = models.CharField(_(u'Name'), max_length=100, blank=False, null=False)
school = models.ForeignKey('School', blank=False, null=False, on_delete=models.CASCADE)
role_permission = models.ManyToManyField(Permission, verbose_name=_('Role permission'),
blank=True, related_name="role_set", related_query_name="role")
objects = SchoolRoleManager()
def __str__(self):
return u'{} - {}'.format(self.school, self.name)
def permissions_as_code(self):
return self.role_permission.values_list('codename', flat=True)
def has_permission(self, permission_name):
try:
self.role_permission.get(codename=permission_name)
return True
except Permission.DoesNotExist:
return False
@staticmethod
def create_key(name):
return name.lower()
class Meta:
permissions = (
# ("can_edit_events", "Can edit events"),
# ("can_edit_own_comments", "Can edit own comments"),
# ("can_delete_comments", "Can delete comments"),
('can_create_contentblocks', 'Can create new contentblocks'),
# ("can_admin_school", "Can admin school"),
)
unique_together = ('key', 'school',)
class UserSchoolRoleManager(models.Manager):
def create_userrole_for_user_and_school(self, hc_user, school, role_key):
try:
school_role = SchoolRole.objects.get(school=school, key=role_key)
except SchoolRole.DoesNotExist:
return None
return self._create_user_schoolrole(hc_user, school_role)
def create_role_and_userrole_for_user_and_school(self, hc_user, school, role_name):
created = False
role_key = role_name.lower()
try:
school_role = SchoolRole.objects.get(school=school, name=role_name)
except SchoolRole.DoesNotExist:
school_role = SchoolRole(school=school, key=role_key, name=role_name)
school_role.save()
created = True
return self._create_user_schoolrole(hc_user, school_role), created
def _create_user_schoolrole(self, hc_user, school_role):
user_school_role = self.model(user=hc_user, school_role=school_role)
user_school_role.save()
return user_school_role
class UserSchoolRole(models.Model):
user = models.ForeignKey(User, blank=False, null=False, on_delete=models.CASCADE)
school_role = models.ForeignKey(SchoolRole, blank=False, null=False, on_delete=models.CASCADE)
objects = UserSchoolRoleManager()
@property
def groups(self):
return UserGroup.objects.filter(Q(school_id=self.school_role.school.id) & Q(users=self.user.id))
@property
def group_ids(self):
return map(lambda g: g.id, self.groups)
def addgroup(self, group):
group.user_set.add(self.user.user)
self.user.user.groups.add(group)
self.user.user.save()
@classmethod
def get_roles_for_user(cls, user):
roles = UserSchoolRole.objects.filter(user=user)
return roles
# TODO: This method is only valid as long as a user can only belong to one school (today's setup)
@classmethod
def get_role_for_user(cls, user):
roles = UserSchoolRole.get_roles_for_user(user)
if len(roles) > 0:
return roles[0]
else:
return None
def __str__(self):
return '%s: %s' % (self.school_role, self.user)

17
server/user/services.py Normal file
View File

@ -0,0 +1,17 @@
from core.factories import UserFactory
from user.factories import UserGroupFactory
from user.models import School, SchoolRole, UserSchoolRole
def create_school_with_users(school_name):
school = School.create_school(school_name)
teacher_role = SchoolRole.objects.get_default_teacher_role_for_school(school)
teacher = UserFactory(username='teacher')
UserSchoolRole.objects.create(user=teacher, school_role=teacher_role)
student_role = SchoolRole.objects.get_default_student_role_for_school(school)
for i in range(1, 7):
student = UserFactory(username='student{}'.format(i))
UserSchoolRole.objects.create(user=student, school_role=student_role)
UserGroupFactory(users=[teacher, student], school=school)