feat(asset): 公司资产权限收敛——仅管理员可见
- 菜单:'公司资产'目录仅 IsCompanyAdmin(admin:company/tenant/super)可见,普通用户隐藏 - 数据范围:FileAssetViewSet 按角色——admin:super 全部 / admin:tenant 本租户所有公司 / admin:company 本公司 / 其他 403 - 上传:Init 管理员校验;Complete/SimpleUpload 归属公司强制解析(租户管理员可指定本租户公司,公司管理员仅本公司)
This commit is contained in:
1 parent
6ec24c8bb3
commit
8775cb37d9
3 files changed
+82
-2
No files matched your search
@@ -11,10 +11,51 @@ from gvsdsdk.model_utils import UUIDObj
|
||||
from . import ELTAuthenticatedAPIView
|
||||
|
||||
|
||||
def _RequireAssetAdmin(request):
|
||||
"""公司资产上传仅公司管理员/租户管理员可用"""
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
from gvsdsdk.auth.admin_service import IsCompanyAdmin
|
||||
if not IsCompanyAdmin(request=request):
|
||||
raise PermissionDenied('需要公司管理员或租户管理员权限')
|
||||
|
||||
|
||||
def _ResolveAssetCompany(request):
|
||||
"""上传归属公司解析:仅公司管理员/租户管理员可用。
|
||||
- 租户管理员:可指定本租户任意公司;不传则用当前公司上下文
|
||||
- 公司管理员:仅本公司(前端传入必须匹配)
|
||||
- 其他用户:403
|
||||
"""
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
from gvsdsdk.auth.admin_service import IsTenantAdmin, IsCompanyAdmin
|
||||
from gvsdsdk.models import Company as SdkCompany
|
||||
if not IsCompanyAdmin(request=request):
|
||||
raise PermissionDenied('需要公司管理员或租户管理员权限')
|
||||
claimed = (request.data.get('CompanyUUID') or '').strip()
|
||||
claimed_bytes = UUIDObj(claimed).bytes if claimed else None
|
||||
cur_company = getattr(request, 'current_company_uuid', None)
|
||||
if IsTenantAdmin(request=request):
|
||||
tenant_uuid = getattr(request, 'current_tenant_uuid', None)
|
||||
if claimed_bytes:
|
||||
tb = UUIDObj(tenant_uuid).bytes if tenant_uuid else None
|
||||
if tb is None or not SdkCompany.objects.filter(CompanyUUID=claimed_bytes, TenantUUID=tb).exists():
|
||||
raise PermissionDenied('目标公司不在本租户')
|
||||
return claimed_bytes
|
||||
if cur_company:
|
||||
return UUIDObj(cur_company).bytes
|
||||
raise PermissionDenied('缺少 CompanyUUID')
|
||||
if cur_company:
|
||||
cb = UUIDObj(cur_company).bytes
|
||||
if claimed_bytes and claimed_bytes != cb:
|
||||
raise PermissionDenied('仅可上传到本公司')
|
||||
return cb
|
||||
raise PermissionDenied('缺少公司上下文')
|
||||
|
||||
|
||||
class AssetUploadInitView(ELTAuthenticatedAPIView):
|
||||
"""上传初始化视图——创建分片上传会话"""
|
||||
|
||||
def post(self, request):
|
||||
_RequireAssetAdmin(request)
|
||||
file_name = request.data.get('FileName', '')
|
||||
file_size = request.data.get('FileSize', 0)
|
||||
mime_type = request.data.get('MimeType', 'application/octet-stream')
|
||||
@@ -134,7 +175,7 @@ class AssetUploadCompleteView(ELTAuthenticatedAPIView):
|
||||
total_size += len(data)
|
||||
file_sha1 = sha1.hexdigest()
|
||||
user_uuid = request.user.UserUUID
|
||||
company_uuid = request.data.get('CompanyUUID')
|
||||
company_uuid = _ResolveAssetCompany(request)
|
||||
from gvsdsdk.auth.managers import AssetManager
|
||||
asset, created = AssetManager.EnsureAsset(
|
||||
file_sha1, file_name, total_size, mime_type, final_path,
|
||||
@@ -182,7 +223,7 @@ class AssetSimpleUploadView(ELTAuthenticatedAPIView):
|
||||
file_name = upload_file.name
|
||||
mime_type = upload_file.content_type or 'application/octet-stream'
|
||||
user_uuid = request.user.UserUUID
|
||||
company_uuid = request.data.get('CompanyUUID')
|
||||
company_uuid = _ResolveAssetCompany(request)
|
||||
|
||||
sha1 = hashlib.sha1()
|
||||
final_dir = os.path.join(settings.MEDIA_ROOT, 'assets')
|
||||
|
||||
@@ -128,6 +128,15 @@ class MenuListCompatView(ELTAuthenticatedAPIView):
|
||||
perm_attr_str = item['PermAttr']
|
||||
perm_attrs = [a.strip() for a in perm_attr_str.split(';') if a.strip()] if perm_attr_str else []
|
||||
if not perm_attrs:
|
||||
# 公司资产目录:仅公司管理员/租户管理员可见(普通用户隐藏)
|
||||
if item['Title'] == '公司资产':
|
||||
from gvsdsdk.auth.admin_service import IsCompanyAdmin
|
||||
try:
|
||||
if not IsCompanyAdmin(request=request, user=user, role_uuid=role_uuid_bytes):
|
||||
no_perm_uuids.add(uuid_str)
|
||||
except Exception:
|
||||
logger.exception('MenuListCompatView 公司资产菜单校验异常 uuid=%s', uuid_str)
|
||||
no_perm_uuids.add(uuid_str)
|
||||
continue
|
||||
if 'admin:super' in perm_attrs:
|
||||
from gvsdsdk.auth.admin_service import IsSuperAdmin
|
||||
|
||||
@@ -574,6 +574,36 @@ class FileAssetViewSet(CompanyScopedMixin, viewsets.ModelViewSet):
|
||||
serializer_class = FileAssetSerializer
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_queryset(self):
|
||||
"""公司资产数据范围:
|
||||
- 跨租户管理员(admin:super):全部
|
||||
- 租户管理员(admin:tenant):本租户所有公司资产
|
||||
- 公司管理员(admin:company):本公司资产
|
||||
- 其他用户:无权限(403)
|
||||
"""
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
from gvsdsdk.auth.admin_service import IsSuperAdmin, IsTenantAdmin, IsCompanyAdmin
|
||||
from gvsdsdk.models import Company as SdkCompany
|
||||
from gvsdsdk.model_utils import UUIDObj as _U
|
||||
qs = SdkFileAsset.objects.all()
|
||||
user = getattr(self.request, 'user', None)
|
||||
if IsSuperAdmin(request=self.request, user=user):
|
||||
return qs
|
||||
if IsTenantAdmin(request=self.request, user=user):
|
||||
tenant_uuid = getattr(self.request, 'current_tenant_uuid', None)
|
||||
if not tenant_uuid:
|
||||
return qs.none()
|
||||
tb = _U(tenant_uuid).bytes
|
||||
companies = SdkCompany.objects.filter(TenantUUID=tb).values_list('CompanyUUID', flat=True)
|
||||
company_bytes = [c.bytes if hasattr(c, 'bytes') else c for c in companies]
|
||||
return qs.filter(CompanyUUID__in=company_bytes)
|
||||
if IsCompanyAdmin(request=self.request, user=user):
|
||||
company_uuid = getattr(self.request, 'current_company_uuid', None)
|
||||
if not company_uuid:
|
||||
return qs.none()
|
||||
return qs.filter(CompanyUUID=_U(company_uuid).bytes)
|
||||
raise PermissionDenied('需要公司管理员或租户管理员权限')
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
page_num = int(request.query_params.get('page', 1))
|
||||
page_size = int(request.query_params.get('pageSize', 24))
|
||||
|
||||
Reference in new issue
Block a user