修改简历详情
完善授权
This commit is contained in:
parent
ae6db6ec44
commit
b6214de247
@ -1,21 +1,45 @@
|
||||
# ✅ 授权管理接口:manager 给 user 授权网站 + 普通用户申请接口
|
||||
from ninja import Router, Schema, Query
|
||||
from pydantic import Field
|
||||
from typing import List
|
||||
from typing import List, Optional
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.db import models
|
||||
|
||||
from accounts.models import User
|
||||
from websites.models import Website
|
||||
from utils.auth import jwt_auth
|
||||
from utils.permissions import manager_required
|
||||
from utils.permissions import manager_required, login_required
|
||||
|
||||
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):
|
||||
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="申请原因")
|
||||
|
||||
# =========================
|
||||
# 授权接口(POST)
|
||||
# =========================
|
||||
@router.post("/authorize", auth=jwt_auth)
|
||||
@manager_required
|
||||
def authorize_user(request, data: AuthorizeIn):
|
||||
@ -24,6 +48,7 @@ def authorize_user(request, data: AuthorizeIn):
|
||||
|
||||
if target_user.role != "user":
|
||||
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:
|
||||
@ -31,44 +56,71 @@ 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 {
|
||||
"success": True,
|
||||
"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
|
||||
def get_user_authorized_sites(request, user_id: int = Query(...)):
|
||||
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):
|
||||
def list_pending_requests(request):
|
||||
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":
|
||||
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)
|
||||
requests = WebsiteAccessRequest.objects.filter(website_id__in=managed_ids, status="pending")
|
||||
|
||||
return {
|
||||
"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
42
resumes/api/detail.py
Normal 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),
|
||||
}
|
||||
}
|
@ -81,3 +81,19 @@ class ResumeBasic(models.Model):
|
||||
class Meta:
|
||||
verbose_name = "简历"
|
||||
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 = "简历详情"
|
Loading…
x
Reference in New Issue
Block a user