Merge branch 'v3' of github.com:jumpserver/jumpserver into v3

pull/8931/head
ibuler 2022-09-23 19:00:09 +08:00
commit f223cf43cc
5 changed files with 39 additions and 23 deletions

View File

@ -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')
@ -40,6 +44,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:

View File

@ -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

View File

@ -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)
@ -163,11 +163,14 @@ class UserGrantedAssetAccounts(ListAPIView):
def get_queryset(self):
# 获取用户-资产的授权规则
assetperms = AssetPermission.filter_permissions(self.user, self.asset)
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):

View File

@ -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'
]

View File

@ -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")
@ -232,17 +230,17 @@ class AssetPermission(OrgModelMixin):
return account_names
@classmethod
def filter_permissions(cls, user=None, asset=None, account=None):
def filter(cls, user=None, asset=None, account=None):
""" 获取同时包含 用户-资产-账号 的授权规则 """
assetperm_ids = []
if user:
user_assetperm_ids = cls.filter_permissions_by_user(user, flat=True)
user_assetperm_ids = cls.filter_by_user(user, flat=True)
assetperm_ids.append(user_assetperm_ids)
if asset:
asset_assetperm_ids = cls.filter_permissions_by_asset(asset, flat=True)
asset_assetperm_ids = cls.filter_by_asset(asset, flat=True)
assetperm_ids.append(asset_assetperm_ids)
if account:
account_assetperm_ids = cls.filter_permissions_by_account(account, flat=True)
account_assetperm_ids = cls.filter_by_account(account, flat=True)
assetperm_ids.append(account_assetperm_ids)
# & 是同时满足,比如有用户,但是用户的规则是空,那么返回也应该是空
assetperm_ids = list(reduce(lambda x, y: set(x) & set(y), assetperm_ids))
@ -250,7 +248,7 @@ class AssetPermission(OrgModelMixin):
return assetperms
@classmethod
def filter_permissions_by_user(cls, user, with_group=True, flat=False):
def filter_by_user(cls, user, with_group=True, flat=False):
assetperm_ids = set()
user_assetperm_ids = AssetPermission.users.through.objects \
.filter(user_id=user.id) \
@ -273,7 +271,7 @@ class AssetPermission(OrgModelMixin):
return assetperms
@classmethod
def filter_permissions_by_asset(cls, asset, with_node=True, flat=False):
def filter_by_asset(cls, asset, with_node=True, flat=False):
assetperm_ids = set()
asset_assetperm_ids = AssetPermission.assets.through.objects \
.filter(asset_id=asset.id) \
@ -294,8 +292,9 @@ class AssetPermission(OrgModelMixin):
return assetperms
@classmethod
def filter_permissions_by_account(cls, account, flat=False):
assetperms = cls.objects.filter(accounts__contains=account).valid()
def filter_by_account(cls, account, flat=False):
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