From b6a0abd9ee1b600ad6e39181b522ef26775c1a7c Mon Sep 17 00:00:00 2001 From: Franklin-F Date: Tue, 15 Apr 2025 15:16:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=9D=83=E9=99=90=E4=BD=93?= =?UTF-8?q?=E7=B3=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- accounts/api/__init__.py | 0 accounts/{api.py => api/auth.py} | 22 +++++++------------ accounts/api/user.py | 18 ++++++++++++++++ api.py | 4 ++++ utils/__init__.py | 0 utils/auth.py | 16 ++++++++++++++ utils/permissions.py | 36 ++++++++++++++++++++++++++++++++ 7 files changed, 82 insertions(+), 14 deletions(-) create mode 100644 accounts/api/__init__.py rename accounts/{api.py => api/auth.py} (81%) create mode 100644 accounts/api/user.py create mode 100644 utils/__init__.py create mode 100644 utils/auth.py create mode 100644 utils/permissions.py diff --git a/accounts/api/__init__.py b/accounts/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/accounts/api.py b/accounts/api/auth.py similarity index 81% rename from accounts/api.py rename to accounts/api/auth.py index 2dca309..61bf74f 100644 --- a/accounts/api.py +++ b/accounts/api/auth.py @@ -1,36 +1,31 @@ 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 - - +auth_router = Router(tags=["认证"]) User = get_user_model() -router = Router(tags=["用户注册 + JWT"]) -@router.post("/register") +@auth_router.post("/register") def register( request, username: str = Form(...), password: str = Form(...), email: str = Form(...), - role: str = Form("user") # 也可写死 "user" + 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": "注册成功", @@ -46,10 +41,10 @@ def register( } -@router.post("/login") +@auth_router.post("/login") def login( - request: HttpRequest, - username: str = Form(...), # 可以是用户名或邮箱 + request, + username: str = Form(...), password: str = Form(...), ): user = User.objects.filter(Q(username=username) | Q(email=username)).first() @@ -61,7 +56,6 @@ def login( return {"success": False, "message": "账号未激活"} refresh = RefreshToken.for_user(user) - return { "success": True, "message": "登录成功", diff --git a/accounts/api/user.py b/accounts/api/user.py new file mode 100644 index 0000000..042b901 --- /dev/null +++ b/accounts/api/user.py @@ -0,0 +1,18 @@ +from ninja import Router +from utils.permissions import login_required +from utils.auth import jwt_auth + +user_router = Router(tags=["用户信息"]) + +@user_router.get("/me", auth=jwt_auth) +@login_required +def get_user_info(request): + user = request.user + return { + "id": user.id, + "username": user.username, + "email": user.email, + "role": user.role, + "is_active": user.is_active, + "is_staff": user.is_staff, + } diff --git a/api.py b/api.py index 57b5a1b..6e2fff0 100644 --- a/api.py +++ b/api.py @@ -1,5 +1,9 @@ from ninja import NinjaAPI from resumes.api.views import router as resume_router +from accounts.api.auth import auth_router +from accounts.api.user import user_router api = NinjaAPI(title="简历管理 API") api.add_router("/resumes/", resume_router) +api.add_router("/auth", auth_router) +api.add_router("/users", user_router) diff --git a/utils/__init__.py b/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/utils/auth.py b/utils/auth.py new file mode 100644 index 0000000..a5a49f2 --- /dev/null +++ b/utils/auth.py @@ -0,0 +1,16 @@ +from ninja.security import HttpBearer +from rest_framework_simplejwt.authentication import JWTAuthentication + + +class JWTAuth(HttpBearer): + def authenticate(self, request, token): + jwt_auth = JWTAuthentication() + try: + validated_token = jwt_auth.get_validated_token(token) + user = jwt_auth.get_user(validated_token) + return user + except Exception: + return None + + +jwt_auth = JWTAuth() diff --git a/utils/permissions.py b/utils/permissions.py new file mode 100644 index 0000000..84cba5c --- /dev/null +++ b/utils/permissions.py @@ -0,0 +1,36 @@ +from functools import wraps +from ninja.errors import HttpError + + +from functools import wraps +from ninja.errors import HttpError + + +def login_required(func): + @wraps(func) + def wrapper(request, *args, **kwargs): + user = getattr(request, 'user', None) + if not user or not user.is_authenticated: + raise HttpError(401, "请先登录") + return func(request, *args, **kwargs) + return wrapper + + +def manager_required(func): + @wraps(func) + def wrapper(request, *args, **kwargs): + user = getattr(request, 'user', None) + if not user or not user.is_authenticated or user.role not in ['admin', 'manager']: + raise HttpError(403, "仅分管理或管理员可访问") + return func(request, *args, **kwargs) + return wrapper + + +def admin_required(func): + @wraps(func) + def wrapper(request, *args, **kwargs): + user = getattr(request, 'user', None) + if not user or not user.is_authenticated or user.role != 'admin': + raise HttpError(403, "仅管理员可访问") + return func(request, *args, **kwargs) + return wrapper