초기 커밋
This commit is contained in:
0
app/admin/__init__.py
Normal file
0
app/admin/__init__.py
Normal file
56
app/admin/setup.py
Normal file
56
app/admin/setup.py
Normal file
@@ -0,0 +1,56 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import FastAPI
|
||||
from sqladmin import Admin
|
||||
from sqladmin.authentication import AuthenticationBackend
|
||||
from starlette.requests import Request
|
||||
|
||||
from app.core.config import settings
|
||||
from app.core.constants import Role
|
||||
from app.core.security import decode_token
|
||||
from app.db.mariadb import async_engine
|
||||
|
||||
|
||||
class AdminAuth(AuthenticationBackend):
|
||||
async def login(self, request: Request) -> bool:
|
||||
form = await request.form()
|
||||
token = str(form.get("token", ""))
|
||||
payload = decode_token(token)
|
||||
if payload and payload.get("role") in Role.ADMIN_ROLES:
|
||||
request.session["token"] = token
|
||||
return True
|
||||
return False
|
||||
|
||||
async def logout(self, request: Request) -> bool:
|
||||
request.session.clear()
|
||||
return True
|
||||
|
||||
async def authenticate(self, request: Request) -> bool:
|
||||
token = request.session.get("token")
|
||||
if not token:
|
||||
return False
|
||||
payload = decode_token(token)
|
||||
return payload is not None and payload.get("role") in Role.ADMIN_ROLES
|
||||
|
||||
|
||||
def setup_admin(app: FastAPI) -> Admin:
|
||||
auth_backend = AdminAuth(secret_key=settings.SECRET_KEY)
|
||||
admin = Admin(
|
||||
app,
|
||||
engine=async_engine,
|
||||
authentication_backend=auth_backend,
|
||||
title=f"{settings.APP_NAME} Admin",
|
||||
)
|
||||
|
||||
from app.admin.views.device_admin import DeviceAdmin, DeviceGroupAdmin
|
||||
from app.admin.views.system_admin import AuditLogAdmin, SystemConfigAdmin
|
||||
from app.admin.views.user_admin import UserAdmin, UserProfileAdmin
|
||||
|
||||
admin.add_view(UserAdmin)
|
||||
admin.add_view(UserProfileAdmin)
|
||||
admin.add_view(DeviceAdmin)
|
||||
admin.add_view(DeviceGroupAdmin)
|
||||
admin.add_view(SystemConfigAdmin)
|
||||
admin.add_view(AuditLogAdmin)
|
||||
|
||||
return admin
|
||||
0
app/admin/views/__init__.py
Normal file
0
app/admin/views/__init__.py
Normal file
32
app/admin/views/device_admin.py
Normal file
32
app/admin/views/device_admin.py
Normal file
@@ -0,0 +1,32 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from sqladmin import ModelView
|
||||
|
||||
from app.models.mariadb.device import Device, DeviceGroup
|
||||
|
||||
|
||||
class DeviceAdmin(ModelView, model=Device):
|
||||
column_list = [
|
||||
Device.id, Device.device_uid, Device.name, Device.device_type,
|
||||
Device.status, Device.last_seen_at, Device.created_at,
|
||||
]
|
||||
column_searchable_list = [Device.device_uid, Device.name]
|
||||
column_sortable_list = [Device.id, Device.name, Device.status, Device.created_at]
|
||||
column_default_sort = ("id", True)
|
||||
can_create = True
|
||||
can_edit = True
|
||||
can_delete = False
|
||||
name = "Device"
|
||||
name_plural = "Devices"
|
||||
icon = "fa-solid fa-microchip"
|
||||
|
||||
|
||||
class DeviceGroupAdmin(ModelView, model=DeviceGroup):
|
||||
column_list = [DeviceGroup.id, DeviceGroup.name, DeviceGroup.description]
|
||||
column_searchable_list = [DeviceGroup.name]
|
||||
can_create = True
|
||||
can_edit = True
|
||||
can_delete = True
|
||||
name = "Device Group"
|
||||
name_plural = "Device Groups"
|
||||
icon = "fa-solid fa-layer-group"
|
||||
31
app/admin/views/system_admin.py
Normal file
31
app/admin/views/system_admin.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from sqladmin import ModelView
|
||||
|
||||
from app.models.mariadb.system import AuditLog, SystemConfig
|
||||
|
||||
|
||||
class SystemConfigAdmin(ModelView, model=SystemConfig):
|
||||
column_list = [SystemConfig.id, SystemConfig.key, SystemConfig.value, SystemConfig.is_secret]
|
||||
column_searchable_list = [SystemConfig.key]
|
||||
can_create = True
|
||||
can_edit = True
|
||||
can_delete = True
|
||||
name = "System Config"
|
||||
name_plural = "System Configs"
|
||||
icon = "fa-solid fa-gear"
|
||||
|
||||
|
||||
class AuditLogAdmin(ModelView, model=AuditLog):
|
||||
column_list = [
|
||||
AuditLog.id, AuditLog.user_id, AuditLog.action,
|
||||
AuditLog.resource_type, AuditLog.resource_id, AuditLog.created_at,
|
||||
]
|
||||
column_sortable_list = [AuditLog.id, AuditLog.created_at]
|
||||
column_default_sort = ("id", True)
|
||||
can_create = False
|
||||
can_edit = False
|
||||
can_delete = False
|
||||
name = "Audit Log"
|
||||
name_plural = "Audit Logs"
|
||||
icon = "fa-solid fa-clipboard-list"
|
||||
28
app/admin/views/user_admin.py
Normal file
28
app/admin/views/user_admin.py
Normal file
@@ -0,0 +1,28 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from sqladmin import ModelView
|
||||
|
||||
from app.models.mariadb.user import User, UserProfile
|
||||
|
||||
|
||||
class UserAdmin(ModelView, model=User):
|
||||
column_list = [User.id, User.email, User.role, User.is_active, User.is_verified, User.created_at]
|
||||
column_searchable_list = [User.email]
|
||||
column_sortable_list = [User.id, User.email, User.created_at]
|
||||
column_default_sort = ("id", True)
|
||||
can_create = True
|
||||
can_edit = True
|
||||
can_delete = False
|
||||
name = "User"
|
||||
name_plural = "Users"
|
||||
icon = "fa-solid fa-user"
|
||||
|
||||
|
||||
class UserProfileAdmin(ModelView, model=UserProfile):
|
||||
column_list = [UserProfile.id, UserProfile.user_id, UserProfile.full_name, UserProfile.organization]
|
||||
column_searchable_list = [UserProfile.full_name]
|
||||
can_create = False
|
||||
can_delete = False
|
||||
name = "User Profile"
|
||||
name_plural = "User Profiles"
|
||||
icon = "fa-solid fa-address-card"
|
||||
Reference in New Issue
Block a user