diff --git a/apps/assets/models/account.py b/apps/assets/models/account.py index 3159cc3b6..12ab80412 100644 --- a/apps/assets/models/account.py +++ b/apps/assets/models/account.py @@ -9,6 +9,10 @@ __all__ = ['Account', 'AccountTemplate'] class Account(BaseAccount): + class InnerAccount(models.TextChoices): + INPUT = '@INPUT', '@INPUT' + USER = '@USER', '@USER' + asset = models.ForeignKey( 'assets.Asset', related_name='accounts', on_delete=models.CASCADE, verbose_name=_('Asset') @@ -44,6 +48,16 @@ class Account(BaseAccount): def __str__(self): return '{}@{}'.format(self.username, self.asset.name) + @classmethod + def get_input_account(cls): + """ @INPUT 手动登录的账号(any) """ + return cls(name=cls.InnerAccount.INPUT.value, username='') + + @classmethod + def get_user_account(cls, username): + """ @USER 动态用户的账号(self) """ + return cls(name=cls.InnerAccount.USER.value, username=username) + class AccountTemplate(BaseAccount): class Meta: diff --git a/apps/assets/models/asset/common.py b/apps/assets/models/asset/common.py index f94143c6e..163d1a873 100644 --- a/apps/assets/models/asset/common.py +++ b/apps/assets/models/asset/common.py @@ -4,8 +4,6 @@ import logging import uuid -from functools import reduce -from collections import Iterable from django.db import models from django.db.models import Q @@ -180,9 +178,11 @@ class Asset(AbsConnectivity, NodesRelationMixin, JMSOrgBaseModel): return tree_node def filter_accounts(self, account_names=None): + from perms.models import AssetPermission if account_names is None: return self.accounts.all() - assert isinstance(account_names, Iterable), '`account_names` must be an iterable object' + if AssetPermission.SpecialAccount.ALL in account_names: + return self.accounts.all() queries = Q(name__in=account_names) | Q(username__in=account_names) accounts = self.accounts.filter(queries) return accounts diff --git a/apps/perms/api/user_permission/common.py b/apps/perms/api/user_permission/common.py index 2e4ff90fb..962d079bb 100644 --- a/apps/perms/api/user_permission/common.py +++ b/apps/perms/api/user_permission/common.py @@ -19,7 +19,7 @@ from perms.utils.permission import ( from common.permissions import IsValidUser from common.utils import get_logger, lazyproperty -from perms.hands import User, Asset +from perms.hands import User, Asset, Account from perms import serializers from perms.models import AssetPermission @@ -150,7 +150,7 @@ class UserGrantedAssetAccounts(ListAPIView): } @lazyproperty - def user(self): + def user(self) -> User: user_id = self.kwargs.get('pk') return User.objects.get(id=user_id) @@ -165,9 +165,12 @@ class UserGrantedAssetAccounts(ListAPIView): # 获取用户-资产的授权规则 assetperms = AssetPermission.filter(self.user, self.asset) account_names = AssetPermission.get_account_names(assetperms) - accounts = self.asset.filter_accounts(account_names) + accounts = list(self.asset.filter_accounts(account_names)) + # @INPUT @USER + inner_accounts = [Account.get_input_account(), Account.get_user_account(self.user.username)] + all_accounts = accounts + inner_accounts # 构造默认包含的账号,如: @INPUT @USER - return accounts + return all_accounts class MyGrantedAssetAccounts(UserGrantedAssetAccounts): diff --git a/apps/perms/hands.py b/apps/perms/hands.py index 1537b7260..dabb9f7c0 100644 --- a/apps/perms/hands.py +++ b/apps/perms/hands.py @@ -2,12 +2,12 @@ # from users.models import User, UserGroup -from assets.models import Asset, Node, Label, FavoriteAsset +from assets.models import Asset, Node, Label, FavoriteAsset, Account from assets.serializers import NodeSerializer __all__ = [ 'User', 'UserGroup', 'Asset', 'Node', 'Label', 'FavoriteAsset', - 'NodeSerializer', + 'NodeSerializer', 'Account' ] diff --git a/apps/perms/models/asset_permission.py b/apps/perms/models/asset_permission.py index d83cd84b3..fe9d1b1b7 100644 --- a/apps/perms/models/asset_permission.py +++ b/apps/perms/models/asset_permission.py @@ -83,6 +83,9 @@ class AssetPermissionManager(OrgManager): class AssetPermission(OrgModelMixin): + class SpecialAccount(models.TextChoices): + ALL = '@ALL', 'All' + id = models.UUIDField(default=uuid.uuid4, primary_key=True) name = models.CharField(max_length=128, verbose_name=_('Name')) users = models.ManyToManyField('users.User', blank=True, verbose_name=_("User"), @@ -113,11 +116,6 @@ class AssetPermission(OrgModelMixin): objects = AssetPermissionManager.from_queryset(AssetPermissionQuerySet)() - class SpecialAccount(models.TextChoices): - ALL = '@ALL', 'All' - INPUT = '@INPUT', 'Input' - USER = '@USER', 'User' - class Meta: unique_together = [('org_id', 'name')] verbose_name = _("Asset permission") @@ -295,7 +293,8 @@ class AssetPermission(OrgModelMixin): @classmethod def filter_by_account(cls, account, flat=False): - assetperms = cls.objects.filter(accounts__contains=account).valid() + queries = Q(accounts__contains=account) | Q(accounts__contains=cls.SpecialAccount.ALL.value) + assetperms = cls.objects.filter(queries).valid() if flat: assetperm_ids = assetperms.values_list('id', flat=True) return assetperm_ids