diff --git a/apps/assets/api/accounts.py b/apps/assets/api/accounts.py index 0c4e01ff2..d4b08b380 100644 --- a/apps/assets/api/accounts.py +++ b/apps/assets/api/accounts.py @@ -26,6 +26,7 @@ class AccountFilterSet(BaseFilterSet): qs = super().qs qs = self.filter_username(qs) qs = self.filter_node(qs) + qs = qs.distinct() return qs def filter_username(self, qs): diff --git a/apps/assets/api/system_user.py b/apps/assets/api/system_user.py index 9e5ca0f19..673a9f34d 100644 --- a/apps/assets/api/system_user.py +++ b/apps/assets/api/system_user.py @@ -1,18 +1,17 @@ # ~*~ coding: utf-8 ~*~ from django.shortcuts import get_object_or_404 +from django.middleware import csrf from rest_framework.response import Response -from django.db.models import Q from common.utils import get_logger, get_object_or_none +from common.utils.crypto import get_aes_crypto from common.permissions import IsOrgAdmin, IsOrgAdminOrAppUser, IsValidUser from orgs.mixins.api import OrgBulkModelViewSet from orgs.mixins import generics from common.mixins.api import SuggestionMixin from orgs.utils import tmp_to_root_org from rest_framework.decorators import action -from users.models import User, UserGroup -from applications.models import Application -from ..models import SystemUser, Asset, CommandFilter, CommandFilterRule +from ..models import SystemUser, CommandFilterRule from .. import serializers from ..serializers import SystemUserWithAuthInfoSerializer, SystemUserTempAuthSerializer from ..tasks import ( @@ -95,17 +94,27 @@ class SystemUserTempAuthInfoApi(generics.CreateAPIView): permission_classes = (IsValidUser,) serializer_class = SystemUserTempAuthSerializer + def decrypt_data_if_need(self, data): + csrf_token = self.request.META.get('CSRF_COOKIE') + aes = get_aes_crypto(csrf_token, 'ECB') + password = data.get('password', '') + try: + data['password'] = aes.decrypt(password) + except: + pass + return data + def create(self, request, *args, **kwargs): serializer = super().get_serializer(data=request.data) serializer.is_valid(raise_exception=True) + pk = kwargs.get('pk') - user = self.request.user - data = serializer.validated_data + data = self.decrypt_data_if_need(serializer.validated_data) instance_id = data.get('instance_id') with tmp_to_root_org(): instance = get_object_or_404(SystemUser, pk=pk) - instance.set_temp_auth(instance_id, user.id, data) + instance.set_temp_auth(instance_id, self.request.user, data) return Response(serializer.data, status=201) diff --git a/apps/assets/serializers/account.py b/apps/assets/serializers/account.py index 5de57474b..daa7f38f8 100644 --- a/apps/assets/serializers/account.py +++ b/apps/assets/serializers/account.py @@ -6,6 +6,7 @@ from orgs.mixins.serializers import BulkOrgResourceModelSerializer from .base import AuthSerializerMixin from .utils import validate_password_contains_left_double_curly_bracket +from common.utils.encode import ssh_pubkey_gen class AccountSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer): @@ -40,6 +41,21 @@ class AccountSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer): } ref_name = 'AssetAccountSerializer' + def _validate_gen_key(self, attrs): + private_key = attrs.get('private_key') + if not private_key: + return attrs + + password = attrs.get('passphrase') + username = attrs.get('username') + public_key = ssh_pubkey_gen(private_key, password=password, username=username) + attrs['public_key'] = public_key + return attrs + + def validate(self, attrs): + attrs = self._validate_gen_key(attrs) + return attrs + def get_protocols(self, v): return v.protocols.replace(' ', ', ') diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index 8a9de3ae8..4bf980374 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -11,6 +11,7 @@ from django.conf import settings from django.core.cache import cache from django.shortcuts import get_object_or_404 from django.http import HttpResponse +from django.utils import timezone from django.utils.translation import ugettext as _ from rest_framework.response import Response from rest_framework.request import Request @@ -20,15 +21,17 @@ from rest_framework.exceptions import PermissionDenied from rest_framework import serializers from applications.models import Application -from authentication.signals import post_auth_failed, post_auth_success +from authentication.signals import post_auth_failed from common.utils import get_logger, random_string from common.mixins.api import SerializerMixin from common.permissions import IsSuperUserOrAppUser, IsValidUser, IsSuperUser from common.utils.common import get_file_by_arch from orgs.mixins.api import RootOrgViewMixin from common.http import is_true -from perms.utils.asset.permission import get_asset_system_user_ids_with_actions_by_user from perms.models.base import Action +from perms.utils.application.permission import validate_permission as app_validate_permission +from perms.utils.application.permission import get_application_actions +from perms.utils.asset.permission import get_asset_actions from ..serializers import ( ConnectionTokenSerializer, ConnectionTokenSecretSerializer, @@ -99,10 +102,14 @@ class ClientProtocolMixin: token = self.create_token(user, asset, application, system_user) # 设置磁盘挂载 - if drives_redirect and asset: - systemuser_actions_mapper = get_asset_system_user_ids_with_actions_by_user(user, asset) - actions = systemuser_actions_mapper.get(system_user.id, 0) - if actions & Action.UPDOWNLOAD: + if drives_redirect: + actions = 0 + if asset: + actions = get_asset_actions(user, asset, system_user) + elif application: + actions = get_application_actions(user, application, system_user) + + if actions & Action.UPDOWNLOAD == Action.UPDOWNLOAD: options['drivestoredirect:s'] = '*' # 全屏 @@ -148,7 +155,6 @@ class ClientProtocolMixin: return name, content def get_encrypt_cmdline(self, app: Application): - parameters = app.get_rdp_remote_app_setting()['parameters'] parameters = parameters.encode('ascii') @@ -231,19 +237,16 @@ class SecretDetailMixin: @staticmethod def _get_application_secret_detail(application): - from perms.models.base import Action gateway = None + remote_app = None + asset = None - if not application.category_remote_app: - actions = Action.NONE - remote_app = {} - asset = None - domain = application.domain - else: + if application.category_remote_app: remote_app = application.get_rdp_remote_app_setting() - actions = Action.CONNECT asset = application.get_remote_app_asset() domain = asset.domain + else: + domain = application.domain if domain and domain.has_gateway(): gateway = domain.random_gateway() @@ -253,15 +256,10 @@ class SecretDetailMixin: 'application': application, 'gateway': gateway, 'remote_app': remote_app, - 'actions': actions } @staticmethod - def _get_asset_secret_detail(asset, user, system_user): - from perms.utils.asset import get_asset_system_user_ids_with_actions_by_user - systemuserid_actions_mapper = get_asset_system_user_ids_with_actions_by_user(user, asset) - actions = systemuserid_actions_mapper.get(system_user.id, []) - + def _get_asset_secret_detail(asset): gateway = None if asset and asset.domain and asset.domain.has_gateway(): gateway = asset.domain.random_gateway() @@ -271,14 +269,13 @@ class SecretDetailMixin: 'application': None, 'gateway': gateway, 'remote_app': None, - 'actions': actions, } @action(methods=['POST'], detail=False, permission_classes=[IsSuperUserOrAppUser], url_path='secret-info/detail') def get_secret_detail(self, request, *args, **kwargs): token = request.data.get('token', '') try: - value, user, system_user, asset, app, expired_at = self.valid_token(token) + value, user, system_user, asset, app, expired_at, actions = self.valid_token(token) except serializers.ValidationError as e: post_auth_failed.send( sender=self.__class__, username='', request=self.request, @@ -286,9 +283,13 @@ class SecretDetailMixin: ) raise e - data = dict(user=user, system_user=system_user, expired_at=expired_at) + data = dict( + id=token, secret=value.get('secret', ''), + user=user, system_user=system_user, + expired_at=expired_at, actions=actions + ) if asset: - asset_detail = self._get_asset_secret_detail(asset, user=user, system_user=system_user) + asset_detail = self._get_asset_secret_detail(asset) system_user.load_asset_more_auth(asset.id, user.username, user.id) data['type'] = 'asset' data.update(asset_detail) @@ -333,11 +334,16 @@ class UserConnectionTokenViewSet( raise PermissionDenied('Only super user can create user token') self.check_resource_permission(user, asset, application, system_user) token = random_string(36) + secret = random_string(16) value = { + 'id': token, + 'secret': secret, 'user': str(user.id), 'username': user.username, 'system_user': str(system_user.id), - 'system_user_name': system_user.name + 'system_user_name': system_user.name, + 'created_by': str(self.request.user), + 'date_created': str(timezone.now()) } if asset: @@ -395,7 +401,7 @@ class UserConnectionTokenViewSet( if not has_perm: raise serializers.ValidationError('Permission expired or invalid') - return value, user, system_user, asset, app, expired_at + return value, user, system_user, asset, app, expired_at, actions def get_permissions(self): if self.action in ["create", "get_rdp_file"]: diff --git a/apps/authentication/serializers.py b/apps/authentication/serializers.py index 3c02dea99..d405e5fb8 100644 --- a/apps/authentication/serializers.py +++ b/apps/authentication/serializers.py @@ -191,6 +191,8 @@ class ConnectionTokenApplicationSerializer(serializers.ModelSerializer): class ConnectionTokenSecretSerializer(serializers.Serializer): + id = serializers.CharField(read_only=True) + secret = serializers.CharField(read_only=True) type = serializers.ChoiceField(choices=[('application', 'Application'), ('asset', 'Asset')]) user = ConnectionTokenUserSerializer(read_only=True) asset = ConnectionTokenAssetSerializer(read_only=True) diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 860c414a6..208e87c10 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-02-08 17:40+0800\n" +"POT-Creation-Date: 2022-02-15 17:52+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -35,12 +35,12 @@ msgid "Name" msgstr "名称" #: acls/models/base.py:27 assets/models/cmd_filter.py:84 -#: assets/models/user.py:214 +#: assets/models/user.py:234 msgid "Priority" msgstr "优先级" #: acls/models/base.py:28 assets/models/cmd_filter.py:84 -#: assets/models/user.py:214 +#: assets/models/user.py:234 msgid "1-100, the lower the value will be match first" msgstr "优先级可选范围为 1-100 (数值越小越优先)" @@ -208,7 +208,7 @@ msgid "" msgstr "格式为逗号分隔的字符串, * 表示匹配所有. 可选的协议有: {}" #: acls/serializers/login_asset_acl.py:55 assets/models/asset.py:214 -#: assets/models/domain.py:63 assets/models/user.py:215 +#: assets/models/domain.py:63 assets/models/user.py:235 #: terminal/serializers/session.py:30 terminal/serializers/storage.py:69 msgid "Protocol" msgstr "协议" @@ -270,7 +270,7 @@ msgid "Application" msgstr "应用程序" #: applications/models/account.py:15 assets/models/authbook.py:20 -#: assets/models/cmd_filter.py:42 assets/models/user.py:305 audits/models.py:40 +#: assets/models/cmd_filter.py:42 assets/models/user.py:325 audits/models.py:40 #: perms/models/application_permission.py:32 #: perms/models/asset_permission.py:26 templates/_nav.html:45 #: terminal/backends/command/models.py:21 @@ -311,11 +311,11 @@ msgstr "类别" #: applications/models/application.py:207 #: applications/serializers/application.py:101 assets/models/backup.py:49 -#: assets/models/cmd_filter.py:82 assets/models/user.py:213 +#: assets/models/cmd_filter.py:82 assets/models/user.py:233 #: perms/models/application_permission.py:23 #: perms/serializers/application/user_permission.py:34 #: terminal/models/storage.py:55 terminal/models/storage.py:116 -#: tickets/models/flow.py:55 tickets/models/ticket.py:52 +#: tickets/models/flow.py:56 tickets/models/ticket.py:52 #: tickets/serializers/ticket/meta/ticket_type/apply_application.py:29 #: xpack/plugins/change_auth_plan/models/app.py:28 #: xpack/plugins/change_auth_plan/models/app.py:153 @@ -564,7 +564,7 @@ msgstr "主机名原始" msgid "Protocols" msgstr "协议组" -#: assets/models/asset.py:219 assets/models/user.py:205 +#: assets/models/asset.py:219 assets/models/user.py:225 #: perms/models/asset_permission.py:25 #: xpack/plugins/change_auth_plan/models/asset.py:43 #: xpack/plugins/gathered_user/models.py:24 @@ -577,7 +577,7 @@ msgid "Is active" msgstr "激活" #: assets/models/asset.py:223 assets/models/cluster.py:19 -#: assets/models/user.py:202 assets/models/user.py:354 templates/_nav.html:44 +#: assets/models/user.py:222 assets/models/user.py:374 templates/_nav.html:44 msgid "Admin user" msgstr "特权用户" @@ -703,7 +703,7 @@ msgstr "可连接性" msgid "Date verified" msgstr "校验日期" -#: assets/models/base.py:177 audits/signals_handler.py:66 +#: assets/models/base.py:177 audits/signals_handler.py:68 #: authentication/forms.py:22 #: authentication/templates/authentication/login.html:151 #: settings/serializers/auth/ldap.py:44 users/forms/profile.py:21 @@ -906,75 +906,75 @@ msgstr "ssh私钥" msgid "Node" msgstr "节点" -#: assets/models/user.py:196 +#: assets/models/user.py:216 msgid "Automatic managed" msgstr "托管密码" -#: assets/models/user.py:197 +#: assets/models/user.py:217 msgid "Manually input" msgstr "手动输入" -#: assets/models/user.py:201 +#: assets/models/user.py:221 msgid "Common user" msgstr "普通用户" -#: assets/models/user.py:204 +#: assets/models/user.py:224 msgid "Username same with user" msgstr "用户名与用户相同" -#: assets/models/user.py:207 assets/serializers/domain.py:29 +#: assets/models/user.py:227 assets/serializers/domain.py:29 #: templates/_nav.html:39 #: terminal/templates/terminal/_msg_command_execute_alert.html:16 #: xpack/plugins/change_auth_plan/models/asset.py:39 msgid "Assets" msgstr "资产" -#: assets/models/user.py:211 templates/_nav.html:17 +#: assets/models/user.py:231 templates/_nav.html:17 #: users/views/profile/pubkey.py:37 msgid "Users" msgstr "用户管理" -#: assets/models/user.py:212 +#: assets/models/user.py:232 msgid "User groups" msgstr "用户组" -#: assets/models/user.py:216 +#: assets/models/user.py:236 msgid "Auto push" msgstr "自动推送" -#: assets/models/user.py:217 +#: assets/models/user.py:237 msgid "Sudo" msgstr "Sudo" -#: assets/models/user.py:218 +#: assets/models/user.py:238 msgid "Shell" msgstr "Shell" -#: assets/models/user.py:219 +#: assets/models/user.py:239 msgid "Login mode" msgstr "认证方式" -#: assets/models/user.py:220 +#: assets/models/user.py:240 msgid "SFTP Root" msgstr "SFTP根路径" -#: assets/models/user.py:221 authentication/models.py:45 +#: assets/models/user.py:241 authentication/models.py:45 msgid "Token" msgstr "" -#: assets/models/user.py:222 +#: assets/models/user.py:242 msgid "Home" msgstr "家目录" -#: assets/models/user.py:223 +#: assets/models/user.py:243 msgid "System groups" msgstr "用户组" -#: assets/models/user.py:226 +#: assets/models/user.py:246 msgid "User switch" msgstr "用户切换" -#: assets/models/user.py:227 +#: assets/models/user.py:247 msgid "Switch from" msgstr "切换自" @@ -1047,6 +1047,7 @@ msgid "Actions" msgstr "动作" #: assets/serializers/backup.py:31 ops/mixin.py:106 ops/mixin.py:147 +#: settings/serializers/auth/ldap.py:59 #: xpack/plugins/change_auth_plan/serializers/base.py:42 msgid "Periodic perform" msgstr "定时执行" @@ -1225,24 +1226,24 @@ msgid "" "The task of self-checking is already running and cannot be started repeatedly" msgstr "自检程序已经在运行,不能重复启动" -#: assets/tasks/push_system_user.py:199 +#: assets/tasks/push_system_user.py:200 msgid "System user is dynamic: {}" msgstr "系统用户是动态的: {}" -#: assets/tasks/push_system_user.py:239 +#: assets/tasks/push_system_user.py:241 msgid "Start push system user for platform: [{}]" msgstr "推送系统用户到平台: [{}]" -#: assets/tasks/push_system_user.py:240 +#: assets/tasks/push_system_user.py:242 #: assets/tasks/system_user_connectivity.py:106 msgid "Hosts count: {}" msgstr "主机数量: {}" -#: assets/tasks/push_system_user.py:282 assets/tasks/push_system_user.py:315 +#: assets/tasks/push_system_user.py:259 assets/tasks/push_system_user.py:292 msgid "Push system users to assets: " msgstr "推送系统用户到入资产: " -#: assets/tasks/push_system_user.py:294 +#: assets/tasks/push_system_user.py:271 msgid "Push system users to asset: " msgstr "推送系统用户到入资产: " @@ -1448,209 +1449,209 @@ msgstr "运行用户名称" msgid "User display" msgstr "用户名称" -#: audits/signals_handler.py:65 +#: audits/signals_handler.py:67 msgid "SSH Key" msgstr "SSH 密钥" -#: audits/signals_handler.py:67 +#: audits/signals_handler.py:69 msgid "SSO" msgstr "" -#: audits/signals_handler.py:68 +#: audits/signals_handler.py:70 msgid "Auth Token" msgstr "认证令牌" -#: audits/signals_handler.py:69 authentication/notifications.py:73 +#: audits/signals_handler.py:71 authentication/notifications.py:73 #: authentication/views/login.py:164 authentication/views/wecom.py:158 #: notifications/backends/__init__.py:11 users/models/user.py:607 msgid "WeCom" msgstr "企业微信" -#: audits/signals_handler.py:70 authentication/views/dingtalk.py:160 +#: audits/signals_handler.py:72 authentication/views/dingtalk.py:160 #: authentication/views/login.py:170 notifications/backends/__init__.py:12 #: users/models/user.py:608 msgid "DingTalk" msgstr "钉钉" -#: audits/signals_handler.py:104 +#: audits/signals_handler.py:106 msgid "User and Organization" msgstr "用户与组织" -#: audits/signals_handler.py:105 +#: audits/signals_handler.py:107 #, python-brace-format msgid "{User} JOINED {Organization}" msgstr "{User} 加入 {Organization}" -#: audits/signals_handler.py:106 +#: audits/signals_handler.py:108 #, python-brace-format msgid "{User} LEFT {Organization}" msgstr "{User} 离开 {Organization}" -#: audits/signals_handler.py:109 +#: audits/signals_handler.py:111 msgid "User and Group" msgstr "用户与用户组" -#: audits/signals_handler.py:110 +#: audits/signals_handler.py:112 #, python-brace-format msgid "{User} JOINED {UserGroup}" msgstr "{User} 加入 {UserGroup}" -#: audits/signals_handler.py:111 +#: audits/signals_handler.py:113 #, python-brace-format msgid "{User} LEFT {UserGroup}" msgstr "{User} 离开 {UserGroup}" -#: audits/signals_handler.py:114 +#: audits/signals_handler.py:116 msgid "Asset and SystemUser" msgstr "资产与系统用户" -#: audits/signals_handler.py:115 +#: audits/signals_handler.py:117 #, python-brace-format msgid "{Asset} ADD {SystemUser}" msgstr "{Asset} 添加 {SystemUser}" -#: audits/signals_handler.py:116 +#: audits/signals_handler.py:118 #, python-brace-format msgid "{Asset} REMOVE {SystemUser}" msgstr "{Asset} 移除 {SystemUser}" -#: audits/signals_handler.py:119 +#: audits/signals_handler.py:121 msgid "Node and Asset" msgstr "节点与资产" -#: audits/signals_handler.py:120 +#: audits/signals_handler.py:122 #, python-brace-format msgid "{Node} ADD {Asset}" msgstr "{Node} 添加 {Asset}" -#: audits/signals_handler.py:121 +#: audits/signals_handler.py:123 #, python-brace-format msgid "{Node} REMOVE {Asset}" msgstr "{Node} 移除 {Asset}" -#: audits/signals_handler.py:124 +#: audits/signals_handler.py:126 msgid "User asset permissions" msgstr "用户资产授权" -#: audits/signals_handler.py:125 +#: audits/signals_handler.py:127 #, python-brace-format msgid "{AssetPermission} ADD {User}" msgstr "{AssetPermission} 添加 {User}" -#: audits/signals_handler.py:126 +#: audits/signals_handler.py:128 #, python-brace-format msgid "{AssetPermission} REMOVE {User}" msgstr "{AssetPermission} 移除 {User}" -#: audits/signals_handler.py:129 +#: audits/signals_handler.py:131 msgid "User group asset permissions" msgstr "用户组资产授权" -#: audits/signals_handler.py:130 +#: audits/signals_handler.py:132 #, python-brace-format msgid "{AssetPermission} ADD {UserGroup}" msgstr "{AssetPermission} 添加 {UserGroup}" -#: audits/signals_handler.py:131 +#: audits/signals_handler.py:133 #, python-brace-format msgid "{AssetPermission} REMOVE {UserGroup}" msgstr "{AssetPermission} 移除 {UserGroup}" -#: audits/signals_handler.py:134 perms/models/asset_permission.py:30 +#: audits/signals_handler.py:136 perms/models/asset_permission.py:30 #: templates/_nav.html:78 users/templates/users/_user_detail_nav_header.html:31 msgid "Asset permission" msgstr "资产授权" -#: audits/signals_handler.py:135 +#: audits/signals_handler.py:137 #, python-brace-format msgid "{AssetPermission} ADD {Asset}" msgstr "{AssetPermission} 添加 {Asset}" -#: audits/signals_handler.py:136 +#: audits/signals_handler.py:138 #, python-brace-format msgid "{AssetPermission} REMOVE {Asset}" msgstr "{AssetPermission} 移除 {Asset}" -#: audits/signals_handler.py:139 +#: audits/signals_handler.py:141 msgid "Node permission" msgstr "节点授权" -#: audits/signals_handler.py:140 +#: audits/signals_handler.py:142 #, python-brace-format msgid "{AssetPermission} ADD {Node}" msgstr "{AssetPermission} 添加 {Node}" -#: audits/signals_handler.py:141 +#: audits/signals_handler.py:143 #, python-brace-format msgid "{AssetPermission} REMOVE {Node}" msgstr "{AssetPermission} 移除 {Node}" -#: audits/signals_handler.py:144 +#: audits/signals_handler.py:146 msgid "Asset permission and SystemUser" msgstr "资产授权与系统用户" -#: audits/signals_handler.py:145 +#: audits/signals_handler.py:147 #, python-brace-format msgid "{AssetPermission} ADD {SystemUser}" msgstr "{AssetPermission} 添加 {SystemUser}" -#: audits/signals_handler.py:146 +#: audits/signals_handler.py:148 #, python-brace-format msgid "{AssetPermission} REMOVE {SystemUser}" msgstr "{AssetPermission} 移除 {SystemUser}" -#: audits/signals_handler.py:149 +#: audits/signals_handler.py:151 msgid "User application permissions" msgstr "用户应用授权" -#: audits/signals_handler.py:150 +#: audits/signals_handler.py:152 #, python-brace-format msgid "{ApplicationPermission} ADD {User}" msgstr "{ApplicationPermission} 添加 {User}" -#: audits/signals_handler.py:151 +#: audits/signals_handler.py:153 #, python-brace-format msgid "{ApplicationPermission} REMOVE {User}" msgstr "{ApplicationPermission} 移除 {User}" -#: audits/signals_handler.py:154 +#: audits/signals_handler.py:156 msgid "User group application permissions" msgstr "用户组应用授权" -#: audits/signals_handler.py:155 +#: audits/signals_handler.py:157 #, python-brace-format msgid "{ApplicationPermission} ADD {UserGroup}" msgstr "{ApplicationPermission} 添加 {UserGroup}" -#: audits/signals_handler.py:156 +#: audits/signals_handler.py:158 #, python-brace-format msgid "{ApplicationPermission} REMOVE {UserGroup}" msgstr "{ApplicationPermission} 移除 {UserGroup}" -#: audits/signals_handler.py:159 perms/models/application_permission.py:37 +#: audits/signals_handler.py:161 perms/models/application_permission.py:37 msgid "Application permission" msgstr "应用授权" -#: audits/signals_handler.py:160 +#: audits/signals_handler.py:162 #, python-brace-format msgid "{ApplicationPermission} ADD {Application}" msgstr "{ApplicationPermission} 添加 {Application}" -#: audits/signals_handler.py:161 +#: audits/signals_handler.py:163 #, python-brace-format msgid "{ApplicationPermission} REMOVE {Application}" msgstr "{ApplicationPermission} 移除 {Application}" -#: audits/signals_handler.py:164 +#: audits/signals_handler.py:166 msgid "Application permission and SystemUser" msgstr "应用授权与系统用户" -#: audits/signals_handler.py:165 +#: audits/signals_handler.py:167 #, python-brace-format msgid "{ApplicationPermission} ADD {SystemUser}" msgstr "{ApplicationPermission} 添加 {SystemUser}" -#: audits/signals_handler.py:166 +#: audits/signals_handler.py:168 #, python-brace-format msgid "{ApplicationPermission} REMOVE {SystemUser}" msgstr "{ApplicationPermission} 移除 {SystemUser}" @@ -2557,15 +2558,16 @@ msgid "Operations" msgstr "运维" #: ops/mixin.py:29 ops/mixin.py:92 ops/mixin.py:162 +#: settings/serializers/auth/ldap.py:66 msgid "Cycle perform" msgstr "周期执行" #: ops/mixin.py:33 ops/mixin.py:90 ops/mixin.py:109 ops/mixin.py:150 -#: settings/serializers/auth/ldap.py:64 +#: settings/serializers/auth/ldap.py:63 msgid "Regularly perform" msgstr "定期执行" -#: ops/mixin.py:112 settings/serializers/auth/ldap.py:61 +#: ops/mixin.py:112 msgid "Interval" msgstr "间隔" @@ -2592,7 +2594,7 @@ msgstr "" "分 时 日 月 星期> (在线工" "具
注意: 如果同时设置了定期执行和周期执行,优先使用定期执行" -#: ops/mixin.py:162 settings/serializers/auth/ldap.py:61 +#: ops/mixin.py:162 msgid "Unit: hour" msgstr "单位: 时" @@ -2873,7 +2875,7 @@ msgstr "用户名称" #: perms/serializers/asset/permission.py:22 msgid "User groups display" -msgstr "用户名称" +msgstr "用户组名称" #: perms/serializers/asset/permission.py:23 msgid "Assets display" @@ -3062,21 +3064,15 @@ msgstr "" "用户属性映射代表怎样将LDAP中用户属性映射到jumpserver用户上,username, name," "email 是jumpserver的用户需要属性" -#: settings/serializers/auth/ldap.py:58 -#: xpack/plugins/cloud/serializers/task.py:70 -#: xpack/plugins/gathered_user/serializers.py:20 -msgid "Periodic display" -msgstr "定时执行" - -#: settings/serializers/auth/ldap.py:68 +#: settings/serializers/auth/ldap.py:70 msgid "Connect timeout" msgstr "连接超时时间" -#: settings/serializers/auth/ldap.py:70 +#: settings/serializers/auth/ldap.py:72 msgid "Search paged size" msgstr "搜索分页数量" -#: settings/serializers/auth/ldap.py:72 +#: settings/serializers/auth/ldap.py:74 msgid "Enable LDAP auth" msgstr "启用 LDAP 认证" @@ -4366,19 +4362,19 @@ msgstr "Jmservisor 是在 windows 远程应用发布服务器中用来拉起远 msgid "Filters" msgstr "过滤" -#: terminal/api/session.py:190 +#: terminal/api/session.py:192 msgid "Session does not exist: {}" msgstr "会话不存在: {}" -#: terminal/api/session.py:193 +#: terminal/api/session.py:195 msgid "Session is finished or the protocol not supported" msgstr "会话已经完成或协议不支持" -#: terminal/api/session.py:198 +#: terminal/api/session.py:200 msgid "User does not exist: {}" msgstr "用户不存在: {}" -#: terminal/api/session.py:205 +#: terminal/api/session.py:207 msgid "User does not have permission" msgstr "用户没有权限" @@ -4935,24 +4931,24 @@ msgstr "用户显示名称" msgid "Body" msgstr "内容" -#: tickets/models/flow.py:18 tickets/models/flow.py:60 +#: tickets/models/flow.py:19 tickets/models/flow.py:61 #: tickets/models/ticket.py:29 msgid "Approve level" msgstr "审批级别" -#: tickets/models/flow.py:23 tickets/serializers/ticket/ticket.py:141 +#: tickets/models/flow.py:24 tickets/serializers/ticket/ticket.py:141 msgid "Approve strategy" msgstr "审批策略" -#: tickets/models/flow.py:28 tickets/serializers/ticket/ticket.py:142 +#: tickets/models/flow.py:29 tickets/serializers/ticket/ticket.py:142 msgid "Assignees" msgstr "受理人" -#: tickets/models/flow.py:32 +#: tickets/models/flow.py:33 msgid "Ticket flow approval rule" msgstr "工单批准信息" -#: tickets/models/flow.py:65 +#: tickets/models/flow.py:66 msgid "Ticket flow" msgstr "工单流程" @@ -6287,6 +6283,11 @@ msgstr "实例个数" msgid "Linux admin user" msgstr "Linux 管理员" +#: xpack/plugins/cloud/serializers/task.py:70 +#: xpack/plugins/gathered_user/serializers.py:20 +msgid "Periodic display" +msgstr "定时执行" + #: xpack/plugins/cloud/utils.py:68 msgid "Account unavailable" msgstr "账户无效" diff --git a/apps/perms/utils/application/permission.py b/apps/perms/utils/application/permission.py index 3f3dc8018..f37ca62b1 100644 --- a/apps/perms/utils/application/permission.py +++ b/apps/perms/utils/application/permission.py @@ -1,4 +1,5 @@ import time +from functools import reduce from django.db.models import Q @@ -79,3 +80,14 @@ def get_application_system_user_ids(user, application): def has_application_system_permission(user, application, system_user): system_user_ids = get_application_system_user_ids(user, application) return system_user.id in system_user_ids + + +def get_application_actions(user, application, system_user): + perm_ids = get_user_all_app_perm_ids(user) + actions = ApplicationPermission.objects.filter( + applications=application, system_users=system_user, + id__in=list(perm_ids) + ).values_list('actions', flat=True) + + actions = reduce(lambda x, y: x | y, actions, 0) + return actions diff --git a/apps/perms/utils/asset/permission.py b/apps/perms/utils/asset/permission.py index e749e630b..86e297426 100644 --- a/apps/perms/utils/asset/permission.py +++ b/apps/perms/utils/asset/permission.py @@ -109,3 +109,9 @@ def get_asset_system_user_ids_with_actions_by_group(group: UserGroup, asset: Ass user_groups=group ).valid().values_list('id', flat=True).distinct() return get_asset_system_user_ids_with_actions(asset_perm_ids, asset) + + +def get_asset_actions(user, asset, system_user): + systemuser_actions_mapper = get_asset_system_user_ids_with_actions_by_user(user, asset) + actions = systemuser_actions_mapper.get(system_user.id, 0) + return actions diff --git a/apps/settings/serializers/auth/ldap.py b/apps/settings/serializers/auth/ldap.py index 8096e5ca2..8508d2ee8 100644 --- a/apps/settings/serializers/auth/ldap.py +++ b/apps/settings/serializers/auth/ldap.py @@ -55,13 +55,15 @@ class LDAPSettingSerializer(serializers.Serializer): help_text=_('User attr map present how to map LDAP user attr to ' 'jumpserver, username,name,email is jumpserver attr') ) - AUTH_LDAP_SYNC_IS_PERIODIC = serializers.BooleanField(required=False, label=_('Periodic display')) - AUTH_LDAP_SYNC_INTERVAL = serializers.CharField( - required=False, max_length=1024, allow_null=True, - label=_('Interval'), help_text=_('Unit: hour') + AUTH_LDAP_SYNC_IS_PERIODIC = serializers.BooleanField( + required=False, label=_('Periodic perform') ) AUTH_LDAP_SYNC_CRONTAB = serializers.CharField( - required=False, max_length=1024, allow_null=True, label=_('Regularly perform') + required=False, max_length=128, allow_null=True, allow_blank=True, + label=_('Regularly perform') + ) + AUTH_LDAP_SYNC_INTERVAL = serializers.IntegerField( + required=False, default=24, allow_null=True, label=_('Cycle perform') ) AUTH_LDAP_CONNECT_TIMEOUT = serializers.IntegerField( min_value=1, max_value=300, diff --git a/apps/terminal/notifications.py b/apps/terminal/notifications.py index 8aa7ef0b5..e43a782e7 100644 --- a/apps/terminal/notifications.py +++ b/apps/terminal/notifications.py @@ -1,7 +1,6 @@ from typing import Callable -import textwrap -from django.utils.translation import gettext_lazy as _ +from django.utils.translation import ugettext_lazy as _ from django.conf import settings from django.template.loader import render_to_string @@ -11,7 +10,6 @@ from notifications.notifications import SystemMessage from terminal.models import Session, Command from notifications.models import SystemMsgSubscription from notifications.backends import BACKEND -from orgs.utils import tmp_to_root_org from common.utils import lazyproperty from common.utils.timezone import local_now_display diff --git a/apps/tickets/api/ticket.py b/apps/tickets/api/ticket.py index bca98e1fd..3d1d3081e 100644 --- a/apps/tickets/api/ticket.py +++ b/apps/tickets/api/ticket.py @@ -81,7 +81,7 @@ class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet): class TicketFlowViewSet(JMSBulkModelViewSet): - permission_classes = (IsOrgAdmin,) + permission_classes = (IsSuperUser,) serializer_class = serializers.TicketFlowSerializer filterset_fields = ['id', 'type']