完善Bug 和 普通用户 所有网站的视图
This commit is contained in:
parent
e18d7a20dc
commit
8a95eb6a7d
4
api.py
4
api.py
@ -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
0
authorize/__init__.py
Normal file
18
authorize/admin.py
Normal file
18
authorize/admin.py
Normal 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')
|
0
authorize/api/__init__.py
Normal file
0
authorize/api/__init__.py
Normal 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
6
authorize/apps.py
Normal 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
47
authorize/models.py
Normal 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
18
authorize/schemas.py
Normal 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
3
authorize/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
3
authorize/views.py
Normal file
3
authorize/views.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.shortcuts import render
|
||||||
|
|
||||||
|
# Create your views here.
|
@ -50,7 +50,8 @@ INSTALLED_APPS = [
|
|||||||
'access_control',
|
'access_control',
|
||||||
'admin_panel',
|
'admin_panel',
|
||||||
'logs',
|
'logs',
|
||||||
'invites'
|
'invites',
|
||||||
|
'authorize'
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user