Newer
Older
pydwiki / accounts / admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import Group
from django.core.exceptions import ValidationError
from django.forms.models import BaseInlineFormSet
from django.utils.translation import gettext_lazy as _

from log_manager.trace_log import trace_log

from .models import CustomGroup, CustomUser, EmailAddress


class EmailAddressInlineFormSet(BaseInlineFormSet):
    """メールアドレス用フォームセット。"""

    @trace_log
    def clean(self):
        """メールアドレスの primary 指定が複数ある場合、ValidationErro を投げます。"""
        super().clean()

        primary_count = sum(1 for form in self.forms if form.cleaned_data.get("is_primary", False))
        if primary_count > 1:
            raise ValidationError(_("Only one primary email address can be set. "))


class EmailAddressInline(admin.TabularInline):
    """メールアドレスインライン用"""

    model = EmailAddress
    formset = EmailAddressInlineFormSet
    extra = 1


@admin.register(CustomUser)
class CustomUserAdmin(UserAdmin):
    """カスタムユーザー管理。"""

    model = CustomUser
    """ 対象モデル。 """

    inlines = [
        EmailAddressInline,
    ]
    """ インライン表示。 """

    list_display = (
        "login_id",
        "username",
        "get_primary_email",
        "is_mfa_enabled",
        "is_staff",
        "is_superuser",
    )
    """ リスト表示のフィールド。 """

    search_fields = (
        "login_id",
        "username",
        "get_primary_email",
        "is_mfa_enabled",
        "is_staff",
        "is_superuser",
    )
    """ 検索フィールド。 """

    ordering = ("login_id",)
    """ 表示順。 """

    fieldsets = (
        (
            None,
            {
                "fields": (
                    "login_id",
                    "username",
                    "password",
                    "is_mfa_enabled",
                )
            },
        ),
        (
            _("Permissions"),
            {
                "fields": (
                    "is_staff",
                    "is_active",
                    "is_superuser",
                    "groups",
                    "user_permissions",
                )
            },
        ),
        (
            _("Password"),
            {
                "fields": (
                    "password_changed",
                    "password_changed_date",
                )
            },
        ),
    )
    """ ユーザー編集時のフィールドセット。 """

    add_fieldsets = (
        (
            None,
            {
                "classes": ("wide",),
                "fields": ("login_id", "username", "_email", "password1", "password2"),
            },
        ),
    )
    """ ユーザー追加時のフィールドセット。 """

    @trace_log
    def get_primary_email(self, obj):
        """プライマリのメールアドレスを返します。

        Return:
            プライマリのメールアドレス。
        """
        primary_email = obj.get_primary_email()
        return primary_email if primary_email else _("None")

    get_primary_email.short_description = _("Email")
    """ プライマリメールアドレスの詳細。 """

    @trace_log
    def save_model(self, request, obj, form, change):
        """`email` が渡された場合、EmailAddress に保存します。"""
        super().save_model(request, obj, form, change)
        email = form.cleaned_data.get("_email")
        if email and not EmailAddress.objects.filter(user=obj, email=email).exists():
            EmailAddress.objects.create(user=obj, email=email, is_primary=True)


class CustomGroupInline(admin.TabularInline):
    """カスタムグループインライン表示用"""

    model = CustomGroup
    extra = 1
    fk_name = "group"
    verbose_name = _("Group Information")
    verbose_name_plural = _("Group Information")


class GroupAdmin(admin.ModelAdmin):
    inlines = [
        CustomGroupInline,
    ]
    """ インライン表示。 """


admin.site.unregister(Group)
admin.site.register(Group, GroupAdmin)