skillbox/server/users/models.py

235 lines
8.5 KiB
Python

from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractUser, Permission
from django.contrib.contenttypes.models import ContentType
from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
DEFAULT_SCHOOL_ID = 1
class User(AbstractUser):
def get_school_permissions(self, school):
perms = set()
for role in SchoolRole.objects.get_school_roles_for_user(self):
perms = perms.union(
('{}.{}'.format(r.content_type.app_label, r.codename) for r in role.role_permission.all())
)
return perms
def get_all_permissions(self, obj=None):
"""
works as long as we have only a single school
:param obj:
:return: django permissions and school permissions for single default school
"""
django_permissions = super().get_all_permissions(obj)
return django_permissions.union(self.get_school_permissions(School.objects.get(pk=DEFAULT_SCHOOL_ID)))
def has_perm(self, perm, obj=None):
return super(User, self).has_perm(perm, obj) or perm in self.get_all_permissions(obj)
class School(models.Model):
name = models.CharField(_(u'Name'), max_length=100, null=False, blank=False)
@classmethod
def create_school(cls, name, id=None):
school = School(name=name, id=id)
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 SchoolClass(models.Model):
name = models.CharField(max_length=100, blank=False, null=False)
year = models.PositiveIntegerField(blank=False, null=False, validators=[MinValueValidator(1900), MaxValueValidator(2200)])
is_deleted = models.BooleanField(blank=False, null=False, default=False)
users = models.ManyToManyField(get_user_model(), related_name='school_classes')
school = models.ForeignKey('School', null=False, on_delete=models.CASCADE)
def __str__(self):
return 'SchoolClass {}-{}-{}'.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_manage_school_class_content, = self._create_default_permissions()
if key == "teacher":
role.role_permission.add(can_manage_school_class_content.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_manage_school_class_content = Permission.objects.get(content_type=content_type, codename='can_manage_school_class_content')
return can_manage_school_class_content,
class SchoolRole(models.Model):
key = models.CharField(_('Key'), max_length=100, blank=False, null=False)
name = models.CharField(_('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_manage_school_class_content', 'Can manage contents for assigned school clases'),
# ("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 SchoolClass.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)