修改简历详情

完善授权
This commit is contained in:
晓丰 2025-04-15 16:33:40 +08:00
parent ae6db6ec44
commit b6214de247
3 changed files with 136 additions and 26 deletions

View File

@ -1,21 +1,45 @@
# ✅ 授权管理接口manager 给 user 授权网站 + 普通用户申请接口
from ninja import Router, Schema, Query from ninja import Router, Schema, Query
from pydantic import Field from pydantic import Field
from typing import List 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 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 from utils.permissions import manager_required, login_required
router = Router(tags=["授权管理"]) router = Router(tags=["授权管理"])
# =========================
# 模型(授权申请)
# =========================
class WebsiteAccessRequest(models.Model):
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): class AuthorizeIn(Schema):
user_id: int = Field(..., description="被授权的用户ID") user_id: int = Field(..., description="被授权的用户ID")
website_ids: List[int] = Field(..., description="要授权的网站ID列表") website_ids: List[int] = Field(..., description="要授权的网站ID列表")
class AccessRequestIn(Schema):
website_id: int = Field(...)
reason: Optional[str] = Field(None, description="申请原因")
# =========================
# 授权接口POST
# =========================
@router.post("/authorize", auth=jwt_auth) @router.post("/authorize", auth=jwt_auth)
@manager_required @manager_required
def authorize_user(request, data: AuthorizeIn): def authorize_user(request, data: AuthorizeIn):
@ -24,6 +48,7 @@ def authorize_user(request, data: AuthorizeIn):
if target_user.role != "user": if target_user.role != "user":
return {"success": False, "message": "只能授权给普通用户"} return {"success": False, "message": "只能授权给普通用户"}
managed_ids = set(manager.managed_websites.values_list("id", flat=True)) managed_ids = set(manager.managed_websites.values_list("id", flat=True))
for wid in data.website_ids: for wid in data.website_ids:
if wid not in managed_ids: if wid not in managed_ids:
@ -31,44 +56,71 @@ def authorize_user(request, data: AuthorizeIn):
target_user.authorized_websites.add(*data.website_ids) target_user.authorized_websites.add(*data.website_ids)
# 如果用户曾申请过,设置为已批准
WebsiteAccessRequest.objects.filter(user=target_user, website_id__in=data.website_ids).update(status="approved")
return { return {
"success": True, "success": True,
"message": f"已授权 {target_user.username} 访问 {len(data.website_ids)} 个网站", "message": f"已授权 {target_user.username} 访问 {len(data.website_ids)} 个网站",
} }
@router.get("/authorized-sites", auth=jwt_auth) # =========================
# 用户发起申请POST
# =========================
@router.post("/apply", auth=jwt_auth)
@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": "您已申请,正在等待审批"}
WebsiteAccessRequest.objects.create(user=user, website=site, reason=data.reason or "")
return {"success": True, "message": "申请已提交,等待分管理审批"}
# =========================
# 分管理查看待审批列表
# =========================
@router.get("/pending", auth=jwt_auth)
@manager_required @manager_required
def get_user_authorized_sites(request, user_id: int = Query(...)): def list_pending_requests(request):
target_user = get_object_or_404(User, id=user_id)
if target_user.role != "user":
return {"success": False, "message": "只能查看普通用户的授权信息"}
sites = target_user.authorized_websites.all().values("id", "name", "db_alias")
return {
"success": True,
"user": target_user.username,
"authorized_websites": list(sites)
}
@router.post("/revoke", auth=jwt_auth)
@manager_required
def revoke_authorization(request, data: AuthorizeIn):
manager = request.user manager = request.user
target_user = get_object_or_404(User, id=data.user_id) managed_ids = manager.managed_websites.values_list("id", flat=True)
if target_user.role != "user": requests = WebsiteAccessRequest.objects.filter(website_id__in=managed_ids, status="pending")
return {"success": False, "message": "只能撤销普通用户的授权"}
managed_ids = set(manager.managed_websites.values_list("id", flat=True))
for wid in data.website_ids:
if wid not in managed_ids:
return {"success": False, "message": f"无权撤销网站ID{wid}"}
target_user.authorized_websites.remove(*data.website_ids)
return { return {
"success": True, "success": True,
"message": f"已撤销 {target_user.username}{len(data.website_ids)} 个授权网站" "items": [
{
"id": r.id,
"user": r.user.username,
"website": r.website.name,
"reason": r.reason,
"created_at": r.created_at,
}
for r in requests
]
} }
# =========================
# 分管理审批接口
# =========================
@router.post("/approve", auth=jwt_auth)
@manager_required
def approve_request(request, request_id: int = Query(...), approve: bool = Query(True)):
r = get_object_or_404(WebsiteAccessRequest, id=request_id)
if r.website not in request.user.managed_websites.all():
return {"success": False, "message": "无权审批此申请"}
r.status = "approved" if approve else "rejected"
r.save()
if approve:
r.user.authorized_websites.add(r.website)
return {"success": True, "message": f"{'通过' if approve else '拒绝'} {r.user.username} 的访问申请"}

42
resumes/api/detail.py Normal file
View File

@ -0,0 +1,42 @@
from ninja import Router
from ninja.errors import HttpError
from django.shortcuts import get_object_or_404
from resumes.models import ResumeBasic, ResumeDetail
from utils.auth import jwt_auth
from utils.permissions import login_required
router = Router(tags=["简历详情"])
@router.get("/{resume_id}", auth=jwt_auth)
@login_required
def get_resume_detail(request, resume_id: int):
user = request.user
resume = get_object_or_404(ResumeBasic, id=resume_id)
# ✅ 权限校验
if user.role == "admin":
pass
elif user.role == "manager":
if resume.source_id not in user.managed_websites.values_list("id", flat=True):
raise HttpError(403, "无权查看该简历")
elif user.role == "user":
if resume.source_id not in user.authorized_websites.values_list("id", flat=True):
raise HttpError(403, "无权查看该简历")
# ✅ 获取详情模型(可选)
detail = ResumeDetail.objects.filter(resume_id=resume.id).first()
return {
"id": resume.id,
"name": resume.name,
"age": resume.age,
"job_status": resume.job_status,
"source_id": resume.source_id,
"phone": detail.phone if detail else None,
"extra": {
"教育经历": getattr(detail, "education", None),
"项目经历": getattr(detail, "projects", None),
}
}

View File

@ -81,3 +81,19 @@ class ResumeBasic(models.Model):
class Meta: class Meta:
verbose_name = "简历" verbose_name = "简历"
verbose_name_plural = "简历列表" verbose_name_plural = "简历列表"
class ResumeDetail(models.Model):
resume = models.OneToOneField(
ResumeBasic,
on_delete=models.CASCADE,
primary_key=True,
related_name="detail",
verbose_name="简历"
)
phone = models.CharField(max_length=20, verbose_name="联系方式", blank=True)
education = models.TextField(verbose_name="教育经历", blank=True)
projects = models.TextField(verbose_name="项目经历", blank=True)
class Meta:
verbose_name = "简历详情"
verbose_name_plural = "简历详情"