refactor: 添加授权相关的获取资产账号API、Model method

pull/8873/head
Jiangjie.Bai 2022-09-15 10:46:57 +08:00
parent a2c006f01b
commit d23446016d
8 changed files with 250 additions and 39 deletions

View File

@ -5,8 +5,10 @@
import logging import logging
import uuid import uuid
from functools import reduce from functools import reduce
from collections import Iterable
from django.db import models from django.db import models
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.utils import lazyproperty from common.utils import lazyproperty
@ -57,13 +59,17 @@ class NodesRelationMixin:
return nodes return nodes
def get_all_nodes(self, flat=False): def get_all_nodes(self, flat=False):
nodes = [] from ..node import Node
node_keys = set()
for node in self.get_nodes(): for node in self.get_nodes():
_nodes = node.get_ancestors(with_self=True) ancestor_keys = node.get_ancestor_keys(with_self=True)
nodes.append(_nodes) node_keys.update(ancestor_keys)
nodes = Node.objects.filter(key__in=node_keys).distinct()
if flat: if flat:
nodes = list(reduce(lambda x, y: set(x) | set(y), nodes)) node_ids = set(nodes.values_list('id', flat=True))
return nodes return node_ids
else:
return nodes
class Asset(AbsConnectivity, NodesRelationMixin, JMSOrgBaseModel): class Asset(AbsConnectivity, NodesRelationMixin, JMSOrgBaseModel):
@ -161,6 +167,14 @@ class Asset(AbsConnectivity, NodesRelationMixin, JMSOrgBaseModel):
tree_node = TreeNode(**data) tree_node = TreeNode(**data)
return tree_node return tree_node
def filter_accounts(self, account_names=None):
if account_names is None:
return self.accounts.all()
assert isinstance(account_names, Iterable), '`account_names` must be an iterable object'
queries = Q(name__in=account_names) | Q(username__in=account_names)
accounts = self.accounts.filter(queries)
return accounts
class Meta: class Meta:
unique_together = [('org_id', 'name')] unique_together = [('org_id', 'name')]
verbose_name = _("Asset") verbose_name = _("Asset")

View File

@ -3,6 +3,7 @@
import uuid import uuid
import time import time
from django.db.models import Q
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from rest_framework.views import APIView, Response from rest_framework.views import APIView, Response
@ -20,6 +21,7 @@ from common.utils import get_logger, lazyproperty
from perms.hands import User, Asset from perms.hands import User, Asset
from perms import serializers from perms import serializers
from perms.models import AssetPermission
logger = get_logger(__name__) logger = get_logger(__name__)
@ -28,6 +30,8 @@ __all__ = [
'ValidateUserAssetPermissionApi', 'ValidateUserAssetPermissionApi',
'GetUserAssetPermissionActionsApi', 'GetUserAssetPermissionActionsApi',
'MyGrantedAssetSystemUsersApi', 'MyGrantedAssetSystemUsersApi',
'UserGrantedAssetAccounts',
'MyGrantedAssetAccounts',
] ]
@ -138,3 +142,37 @@ class MyGrantedAssetSystemUsersApi(UserGrantedAssetSystemUsersForAdminApi):
def user(self): def user(self):
return self.request.user return self.request.user
class UserGrantedAssetAccounts(ListAPIView):
serializer_class = serializers.AccountsGrantedSerializer
rbac_perms = {
'list': 'perms.view_userassets'
}
@lazyproperty
def user(self):
user_id = self.kwargs.get('pk')
return User.objects.get(id=user_id)
@lazyproperty
def asset(self):
asset_id = self.kwargs.get('asset_id')
kwargs = {'id': asset_id, 'is_active': True}
asset = get_object_or_404(Asset, **kwargs)
return asset
def get_queryset(self):
# 获取用户-资产的授权规则
assetperms = AssetPermission.filter_permissions(self.user, self.asset)
account_names = AssetPermission.get_account_names(assetperms)
accounts = self.asset.filter_accounts(account_names)
# 构造默认包含的账号,如: @INPUT @USER
return accounts
class MyGrantedAssetAccounts(UserGrantedAssetAccounts):
permission_classes = (IsValidUser,)
@lazyproperty
def user(self):
return self.request.user

View File

@ -19,7 +19,7 @@ from perms.utils.user_permission import UserGrantedNodesQueryUtils
logger = get_logger(__name__) logger = get_logger(__name__)
__all__ = [ __all__ = [
'UserGrantedNodesForAdminApi', 'UserGrantedNodesApi',
'MyGrantedNodesApi', 'MyGrantedNodesApi',
'MyGrantedNodesAsTreeApi', 'MyGrantedNodesAsTreeApi',
'UserGrantedNodeChildrenForAdminApi', 'UserGrantedNodeChildrenForAdminApi',
@ -118,11 +118,11 @@ class MyGrantedNodeChildrenAsTreeApi(AssetRoleUserMixin, UserGrantedNodeChildren
return permissions return permissions
class UserGrantedNodesForAdminApi(AssetRoleAdminMixin, UserGrantedNodesMixin, BaseGrantedNodeApi): class UserGrantedNodesApi(AssetRoleAdminMixin, UserGrantedNodesMixin, BaseGrantedNodeApi):
pass pass
class MyGrantedNodesApi(AssetRoleUserMixin, UserGrantedNodesMixin, BaseGrantedNodeApi): class MyGrantedNodesApi(AssetRoleUserMixin, UserGrantedNodesApi):
pass pass

View File

@ -1,17 +1,17 @@
import uuid import uuid
import logging import logging
from functools import reduce
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.db import models from django.db import models
from django.db.models import F, Q, TextChoices from django.db.models import F, Q, TextChoices
from assets.models import Asset, Node, FamilyMixin from assets.models import Asset, Node, FamilyMixin, Account
from orgs.mixins.models import OrgModelMixin from orgs.mixins.models import OrgModelMixin
from orgs.mixins.models import OrgManager from orgs.mixins.models import OrgManager
from common.utils import lazyproperty, date_expired_default from common.utils import lazyproperty, date_expired_default
from common.db.models import BaseCreateUpdateModel, BitOperationChoice, UnionQuerySet from common.db.models import BaseCreateUpdateModel, BitOperationChoice, UnionQuerySet
__all__ = [ __all__ = [
'AssetPermission', 'PermNode', 'AssetPermission', 'PermNode',
'UserAssetGrantedTreeNodeRelation', 'UserAssetGrantedTreeNodeRelation',
@ -85,20 +85,27 @@ class AssetPermissionManager(OrgManager):
class AssetPermission(OrgModelMixin): class AssetPermission(OrgModelMixin):
id = models.UUIDField(default=uuid.uuid4, primary_key=True) id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(max_length=128, verbose_name=_('Name')) name = models.CharField(max_length=128, verbose_name=_('Name'))
users = models.ManyToManyField('users.User', blank=True, verbose_name=_("User"), related_name='%(class)ss') users = models.ManyToManyField('users.User', blank=True, verbose_name=_("User"),
user_groups = models.ManyToManyField('users.UserGroup', blank=True, verbose_name=_("User group"), related_name='%(class)ss') related_name='%(class)ss')
assets = models.ManyToManyField('assets.Asset', related_name='granted_by_permissions', blank=True, verbose_name=_("Asset")) user_groups = models.ManyToManyField('users.UserGroup', blank=True,
nodes = models.ManyToManyField('assets.Node', related_name='granted_by_permissions', blank=True, verbose_name=_("Nodes")) verbose_name=_("User group"), related_name='%(class)ss')
assets = models.ManyToManyField('assets.Asset', related_name='granted_by_permissions',
blank=True, verbose_name=_("Asset"))
nodes = models.ManyToManyField('assets.Node', related_name='granted_by_permissions', blank=True,
verbose_name=_("Nodes"))
# 只保存 @ALL (@INPUT @USER 默认包含,将来在全局设置中进行控制) # 只保存 @ALL (@INPUT @USER 默认包含,将来在全局设置中进行控制)
# 特殊的账号描述 # 特殊的账号描述
# ['@ALL',] # ['@ALL',]
# 指定账号授权 # 指定账号授权
# ['web', 'root',] # ['web', 'root',]
accounts = models.JSONField(default=list, verbose_name=_("Accounts")) accounts = models.JSONField(default=list, verbose_name=_("Accounts"))
actions = models.IntegerField(choices=Action.DB_CHOICES, default=Action.ALL, verbose_name=_("Actions")) actions = models.IntegerField(choices=Action.DB_CHOICES, default=Action.ALL,
verbose_name=_("Actions"))
is_active = models.BooleanField(default=True, verbose_name=_('Active')) is_active = models.BooleanField(default=True, verbose_name=_('Active'))
date_start = models.DateTimeField(default=timezone.now, db_index=True, verbose_name=_("Date start")) date_start = models.DateTimeField(default=timezone.now, db_index=True,
date_expired = models.DateTimeField(default=date_expired_default, db_index=True, verbose_name=_('Date expired')) verbose_name=_("Date start"))
date_expired = models.DateTimeField(default=date_expired_default, db_index=True,
verbose_name=_('Date expired'))
created_by = models.CharField(max_length=128, blank=True, verbose_name=_('Created by')) created_by = models.CharField(max_length=128, blank=True, verbose_name=_('Created by'))
date_created = models.DateTimeField(auto_now_add=True, verbose_name=_('Date created')) date_created = models.DateTimeField(auto_now_add=True, verbose_name=_('Date created'))
from_ticket = models.BooleanField(default=False, verbose_name=_('From ticket')) from_ticket = models.BooleanField(default=False, verbose_name=_('From ticket'))
@ -106,6 +113,11 @@ class AssetPermission(OrgModelMixin):
objects = AssetPermissionManager.from_queryset(AssetPermissionQuerySet)() objects = AssetPermissionManager.from_queryset(AssetPermissionQuerySet)()
class SpecialAccount(models.TextChoices):
ALL = '@ALL', 'All'
INPUT = '@INPUT', 'Input'
USER = '@USER', 'User'
class Meta: class Meta:
unique_together = [('org_id', 'name')] unique_together = [('org_id', 'name')]
verbose_name = _("Asset permission") verbose_name = _("Asset permission")
@ -174,14 +186,17 @@ class AssetPermission(OrgModelMixin):
models.Prefetch('assets', queryset=Asset.objects.all().only('id')), models.Prefetch('assets', queryset=Asset.objects.all().only('id')),
).order_by() ).order_by()
def get_all_assets(self): def get_all_assets(self, flat=False):
from assets.models import Node from assets.models import Node
nodes_keys = self.nodes.all().values_list('key', flat=True) nodes_keys = self.nodes.all().values_list('key', flat=True)
asset_ids = set(self.assets.all().values_list('id', flat=True)) asset_ids = set(self.assets.all().values_list('id', flat=True))
nodes_asset_ids = Node.get_nodes_all_asset_ids_by_keys(nodes_keys) nodes_asset_ids = Node.get_nodes_all_asset_ids_by_keys(nodes_keys)
asset_ids.update(nodes_asset_ids) asset_ids.update(nodes_asset_ids)
assets = Asset.objects.filter(id__in=asset_ids) if flat:
return assets return asset_ids
else:
assets = Asset.objects.filter(id__in=asset_ids)
return assets
def users_display(self): def users_display(self):
names = [user.username for user in self.users.all()] names = [user.username for user in self.users.all()]
@ -199,6 +214,94 @@ class AssetPermission(OrgModelMixin):
names = [node.full_value for node in self.nodes.all()] names = [node.full_value for node in self.nodes.all()]
return names return names
def get_asset_accounts(self):
asset_ids = self.get_all_assets(flat=True)
queries = Q(asset_id__in=asset_ids) \
& (Q(username__in=self.accounts) | Q(name__in=self.accounts))
accounts = Account.objects.filter(queries)
return accounts
@classmethod
def get_account_names(cls, perms):
account_names = set()
for perm in perms:
perm: cls
if not isinstance(perm.accounts, list):
continue
account_names.update(perm.accounts)
return account_names
@classmethod
def filter_permissions(cls, user=None, asset=None, account=None):
""" 获取同时包含 用户-资产-账号 的授权规则 """
assetperm_ids = []
if user:
user_assetperm_ids = cls.filter_permissions_by_user(user, flat=True)
assetperm_ids.append(user_assetperm_ids)
if asset:
asset_assetperm_ids = cls.filter_permissions_by_asset(asset, flat=True)
assetperm_ids.append(asset_assetperm_ids)
if account:
account_assetperm_ids = cls.filter_permissions_by_account(account, flat=True)
assetperm_ids.append(account_assetperm_ids)
# & 是同时满足,比如有用户,但是用户的规则是空,那么返回也应该是空
assetperm_ids = list(reduce(lambda x, y: set(x) & set(y), assetperm_ids))
assetperms = cls.objects.filter(id__in=assetperm_ids).valid().order_by('-date_expired')
return assetperms
@classmethod
def filter_permissions_by_user(cls, user, with_group=True, flat=False):
assetperm_ids = set()
user_assetperm_ids = AssetPermission.users.through.objects \
.filter(user_id=user.id) \
.values_list('assetpermission_id', flat=True) \
.distinct()
assetperm_ids.update(user_assetperm_ids)
if with_group:
usergroup_ids = user.get_groups(flat=True)
usergroups_assetperm_id = AssetPermission.user_groups.through.objects \
.filter(usergroup_id__in=usergroup_ids) \
.values_list('assetpermission_id', flat=True) \
.distinct()
assetperm_ids.update(usergroups_assetperm_id)
if flat:
return assetperm_ids
else:
assetperms = cls.objects.filter(id__in=assetperm_ids).valid()
return assetperms
@classmethod
def filter_permissions_by_asset(cls, asset, with_node=True, flat=False):
assetperm_ids = set()
asset_assetperm_ids = AssetPermission.assets.through.objects \
.filter(asset_id=asset.id) \
.values_list('assetpermission_id', flat=True)
assetperm_ids.update(asset_assetperm_ids)
if with_node:
node_ids = asset.get_all_nodes(flat=True)
node_assetperm_ids = AssetPermission.nodes.through.objects \
.filter(node_id__in=node_ids) \
.values_list('assetpermission_id', flat=True)
assetperm_ids.update(node_assetperm_ids)
if flat:
return assetperm_ids
else:
assetperms = cls.objects.filter(id__in=assetperm_ids).valid()
return assetperms
@classmethod
def filter_permissions_by_account(cls, account, flat=False):
assetperms = cls.objects.filter(accounts__contains=account).valid()
if flat:
assetperm_ids = assetperms.values_list('id', flat=True)
return assetperm_ids
else:
return assetperms
class UserAssetGrantedTreeNodeRelation(OrgModelMixin, FamilyMixin, BaseCreateUpdateModel): class UserAssetGrantedTreeNodeRelation(OrgModelMixin, FamilyMixin, BaseCreateUpdateModel):
class NodeFrom(TextChoices): class NodeFrom(TextChoices):
@ -210,7 +313,8 @@ class UserAssetGrantedTreeNodeRelation(OrgModelMixin, FamilyMixin, BaseCreateUpd
node = models.ForeignKey('assets.Node', default=None, on_delete=models.CASCADE, node = models.ForeignKey('assets.Node', default=None, on_delete=models.CASCADE,
db_constraint=False, null=False, related_name='granted_node_rels') db_constraint=False, null=False, related_name='granted_node_rels')
node_key = models.CharField(max_length=64, verbose_name=_("Key"), db_index=True) node_key = models.CharField(max_length=64, verbose_name=_("Key"), db_index=True)
node_parent_key = models.CharField(max_length=64, default='', verbose_name=_('Parent key'), db_index=True) node_parent_key = models.CharField(max_length=64, default='', verbose_name=_('Parent key'),
db_index=True)
node_from = models.CharField(choices=NodeFrom.choices, max_length=16, db_index=True) node_from = models.CharField(choices=NodeFrom.choices, max_length=16, db_index=True)
node_assets_amount = models.IntegerField(default=0) node_assets_amount = models.IntegerField(default=0)
@ -297,4 +401,3 @@ class PermedAsset(Asset):
('view_userassets', _('Can view user assets')), ('view_userassets', _('Can view user assets')),
('view_usergroupassets', _('Can view usergroup assets')), ('view_usergroupassets', _('Can view usergroup assets')),
] ]

View File

@ -4,20 +4,19 @@
from rest_framework import serializers from rest_framework import serializers
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from assets.models import Node, Asset, Platform from assets.models import Node, Asset, Platform, Account
from perms.serializers.permission import ActionsField from perms.serializers.permission import ActionsField
__all__ = [ __all__ = [
'NodeGrantedSerializer', 'NodeGrantedSerializer',
'AssetGrantedSerializer', 'AssetGrantedSerializer',
'ActionsSerializer', 'ActionsSerializer',
'AccountsGrantedSerializer'
] ]
class AssetGrantedSerializer(serializers.ModelSerializer): class AssetGrantedSerializer(serializers.ModelSerializer):
""" """ 被授权资产的数据结构 """
被授权资产的数据结构
"""
platform = serializers.SlugRelatedField( platform = serializers.SlugRelatedField(
slug_field='name', queryset=Platform.objects.all(), label=_("Platform") slug_field='name', queryset=Platform.objects.all(), label=_("Platform")
) )
@ -44,3 +43,14 @@ class NodeGrantedSerializer(serializers.ModelSerializer):
class ActionsSerializer(serializers.Serializer): class ActionsSerializer(serializers.Serializer):
actions = ActionsField(read_only=True) actions = ActionsField(read_only=True)
class AccountsGrantedSerializer(serializers.ModelSerializer):
""" 授权的账号序列类 """
# Todo: 添加前端登录逻辑中需要的一些字段,比如:是否需要手动输入密码
# need_manual = serializers.BooleanField(label=_('Need manual input'))
class Meta:
model = Account
fields = ['id', 'name', 'username']
read_only_fields = fields

View File

@ -5,7 +5,6 @@ from rest_framework_bulk.routes import BulkRouter
from .. import api from .. import api
# v3 Done
router = BulkRouter() router = BulkRouter()
router.register('asset-permissions', api.AssetPermissionViewSet, 'asset-permission') router.register('asset-permissions', api.AssetPermissionViewSet, 'asset-permission')
router.register('asset-permissions-users-relations', api.AssetPermissionUserRelationViewSet, 'asset-permissions-users-relation') router.register('asset-permissions-users-relations', api.AssetPermissionUserRelationViewSet, 'asset-permissions-users-relation')
@ -14,42 +13,31 @@ router.register('asset-permissions-assets-relations', api.AssetPermissionAssetRe
router.register('asset-permissions-nodes-relations', api.AssetPermissionNodeRelationViewSet, 'asset-permissions-nodes-relation') router.register('asset-permissions-nodes-relations', api.AssetPermissionNodeRelationViewSet, 'asset-permissions-nodes-relation')
user_permission_urlpatterns = [ user_permission_urlpatterns = [
# 统一说明:
# `<uuid:pk>`: `User.pk`
# 直接授权:在 `AssetPermission` 中关联的对象
# ---------------------------------------------------------
# 以 serializer 格式返回 # 以 serializer 格式返回
path('<uuid:pk>/assets/', api.UserAllGrantedAssetsApi.as_view(), name='user-assets'), path('<uuid:pk>/assets/', api.UserAllGrantedAssetsApi.as_view(), name='user-assets'),
path('assets/', api.MyAllGrantedAssetsApi.as_view(), name='my-assets'), path('assets/', api.MyAllGrantedAssetsApi.as_view(), name='my-assets'),
# Tree Node 的数据格式返回 # Tree Node 的数据格式返回
path('<uuid:pk>/assets/tree/', api.UserDirectGrantedAssetsAsTreeApi.as_view(), name='user-assets-as-tree'), path('<uuid:pk>/assets/tree/', api.UserDirectGrantedAssetsAsTreeApi.as_view(), name='user-assets-as-tree'),
path('assets/tree/', api.MyAllAssetsAsTreeApi.as_view(), name='my-assets-as-tree'), path('assets/tree/', api.MyAllAssetsAsTreeApi.as_view(), name='my-assets-as-tree'),
path('ungroup/assets/tree/', api.MyUngroupAssetsAsTreeApi.as_view(), name='my-ungroup-assets-as-tree'), path('ungroup/assets/tree/', api.MyUngroupAssetsAsTreeApi.as_view(), name='my-ungroup-assets-as-tree'),
# ^--------------------------------------------------------^
# 获取用户所有`直接授权的节点`与`直接授权资产`关联的节点 # 获取用户所有`直接授权的节点`与`直接授权资产`关联的节点
# 以 serializer 格式返回 # 以 serializer 格式返回
path('<uuid:pk>/nodes/', api.UserGrantedNodesForAdminApi.as_view(), name='user-nodes'), path('<uuid:pk>/nodes/', api.UserGrantedNodesApi.as_view(), name='user-nodes'),
path('nodes/', api.MyGrantedNodesApi.as_view(), name='my-nodes'), path('nodes/', api.MyGrantedNodesApi.as_view(), name='my-nodes'),
# 以 Tree Node 的数据格式返回 # 以 Tree Node 的数据格式返回
path('<uuid:pk>/nodes/tree/', api.MyGrantedNodesAsTreeApi.as_view(), name='user-nodes-as-tree'), path('<uuid:pk>/nodes/tree/', api.MyGrantedNodesAsTreeApi.as_view(), name='user-nodes-as-tree'),
path('nodes/tree/', api.MyGrantedNodesAsTreeApi.as_view(), name='my-nodes-as-tree'), path('nodes/tree/', api.MyGrantedNodesAsTreeApi.as_view(), name='my-nodes-as-tree'),
# ^--------------------------------------------------------^
# 一层一层的获取用户授权的节点, # 一层一层的获取用户授权的节点,
# 以 Serializer 的数据格式返回 # 以 Serializer 的数据格式返回
path('<uuid:pk>/nodes/children/', api.UserGrantedNodeChildrenForAdminApi.as_view(), name='user-nodes-children'), path('<uuid:pk>/nodes/children/', api.UserGrantedNodeChildrenForAdminApi.as_view(), name='user-nodes-children'),
path('nodes/children/', api.MyGrantedNodeChildrenApi.as_view(), name='my-nodes-children'), path('nodes/children/', api.MyGrantedNodeChildrenApi.as_view(), name='my-nodes-children'),
# 以 Tree Node 的数据格式返回 # 以 Tree Node 的数据格式返回
path('<uuid:pk>/nodes/children/tree/', api.UserGrantedNodeChildrenAsTreeForAdminApi.as_view(), name='user-nodes-children-as-tree'), path('<uuid:pk>/nodes/children/tree/', api.UserGrantedNodeChildrenAsTreeForAdminApi.as_view(), name='user-nodes-children-as-tree'),
# 部分调用位置 # 部分调用位置
# - 普通用户 -> 我的资产 -> 展开节点 时调用 # - 普通用户 -> 我的资产 -> 展开节点 时调用
path('nodes/children/tree/', api.MyGrantedNodeChildrenAsTreeApi.as_view(), name='my-nodes-children-as-tree'), path('nodes/children/tree/', api.MyGrantedNodeChildrenAsTreeApi.as_view(), name='my-nodes-children-as-tree'),
# ^--------------------------------------------------------^
# 此接口会返回整棵树 # 此接口会返回整棵树
# 普通用户 -> 命令执行 -> 左侧树 # 普通用户 -> 命令执行 -> 左侧树
@ -75,6 +63,11 @@ user_permission_urlpatterns = [
# Asset System users # Asset System users
path('<uuid:pk>/assets/<uuid:asset_id>/system-users/', api.UserGrantedAssetSystemUsersForAdminApi.as_view(), name='user-asset-system-users'), path('<uuid:pk>/assets/<uuid:asset_id>/system-users/', api.UserGrantedAssetSystemUsersForAdminApi.as_view(), name='user-asset-system-users'),
path('assets/<uuid:asset_id>/system-users/', api.MyGrantedAssetSystemUsersApi.as_view(), name='my-asset-system-users'), path('assets/<uuid:asset_id>/system-users/', api.MyGrantedAssetSystemUsersApi.as_view(), name='my-asset-system-users'),
# Todo: 增加
# 获取所有和资产相关联的账号列表
path('<uuid:pk>/assets/<uuid:asset_id>/accounts/', api.UserGrantedAssetAccounts.as_view(), name='user-asset-accounts'),
path('assets/<uuid:asset_id>/accounts/', api.MyGrantedAssetAccounts.as_view(), name='my-asset-accounts')
] ]
user_group_permission_urlpatterns = [ user_group_permission_urlpatterns = [

View File

@ -918,6 +918,21 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser):
return True return True
return False return False
def get_groups(self, flat=False):
from users.models import UserGroup
usergroup_ids = self.groups.through.objects\
.filter(user_id=self.id)\
.distinct()\
.values_list('usergroup_id', flat=True)
usergroups = UserGroup.objects.filter(id__in=usergroup_ids)
if flat:
usergroup_ids = usergroups.values_list('id', flat=True)
return usergroup_ids
else:
return usergroups
class UserPasswordHistory(models.Model): class UserPasswordHistory(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True) id = models.UUIDField(default=uuid.uuid4, primary_key=True)

38
generateV3Data.py Normal file
View File

@ -0,0 +1,38 @@
#!/usr/bin/env python
#
# >>> Django 环境配置
import django
import os
import sys
if os.path.exists('../apps'):
sys.path.insert(0, '../apps')
elif os.path.exists('./apps'):
sys.path.insert(0, './apps')
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
APPS_DIR = os.path.join(BASE_DIR, 'apps')
sys.path.insert(0, APPS_DIR)
os.environ.setdefault('PYTHONOPTIMIZE', '1')
if os.getuid() == 0:
os.environ.setdefault('C_FORCE_ROOT', '1')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jumpserver.settings")
django.setup()
# <<<
class Generator(object):
def generate(self):
pass
def generate_assets(self):
pass
if __name__ == '__main__':
pass