Files
2025-04-05 12:44:21 +03:00

124 lines
4.6 KiB
Python

import csv
import logging
from django import forms
from django.conf import settings
from django.contrib import admin
from django.core.exceptions import ValidationError
from django.utils.html import format_html
from .models import SAMLConfiguration
class SAMLConfigurationForm(forms.ModelForm):
import_csv = forms.FileField(required=False, label="CSV file", help_text="Make sure headers are group_id, name")
class Meta:
model = SAMLConfiguration
fields = '__all__'
def clean_import_csv(self):
csv_file = self.cleaned_data.get('import_csv')
if not csv_file:
return csv_file
if not csv_file.name.endswith('.csv'):
raise ValidationError("Uploaded file must be a CSV file.")
try:
decoded_file = csv_file.read().decode('utf-8').splitlines()
csv_reader = csv.reader(decoded_file)
headers = next(csv_reader, None)
if not headers or 'group_id' not in headers or 'name' not in headers:
raise ValidationError("CSV file must contain 'group_id' and 'name' headers. " f"Found headers: {', '.join(headers) if headers else 'none'}")
csv_file.seek(0)
return csv_file
except csv.Error:
raise ValidationError("Invalid CSV file. Please ensure the file is properly formatted.")
except UnicodeDecodeError:
raise ValidationError("Invalid file encoding. Please upload a CSV file with UTF-8 encoding.")
class SAMLConfigurationAdmin(admin.ModelAdmin):
form = SAMLConfigurationForm
list_display = ['social_app', 'idp_id', 'remove_from_groups', 'save_saml_response_logs', 'view_metadata_url']
list_filter = ['social_app', 'remove_from_groups', 'save_saml_response_logs']
search_fields = ['social_app__name', 'idp_id', 'sp_metadata_url']
fieldsets = [
('Provider Settings', {'fields': ['social_app', 'idp_id', 'idp_cert']}),
('URLs', {'fields': ['sso_url', 'slo_url', 'sp_metadata_url']}),
('Group Management', {'fields': ['remove_from_groups', 'save_saml_response_logs']}),
('Attribute Mapping', {'fields': ['uid', 'name', 'email', 'groups', 'first_name', 'last_name', 'user_logo', 'role']}),
(
'Email Settings',
{
'fields': [
'verified_email',
'email_authentication',
]
},
),
]
def view_metadata_url(self, obj):
"""Display metadata URL as a clickable link"""
return format_html('<a href="{}" target="_blank">View Metadata</a>', obj.sp_metadata_url)
view_metadata_url.short_description = 'Metadata'
def formfield_for_dbfield(self, db_field, **kwargs):
field = super().formfield_for_dbfield(db_field, **kwargs)
if db_field.name == 'social_app':
field.label = 'IDP Config Name'
return field
def get_fieldsets(self, request, obj=None):
fieldsets = super().get_fieldsets(request, obj)
fieldsets = list(fieldsets)
fieldsets.append(('BULK GROUP MAPPINGS', {'fields': ('import_csv',), 'description': 'Optionally upload a CSV file with group_id and name as headers to add multiple group mappings at once.'}))
return fieldsets
def save_model(self, request, obj, form, change):
super().save_model(request, obj, form, change)
csv_file = form.cleaned_data.get('import_csv')
if csv_file:
from rbac.models import RBACGroup
try:
csv_file.seek(0)
decoded_file = csv_file.read().decode('utf-8').splitlines()
csv_reader = csv.DictReader(decoded_file)
for row in csv_reader:
group_id = row.get('group_id')
name = row.get('name')
if group_id and name:
if not RBACGroup.objects.filter(uid=group_id, social_app=obj.social_app).exists():
try:
rbac_group = RBACGroup.objects.create(uid=group_id, name=name, social_app=obj.social_app) # noqa
except Exception as e:
logging.error(e)
except Exception as e:
logging.error(e)
if getattr(settings, 'USE_SAML', False):
for field in SAMLConfiguration._meta.fields:
if field.name == 'social_app':
field.verbose_name = "ID Provider"
admin.site.register(SAMLConfiguration, SAMLConfigurationAdmin)
SAMLConfiguration._meta.app_config.verbose_name = "SAML settings and logs"
SAMLConfiguration._meta.verbose_name_plural = "SAML Configuration"