231 lines
6.7 KiB
Python
231 lines
6.7 KiB
Python
"""
|
|
Admin configuration for accounts app.
|
|
"""
|
|
|
|
from django.contrib import admin
|
|
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
|
from django.utils.html import format_html
|
|
from .models import User, TwoFactorDevice, SocialAccount, UserSession, PasswordHistory
|
|
|
|
|
|
@admin.register(User)
|
|
class UserAdmin(BaseUserAdmin):
|
|
"""
|
|
Admin configuration for User model.
|
|
"""
|
|
list_display = [
|
|
'username', 'email', 'get_full_name', 'role', 'tenant',
|
|
'is_active', 'is_verified', 'is_approved', 'last_login'
|
|
]
|
|
list_filter = [
|
|
'role', 'tenant', 'is_active', 'is_verified', 'is_approved',
|
|
'two_factor_enabled', 'is_staff', 'is_superuser'
|
|
]
|
|
search_fields = [
|
|
'username', 'email', 'first_name', 'last_name',
|
|
'employee_id', 'license_number', 'npi_number'
|
|
]
|
|
ordering = ['last_name', 'first_name']
|
|
|
|
fieldsets = BaseUserAdmin.fieldsets + (
|
|
('Tenant Information', {
|
|
'fields': ('tenant', 'user_id')
|
|
}),
|
|
('Personal Information', {
|
|
'fields': (
|
|
'middle_name', 'preferred_name', 'phone_number', 'mobile_number',
|
|
'profile_picture', 'bio'
|
|
)
|
|
}),
|
|
('Professional Information', {
|
|
'fields': (
|
|
'employee_id', 'department', 'job_title', 'role',
|
|
'license_number', 'license_state', 'license_expiry',
|
|
'dea_number', 'npi_number'
|
|
)
|
|
}),
|
|
('Security Settings', {
|
|
'fields': (
|
|
'force_password_change', 'password_expires_at',
|
|
'failed_login_attempts', 'locked_until', 'two_factor_enabled',
|
|
'max_concurrent_sessions', 'session_timeout_minutes'
|
|
)
|
|
}),
|
|
('Preferences', {
|
|
'fields': ( 'language', 'theme')
|
|
}),
|
|
('Status', {
|
|
'fields': (
|
|
'is_verified', 'is_approved', 'approval_date', 'approved_by'
|
|
)
|
|
}),
|
|
('Metadata', {
|
|
'fields': ('created_at', 'updated_at', 'last_password_change'),
|
|
'classes': ('collapse',)
|
|
}),
|
|
)
|
|
|
|
readonly_fields = [
|
|
'user_id', 'created_at', 'updated_at', 'last_password_change'
|
|
]
|
|
|
|
def get_queryset(self, request):
|
|
return super().get_queryset(request).select_related('tenant', 'approved_by')
|
|
|
|
|
|
@admin.register(TwoFactorDevice)
|
|
class TwoFactorDeviceAdmin(admin.ModelAdmin):
|
|
"""
|
|
Admin configuration for TwoFactorDevice model.
|
|
"""
|
|
list_display = [
|
|
'user', 'name', 'device_type', 'is_active', 'is_verified',
|
|
'last_used_at', 'usage_count'
|
|
]
|
|
list_filter = ['device_type', 'is_active', 'is_verified']
|
|
search_fields = ['user__username', 'user__email', 'name']
|
|
ordering = ['-created_at']
|
|
|
|
fieldsets = (
|
|
('Device Information', {
|
|
'fields': ('user', 'device_id', 'name', 'device_type')
|
|
}),
|
|
('Configuration', {
|
|
'fields': ('secret_key', 'phone_number', 'email_address')
|
|
}),
|
|
('Status', {
|
|
'fields': ('is_active', 'is_verified', 'verified_at')
|
|
}),
|
|
('Usage Statistics', {
|
|
'fields': ('last_used_at', 'usage_count')
|
|
}),
|
|
('Metadata', {
|
|
'fields': ('created_at', 'updated_at'),
|
|
'classes': ('collapse',)
|
|
}),
|
|
)
|
|
|
|
readonly_fields = ['device_id', 'created_at', 'updated_at']
|
|
|
|
|
|
@admin.register(SocialAccount)
|
|
class SocialAccountAdmin(admin.ModelAdmin):
|
|
"""
|
|
Admin configuration for SocialAccount model.
|
|
"""
|
|
list_display = [
|
|
'user', 'provider', 'provider_email', 'display_name',
|
|
'is_active', 'last_login_at'
|
|
]
|
|
list_filter = ['provider', 'is_active']
|
|
search_fields = [
|
|
'user__username', 'user__email', 'provider_email',
|
|
'display_name', 'provider_id'
|
|
]
|
|
ordering = ['-created_at']
|
|
|
|
fieldsets = (
|
|
('User Information', {
|
|
'fields': ('user',)
|
|
}),
|
|
('Provider Information', {
|
|
'fields': (
|
|
'provider', 'provider_id', 'provider_email',
|
|
'display_name', 'profile_url', 'avatar_url'
|
|
)
|
|
}),
|
|
('Tokens', {
|
|
'fields': ('access_token', 'refresh_token', 'token_expires_at'),
|
|
'classes': ('collapse',)
|
|
}),
|
|
('Status', {
|
|
'fields': ('is_active',)
|
|
}),
|
|
('Metadata', {
|
|
'fields': ('created_at', 'updated_at', 'last_login_at'),
|
|
'classes': ('collapse',)
|
|
}),
|
|
)
|
|
|
|
readonly_fields = ['created_at', 'updated_at']
|
|
|
|
|
|
@admin.register(UserSession)
|
|
class UserSessionAdmin(admin.ModelAdmin):
|
|
"""
|
|
Admin configuration for UserSession model.
|
|
"""
|
|
list_display = [
|
|
'user', 'ip_address', 'device_type', 'browser',
|
|
'is_active', 'login_method', 'created_at', 'expires_at'
|
|
]
|
|
list_filter = [
|
|
'device_type', 'is_active', 'login_method',
|
|
'country', 'created_at'
|
|
]
|
|
search_fields = [
|
|
'user__username', 'user__email', 'ip_address',
|
|
'user_agent', 'browser', 'operating_system'
|
|
]
|
|
ordering = ['-created_at']
|
|
|
|
fieldsets = (
|
|
('User Information', {
|
|
'fields': ('user', 'session_key', 'session_id')
|
|
}),
|
|
('Device Information', {
|
|
'fields': (
|
|
'ip_address', 'user_agent', 'device_type',
|
|
'browser', 'operating_system'
|
|
)
|
|
}),
|
|
('Location Information', {
|
|
'fields': ('country', 'region', 'city')
|
|
}),
|
|
('Session Status', {
|
|
'fields': ('is_active', 'login_method')
|
|
}),
|
|
('Timestamps', {
|
|
'fields': (
|
|
'created_at', 'last_activity_at',
|
|
'expires_at', 'ended_at'
|
|
)
|
|
}),
|
|
)
|
|
|
|
readonly_fields = [
|
|
'session_id', 'created_at', 'last_activity_at'
|
|
]
|
|
|
|
def get_queryset(self, request):
|
|
return super().get_queryset(request).select_related('user')
|
|
|
|
|
|
@admin.register(PasswordHistory)
|
|
class PasswordHistoryAdmin(admin.ModelAdmin):
|
|
"""
|
|
Admin configuration for PasswordHistory model.
|
|
"""
|
|
list_display = ['user', 'created_at']
|
|
list_filter = ['created_at']
|
|
search_fields = ['user__username', 'user__email']
|
|
ordering = ['-created_at']
|
|
|
|
fieldsets = (
|
|
('User Information', {
|
|
'fields': ('user',)
|
|
}),
|
|
('Password Information', {
|
|
'fields': ('password_hash',)
|
|
}),
|
|
('Metadata', {
|
|
'fields': ('created_at',)
|
|
}),
|
|
)
|
|
|
|
readonly_fields = ['created_at']
|
|
|
|
def get_queryset(self, request):
|
|
return super().get_queryset(request).select_related('user')
|
|
|