diff --git a/accounts/admin.py b/accounts/admin.py index 3fa052e..1e1efa5 100644 --- a/accounts/admin.py +++ b/accounts/admin.py @@ -12,8 +12,10 @@ class UserAdmin(DefaultUserAdmin): def get_fieldsets(self, request, obj=None): base = list(super().get_fieldsets(request, obj)) - base.append(("角色权限", {"fields": ("role", "source_manager")})) - + role_fields = ["role"] + if obj and obj.role == "user": + role_fields.append("source_manager") + base.append(("角色和权限", {"fields": role_fields})) if obj: if obj.role == "manager": base.append(("管理权限", {"fields": ("managed_websites",)})) diff --git a/api.py b/api.py index 67cc0ba..fdfbb55 100644 --- a/api.py +++ b/api.py @@ -2,10 +2,12 @@ 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 -from authorize.api.view import authorize_router +from authorize.api.website_authorize import website_authorize_router +from authorize.api.resume_authorize import resume_authorize_router api = NinjaAPI(title="简历管理 API") -api.add_router("/resumes/", resume_router) +api.add_router("/resumes", resume_router) api.add_router("/auth", auth_router) api.add_router("/users", user_router) -api.add_router("/authorize", authorize_router) \ No newline at end of file +api.add_router("/website", website_authorize_router) +api.add_router("/resume", resume_authorize_router) \ No newline at end of file diff --git a/authorize/api/resume_authorize.py b/authorize/api/resume_authorize.py new file mode 100644 index 0000000..c2c3f9e --- /dev/null +++ b/authorize/api/resume_authorize.py @@ -0,0 +1,37 @@ +from ninja import Router, Query +from django.shortcuts import get_object_or_404 +from accounts.models import User +from authorize.models import ResumeDetailAccessRequest +from authorize.schemas import ResumeAccessRequestIn +from resumes.models import ResumeDetail +from utils.auth import jwt_auth +from utils.permissions import login_required + +resume_authorize_router = Router(tags=["简历授权管理"]) + + +@resume_authorize_router.post("/apply", auth=jwt_auth, summary="申请简历详情[普]", + description="普通用户申请查看某一份简历详情") +@login_required +def apply_resume_access(request, data: ResumeAccessRequestIn): + user = request.user + + if not user.is_user(): + return {"success": False, "message": "仅普通用户可申请查看简历"} + + resume = get_object_or_404(ResumeDetail, id=data.resume_id) + + exists = ResumeDetailAccessRequest.objects.filter( + user=user, resume=resume, status="pending" + ).exists() + + if exists: + return {"success": False, "message": "您已申请过该简历,正在等待审批"} + + ResumeDetailAccessRequest.objects.create( + user=user, + resume=resume, + reason=data.reason or "" + ) + + return {"success": True, "message": "申请已提交,等待审批"} diff --git a/authorize/api/view.py b/authorize/api/website_authorize.py similarity index 66% rename from authorize/api/view.py rename to authorize/api/website_authorize.py index b5ff7e5..15e406c 100644 --- a/authorize/api/view.py +++ b/authorize/api/website_authorize.py @@ -8,10 +8,11 @@ from websites.models import Website from utils.auth import jwt_auth from utils.permissions import manager_required, login_required -authorize_router = Router(tags=["授权管理"]) +website_authorize_router = Router(tags=["网站(简历一般信息)授权管理"]) -@authorize_router.post("/authorize", auth=jwt_auth) +@website_authorize_router.post("/authorize", auth=jwt_auth, summary="分管手动授权网站[分管]", + description="分管理授权普通用户访问指定网站") @manager_required def authorize_user(request, data: AuthorizeIn): manager = request.user @@ -27,7 +28,6 @@ def authorize_user(request, data: AuthorizeIn): target_user.authorized_websites.add(*data.website_ids) - # 如果用户曾申请过,设置为已批准 WebsiteAccessRequest.objects.filter(user=target_user, website_id__in=data.website_ids).update(status="approved") return { @@ -36,13 +36,13 @@ def authorize_user(request, data: AuthorizeIn): } -@authorize_router.post("/apply", auth=jwt_auth) +@website_authorize_router.post("/apply", auth=jwt_auth, summary="申请网站授权[普]", + description="普通用户发起网站访问申请") @login_required def request_access(request, data: AccessRequestIn): user = request.user site = get_object_or_404(Website, id=data.website_id) - # 不允许重复申请 if WebsiteAccessRequest.objects.filter(user=user, website=site, status="pending").exists(): return {"success": False, "message": "您已申请,正在等待审批"} @@ -51,7 +51,8 @@ def request_access(request, data: AccessRequestIn): return {"success": True, "message": "申请已提交,等待分管理审批"} -@authorize_router.get("/pending", auth=jwt_auth) +@website_authorize_router.get("/pending", auth=jwt_auth, summary="待审批列表[分管]", + description="分管理查看自己负责的网站的待审批访问申请") @manager_required def list_pending_requests(request): manager = request.user @@ -74,7 +75,8 @@ def list_pending_requests(request): } -@authorize_router.post("/approve", auth=jwt_auth) +@website_authorize_router.post("/approve", auth=jwt_auth, summary="审批网站授权[分管]", + description="分管理审批网站访问申请(通过或拒绝)") @manager_required def approve_request(request, request_id: int = Query(...), approve: bool = Query(True)): r = get_object_or_404(WebsiteAccessRequest, id=request_id) @@ -91,48 +93,29 @@ def approve_request(request, request_id: int = Query(...), approve: bool = Query return {"success": True, "message": f"已{'通过' if approve else '拒绝'} {r.user.username} 的访问申请"} -@authorize_router.get("/my-sites", auth=jwt_auth) +@website_authorize_router.get("/my-sites", auth=jwt_auth, summary="我的网站列表[普]", + description="展示当前用户可申请与已授权的网站列表,并标记授权状态") @login_required -def list_user_manager_websites(request): +def list_user_sites_with_status(request): user = request.user if not user.is_user(): - return {"success": False, "message": "仅普通用户可申请网站"} + return {"success": False, "message": "仅普通用户可访问"} if not user.source_manager: return {"success": False, "message": "您尚未绑定所属分管理,无法申请网站"} - sites = user.source_manager.managed_websites.all().values("id", "name", "db_alias") - return {"success": True, "websites": list(sites)} + # 可申请的网站(所属分管理可管理) + manageable_sites = user.source_manager.managed_websites.all() + authorized_site_ids = set(user.authorized_websites.values_list("id", flat=True)) + websites = [] + for site in manageable_sites: + websites.append({ + "id": site.id, + "name": site.name, + "db_alias": site.db_alias, + "authorized": site.id in authorized_site_ids + }) -@authorize_router.get("/public-sites") -def list_public_websites(request): - websites = Website.objects.all().values("id", "name") - return {"success": True, "websites": list(websites)} - - -@authorize_router.post("/apply-resume", auth=jwt_auth) -@login_required -def apply_resume_access(request, data: ResumeAccessRequestIn): - user = request.user - - if not user.is_user(): - return {"success": False, "message": "仅普通用户可申请查看简历"} - - resume = get_object_or_404(ResumeDetail, id=data.resume_id) - - exists = ResumeDetailAccessRequest.objects.filter( - user=user, resume=resume, status="pending" - ).exists() - - if exists: - return {"success": False, "message": "您已申请过该简历,正在等待审批"} - - ResumeDetailAccessRequest.objects.create( - user=user, - resume=resume, - reason=data.reason or "" - ) - - return {"success": True, "message": "申请已提交,等待审批"} + return {"success": True, "websites": websites} diff --git a/invites/models.py b/invites/models.py index cf0d138..dba7000 100644 --- a/invites/models.py +++ b/invites/models.py @@ -14,6 +14,10 @@ class RegistrationCode(models.Model): used_count = models.IntegerField(default=0, verbose_name="已使用次数") created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间") + class Meta: + verbose_name = "注册码申请" + verbose_name_plural = "注册码申请" + def __str__(self): return f"{self.code} ({self.used_count}/{self.usage_limit})"