Merge pull request #7844 from jumpserver/dev

v2.20.0-rc3
pull/7919/head
Jiangjie.Bai 2022-03-15 11:37:30 +08:00 committed by GitHub
commit c77f02b295
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 436 additions and 471 deletions

View File

@ -7,6 +7,7 @@ from django.db.models import F, Q
from common.drf.filters import BaseFilterSet from common.drf.filters import BaseFilterSet
from common.drf.api import JMSBulkModelViewSet from common.drf.api import JMSBulkModelViewSet
from rbac.permissions import RBACPermission from rbac.permissions import RBACPermission
from assets.models import SystemUser
from ..models import Account from ..models import Account
from ..hands import NeedMFAVerify from ..hands import NeedMFAVerify
from .. import serializers from .. import serializers
@ -49,6 +50,10 @@ class ApplicationAccountViewSet(JMSBulkModelViewSet):
return queryset return queryset
class SystemUserAppRelationViewSet(ApplicationAccountViewSet):
perm_model = SystemUser
class ApplicationAccountSecretViewSet(ApplicationAccountViewSet): class ApplicationAccountSecretViewSet(ApplicationAccountViewSet):
serializer_class = serializers.AppAccountSecretSerializer serializer_class = serializers.AppAccountSecretSerializer
permission_classes = [RBACPermission, NeedMFAVerify] permission_classes = [RBACPermission, NeedMFAVerify]

View File

@ -12,7 +12,7 @@ class Migration(migrations.Migration):
operations = [ operations = [
migrations.AlterModelOptions( migrations.AlterModelOptions(
name='account', name='account',
options={'permissions': [('view_applicationaccountsecret', 'Can view application account secret'), ('change_appplicationaccountsecret', 'Can view application account secret')], 'verbose_name': 'Application account'}, options={'permissions': [('view_applicationaccountsecret', 'Can view application account secret'), ('change_appplicationaccountsecret', 'Can change application account secret')], 'verbose_name': 'Application account'},
), ),
migrations.AlterModelOptions( migrations.AlterModelOptions(
name='applicationuser', name='applicationuser',

View File

@ -24,7 +24,7 @@ class Account(BaseUser):
unique_together = [('username', 'app', 'systemuser')] unique_together = [('username', 'app', 'systemuser')]
permissions = [ permissions = [
('view_applicationaccountsecret', _('Can view application account secret')), ('view_applicationaccountsecret', _('Can view application account secret')),
('change_appplicationaccountsecret', _('Can view application account secret')), ('change_appplicationaccountsecret', _('Can change application account secret')),
] ]
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):

View File

@ -11,6 +11,7 @@ app_name = 'applications'
router = BulkRouter() router = BulkRouter()
router.register(r'applications', api.ApplicationViewSet, 'application') router.register(r'applications', api.ApplicationViewSet, 'application')
router.register(r'accounts', api.ApplicationAccountViewSet, 'application-account') router.register(r'accounts', api.ApplicationAccountViewSet, 'application-account')
router.register(r'system-users-apps-relations', api.SystemUserAppRelationViewSet, 'system-users-apps-relation')
router.register(r'account-secrets', api.ApplicationAccountSecretViewSet, 'application-account-secret') router.register(r'account-secrets', api.ApplicationAccountSecretViewSet, 'application-account-secret')

View File

@ -64,7 +64,8 @@ class AccountViewSet(OrgBulkModelViewSet):
'verify_account': serializers.AssetTaskSerializer 'verify_account': serializers.AssetTaskSerializer
} }
rbac_perms = { rbac_perms = {
'verify_account': 'assets.add_authbook' 'verify_account': 'assets.test_authbook',
'PATCH': 'assets.change_assetaccountsecret'
} }
def get_queryset(self): def get_queryset(self):

View File

@ -38,7 +38,7 @@ class SuggestionMixin:
class RenderToJsonMixin: class RenderToJsonMixin:
@action(methods=[POST], detail=False, url_path='render-to-json') @action(methods=[POST], detail=False, url_path='render-to-json')
def render_to_json(self, request: Request): def render_to_json(self, request: Request, *args, **kwargs):
data = { data = {
'title': (), 'title': (),
'data': request.data, 'data': request.data,

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:a885732955761c2942989a3e93751709e2be4ec75504bd009406671b93e0bfda oid sha256:675f93d2cc6b2049fdafc7f6b70edb8f73bbe132de9b91e98f2ec7acb2e89620
size 107544 size 104134

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,7 @@ from django.conf import settings
from assets.models import Asset, Node from assets.models import Asset, Node
from orgs.mixins.api import RootOrgViewMixin from orgs.mixins.api import RootOrgViewMixin
from common.permissions import IsValidUser from common.permissions import IsValidUser
from rbac.permissions import RBACPermission
from ..models import CommandExecution from ..models import CommandExecution
from ..serializers import CommandExecutionSerializer from ..serializers import CommandExecutionSerializer
from ..tasks import run_command_execution from ..tasks import run_command_execution
@ -17,12 +18,10 @@ from ..tasks import run_command_execution
class CommandExecutionViewSet(RootOrgViewMixin, viewsets.ModelViewSet): class CommandExecutionViewSet(RootOrgViewMixin, viewsets.ModelViewSet):
serializer_class = CommandExecutionSerializer serializer_class = CommandExecutionSerializer
permission_classes = (IsValidUser,) permission_classes = (RBACPermission,)
def get_queryset(self): def get_queryset(self):
return CommandExecution.objects.filter( return CommandExecution.objects.filter(user_id=str(self.request.user.id))
user_id=str(self.request.user.id)
)
def check_hosts(self, serializer): def check_hosts(self, serializer):
data = serializer.validated_data data = serializer.validated_data
@ -36,11 +35,7 @@ class CommandExecutionViewSet(RootOrgViewMixin, viewsets.ModelViewSet):
) )
permed_assets = set() permed_assets = set()
permed_assets.update( permed_assets.update(Asset.objects.filter(id__in=[a.id for a in assets]).filter(q).distinct())
Asset.objects.filter(
id__in=[a.id for a in assets]
).filter(q).distinct()
)
node_keys = Node.objects.filter(q).distinct().values_list('key', flat=True) node_keys = Node.objects.filter(q).distinct().values_list('key', flat=True)
nodes_assets_q = Q() nodes_assets_q = Q()

View File

@ -16,7 +16,7 @@ from perms.utils.application.permission import (
get_application_system_user_ids, get_application_system_user_ids,
validate_permission, validate_permission,
) )
from .mixin import RoleAdminMixin, RoleUserMixin from .mixin import AppRoleAdminMixin, AppRoleUserMixin
from perms.hands import User, SystemUser from perms.hands import User, SystemUser
from perms import serializers from perms import serializers
@ -45,11 +45,11 @@ class BaseGrantedApplicationSystemUsersApi(ListAPIView):
return system_users return system_users
class UserGrantedApplicationSystemUsersApi(RoleAdminMixin, BaseGrantedApplicationSystemUsersApi): class UserGrantedApplicationSystemUsersApi(AppRoleAdminMixin, BaseGrantedApplicationSystemUsersApi):
pass pass
class MyGrantedApplicationSystemUsersApi(RoleUserMixin, BaseGrantedApplicationSystemUsersApi): class MyGrantedApplicationSystemUsersApi(AppRoleUserMixin, BaseGrantedApplicationSystemUsersApi):
pass pass

View File

@ -6,7 +6,7 @@ from common.mixins.api import RoleUserMixin as _RoleUserMixin
from orgs.utils import tmp_to_root_org from orgs.utils import tmp_to_root_org
class RoleAdminMixin(_RoleAdminMixin): class AppRoleAdminMixin(_RoleAdminMixin):
rbac_perms = ( rbac_perms = (
('list', 'perms.view_userapp'), ('list', 'perms.view_userapp'),
('retrieve', 'perms.view_userapps'), ('retrieve', 'perms.view_userapps'),
@ -15,7 +15,7 @@ class RoleAdminMixin(_RoleAdminMixin):
) )
class RoleUserMixin(_RoleUserMixin): class AppRoleUserMixin(_RoleUserMixin):
rbac_perms = ( rbac_perms = (
('list', 'perms.view_myapps'), ('list', 'perms.view_myapps'),
('retrieve', 'perms.view_myapps'), ('retrieve', 'perms.view_myapps'),

View File

@ -9,7 +9,7 @@ from applications.api.mixin import (
SerializeApplicationToTreeNodeMixin SerializeApplicationToTreeNodeMixin
) )
from perms import serializers from perms import serializers
from perms.api.asset.user_permission.mixin import RoleAdminMixin, RoleUserMixin from .mixin import AppRoleAdminMixin, AppRoleUserMixin
from perms.utils.application.user_permission import ( from perms.utils.application.user_permission import (
get_user_granted_all_applications get_user_granted_all_applications
) )
@ -41,11 +41,11 @@ class AllGrantedApplicationsMixin(CommonApiMixin, ListAPIView):
return queryset.only(*self.only_fields) return queryset.only(*self.only_fields)
class UserAllGrantedApplicationsApi(RoleAdminMixin, AllGrantedApplicationsMixin): class UserAllGrantedApplicationsApi(AppRoleAdminMixin, AllGrantedApplicationsMixin):
pass pass
class MyAllGrantedApplicationsApi(RoleUserMixin, AllGrantedApplicationsMixin): class MyAllGrantedApplicationsApi(AppRoleUserMixin, AllGrantedApplicationsMixin):
pass pass

View File

@ -20,7 +20,7 @@ class PermBaseMixin:
return super().get(request, *args, **kwargs) return super().get(request, *args, **kwargs)
class RoleAdminMixin(PermBaseMixin, _RoleAdminMixin): class AssetRoleAdminMixin(PermBaseMixin, _RoleAdminMixin):
rbac_perms = ( rbac_perms = (
('list', 'perms.view_userassets'), ('list', 'perms.view_userassets'),
('retrieve', 'perms.view_userassets'), ('retrieve', 'perms.view_userassets'),
@ -29,7 +29,7 @@ class RoleAdminMixin(PermBaseMixin, _RoleAdminMixin):
) )
class RoleUserMixin(PermBaseMixin, _RoleUserMixin): class AssetRoleUserMixin(PermBaseMixin, _RoleUserMixin):
rbac_perms = ( rbac_perms = (
('list', 'perms.view_myassets'), ('list', 'perms.view_myassets'),
('retrieve', 'perms.view_myassets'), ('retrieve', 'perms.view_myassets'),

View File

@ -2,7 +2,7 @@ from rest_framework.generics import ListAPIView
from django.conf import settings from django.conf import settings
from common.utils import get_logger from common.utils import get_logger
from ..mixin import RoleAdminMixin, RoleUserMixin from ..mixin import AssetRoleAdminMixin, AssetRoleUserMixin
from .mixin import ( from .mixin import (
UserAllGrantedAssetsQuerysetMixin, UserDirectGrantedAssetsQuerysetMixin, UserFavoriteGrantedAssetsMixin, UserAllGrantedAssetsQuerysetMixin, UserDirectGrantedAssetsQuerysetMixin, UserFavoriteGrantedAssetsMixin,
UserGrantedNodeAssetsMixin, AssetsSerializerFormatMixin, AssetsTreeFormatMixin, UserGrantedNodeAssetsMixin, AssetsSerializerFormatMixin, AssetsTreeFormatMixin,
@ -19,42 +19,42 @@ logger = get_logger(__name__)
class UserDirectGrantedAssetsForAdminApi(UserDirectGrantedAssetsQuerysetMixin, class UserDirectGrantedAssetsForAdminApi(UserDirectGrantedAssetsQuerysetMixin,
RoleAdminMixin, AssetRoleAdminMixin,
AssetsSerializerFormatMixin, AssetsSerializerFormatMixin,
ListAPIView): ListAPIView):
pass pass
class MyDirectGrantedAssetsApi(UserDirectGrantedAssetsQuerysetMixin, class MyDirectGrantedAssetsApi(UserDirectGrantedAssetsQuerysetMixin,
RoleUserMixin, AssetRoleUserMixin,
AssetsSerializerFormatMixin, AssetsSerializerFormatMixin,
ListAPIView): ListAPIView):
pass pass
class UserFavoriteGrantedAssetsForAdminApi(UserFavoriteGrantedAssetsMixin, class UserFavoriteGrantedAssetsForAdminApi(UserFavoriteGrantedAssetsMixin,
RoleAdminMixin, AssetRoleAdminMixin,
AssetsSerializerFormatMixin, AssetsSerializerFormatMixin,
ListAPIView): ListAPIView):
pass pass
class MyFavoriteGrantedAssetsApi(UserFavoriteGrantedAssetsMixin, class MyFavoriteGrantedAssetsApi(UserFavoriteGrantedAssetsMixin,
RoleUserMixin, AssetRoleUserMixin,
AssetsSerializerFormatMixin, AssetsSerializerFormatMixin,
ListAPIView): ListAPIView):
pass pass
class UserDirectGrantedAssetsAsTreeForAdminApi(UserDirectGrantedAssetsQuerysetMixin, class UserDirectGrantedAssetsAsTreeForAdminApi(UserDirectGrantedAssetsQuerysetMixin,
RoleAdminMixin, AssetRoleAdminMixin,
AssetsTreeFormatMixin, AssetsTreeFormatMixin,
ListAPIView): ListAPIView):
pass pass
class MyUngroupAssetsAsTreeApi(UserDirectGrantedAssetsQuerysetMixin, class MyUngroupAssetsAsTreeApi(UserDirectGrantedAssetsQuerysetMixin,
RoleUserMixin, AssetRoleUserMixin,
AssetsTreeFormatMixin, AssetsTreeFormatMixin,
ListAPIView): ListAPIView):
def get_queryset(self): def get_queryset(self):
@ -65,34 +65,34 @@ class MyUngroupAssetsAsTreeApi(UserDirectGrantedAssetsQuerysetMixin,
class UserAllGrantedAssetsApi(UserAllGrantedAssetsQuerysetMixin, class UserAllGrantedAssetsApi(UserAllGrantedAssetsQuerysetMixin,
RoleAdminMixin, AssetRoleAdminMixin,
AssetsSerializerFormatMixin, AssetsSerializerFormatMixin,
ListAPIView): ListAPIView):
pass pass
class MyAllGrantedAssetsApi(UserAllGrantedAssetsQuerysetMixin, class MyAllGrantedAssetsApi(UserAllGrantedAssetsQuerysetMixin,
RoleUserMixin, AssetRoleUserMixin,
AssetsSerializerFormatMixin, AssetsSerializerFormatMixin,
ListAPIView): ListAPIView):
pass pass
class MyAllAssetsAsTreeApi(UserAllGrantedAssetsQuerysetMixin, class MyAllAssetsAsTreeApi(UserAllGrantedAssetsQuerysetMixin,
RoleUserMixin, AssetRoleUserMixin,
AssetsTreeFormatMixin, AssetsTreeFormatMixin,
ListAPIView): ListAPIView):
pass pass
class UserGrantedNodeAssetsForAdminApi(RoleAdminMixin, class UserGrantedNodeAssetsForAdminApi(AssetRoleAdminMixin,
UserGrantedNodeAssetsMixin, UserGrantedNodeAssetsMixin,
AssetsSerializerFormatMixin, AssetsSerializerFormatMixin,
ListAPIView): ListAPIView):
pass pass
class MyGrantedNodeAssetsApi(RoleUserMixin, class MyGrantedNodeAssetsApi(AssetRoleUserMixin,
UserGrantedNodeAssetsMixin, UserGrantedNodeAssetsMixin,
AssetsSerializerFormatMixin, AssetsSerializerFormatMixin,
ListAPIView): ListAPIView):

View File

@ -9,7 +9,7 @@ from rest_framework.request import Request
from assets.api.mixin import SerializeToTreeNodeMixin from assets.api.mixin import SerializeToTreeNodeMixin
from common.utils import get_logger from common.utils import get_logger
from .mixin import RoleAdminMixin, RoleUserMixin from .mixin import AssetRoleAdminMixin, AssetRoleUserMixin
from perms.hands import User from perms.hands import User
from perms import serializers from perms import serializers
@ -100,33 +100,33 @@ class UserGrantedNodesMixin:
# ------------------------------------------ # ------------------------------------------
# 最终的 api # 最终的 api
class UserGrantedNodeChildrenForAdminApi(RoleAdminMixin, UserGrantedNodeChildrenMixin, BaseNodeChildrenApi): class UserGrantedNodeChildrenForAdminApi(AssetRoleAdminMixin, UserGrantedNodeChildrenMixin, BaseNodeChildrenApi):
pass pass
class MyGrantedNodeChildrenApi(RoleUserMixin, UserGrantedNodeChildrenMixin, BaseNodeChildrenApi): class MyGrantedNodeChildrenApi(AssetRoleUserMixin, UserGrantedNodeChildrenMixin, BaseNodeChildrenApi):
pass pass
class UserGrantedNodeChildrenAsTreeForAdminApi(RoleAdminMixin, UserGrantedNodeChildrenMixin, BaseNodeChildrenAsTreeApi): class UserGrantedNodeChildrenAsTreeForAdminApi(AssetRoleAdminMixin, UserGrantedNodeChildrenMixin, BaseNodeChildrenAsTreeApi):
pass pass
class MyGrantedNodeChildrenAsTreeApi(RoleUserMixin, UserGrantedNodeChildrenMixin, BaseNodeChildrenAsTreeApi): class MyGrantedNodeChildrenAsTreeApi(AssetRoleUserMixin, UserGrantedNodeChildrenMixin, BaseNodeChildrenAsTreeApi):
def get_permissions(self): def get_permissions(self):
permissions = super().get_permissions() permissions = super().get_permissions()
return permissions return permissions
class UserGrantedNodesForAdminApi(RoleAdminMixin, UserGrantedNodesMixin, BaseGrantedNodeApi): class UserGrantedNodesForAdminApi(AssetRoleAdminMixin, UserGrantedNodesMixin, BaseGrantedNodeApi):
pass pass
class MyGrantedNodesApi(RoleUserMixin, UserGrantedNodesMixin, BaseGrantedNodeApi): class MyGrantedNodesApi(AssetRoleUserMixin, UserGrantedNodesMixin, BaseGrantedNodeApi):
pass pass
class MyGrantedNodesAsTreeApi(RoleUserMixin, UserGrantedNodesMixin, BaseGrantedNodeAsTreeApi): class MyGrantedNodesAsTreeApi(AssetRoleUserMixin, UserGrantedNodesMixin, BaseGrantedNodeAsTreeApi):
pass pass
# ------------------------------------------ # ------------------------------------------

View File

@ -10,7 +10,7 @@ from common.utils.common import timeit
from orgs.utils import tmp_to_root_org from orgs.utils import tmp_to_root_org
from common.permissions import IsValidUser from common.permissions import IsValidUser
from common.utils import get_logger, get_object_or_none from common.utils import get_logger, get_object_or_none
from .mixin import RoleUserMixin, RoleAdminMixin from .mixin import AssetRoleUserMixin, AssetRoleAdminMixin
from perms.utils.asset.user_permission import ( from perms.utils.asset.user_permission import (
UserGrantedTreeBuildUtils, get_user_all_asset_perm_ids, UserGrantedTreeBuildUtils, get_user_all_asset_perm_ids,
UserGrantedNodesQueryUtils, UserGrantedAssetsQueryUtils, UserGrantedNodesQueryUtils, UserGrantedAssetsQueryUtils,
@ -146,9 +146,9 @@ class GrantedNodeChildrenWithAssetsAsTreeApiMixin(SerializeToTreeNodeMixin,
return Response(data=[*tree_nodes, *tree_assets]) return Response(data=[*tree_nodes, *tree_assets])
class UserGrantedNodeChildrenWithAssetsAsTreeApi(RoleAdminMixin, GrantedNodeChildrenWithAssetsAsTreeApiMixin): class UserGrantedNodeChildrenWithAssetsAsTreeApi(AssetRoleAdminMixin, GrantedNodeChildrenWithAssetsAsTreeApiMixin):
pass pass
class MyGrantedNodeChildrenWithAssetsAsTreeApi(RoleUserMixin, GrantedNodeChildrenWithAssetsAsTreeApiMixin): class MyGrantedNodeChildrenWithAssetsAsTreeApi(AssetRoleUserMixin, GrantedNodeChildrenWithAssetsAsTreeApiMixin):
pass pass

View File

@ -18,7 +18,7 @@ class Migration(migrations.Migration):
], ],
options={ options={
'verbose_name': 'Permed asset', 'verbose_name': 'Permed asset',
'permissions': [('view_myassets', 'Can view my assets'), ('connect_myassets', 'Can connect my assets'), ('view_userassets', 'Can view user assets'), ('view_usergroupassets', 'Can view usergroup assets')], 'permissions': [('view_myassets', 'Can view my assets'), ('view_userassets', 'Can view user assets'), ('view_usergroupassets', 'Can view usergroup assets')],
'proxy': True, 'proxy': True,
'indexes': [], 'indexes': [],
'constraints': [], 'constraints': [],

View File

@ -17,7 +17,7 @@ class Migration(migrations.Migration):
], ],
options={ options={
'verbose_name': 'Permed application', 'verbose_name': 'Permed application',
'permissions': [('view_myapps', 'Can view my apps'), ('connect_myapps', 'Can connect my apps'), ('view_userapps', 'Can view user apps'), ('view_usergroupapps', 'Can view usergroup apps')], 'permissions': [('view_myapps', 'Can view my apps'), ('view_userapps', 'Can view user apps'), ('view_usergroupapps', 'Can view usergroup apps')],
'proxy': True, 'proxy': True,
'default_permissions': [], 'default_permissions': [],
'indexes': [], 'indexes': [],

View File

@ -113,7 +113,6 @@ class PermedApplication(Application):
default_permissions = [] default_permissions = []
permissions = [ permissions = [
('view_myapps', 'Can view my apps'), ('view_myapps', 'Can view my apps'),
('connect_myapps', 'Can connect my apps'),
('view_userapps', _('Can view user apps')), ('view_userapps', _('Can view user apps')),
('view_usergroupapps', _('Can view usergroup apps')), ('view_usergroupapps', _('Can view usergroup apps')),
] ]

View File

@ -185,7 +185,6 @@ class PermedAsset(Asset):
verbose_name = _('Permed asset') verbose_name = _('Permed asset')
permissions = [ permissions = [
('view_myassets', _('Can view my assets')), ('view_myassets', _('Can view my assets')),
('connect_myassets', _('Can connect my assets')),
('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

@ -11,7 +11,6 @@ exclude_permissions = (
# ('App', 'Model', 'Action', 'Resource') Model 和 Resource 可能不同 # ('App', 'Model', 'Action', 'Resource') Model 和 Resource 可能不同
# users.add_user # users.add_user
('auth', '*', '*', '*'), ('auth', '*', '*', '*'),
('authentication', 'loginconfirmsetting', '*', '*'),
('captcha', '*', '*', '*'), ('captcha', '*', '*', '*'),
('contenttypes', '*', '*', '*'), ('contenttypes', '*', '*', '*'),
('django_cas_ng', '*', '*', '*'), ('django_cas_ng', '*', '*', '*'),
@ -30,6 +29,7 @@ exclude_permissions = (
('users', 'userpasswordhistory', '*', '*'), ('users', 'userpasswordhistory', '*', '*'),
('applications', 'applicationuser', '*', '*'), ('applications', 'applicationuser', '*', '*'),
('applications', 'historicalaccount', '*', '*'), ('applications', 'historicalaccount', '*', '*'),
('applications', 'account', 'add,change', 'account'),
('assets', 'adminuser', '*', '*'), ('assets', 'adminuser', '*', '*'),
('assets', 'assetgroup', '*', '*'), ('assets', 'assetgroup', '*', '*'),
('assets', 'cluster', '*', '*'), ('assets', 'cluster', '*', '*'),
@ -38,9 +38,7 @@ exclude_permissions = (
('assets', 'assetuser', '*', '*'), ('assets', 'assetuser', '*', '*'),
('assets', 'gathereduser', 'add,delete,change', 'gathereduser'), ('assets', 'gathereduser', 'add,delete,change', 'gathereduser'),
('assets', 'accountbackupplanexecution', 'delete,change', 'accountbackupplanexecution'), ('assets', 'accountbackupplanexecution', 'delete,change', 'accountbackupplanexecution'),
('perms', 'databaseapppermission', '*', '*'), ('assets', 'authbook', 'add,change', 'authbook'),
('perms', 'k8sapppermission', '*', '*'),
('perms', 'remoteapppermission', '*', '*'),
('perms', 'userassetgrantedtreenoderelation', '*', '*'), ('perms', 'userassetgrantedtreenoderelation', '*', '*'),
('perms', 'usergrantedmappingnode', '*', '*'), ('perms', 'usergrantedmappingnode', '*', '*'),
('perms', 'permnode', '*', '*'), ('perms', 'permnode', '*', '*'),
@ -51,7 +49,7 @@ exclude_permissions = (
('rbac', 'permission', 'add,delete,change', 'permission'), ('rbac', 'permission', 'add,delete,change', 'permission'),
('rbac', 'rolebinding', '*', '*'), ('rbac', 'rolebinding', '*', '*'),
('rbac', 'role', '*', '*'), ('rbac', 'role', '*', '*'),
('ops', 'adhoc', '*', '*'), ('ops', 'adhoc', 'delete,change', '*'),
('ops', 'adhocexecution', 'delete,change', '*'), ('ops', 'adhocexecution', 'delete,change', '*'),
('ops', 'celerytask', '*', '*'), ('ops', 'celerytask', '*', '*'),
('ops', 'task', 'add,change', 'task'), ('ops', 'task', 'add,change', 'task'),
@ -74,11 +72,13 @@ exclude_permissions = (
('xpack', 'license', '*', '*'), ('xpack', 'license', '*', '*'),
('xpack', 'syncinstancedetail', 'add,delete,change', 'syncinstancedetail'), ('xpack', 'syncinstancedetail', 'add,delete,change', 'syncinstancedetail'),
('xpack', 'syncinstancetaskexecution', 'add,delete,change', 'syncinstancetaskexecution'), ('xpack', 'syncinstancetaskexecution', 'add,delete,change', 'syncinstancetaskexecution'),
('xpack', 'changeauthplanexecution', 'add,delete,change', 'changeauthplanexecution'),
('xpack', 'changeauthplantask', 'add,delete', 'changeauthplantask'),
('common', 'permission', 'add,delete,view,change', 'permission'), ('common', 'permission', 'add,delete,view,change', 'permission'),
('terminal', 'command', 'delete,change', 'command'), ('terminal', 'command', 'delete,change', 'command'),
('terminal', 'status', 'delete,change', 'status'), ('terminal', 'status', 'delete,change', 'status'),
('terminal', 'sessionjoinrecord', 'delete', 'sessionjoinrecord'), ('terminal', 'sessionjoinrecord', 'delete', 'sessionjoinrecord'),
('terminal', 'sessionreplay', 'delete', 'sessionreplay'), ('terminal', 'sessionreplay', 'add,change,delete', 'sessionreplay'),
('terminal', 'session', 'delete', 'session'), ('terminal', 'session', 'delete', 'session'),
('terminal', 'session', 'delete,change', 'command'), ('terminal', 'session', 'delete,change', 'command'),
) )

View File

@ -0,0 +1,30 @@
# Generated by Django 3.1.14 on 2022-03-14 07:25
from django.db import migrations
def migrate_old_permissions(apps, *args):
ContentType = apps.get_model('rbac', 'ContentType')
content_type_delete_required = [
('common', 'permission'),
('applications', 'databaseapp'),
('applications', 'k8sapp'),
('applications', 'remoteapp'),
('perms', 'databaseapppermission'),
('perms', 'k8sapppermission'),
('perms', 'remoteapppermission'),
('authentication', 'loginconfirmsetting'),
]
for app, model in content_type_delete_required:
ContentType.objects.filter(app_label=app, model=model).delete()
class Migration(migrations.Migration):
dependencies = [
('rbac', '0006_auto_20220310_0616'),
]
operations = [
migrations.RunPython(migrate_old_permissions)
]

View File

@ -14,6 +14,10 @@ class ContentType(DjangoContentType):
class Meta: class Meta:
proxy = True proxy = True
@property
def app_model(self):
return '%s.%s' % (self.app_label, self.model)
class Permission(DjangoPermission): class Permission(DjangoPermission):
""" 权限类 """ """ 权限类 """

View File

@ -72,7 +72,7 @@ special_pid_mapper = {
'xpack.applicationchangeauthplanexecution': 'app_change_plan_node', 'xpack.applicationchangeauthplanexecution': 'app_change_plan_node',
'xpack.applicationchangeauthplantask': 'app_change_plan_node', 'xpack.applicationchangeauthplantask': 'app_change_plan_node',
'xpack.changeauthplan': 'asset_change_plan_node', 'xpack.changeauthplan': 'asset_change_plan_node',
'xpack.changeauthplanexecution': 'gather_account_node', 'xpack.changeauthplanexecution': 'asset_change_plan_node',
'xpack.changeauthplantask': 'asset_change_plan_node', 'xpack.changeauthplantask': 'asset_change_plan_node',
"assets.gathereduser": "gather_account_node", "assets.gathereduser": "gather_account_node",
'xpack.gatherusertask': 'gather_account_node', 'xpack.gatherusertask': 'gather_account_node',
@ -87,10 +87,9 @@ special_pid_mapper = {
'audits.ftplog': 'terminal', 'audits.ftplog': 'terminal',
'rbac.menupermission': 'view_other', 'rbac.menupermission': 'view_other',
'perms.view_myassets': 'my_assets', 'perms.view_myassets': 'my_assets',
'perms.connect_myassets': 'my_assets',
'perms.view_myapps': 'my_apps', 'perms.view_myapps': 'my_apps',
'perms.connect_myapps': 'my_apps', 'ops.add_commandexecution': 'view_workspace',
'ops.commandexecution': 'view_workspace', 'ops.view_commandexecution': 'audits',
"perms.view_mykubernetsapp": "my_apps", "perms.view_mykubernetsapp": "my_apps",
"perms.connect_mykubernetsapp": "my_apps", "perms.connect_mykubernetsapp": "my_apps",
"perms.view_myremoteapp": "my_apps", "perms.view_myremoteapp": "my_apps",
@ -123,28 +122,30 @@ xpack_nodes = [
def _sort_action(node): def _sort_action(node):
value = 0 if node.isParent:
return ['zz', 0]
if 'view' in node.title: action_resource = node.title.split('.')[-1]
value += 2 action, resource = action_resource.split('_', 2)
elif 'add' in node.title: action_value_mapper = {
value += 4 'view': 2,
elif 'change' in node.title: 'add': 4,
value += 6 'change': 6,
elif 'delete' in node.title: 'delete': 8
value += 8 }
else: v = action_value_mapper.get(action, 10)
value += 10 return [resource, v]
return value
def sort_nodes(node): def sort_nodes(node):
value = 0 value = []
if node.isParent: if node.isParent:
value += 50 value.append(50)
else: else:
value += _sort_action(node) value.append(0)
value.extend(_sort_action(node))
return value return value
@ -263,6 +264,7 @@ class PermissionTreeUtil:
@staticmethod @staticmethod
def _get_permission_name(p, content_types_name_mapper): def _get_permission_name(p, content_types_name_mapper):
p: Permission
code_name = p.codename code_name = p.codename
action_mapper = { action_mapper = {
'add': ugettext('Create'), 'add': ugettext('Create'),
@ -285,8 +287,9 @@ class PermissionTreeUtil:
name = action_mapper['delete'] name = action_mapper['delete']
ct = code_name.replace('delete_', '') ct = code_name.replace('delete_', '')
if ct in content_types_name_mapper: app_model = '%s.%s' % (p.content_type.app_label, ct)
name += content_types_name_mapper[ct] if app_model in content_types_name_mapper:
name += content_types_name_mapper[app_model]
else: else:
name = gettext(p.name) name = gettext(p.name)
name = name.replace('Can ', '').replace('可以', '') name = name.replace('Can ', '').replace('可以', '')
@ -296,7 +299,7 @@ class PermissionTreeUtil:
permissions_id = self.permissions.values_list('id', flat=True) permissions_id = self.permissions.values_list('id', flat=True)
nodes = [] nodes = []
content_types = ContentType.objects.all() content_types = ContentType.objects.all()
content_types_name_mapper = {ct.model: ct.name for ct in content_types} content_types_name_mapper = {ct.app_model: ct.name for ct in content_types}
for p in self.all_permissions: for p in self.all_permissions:
model_id = f'{p.app}.{p.model}' model_id = f'{p.app}.{p.model}'

View File

@ -12,6 +12,6 @@ class Migration(migrations.Migration):
operations = [ operations = [
migrations.AlterModelOptions( migrations.AlterModelOptions(
name='setting', name='setting',
options={'permissions': [('change_email', 'Can change email setting'), ('change_auth', 'Can change auth setting'), ('change_systemmsgsubscription', 'Can sys msg sub setting'), ('change_sms', 'Can change sms setting'), ('change_security', 'Can change security setting'), ('change_clean', 'Can change clean setting'), ('change_interface', 'Can change interface setting'), ('change_license', 'Can change license setting'), ('change_terminal', 'Can change terminal setting'), ('change_other', 'Can change other setting')], 'verbose_name': 'System setting'}, options={'permissions': [('change_email', 'Can change email setting'), ('change_auth', 'Can change auth setting'), ('change_systemmsgsubscription', 'Can change system msg sub setting'), ('change_sms', 'Can change sms setting'), ('change_security', 'Can change security setting'), ('change_clean', 'Can change clean setting'), ('change_interface', 'Can change interface setting'), ('change_license', 'Can change license setting'), ('change_terminal', 'Can change terminal setting'), ('change_other', 'Can change other setting')], 'verbose_name': 'System setting'},
), ),
] ]

View File

@ -141,7 +141,7 @@ class Setting(models.Model):
permissions = [ permissions = [
('change_email', _('Can change email setting')), ('change_email', _('Can change email setting')),
('change_auth', _('Can change auth setting')), ('change_auth', _('Can change auth setting')),
('change_systemmsgsubscription', _('Can sys msg sub setting')), ('change_systemmsgsubscription', _('Can change system msg sub setting')),
('change_sms', _('Can change sms setting')), ('change_sms', _('Can change sms setting')),
('change_security', _('Can change security setting')), ('change_security', _('Can change security setting')),
('change_clean', _('Can change clean setting')), ('change_clean', _('Can change clean setting')),

View File

@ -126,7 +126,7 @@ class SessionReplayViewSet(AsyncApiMixin, viewsets.ViewSet):
session = None session = None
rbac_perms = { rbac_perms = {
'create': 'terminal.upload_sessionreplay', 'create': 'terminal.upload_sessionreplay',
'retrieve': 'terminal.download_sessionreplay', 'retrieve': 'terminal.view_sessionreplay',
} }
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):

View File

@ -22,6 +22,9 @@ def clean_db_content_types():
ContentType.objects.filter(app_label=app, model=model).delete() ContentType.objects.filter(app_label=app, model=model).delete()
permissions_delete_required = [ permissions_delete_required = [
('perms', 'permedasset', 'connect_myassets'),
('perms', 'permedapplication', 'connect_myapps'),
('perms', 'assetpermission', 'connect_myassets'), ('perms', 'assetpermission', 'connect_myassets'),
('perms', 'assetpermission', 'view_myassets'), ('perms', 'assetpermission', 'view_myassets'),
('perms', 'assetpermission', 'view_userassets'), ('perms', 'assetpermission', 'view_userassets'),