完善Bug 和 普通用户 所有网站的视图

This commit is contained in:
晓丰 2025-04-16 18:44:28 +08:00
parent e18d7a20dc
commit 8a95eb6a7d
11 changed files with 136 additions and 38 deletions

4
api.py
View File

@ -2,10 +2,10 @@ from ninja import NinjaAPI
from resumes.api.views import router as resume_router from resumes.api.views import router as resume_router
from accounts.api.auth import auth_router from accounts.api.auth import auth_router
from accounts.api.user import user_router from accounts.api.user import user_router
from accounts.api.authorize import router from authorize.api.view import authorize_router
api = NinjaAPI(title="简历管理 API") 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("/auth", auth_router)
api.add_router("/users", user_router) api.add_router("/users", user_router)
api.add_router("/authorize", router) api.add_router("/authorize", authorize_router)

0
authorize/__init__.py Normal file
View File

18
authorize/admin.py Normal file
View File

@ -0,0 +1,18 @@
from django.contrib import admin
from authorize.models import WebsiteAccessRequest, ResumeDetailAccessRequest
# Register your models here.
@admin.register(WebsiteAccessRequest)
class WebsiteAccessRequestAdmin(admin.ModelAdmin):
list_display = ('user', 'website', 'status', 'reason', 'created_at', 'updated_at')
list_filter = ('status', 'website', 'created_at')
search_fields = ('user__username', 'website__name', 'reason')
ordering = ('-created_at',)
readonly_fields = ('created_at', 'updated_at')
@admin.register(ResumeDetailAccessRequest)
class ResumeDetailAccessRequestAdmin(admin.ModelAdmin):
list_display = ('user', 'resume', 'reason', 'status', 'created_at')
list_filter = ('status', 'created_at')
search_fields = ('user__username', 'resume__id')

View File

View File

@ -1,41 +1,17 @@
# ✅ 授权管理接口manager 给 user 授权网站 + 普通用户申请接口 from ninja import Router, Query
from ninja import Router, Schema, Query
from pydantic import Field
from typing import List, Optional
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.db import models
from accounts.models import User from accounts.models import User
from authorize.models import WebsiteAccessRequest, ResumeDetailAccessRequest
from authorize.schemas import ResumeAccessRequestIn, AccessRequestIn, AuthorizeIn
from resumes.models import ResumeDetail
from websites.models import Website from websites.models import Website
from utils.auth import jwt_auth from utils.auth import jwt_auth
from utils.permissions import manager_required, login_required from utils.permissions import manager_required, login_required
router = Router(tags=["授权管理"]) authorize_router = Router(tags=["授权管理"])
class WebsiteAccessRequest(models.Model): @authorize_router.post("/authorize", auth=jwt_auth)
user = models.ForeignKey(User, on_delete=models.CASCADE)
website = models.ForeignKey(Website, on_delete=models.CASCADE)
status = models.CharField(
max_length=20,
choices=[("pending", "待审批"), ("approved", "已通过"), ("rejected", "已拒绝")],
default="pending"
)
reason = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
class AuthorizeIn(Schema):
user_id: int = Field(..., description="被授权的用户ID")
website_ids: List[int] = Field(..., description="要授权的网站ID列表")
class AccessRequestIn(Schema):
website_id: int = Field(...)
reason: Optional[str] = Field(None, description="申请原因")
@router.post("/authorize", auth=jwt_auth)
@manager_required @manager_required
def authorize_user(request, data: AuthorizeIn): def authorize_user(request, data: AuthorizeIn):
manager = request.user manager = request.user
@ -60,7 +36,7 @@ def authorize_user(request, data: AuthorizeIn):
} }
@router.post("/apply", auth=jwt_auth) @authorize_router.post("/apply", auth=jwt_auth)
@login_required @login_required
def request_access(request, data: AccessRequestIn): def request_access(request, data: AccessRequestIn):
user = request.user user = request.user
@ -75,7 +51,7 @@ def request_access(request, data: AccessRequestIn):
return {"success": True, "message": "申请已提交,等待分管理审批"} return {"success": True, "message": "申请已提交,等待分管理审批"}
@router.get("/pending", auth=jwt_auth) @authorize_router.get("/pending", auth=jwt_auth)
@manager_required @manager_required
def list_pending_requests(request): def list_pending_requests(request):
manager = request.user manager = request.user
@ -98,7 +74,7 @@ def list_pending_requests(request):
} }
@router.post("/approve", auth=jwt_auth) @authorize_router.post("/approve", auth=jwt_auth)
@manager_required @manager_required
def approve_request(request, request_id: int = Query(...), approve: bool = Query(True)): def approve_request(request, request_id: int = Query(...), approve: bool = Query(True)):
r = get_object_or_404(WebsiteAccessRequest, id=request_id) r = get_object_or_404(WebsiteAccessRequest, id=request_id)
@ -115,7 +91,7 @@ def approve_request(request, request_id: int = Query(...), approve: bool = Query
return {"success": True, "message": f"{'通过' if approve else '拒绝'} {r.user.username} 的访问申请"} return {"success": True, "message": f"{'通过' if approve else '拒绝'} {r.user.username} 的访问申请"}
@router.get("/my-sites", auth=jwt_auth) @authorize_router.get("/my-sites", auth=jwt_auth)
@login_required @login_required
def list_user_manager_websites(request): def list_user_manager_websites(request):
user = request.user user = request.user
@ -130,7 +106,33 @@ def list_user_manager_websites(request):
return {"success": True, "websites": list(sites)} return {"success": True, "websites": list(sites)}
@router.get("/public-sites") @authorize_router.get("/public-sites")
def list_public_websites(request): def list_public_websites(request):
websites = Website.objects.all().values("id", "name") websites = Website.objects.all().values("id", "name")
return {"success": True, "websites": list(websites)} 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": "申请已提交,等待审批"}

6
authorize/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class AuthorizeConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'authorize'

47
authorize/models.py Normal file
View File

@ -0,0 +1,47 @@
from django.db import models
from accounts.models import User
from websites.models import Website
from resumes.models import ResumeDetail
# Create your models here.
class WebsiteAccessRequest(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
website = models.ForeignKey(Website, on_delete=models.CASCADE)
updated_at = models.DateTimeField(auto_now=True)
status = models.CharField(
max_length=20,
choices=[("pending", "待审批"), ("approved", "已通过"), ("rejected", "已拒绝")],
default="pending"
)
reason = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = "网站访问申请"
verbose_name_plural = "网站访问申请"
def __str__(self):
return f"{self.user.username} 申请网站 {self.website.name} ({self.status})"
class ResumeDetailAccessRequest(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="申请用户")
resume = models.ForeignKey(ResumeDetail, on_delete=models.CASCADE, verbose_name="目标简历")
reason = models.TextField(blank=True, verbose_name="申请理由")
status = models.CharField(
max_length=20,
choices=[("pending", "待审批"), ("approved", "已通过"), ("rejected", "已拒绝")],
default="pending",
verbose_name="审批状态"
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="申请时间")
class Meta:
unique_together = ("user", "resume")
verbose_name = "简历详情访问申请"
verbose_name_plural = "简历详情访问申请"
def __str__(self):
return f"{self.user.username} 申请查看简历 {self.resume.id} ({self.status})"

18
authorize/schemas.py Normal file
View File

@ -0,0 +1,18 @@
from ninja import Schema, Query
from pydantic import Field
from typing import List, Optional
class AuthorizeIn(Schema):
user_id: int = Field(..., description="被授权的用户ID")
website_ids: List[int] = Field(..., description="要授权的网站ID列表")
class AccessRequestIn(Schema):
website_id: int = Field(...)
reason: Optional[str] = Field(None, description="申请原因")
class ResumeAccessRequestIn(Schema):
resume_id: int = Field(..., description="简历ID")
reason: Optional[str] = Field(None, description="申请理由")

3
authorize/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

3
authorize/views.py Normal file
View File

@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.

View File

@ -50,7 +50,8 @@ INSTALLED_APPS = [
'access_control', 'access_control',
'admin_panel', 'admin_panel',
'logs', 'logs',
'invites' 'invites',
'authorize'
] ]
MIDDLEWARE = [ MIDDLEWARE = [