mirror of
https://github.com/mediacms-io/mediacms.git
synced 2025-11-20 13:36:05 -05:00
feat: RBAC + SAML support
This commit is contained in:
@@ -10,6 +10,9 @@ class MyAccountAdapter(DefaultAccountAdapter):
|
||||
return settings.SSL_FRONTEND_HOST + url
|
||||
|
||||
def clean_email(self, email):
|
||||
if "@" not in email:
|
||||
raise ValidationError("Email is not valid")
|
||||
|
||||
if hasattr(settings, "ALLOWED_DOMAINS_FOR_USER_REGISTRATION") and settings.ALLOWED_DOMAINS_FOR_USER_REGISTRATION:
|
||||
if email.split("@")[1] not in settings.ALLOWED_DOMAINS_FOR_USER_REGISTRATION:
|
||||
raise ValidationError("Domain is not in the permitted list")
|
||||
|
||||
@@ -44,6 +44,9 @@ class UserForm(forms.ModelForm):
|
||||
self.fields.pop("advancedUser")
|
||||
self.fields.pop("is_manager")
|
||||
self.fields.pop("is_editor")
|
||||
if user.socialaccount_set.exists():
|
||||
# for Social Accounts do not allow to edit the name
|
||||
self.fields["name"].widget.attrs['readonly'] = True
|
||||
|
||||
|
||||
class ChannelForm(forms.ModelForm):
|
||||
|
||||
@@ -12,6 +12,7 @@ from imagekit.processors import ResizeToFill
|
||||
|
||||
import files.helpers as helpers
|
||||
from files.models import Category, Media, Tag
|
||||
from rbac.models import RBACGroup
|
||||
|
||||
|
||||
class User(AbstractUser):
|
||||
@@ -45,6 +46,9 @@ class User(AbstractUser):
|
||||
ordering = ["-date_added", "name"]
|
||||
indexes = [models.Index(fields=["-date_added", "name"])]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.name} - {self.email}"
|
||||
|
||||
def update_user_media(self):
|
||||
self.media_count = Media.objects.filter(listable=True, user=self).count()
|
||||
self.save(update_fields=["media_count"])
|
||||
@@ -110,6 +114,73 @@ class User(AbstractUser):
|
||||
setattr(self, item, strip_tags(getattr(self, item, None)))
|
||||
super(User, self).save(*args, **kwargs)
|
||||
|
||||
def get_user_rbac_groups(self):
|
||||
"""Get all RBAC groups the user belongs to"""
|
||||
return RBACGroup.objects.filter(memberships__user=self)
|
||||
|
||||
def get_rbac_categories_as_member(self):
|
||||
"""
|
||||
Get all categories related to RBAC groups the user belongs to
|
||||
"""
|
||||
rbac_groups = RBACGroup.objects.filter(memberships__user=self, memberships__role__in=["member", "contributor", "manager"])
|
||||
categories = Category.objects.filter(rbac_groups__in=rbac_groups).distinct()
|
||||
return categories
|
||||
|
||||
def has_member_access_to_category(self, category):
|
||||
rbac_groups = RBACGroup.objects.filter(memberships__user=self, memberships__role__in=["member", "contributor", "manager"], categories=category)
|
||||
return rbac_groups.exists()
|
||||
|
||||
def has_member_access_to_media(self, media):
|
||||
rbac_groups = RBACGroup.objects.filter(memberships__user=self, memberships__role__in=["member", "contributor", "manager"], categories__in=media.category.all()).distinct()
|
||||
return rbac_groups.exists()
|
||||
|
||||
def get_rbac_categories_as_contributor(self):
|
||||
"""
|
||||
Get all categories related to RBAC groups the user belongs to
|
||||
"""
|
||||
rbac_groups = RBACGroup.objects.filter(memberships__user=self, memberships__role__in=["contributor", "manager"])
|
||||
categories = Category.objects.filter(rbac_groups__in=rbac_groups).distinct()
|
||||
return categories
|
||||
|
||||
def set_role_from_mapping(self, role_mapping):
|
||||
"""
|
||||
Sets user permissions based on a role mapping string.
|
||||
|
||||
Args:
|
||||
role_mapping (str): The role identifier to map to internal permissions.
|
||||
|
||||
Returns:
|
||||
bool: True if a valid role was applied, False otherwise.
|
||||
"""
|
||||
update_fields = []
|
||||
|
||||
if role_mapping == 'advancedUser':
|
||||
self.advancedUser = True
|
||||
update_fields.append('advancedUser')
|
||||
elif role_mapping == 'editor':
|
||||
self.is_editor = True
|
||||
update_fields.append('is_editor')
|
||||
elif role_mapping == 'manager':
|
||||
self.is_manager = True
|
||||
update_fields.append('is_manager')
|
||||
elif role_mapping == 'admin':
|
||||
self.is_superuser = True
|
||||
self.is_staff = True
|
||||
update_fields.extend(['is_superuser', 'is_staff'])
|
||||
else:
|
||||
self.is_superuser = False
|
||||
self.is_staff = False
|
||||
self.advancedUser = False
|
||||
self.is_editor = False
|
||||
self.is_manager = False
|
||||
update_fields.extend(['is_superuser', 'is_staff', 'advancedUser', 'is_editor', 'is_manager'])
|
||||
# XYZ TODO: to confirm with Thorkild
|
||||
# return True
|
||||
|
||||
if update_fields:
|
||||
self.save(update_fields=update_fields)
|
||||
return True
|
||||
|
||||
|
||||
class Channel(models.Model):
|
||||
title = models.CharField(max_length=90, db_index=True)
|
||||
|
||||
@@ -12,4 +12,12 @@ class ASCIIUsernameValidator(validators.RegexValidator):
|
||||
flags = re.ASCII
|
||||
|
||||
|
||||
@deconstructible
|
||||
class LEssRestrictiveUsernameValidator(validators.RegexValidator):
|
||||
regex = r"^[^\x00-\x1F\\/:*?\"<>|%#&`=~]+$"
|
||||
message = _("Enter a valid username. This value may contain UTF-8 characters except those reserved for file systems")
|
||||
flags = 0 # Allow UTF-8 characters
|
||||
|
||||
|
||||
custom_username_validators = [ASCIIUsernameValidator()]
|
||||
less_restrictive_username_validators = [LEssRestrictiveUsernameValidator]
|
||||
|
||||
Reference in New Issue
Block a user