feat: cas

This commit is contained in:
2025-10-29 00:50:26 +01:00
parent 578a5af3df
commit 498a1063f7
14 changed files with 473 additions and 37 deletions
View File
+32
View File
@@ -0,0 +1,32 @@
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser
@admin.register(CustomUser)
class CustomUserAdmin(UserAdmin):
"""Admin interface for CustomUser."""
# Add custom fields to the user admin
fieldsets = UserAdmin.fieldsets + (
('CAS Information', {
'fields': ('cas_user_id', 'cas_groups', 'cas_attributes'),
}),
)
# Add custom fields to the list display
list_display = UserAdmin.list_display + ('cas_user_id', 'get_cas_groups_display')
# Add search fields
search_fields = UserAdmin.search_fields + ('cas_user_id',)
# Add filters
list_filter = UserAdmin.list_filter + ('cas_groups',)
# Make CAS fields readonly in admin
readonly_fields = ('cas_user_id', 'cas_groups', 'cas_attributes')
def get_cas_groups_display(self, obj):
"""Display CAS groups in admin list."""
return obj.get_cas_groups_display()
get_cas_groups_display.short_description = 'CAS Groups'
+6
View File
@@ -0,0 +1,6 @@
from django.apps import AppConfig
class AccountsConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'accounts'
@@ -0,0 +1,47 @@
# Generated by Django 5.2.7 on 2025-10-28 23:41
import django.contrib.auth.models
import django.contrib.auth.validators
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
]
operations = [
migrations.CreateModel(
name='CustomUser',
fields=[
('id', models.BigAutoField(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=150, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, 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')),
('cas_user_id', models.CharField(blank=True, max_length=50, null=True, unique=True)),
('cas_groups', models.JSONField(blank=True, default=list)),
('cas_attributes', models.JSONField(blank=True, default=dict)),
('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={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
],
),
]
+60
View File
@@ -0,0 +1,60 @@
from django.contrib.auth.models import AbstractUser
from django.db import models
import json
class CustomUser(AbstractUser):
"""Custom User model to store CAS attributes from PolyLAN."""
# Store CAS user ID (the numeric ID from CAS)
cas_user_id = models.CharField(max_length=50, blank=True, null=True, unique=True)
# Store CAS groups as JSON
cas_groups = models.JSONField(default=list, blank=True)
# Additional fields that might come from CAS
cas_attributes = models.JSONField(default=dict, blank=True)
def __str__(self):
return f"{self.username} ({self.cas_user_id})"
def has_cas_group(self, group_name):
"""Check if user has a specific CAS group."""
return group_name in self.cas_groups
def get_cas_groups_display(self):
"""Get a comma-separated list of CAS groups for display."""
return ", ".join(self.cas_groups) if self.cas_groups else "No groups"
def update_cas_data(self, cas_user_id, attributes):
"""Update user with CAS data."""
self.cas_user_id = cas_user_id
# Update basic fields from CAS attributes
if "firstname" in attributes:
self.first_name = attributes["firstname"]
if "lastname" in attributes:
self.last_name = attributes["lastname"]
if "email" in attributes:
self.email = attributes["email"]
# Store groups
if "groups" in attributes:
# CAS groups come as a list or single value
groups = attributes["groups"]
if isinstance(groups, str):
self.cas_groups = [groups]
elif isinstance(groups, list):
self.cas_groups = groups
else:
self.cas_groups = []
if "RESPONSABLE_ANIMATION" in self.cas_groups:
self.is_staff = True
self.is_superuser = True
# Store all other attributes
self.cas_attributes = attributes
self.save()
+3
View File
@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.
+3
View File
@@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.