diff --git a/accounts/admin.py b/accounts/admin.py index 8c38f3f..e06ba4f 100644 --- a/accounts/admin.py +++ b/accounts/admin.py @@ -1,3 +1,12 @@ from django.contrib import admin +from django.contrib.auth.admin import UserAdmin as DefaultUserAdmin +from .models import User -# Register your models here. + +@admin.register(User) +class UserAdmin(DefaultUserAdmin): + list_display = ("username", "email", "role", "is_active", "is_staff", "last_login") + list_filter = ("role", "is_active", "is_staff", "is_superuser") + fieldsets = DefaultUserAdmin.fieldsets + ( + ("角色权限", {"fields": ("role",)}), + ) \ No newline at end of file diff --git a/accounts/api.py b/accounts/api.py new file mode 100644 index 0000000..2dca309 --- /dev/null +++ b/accounts/api.py @@ -0,0 +1,77 @@ +from ninja import Router, Form +from django.contrib.auth import get_user_model +from rest_framework_simplejwt.tokens import RefreshToken +from django.contrib.auth import authenticate +from django.http import HttpRequest +from django.db.models import Q +from django.contrib.auth.hashers import check_password + + + +User = get_user_model() +router = Router(tags=["用户注册 + JWT"]) + + +@router.post("/register") +def register( + request, + username: str = Form(...), + password: str = Form(...), + email: str = Form(...), + role: str = Form("user") # 也可写死 "user" +): + if User.objects.filter(username=username).exists(): + return {"success": False, "message": "用户名已存在"} + if role != "user": + return {"success": False, "message": "不能注册管理员或分管理账号"} + user = User(username=username, email=email, role=role) + user.set_password(password) + user.save() + + # 生成 JWT token + refresh = RefreshToken.for_user(user) + + return { + "success": True, + "message": "注册成功", + "user": { + "id": user.id, + "username": user.username, + "role": user.role, + }, + "token": { + "access": str(refresh.access_token), + "refresh": str(refresh), + } + } + + +@router.post("/login") +def login( + request: HttpRequest, + username: str = Form(...), # 可以是用户名或邮箱 + password: str = Form(...), +): + user = User.objects.filter(Q(username=username) | Q(email=username)).first() + + if not user or not user.check_password(password): + return {"success": False, "message": "用户名或密码错误"} + + if not user.is_active: + return {"success": False, "message": "账号未激活"} + + refresh = RefreshToken.for_user(user) + + return { + "success": True, + "message": "登录成功", + "user": { + "id": user.id, + "username": user.username, + "role": user.role, + }, + "token": { + "access": str(refresh.access_token), + "refresh": str(refresh), + } + } \ No newline at end of file diff --git a/accounts/models.py b/accounts/models.py index 71a8362..8a63bb5 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -1,3 +1,23 @@ +from django.contrib.auth.models import AbstractUser from django.db import models -# Create your models here. + +class User(AbstractUser): + ROLE_CHOICES = [ + ('admin', '管理员'), + ('manager', '分管理'), + ('user', '普通用户'), + ] + role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='user', help_text="用户角色") + + def is_admin(self): + return self.role == 'admin' + + def is_manager(self): + return self.role == 'manager' + + def is_user(self): + return self.role == 'user' + + def __str__(self): + return f"{self.username} ({self.get_role_display()})" diff --git a/core/settings.py b/core/settings.py index 60cd9fd..5e389fa 100644 --- a/core/settings.py +++ b/core/settings.py @@ -118,7 +118,7 @@ AUTH_PASSWORD_VALIDATORS = [ }, ] - +AUTH_USER_MODEL = 'accounts.User' # Internationalization # https://docs.djangoproject.com/en/5.0/topics/i18n/ @@ -130,6 +130,11 @@ USE_I18N = True USE_TZ = True +REST_FRAMEWORK = { + "DEFAULT_AUTHENTICATION_CLASSES": [ + "rest_framework_simplejwt.authentication.JWTAuthentication", + ], +} # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/5.0/howto/static-files/