mirror of https://github.com/jumpserver/jumpserver
commit
166745baf6
63
Dockerfile
63
Dockerfile
|
@ -8,7 +8,6 @@ WORKDIR /opt/jumpserver
|
|||
ADD . .
|
||||
RUN cd utils && bash -ixeu build.sh
|
||||
|
||||
# 构建运行时环境
|
||||
FROM python:3.8-slim
|
||||
ARG PIP_MIRROR=https://pypi.douban.com/simple
|
||||
ENV PIP_MIRROR=$PIP_MIRROR
|
||||
|
@ -17,38 +16,66 @@ ENV PIP_JMS_MIRROR=$PIP_JMS_MIRROR
|
|||
|
||||
WORKDIR /opt/jumpserver
|
||||
|
||||
COPY ./requirements/deb_requirements.txt ./requirements/deb_requirements.txt
|
||||
ARG BUILD_DEPENDENCIES=" \
|
||||
g++ \
|
||||
make \
|
||||
pkg-config"
|
||||
|
||||
ARG DEPENDENCIES=" \
|
||||
default-libmysqlclient-dev \
|
||||
freetds-dev \
|
||||
libpq-dev \
|
||||
libffi-dev \
|
||||
libldap2-dev \
|
||||
libsasl2-dev \
|
||||
libxml2-dev \
|
||||
libxmlsec1-dev \
|
||||
libxmlsec1-openssl \
|
||||
libaio-dev \
|
||||
sshpass"
|
||||
|
||||
ARG TOOLS=" \
|
||||
curl \
|
||||
default-mysql-client \
|
||||
iproute2 \
|
||||
iputils-ping \
|
||||
locales \
|
||||
procps \
|
||||
redis-tools \
|
||||
telnet \
|
||||
vim \
|
||||
wget"
|
||||
|
||||
RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list \
|
||||
&& sed -i 's/security.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list \
|
||||
&& apt update \
|
||||
&& apt -y install telnet iproute2 redis-tools default-mysql-client vim wget curl locales procps \
|
||||
&& apt -y install $(cat requirements/deb_requirements.txt) \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& apt -y install ${BUILD_DEPENDENCIES} \
|
||||
&& apt -y install ${DEPENDENCIES} \
|
||||
&& apt -y install ${TOOLS} \
|
||||
&& localedef -c -f UTF-8 -i zh_CN zh_CN.UTF-8 \
|
||||
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
|
||||
&& sed -i "s@# alias l@alias l@g" ~/.bashrc \
|
||||
&& echo "set mouse-=a" > ~/.vimrc
|
||||
|
||||
COPY ./requirements/requirements.txt ./requirements/requirements.txt
|
||||
RUN pip install --upgrade pip==20.2.4 setuptools==49.6.0 wheel==0.34.2 -i ${PIP_MIRROR} \
|
||||
&& pip install --no-cache-dir $(grep -E 'jms|jumpserver' requirements/requirements.txt) -i ${PIP_JMS_MIRROR} \
|
||||
&& pip install --no-cache-dir -r requirements/requirements.txt -i ${PIP_MIRROR} \
|
||||
&& rm -rf ~/.cache/pip
|
||||
|
||||
COPY --from=stage-build /opt/jumpserver/release/jumpserver /opt/jumpserver
|
||||
RUN mkdir -p /root/.ssh/ \
|
||||
&& mkdir -p /root/.ssh/ \
|
||||
&& echo "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile /dev/null" > /root/.ssh/config \
|
||||
&& sed -i "s@# alias l@alias l@g" ~/.bashrc \
|
||||
&& echo "set mouse-=a" > ~/.vimrc \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& mv /bin/sh /bin/sh.bak \
|
||||
&& ln -s /bin/bash /bin/sh
|
||||
|
||||
RUN mkdir -p /opt/jumpserver/oracle/ \
|
||||
&& wget https://download.jumpserver.org/public/instantclient-basiclite-linux.x64-21.1.0.0.0.tar > /dev/null \
|
||||
&& wget https://download.jumpserver.org/public/instantclient-basiclite-linux.x64-21.1.0.0.0.tar \
|
||||
&& tar xf instantclient-basiclite-linux.x64-21.1.0.0.0.tar -C /opt/jumpserver/oracle/ \
|
||||
&& echo "/opt/jumpserver/oracle/instantclient_21_1" > /etc/ld.so.conf.d/oracle-instantclient.conf \
|
||||
&& ldconfig \
|
||||
&& rm -f instantclient-basiclite-linux.x64-21.1.0.0.0.tar
|
||||
|
||||
RUN echo > config.yml
|
||||
COPY --from=stage-build /opt/jumpserver/release/jumpserver /opt/jumpserver
|
||||
|
||||
RUN echo > config.yml \
|
||||
&& pip install --upgrade pip==20.2.4 setuptools==49.6.0 wheel==0.34.2 -i ${PIP_MIRROR} \
|
||||
&& pip install --no-cache-dir $(grep -E 'jms|jumpserver' requirements/requirements.txt) -i ${PIP_JMS_MIRROR} \
|
||||
&& pip install --no-cache-dir -r requirements/requirements.txt -i ${PIP_MIRROR} \
|
||||
&& rm -rf ~/.cache/pip
|
||||
|
||||
VOLUME /opt/jumpserver/data
|
||||
VOLUME /opt/jumpserver/logs
|
||||
|
|
|
@ -13,13 +13,17 @@ class AppCategory(models.TextChoices):
|
|||
def get_label(cls, category):
|
||||
return dict(cls.choices).get(category, '')
|
||||
|
||||
@classmethod
|
||||
def is_xpack(cls, category):
|
||||
return category in ['remote_app']
|
||||
|
||||
|
||||
class AppType(models.TextChoices):
|
||||
# db category
|
||||
mysql = 'mysql', 'MySQL'
|
||||
mariadb = 'mariadb', 'MariaDB'
|
||||
oracle = 'oracle', 'Oracle'
|
||||
pgsql = 'postgresql', 'PostgreSQL'
|
||||
mariadb = 'mariadb', 'MariaDB'
|
||||
sqlserver = 'sqlserver', 'SQLServer'
|
||||
redis = 'redis', 'Redis'
|
||||
mongodb = 'mongodb', 'MongoDB'
|
||||
|
@ -37,9 +41,13 @@ class AppType(models.TextChoices):
|
|||
def category_types_mapper(cls):
|
||||
return {
|
||||
AppCategory.db: [
|
||||
cls.mysql, cls.oracle, cls.pgsql, cls.mariadb, cls.sqlserver, cls.redis, cls.mongodb
|
||||
cls.mysql, cls.oracle, cls.pgsql, cls.mariadb,
|
||||
cls.sqlserver, cls.redis, cls.mongodb
|
||||
],
|
||||
AppCategory.remote_app: [
|
||||
cls.chrome, cls.mysql_workbench,
|
||||
cls.vmware_client, cls.custom
|
||||
],
|
||||
AppCategory.remote_app: [cls.chrome, cls.mysql_workbench, cls.vmware_client, cls.custom],
|
||||
AppCategory.cloud: [cls.k8s]
|
||||
}
|
||||
|
||||
|
@ -66,3 +74,12 @@ class AppType(models.TextChoices):
|
|||
@classmethod
|
||||
def cloud_types(cls):
|
||||
return [tp.value for tp in cls.category_types_mapper()[AppCategory.cloud]]
|
||||
|
||||
@classmethod
|
||||
def is_xpack(cls, tp):
|
||||
tp_category_mapper = cls.type_category_mapper()
|
||||
category = tp_category_mapper[tp]
|
||||
|
||||
if AppCategory.is_xpack(category):
|
||||
return True
|
||||
return tp in ['oracle', 'postgresql', 'sqlserver']
|
||||
|
|
|
@ -3,6 +3,7 @@ from urllib.parse import urlencode, parse_qsl
|
|||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.conf import settings
|
||||
|
||||
from orgs.mixins.models import OrgModelMixin
|
||||
from common.mixins import CommonModelMixin
|
||||
|
@ -79,6 +80,8 @@ class ApplicationTreeNodeMixin:
|
|||
nodes = []
|
||||
categories = const.AppType.category_types_mapper().keys()
|
||||
for category in categories:
|
||||
if not settings.XPACK_ENABLED and const.AppCategory.is_xpack(category):
|
||||
continue
|
||||
i = cls.create_tree_id(pid, 'category', category.value)
|
||||
node = cls.create_choice_node(
|
||||
category, i, pid=pid, tp='category',
|
||||
|
@ -97,6 +100,8 @@ class ApplicationTreeNodeMixin:
|
|||
type_category_mapper = const.AppType.type_category_mapper()
|
||||
types = const.AppType.type_category_mapper().keys()
|
||||
for tp in types:
|
||||
if not settings.XPACK_ENABLED and const.AppType.is_xpack(tp):
|
||||
continue
|
||||
category = type_category_mapper.get(tp)
|
||||
pid = cls.create_tree_id(pid, 'category', category.value)
|
||||
i = cls.create_tree_id(pid, 'type', tp.value)
|
||||
|
@ -155,6 +160,8 @@ class ApplicationTreeNodeMixin:
|
|||
|
||||
# 应用的节点
|
||||
for app in queryset:
|
||||
if not settings.XPACK_ENABLED and const.AppType.is_xpack(app.type):
|
||||
continue
|
||||
node = app.as_tree_node(root_node.id)
|
||||
tree_nodes.append(node)
|
||||
return tree_nodes
|
||||
|
|
|
@ -131,6 +131,9 @@ class CommandExecutionHostRelationViewSet(OrgRelationMixin, OrgBulkModelViewSet)
|
|||
]
|
||||
search_fields = ('asset__hostname', )
|
||||
http_method_names = ['options', 'get']
|
||||
rbac_perms = {
|
||||
'GET': 'audits.view_commandexecution'
|
||||
}
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
|
|
|
@ -44,13 +44,13 @@ class MFASms(BaseMFA):
|
|||
return settings.SMS_ENABLED
|
||||
|
||||
def get_enable_url(self) -> str:
|
||||
return '/ui/#/users/profile/?activeTab=ProfileUpdate'
|
||||
return '/ui/#/profile/setting?activeTab=ProfileUpdate'
|
||||
|
||||
def can_disable(self) -> bool:
|
||||
return True
|
||||
|
||||
def disable(self):
|
||||
return '/ui/#/users/profile/?activeTab=ProfileUpdate'
|
||||
return '/ui/#/profile/setting?activeTab=ProfileUpdate'
|
||||
|
||||
@staticmethod
|
||||
def help_text_of_enable():
|
||||
|
@ -61,4 +61,4 @@ class MFASms(BaseMFA):
|
|||
return _("Clear phone number to disable")
|
||||
|
||||
def get_disable_url(self) -> str:
|
||||
return '/ui/#/users/profile/?activeTab=ProfileUpdate'
|
||||
return '/ui/#/profile/setting?activeTab=ProfileUpdate'
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:675f93d2cc6b2049fdafc7f6b70edb8f73bbe132de9b91e98f2ec7acb2e89620
|
||||
size 104134
|
||||
oid sha256:a8c1155ea28b70a0eb06aa39ab6ae04619cd30d02f59698fadaa6068d91a7900
|
||||
size 104348
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: JumpServer 0.3.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-03-14 15:58+0800\n"
|
||||
"POT-Creation-Date: 2022-03-15 19:46+0800\n"
|
||||
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
|
||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
||||
|
@ -305,10 +305,14 @@ msgstr "版本"
|
|||
msgid "Application account"
|
||||
msgstr "应用账号"
|
||||
|
||||
#: applications/models/account.py:26 applications/models/account.py:27
|
||||
#: applications/models/account.py:26
|
||||
msgid "Can view application account secret"
|
||||
msgstr "可以查看应用账号密码"
|
||||
|
||||
#: applications/models/account.py:27
|
||||
msgid "Can change application account secret"
|
||||
msgstr "可以查看应用账号密码"
|
||||
|
||||
#: applications/models/application.py:204
|
||||
#: applications/serializers/application.py:99 assets/models/label.py:21
|
||||
#: perms/models/application_permission.py:21
|
||||
|
@ -1379,7 +1383,7 @@ msgstr "日志审计"
|
|||
|
||||
#: audits/models.py:27 audits/models.py:57
|
||||
#: authentication/templates/authentication/_access_key_modal.html:65
|
||||
#: rbac/tree.py:273 users/templates/users/user_asset_permission.html:128
|
||||
#: rbac/tree.py:158 users/templates/users/user_asset_permission.html:128
|
||||
#: users/templates/users/user_database_app_permission.html:111
|
||||
msgid "Delete"
|
||||
msgstr "删除"
|
||||
|
@ -1433,11 +1437,11 @@ msgstr "文件管理"
|
|||
|
||||
#: audits/models.py:55
|
||||
#: authentication/templates/authentication/_access_key_modal.html:22
|
||||
#: rbac/tree.py:270
|
||||
#: rbac/tree.py:155
|
||||
msgid "Create"
|
||||
msgstr "创建"
|
||||
|
||||
#: audits/models.py:56 rbac/tree.py:272 templates/_csv_import_export.html:18
|
||||
#: audits/models.py:56 rbac/tree.py:157 templates/_csv_import_export.html:18
|
||||
#: templates/_csv_update_modal.html:6
|
||||
#: users/templates/users/user_asset_permission.html:127
|
||||
#: users/templates/users/user_database_app_permission.html:110
|
||||
|
@ -2117,7 +2121,7 @@ msgstr "显示"
|
|||
|
||||
#: authentication/templates/authentication/_access_key_modal.html:66
|
||||
#: settings/serializers/security.py:39 users/models/user.py:469
|
||||
#: users/serializers/profile.py:111 users/templates/users/mfa_setting.html:60
|
||||
#: users/serializers/profile.py:111 users/templates/users/mfa_setting.html:61
|
||||
#: users/templates/users/user_verify_mfa.html:36
|
||||
msgid "Disable"
|
||||
msgstr "禁用"
|
||||
|
@ -2125,7 +2129,7 @@ msgstr "禁用"
|
|||
#: authentication/templates/authentication/_access_key_modal.html:67
|
||||
#: users/models/user.py:470 users/serializers/profile.py:112
|
||||
#: users/templates/users/mfa_setting.html:26
|
||||
#: users/templates/users/mfa_setting.html:67
|
||||
#: users/templates/users/mfa_setting.html:68
|
||||
msgid "Enable"
|
||||
msgstr "启用"
|
||||
|
||||
|
@ -2679,7 +2683,7 @@ msgstr "站内信"
|
|||
msgid "Waiting task start"
|
||||
msgstr "等待任务开始"
|
||||
|
||||
#: ops/api/command.py:61
|
||||
#: ops/api/command.py:56
|
||||
msgid "Not has host {} permission"
|
||||
msgstr "没有该主机 {} 权限"
|
||||
|
||||
|
@ -2767,7 +2771,7 @@ msgstr "创建者"
|
|||
|
||||
#: ops/models/adhoc.py:243
|
||||
msgid "AdHoc"
|
||||
msgstr ""
|
||||
msgstr "任务各版本"
|
||||
|
||||
#: ops/models/adhoc.py:252
|
||||
msgid "Task display"
|
||||
|
@ -2800,7 +2804,7 @@ msgstr "汇总"
|
|||
|
||||
#: ops/models/adhoc.py:339
|
||||
msgid "AdHoc execution"
|
||||
msgstr "命令执行"
|
||||
msgstr "任务执行历史"
|
||||
|
||||
#: ops/models/command.py:32
|
||||
msgid "Date finished"
|
||||
|
@ -2874,7 +2878,7 @@ msgstr "当前组织 ({}) 不能被删除"
|
|||
msgid "The organization have resource ({}) cannot be deleted"
|
||||
msgstr "组织存在资源 ({}) 不能被删除"
|
||||
|
||||
#: orgs/apps.py:7 rbac/tree.py:112
|
||||
#: orgs/apps.py:7 rbac/tree.py:111
|
||||
msgid "App organizations"
|
||||
msgstr "组织管理"
|
||||
|
||||
|
@ -2917,11 +2921,15 @@ msgstr "可以查看授权给用户的应用"
|
|||
msgid "Permed application"
|
||||
msgstr "授权的应用"
|
||||
|
||||
#: perms/models/application_permission.py:117
|
||||
#: perms/models/application_permission.py:115
|
||||
msgid "Can view my apps"
|
||||
msgstr "可以查看我的应用"
|
||||
|
||||
#: perms/models/application_permission.py:116
|
||||
msgid "Can view user apps"
|
||||
msgstr "可以查看用户授权的应用"
|
||||
|
||||
#: perms/models/application_permission.py:118
|
||||
#: perms/models/application_permission.py:117
|
||||
msgid "Can view usergroup apps"
|
||||
msgstr "可以查看用户组授权的应用"
|
||||
|
||||
|
@ -2950,14 +2958,10 @@ msgid "Can view my assets"
|
|||
msgstr "可以查看我的资产"
|
||||
|
||||
#: perms/models/asset_permission.py:188
|
||||
msgid "Can connect my assets"
|
||||
msgstr "可以连接我的资产"
|
||||
|
||||
#: perms/models/asset_permission.py:189
|
||||
msgid "Can view user assets"
|
||||
msgstr "可以查看用户授权的资产"
|
||||
|
||||
#: perms/models/asset_permission.py:190
|
||||
#: perms/models/asset_permission.py:189
|
||||
msgid "Can view usergroup assets"
|
||||
msgstr "可以查看用户组授权的资产"
|
||||
|
||||
|
@ -3173,7 +3177,7 @@ msgstr "Web终端"
|
|||
msgid "Can view file manager"
|
||||
msgstr "文件管理"
|
||||
|
||||
#: rbac/models/permission.py:22
|
||||
#: rbac/models/permission.py:26
|
||||
msgid "Permission"
|
||||
msgstr "授权"
|
||||
|
||||
|
@ -3299,15 +3303,15 @@ msgstr "我的资产"
|
|||
msgid "My apps"
|
||||
msgstr "我的应用"
|
||||
|
||||
#: rbac/tree.py:113
|
||||
#: rbac/tree.py:112
|
||||
msgid "Ticket comment"
|
||||
msgstr "工单评论"
|
||||
|
||||
#: rbac/tree.py:114
|
||||
#: rbac/tree.py:113
|
||||
msgid "Common setting"
|
||||
msgstr "一般设置"
|
||||
|
||||
#: rbac/tree.py:271
|
||||
#: rbac/tree.py:156
|
||||
msgid "View"
|
||||
msgstr "查看"
|
||||
|
||||
|
@ -4962,6 +4966,10 @@ msgstr "HTTP端口"
|
|||
msgid "Terminal"
|
||||
msgstr "终端"
|
||||
|
||||
#: terminal/models/terminal.py:185
|
||||
msgid "Can view terminal config"
|
||||
msgstr "可以查看终端配置"
|
||||
|
||||
#: terminal/notifications.py:22
|
||||
msgid "Sessions"
|
||||
msgstr "会话管理"
|
||||
|
@ -6799,11 +6807,11 @@ msgstr "退出页面logo"
|
|||
msgid "Interface setting"
|
||||
msgstr "界面设置"
|
||||
|
||||
#: xpack/plugins/license/api.py:41
|
||||
#: xpack/plugins/license/api.py:43
|
||||
msgid "License import successfully"
|
||||
msgstr "许可证导入成功"
|
||||
|
||||
#: xpack/plugins/license/api.py:42
|
||||
#: xpack/plugins/license/api.py:44
|
||||
msgid "License is invalid"
|
||||
msgstr "无效的许可证"
|
||||
|
||||
|
@ -6827,6 +6835,9 @@ msgstr "旗舰版"
|
|||
msgid "Community edition"
|
||||
msgstr "社区版"
|
||||
|
||||
#~ msgid "Can connect my assets"
|
||||
#~ msgstr "可以连接我的资产"
|
||||
|
||||
#~ msgid "Can view dashboard"
|
||||
#~ msgstr "仪表盘"
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import os
|
|||
from django.test import TestCase
|
||||
|
||||
from ops.models import Task, AdHoc
|
||||
from ops.utils import run_adhoc_object
|
||||
|
||||
|
||||
class TestRunAdHoc(TestCase):
|
||||
|
|
|
@ -22,7 +22,6 @@ from perms import serializers
|
|||
logger = get_logger(__name__)
|
||||
|
||||
__all__ = [
|
||||
'RefreshAssetPermissionCacheApi',
|
||||
'UserGrantedAssetSystemUsersForAdminApi',
|
||||
'ValidateUserAssetPermissionApi',
|
||||
'GetUserAssetPermissionActionsApi',
|
||||
|
@ -97,12 +96,6 @@ class ValidateUserAssetPermissionApi(APIView):
|
|||
return Response(data, status=status_code)
|
||||
|
||||
|
||||
# TODO 删除
|
||||
class RefreshAssetPermissionCacheApi(RetrieveAPIView):
|
||||
def retrieve(self, request, *args, **kwargs):
|
||||
return Response({'msg': True}, status=200)
|
||||
|
||||
|
||||
class UserGrantedAssetSystemUsersForAdminApi(ListAPIView):
|
||||
serializer_class = serializers.AssetSystemUserSerializer
|
||||
only_fields = serializers.AssetSystemUserSerializer.Meta.only_fields
|
||||
|
|
|
@ -112,7 +112,7 @@ class PermedApplication(Application):
|
|||
verbose_name = _('Permed application')
|
||||
default_permissions = []
|
||||
permissions = [
|
||||
('view_myapps', 'Can view my apps'),
|
||||
('view_myapps', _('Can view my apps')),
|
||||
('view_userapps', _('Can view user apps')),
|
||||
('view_usergroupapps', _('Can view usergroup apps')),
|
||||
]
|
||||
|
|
|
@ -12,7 +12,7 @@ class ActionsField(serializers.MultipleChoiceField):
|
|||
super().__init__(*args, **kwargs)
|
||||
|
||||
def run_validation(self, data=empty):
|
||||
data = super(ActionsField, self).run_validation()
|
||||
data = super(ActionsField, self).run_validation(data)
|
||||
if isinstance(data, list):
|
||||
data = Action.choices_to_value(value=data)
|
||||
return data
|
||||
|
|
|
@ -100,8 +100,6 @@ permission_urlpatterns = [
|
|||
path('user/validate/', api.ValidateUserAssetPermissionApi.as_view(), name='validate-user-asset-permission'),
|
||||
path('user/actions/', api.GetUserAssetPermissionActionsApi.as_view(), name='get-user-asset-permission-actions'),
|
||||
|
||||
# 刷新缓存
|
||||
path('cache/refresh/', api.RefreshAssetPermissionCacheApi.as_view(), name='refresh-asset-permission-cache'),
|
||||
]
|
||||
|
||||
asset_permission_urlpatterns = [
|
||||
|
|
|
@ -55,7 +55,7 @@ exclude_permissions = (
|
|||
('ops', 'task', 'add,change', 'task'),
|
||||
('ops', 'commandexecution', 'delete,change', 'commandexecution'),
|
||||
('orgs', 'organizationmember', '*', '*'),
|
||||
('settings', 'setting', 'add,delete', 'setting'),
|
||||
('settings', 'setting', 'add,change,delete', 'setting'),
|
||||
('audits', 'operatelog', 'add,delete,change', 'operatelog'),
|
||||
('audits', 'passwordchangelog', 'add,change,delete', 'passwordchangelog'),
|
||||
('audits', 'userloginlog', 'add,change,delete,change', 'userloginlog'),
|
||||
|
@ -71,15 +71,16 @@ exclude_permissions = (
|
|||
('xpack', 'interface', '*', '*'),
|
||||
('xpack', 'license', '*', '*'),
|
||||
('xpack', 'syncinstancedetail', 'add,delete,change', 'syncinstancedetail'),
|
||||
('xpack', 'syncinstancetaskexecution', 'add,delete,change', 'syncinstancetaskexecution'),
|
||||
('xpack', 'changeauthplanexecution', 'add,delete,change', 'changeauthplanexecution'),
|
||||
('xpack', 'syncinstancetaskexecution', 'delete,change', 'syncinstancetaskexecution'),
|
||||
('xpack', 'changeauthplanexecution', 'delete,change', 'changeauthplanexecution'),
|
||||
('xpack', 'changeauthplantask', 'add,delete', 'changeauthplantask'),
|
||||
('common', 'permission', 'add,delete,view,change', 'permission'),
|
||||
('terminal', 'command', 'delete,change', 'command'),
|
||||
('terminal', 'status', 'delete,change', 'status'),
|
||||
('terminal', 'sessionjoinrecord', 'delete', 'sessionjoinrecord'),
|
||||
('terminal', 'sessionreplay', 'add,change,delete', 'sessionreplay'),
|
||||
('terminal', 'session', 'delete', 'session'),
|
||||
('terminal', 'sessionsharing', 'view,add,change,delete', 'sessionsharing'),
|
||||
('terminal', 'session', 'delete,share', 'session'),
|
||||
('terminal', 'session', 'delete,change', 'command'),
|
||||
)
|
||||
|
||||
|
|
|
@ -99,7 +99,6 @@ special_pid_mapper = {
|
|||
"xpack.interface": "view_setting",
|
||||
"settings.change_terminal": "terminal_node",
|
||||
"settings.view_setting": "view_setting",
|
||||
"settings.change_setting": "view_setting",
|
||||
"rbac.view_console": "view_console",
|
||||
"rbac.view_audit": "view_audit",
|
||||
"rbac.view_workspace": "view_workspace",
|
||||
|
@ -151,6 +150,21 @@ def sort_nodes(node):
|
|||
|
||||
class PermissionTreeUtil:
|
||||
get_permissions: Callable
|
||||
action_mapper = {
|
||||
'add': ugettext('Create'),
|
||||
'view': ugettext('View'),
|
||||
'change': ugettext('Update'),
|
||||
'delete': ugettext('Delete')
|
||||
}
|
||||
action_icon = {
|
||||
'add': 'add',
|
||||
'view': 'view',
|
||||
'change': 'change',
|
||||
'delete': 'delete',
|
||||
'invite': 'invite',
|
||||
'match': 'match',
|
||||
'remove': 'remove'
|
||||
}
|
||||
|
||||
def __init__(self, permissions, scope, check_disabled=False):
|
||||
self.permissions = self.prefetch_permissions(permissions)
|
||||
|
@ -262,38 +276,17 @@ class PermissionTreeUtil:
|
|||
nodes.append(node)
|
||||
return nodes
|
||||
|
||||
@staticmethod
|
||||
def _get_permission_name(p, content_types_name_mapper):
|
||||
p: Permission
|
||||
code_name = p.codename
|
||||
action_mapper = {
|
||||
'add': ugettext('Create'),
|
||||
'view': ugettext('View'),
|
||||
'change': ugettext('Update'),
|
||||
'delete': ugettext('Delete')
|
||||
}
|
||||
name = ''
|
||||
ct = ''
|
||||
if 'add_' in p.codename:
|
||||
name = action_mapper['add']
|
||||
ct = code_name.replace('add_', '')
|
||||
elif 'view_' in p.codename:
|
||||
name = action_mapper['view']
|
||||
ct = code_name.replace('view_', '')
|
||||
elif 'change_' in p.codename:
|
||||
name = action_mapper['change']
|
||||
ct = code_name.replace('change_', '')
|
||||
elif 'delete' in code_name:
|
||||
name = action_mapper['delete']
|
||||
ct = code_name.replace('delete_', '')
|
||||
|
||||
app_model = '%s.%s' % (p.content_type.app_label, ct)
|
||||
if app_model in content_types_name_mapper:
|
||||
name += content_types_name_mapper[app_model]
|
||||
def _get_permission_name_icon(self, p: Permission, content_types_name_mapper: dict):
|
||||
action, resource = p.codename.split('_', 1)
|
||||
app_model = '%s.%s' % (p.content_type.app_label, resource)
|
||||
if action in self.action_mapper and app_model in content_types_name_mapper:
|
||||
action_name = self.action_mapper[action]
|
||||
name = action_name + content_types_name_mapper[app_model]
|
||||
else:
|
||||
name = gettext(p.name)
|
||||
name = name.replace('Can ', '').replace('可以', '')
|
||||
return name
|
||||
icon = self.action_icon.get(action, 'file')
|
||||
name = name.replace('Can ', '').replace('可以', '')
|
||||
return name, icon
|
||||
|
||||
def _create_perms_nodes(self):
|
||||
permissions_id = self.permissions.values_list('id', flat=True)
|
||||
|
@ -306,7 +299,7 @@ class PermissionTreeUtil:
|
|||
if not self._check_model_xpack(model_id):
|
||||
continue
|
||||
# name 要特殊处理,解决 i18n 问题
|
||||
name = self._get_permission_name(p, content_types_name_mapper)
|
||||
name, icon = self._get_permission_name_icon(p, content_types_name_mapper)
|
||||
if settings.DEBUG:
|
||||
name += '[{}]'.format(p.app_label_codename)
|
||||
|
||||
|
@ -328,7 +321,7 @@ class PermissionTreeUtil:
|
|||
'pId': pid,
|
||||
'isParent': False,
|
||||
'chkDisabled': self.check_disabled,
|
||||
'iconSkin': 'file',
|
||||
'iconSkin': icon,
|
||||
'checked': p.id in permissions_id,
|
||||
'open': False,
|
||||
'meta': {
|
||||
|
|
|
@ -14,7 +14,7 @@ from .. import serializers
|
|||
class AlibabaSMSTestingAPI(GenericAPIView):
|
||||
serializer_class = serializers.AlibabaSMSSettingSerializer
|
||||
rbac_perms = {
|
||||
'POST': 'settings.change_setting'
|
||||
'POST': 'settings.change_sms'
|
||||
}
|
||||
|
||||
def post(self, request):
|
||||
|
|
|
@ -19,7 +19,7 @@ class MailTestingAPI(APIView):
|
|||
serializer_class = serializers.MailTestSerializer
|
||||
success_message = _("Test mail sent to {}, please check")
|
||||
rbac_perms = {
|
||||
'POST': 'settings.change_setting'
|
||||
'POST': 'settings.change_email'
|
||||
}
|
||||
|
||||
def post(self, request):
|
||||
|
|
|
@ -13,7 +13,7 @@ from .. import serializers
|
|||
class FeiShuTestingAPI(GenericAPIView):
|
||||
serializer_class = serializers.FeiShuSettingSerializer
|
||||
rbac_perms = {
|
||||
'POST': 'settings.change_setting'
|
||||
'POST': 'settings.change_auth'
|
||||
}
|
||||
|
||||
def post(self, request):
|
||||
|
|
|
@ -16,7 +16,7 @@ from .. import serializers
|
|||
class TencentSMSTestingAPI(GenericAPIView):
|
||||
serializer_class = serializers.TencentSMSSettingSerializer
|
||||
rbac_perms = {
|
||||
'POST': 'settings.change_setting'
|
||||
'POST': 'settings.change_sms'
|
||||
}
|
||||
|
||||
def post(self, request):
|
||||
|
|
|
@ -13,7 +13,7 @@ from .. import serializers
|
|||
class WeComTestingAPI(GenericAPIView):
|
||||
serializer_class = serializers.WeComSettingSerializer
|
||||
rbac_perms = {
|
||||
'POST': 'settings.change_setting'
|
||||
'POST': 'settings.change_auth'
|
||||
}
|
||||
|
||||
def post(self, request):
|
||||
|
|
|
@ -121,7 +121,8 @@
|
|||
url: url,
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
success: onSuccess
|
||||
success: onSuccess,
|
||||
flash_message: false
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -131,7 +131,13 @@ class BaseStorageTestConnectiveMixin:
|
|||
|
||||
class CommandStorageTestConnectiveApi(BaseStorageTestConnectiveMixin, generics.RetrieveAPIView):
|
||||
queryset = CommandStorage.objects.all()
|
||||
rbac_perms = {
|
||||
'retrieve': 'terminal.view_commandstorage'
|
||||
}
|
||||
|
||||
|
||||
class ReplayStorageTestConnectiveApi(BaseStorageTestConnectiveMixin, generics.RetrieveAPIView):
|
||||
queryset = ReplayStorage.objects.all()
|
||||
rbac_perms = {
|
||||
'retrieve': 'terminal.view_replaystorage'
|
||||
}
|
||||
|
|
|
@ -182,6 +182,6 @@ class Terminal(StorageMixin, TerminalStatusMixin, models.Model):
|
|||
db_table = "terminal"
|
||||
verbose_name = _("Terminal")
|
||||
permissions = (
|
||||
('view_terminalconfig', 'Can view terminal config'),
|
||||
('view_terminalconfig', _('Can view terminal config')),
|
||||
)
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ __all__ = ['CommentViewSet']
|
|||
|
||||
class CommentViewSet(mixins.CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
||||
serializer_class = serializers.CommentSerializer
|
||||
permission_classes = (RBACPermission| IsSwagger | IsAssignee | IsApplicant)
|
||||
permission_classes = (RBACPermission, IsSwagger | IsAssignee | IsApplicant)
|
||||
|
||||
@lazyproperty
|
||||
def ticket(self):
|
||||
|
|
|
@ -17,6 +17,7 @@ class TicketSessionRelationViewSet(CreateModelMixin, JMSGenericViewSet):
|
|||
|
||||
# Todo: 放到上面的 ViewSet 中
|
||||
class TicketSessionApi(views.APIView):
|
||||
perm_model = TicketSession
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
with tmp_to_root_org():
|
||||
|
|
|
@ -49,8 +49,9 @@
|
|||
<div style="height: 100%; width: 100%;">
|
||||
{% for b in mfa_backends %}
|
||||
<div class="row" style="padding-top: 10px">
|
||||
<li class="col-sm-6" style="font-size: 14px">{{ b.display_name }}
|
||||
{{ b.enable }}</li>
|
||||
<li class="col-sm-6" style="font-size: 14px">
|
||||
{{ b.display_name }}
|
||||
</li>
|
||||
<span class="col-sm-6">
|
||||
{% if b.is_active %}
|
||||
<button class="btn btn-warning btn-xs" style="float: right"
|
||||
|
|
Loading…
Reference in New Issue