Files
jumpserver/apps/terminal/api/storage.py
fit2bot e259d2a9e9 fix: fix rbac to dev (#7636)
* feat: 添加 RBAC 应用模块

* feat: 添加 RBAC Model、API

* feat: 添加 RBAC Model、API 2

* feat: 添加 RBAC Model、API 3

* feat: 添加 RBAC Model、API 4

* feat: RBAC

* feat: RBAC

* feat: RBAC

* feat: RBAC

* feat: RBAC

* feat: RBAC 整理权限位

* feat: RBAC 整理权限位2

* feat: RBAC 整理权限位2

* feat: RBAC 整理权限位

* feat: RBAC 添加默认角色

* feat: RBAC 添加迁移文件;迁移用户角色->用户角色绑定

* feat: RBAC 添加迁移文件;迁移用户角色->用户角色绑定

* feat: RBAC 修改用户模块API

* feat: RBAC 添加组织模块迁移文件 & 修改组织模块API

* feat: RBAC 添加组织模块迁移文件 & 修改组织模块API

* feat: RBAC 修改用户角色属性的使用

* feat: RBAC No.1

* xxx

* perf: 暂存

* perf: ...

* perf(rbac): 添加 perms 到 profile serializer 中

* stash

* perf: 使用init

* perf: 修改migrations

* perf: rbac

* stash

* stash

* pref: 修改rbac

* stash it

* stash: 先去修复其他bug

* perf: 修改 role 添加 users

* pref: 修改 RBAC Model

* feat: 添加权限的 tree api

* stash: 暂存一下

* stash: 暂存一下

* perf: 修改 model verbose name

* feat: 添加model各种 verbose name

* perf: 生成 migrations

* perf: 优化权限位

* perf: 添加迁移脚本

* feat: 添加组织角色迁移

* perf: 添加迁移脚本

* stash

* perf: 添加migrateion

* perf: 暂存一下

* perf: 修改rbac

* perf: stash it

* fix: 迁移冲突

* fix: 迁移冲突

* perf: 暂存一下

* perf: 修改 rbac 逻辑

* stash: 暂存一下

* perf: 修改内置角色

* perf: 解决 root 组织的问题

* perf: stash it

* perf: 优化 rbac

* perf: 优化 rolebinding 处理

* perf: 完成用户离开组织的问题

* perf: 暂存一下

* perf: 修改翻译

* perf: 去掉了 IsSuperUser

* perf: IsAppUser 去掉完成

* perf: 修改 connection token 的权限

* perf: 去掉导入的问题

* perf: perms define 格式,修改 app 用户 的全新啊

* perf: 修改 permission

* perf: 去掉一些 org admin

* perf: 去掉部分 org admin

* perf: 再去掉点 org admin role

* perf: 再去掉部分 org admin

* perf: user 角色搜索

* perf: 去掉很多 js

* perf: 添加权限位

* perf: 修改权限

* perf: 去掉一个 todo

* merge: with dev

* fix: 修复冲突

Co-authored-by: Bai <bugatti_it@163.com>
Co-authored-by: Michael Bai <baijiangjie@gmail.com>
Co-authored-by: ibuler <ibuler@qq.com>
2022-02-17 20:13:31 +08:00

139 lines
4.7 KiB
Python

# coding: utf-8
#
from rest_framework import viewsets, generics, status
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.decorators import action
from django.utils.translation import ugettext_lazy as _
from django_filters import utils
from terminal import const
from common.const.http import GET
from terminal.filters import CommandStorageFilter, CommandFilter, CommandFilterForStorageTree
from ..models import CommandStorage, ReplayStorage
from ..serializers import CommandStorageSerializer, ReplayStorageSerializer
__all__ = [
'CommandStorageViewSet', 'CommandStorageTestConnectiveApi',
'ReplayStorageViewSet', 'ReplayStorageTestConnectiveApi'
]
class BaseStorageViewSetMixin:
def destroy(self, request, *args, **kwargs):
instance = self.get_object()
if instance.type_null_or_server:
data = {'msg': _('Deleting the default storage is not allowed')}
return Response(data=data, status=status.HTTP_400_BAD_REQUEST)
if instance.is_use():
data = {'msg': _('Cannot delete storage that is being used')}
return Response(data=data, status=status.HTTP_400_BAD_REQUEST)
return super().destroy(request, *args, **kwargs)
class CommandStorageViewSet(BaseStorageViewSetMixin, viewsets.ModelViewSet):
search_fields = ('name', 'type')
queryset = CommandStorage.objects.all()
serializer_class = CommandStorageSerializer
filterset_class = CommandStorageFilter
rbac_perms = {
'tree': 'terminal.view_commandstorage'
}
@action(methods=[GET], detail=False, filterset_class=CommandFilterForStorageTree)
def tree(self, request: Request):
storage_qs = self.get_queryset().exclude(name='null')
storages_with_count = []
invalid_storages = []
for storage in storage_qs:
if not storage.is_valid():
invalid_storages.append(storage)
continue
command_qs = storage.get_command_queryset()
filterset = CommandFilter(
data=request.query_params, queryset=command_qs,
request=request
)
if not filterset.is_valid():
raise utils.translate_validation(filterset.errors)
command_qs = filterset.qs
if storage.type == const.CommandStorageTypeChoices.es:
command_count = command_qs.count(limit_to_max_result_window=False)
else:
command_count = command_qs.count()
storages_with_count.append((storage, command_count))
root = {
'id': 'root',
'name': _('Command storages'),
'title': _('Command storages'),
'pId': '',
'isParent': True,
'open': True,
}
invalid = _('Invalid')
nodes = [
{
'id': storage.id,
'name': f'{storage.name}({storage.type})({command_count})',
'title': f'{storage.name}({storage.type})',
'pId': 'root',
'isParent': False,
'open': False,
'valid': True,
} for storage, command_count in storages_with_count
] + [
{
'id': storage.id,
'name': f'{storage.name}({storage.type}) *{invalid}',
'title': f'{storage.name}({storage.type})',
'pId': 'root',
'isParent': False,
'open': False,
'valid': False,
} for storage in invalid_storages
]
nodes.append(root)
return Response(data=nodes)
class ReplayStorageViewSet(BaseStorageViewSetMixin, viewsets.ModelViewSet):
filterset_fields = ('name', 'type', 'is_default')
search_fields = filterset_fields
queryset = ReplayStorage.objects.all()
serializer_class = ReplayStorageSerializer
class BaseStorageTestConnectiveMixin:
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
try:
is_valid = instance.is_valid()
except Exception as e:
is_valid = False
msg = _("Test failure: {}".format(str(e)))
else:
if is_valid:
msg = _("Test successful")
else:
msg = _("Test failure: Account invalid")
data = {
'is_valid': is_valid,
'msg': msg
}
return Response(data)
class CommandStorageTestConnectiveApi(BaseStorageTestConnectiveMixin, generics.RetrieveAPIView):
queryset = CommandStorage.objects.all()
class ReplayStorageTestConnectiveApi(BaseStorageTestConnectiveMixin, generics.RetrieveAPIView):
queryset = ReplayStorage.objects.all()