mirror of https://github.com/jumpserver/jumpserver
commit
a64ec8a1d2
|
@ -214,7 +214,7 @@ class DatesLoginMetricMixin:
|
|||
class IndexApi(DatesLoginMetricMixin, APIView):
|
||||
http_method_names = ['get']
|
||||
rbac_perms = {
|
||||
'GET': 'rbac.view_dashboard'
|
||||
'GET': 'rbac.view_audit | rbac.view_console'
|
||||
}
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
|
|
@ -390,7 +390,6 @@ class Config(dict):
|
|||
'HELP_DOCUMENT_URL': 'http://docs.jumpserver.org',
|
||||
'HELP_SUPPORT_URL': 'http://www.jumpserver.org/support/',
|
||||
|
||||
'TICKETS_ENABLED': True,
|
||||
'FORGOT_PASSWORD_URL': '',
|
||||
'HEALTH_CHECK_TOKEN': '',
|
||||
}
|
||||
|
|
|
@ -119,7 +119,6 @@ CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED = CONFIG.CHANGE_AUTH_PLAN_SECURE_MODE_ENABL
|
|||
|
||||
DATETIME_DISPLAY_FORMAT = '%Y-%m-%d %H:%M:%S'
|
||||
|
||||
TICKETS_ENABLED = CONFIG.TICKETS_ENABLED
|
||||
REFERER_CHECK_ENABLED = CONFIG.REFERER_CHECK_ENABLED
|
||||
|
||||
CONNECTION_TOKEN_ENABLED = CONFIG.CONNECTION_TOKEN_ENABLED
|
||||
|
|
|
@ -14,6 +14,7 @@ from orgs.models import Organization
|
|||
from orgs.hands import set_current_org, Node, get_current_org
|
||||
from perms.models import (AssetPermission, ApplicationPermission)
|
||||
from users.models import UserGroup, User
|
||||
from assets.models import SystemUser
|
||||
from common.const.signals import PRE_REMOVE, POST_REMOVE
|
||||
from common.decorator import on_transaction_commit
|
||||
from common.signals import django_ready
|
||||
|
@ -135,7 +136,7 @@ def _clear_users_from_org(org, users):
|
|||
if not users:
|
||||
return
|
||||
|
||||
models = (AssetPermission, ApplicationPermission, UserGroup)
|
||||
models = (AssetPermission, ApplicationPermission, UserGroup, SystemUser)
|
||||
|
||||
for m in models:
|
||||
_remove_users(m, users, org)
|
||||
|
|
|
@ -5,7 +5,7 @@ from rest_framework import serializers
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from perms.models import ApplicationPermission
|
||||
from perms.models import ApplicationPermission, Action
|
||||
from ..base import ActionsField, BasePermissionSerializer
|
||||
|
||||
__all__ = [
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from rest_framework import serializers
|
||||
from perms.models import Action
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from rest_framework.fields import empty
|
||||
|
||||
__all__ = ['ActionsDisplayField', 'ActionsField', 'BasePermissionSerializer']
|
||||
|
||||
|
@ -10,6 +11,12 @@ class ActionsField(serializers.MultipleChoiceField):
|
|||
kwargs['choices'] = Action.CHOICES
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def run_validation(self, data=empty):
|
||||
data = super(ActionsField, self).run_validation()
|
||||
if isinstance(data, list):
|
||||
data = Action.choices_to_value(value=data)
|
||||
return data
|
||||
|
||||
def to_representation(self, value):
|
||||
return Action.value_to_choices(value)
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ auditor_perms = user_perms + (
|
|||
('terminal', 'sessionreplay', 'view,download', 'sessionreplay'),
|
||||
('terminal', 'session', '*', '*'),
|
||||
('terminal', 'command', '*', '*'),
|
||||
('ops', 'commandexecution', 'view', 'commandexecution')
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -23,6 +23,10 @@ exclude_permissions = (
|
|||
('common', 'setting', '*', '*'),
|
||||
|
||||
('authentication', 'privatetoken', '*', '*'),
|
||||
('authentication', 'accesskey', 'change,delete', 'accesskey'),
|
||||
('authentication', 'connectiontoken', 'change,delete', 'connectiontoken'),
|
||||
('authentication', 'ssotoken', 'change,delete', 'ssotoken'),
|
||||
('authentication', 'superconnectiontoken', 'change,delete', 'superconnectiontoken'),
|
||||
('users', 'userpasswordhistory', '*', '*'),
|
||||
('applications', 'applicationuser', '*', '*'),
|
||||
('applications', 'historicalaccount', '*', '*'),
|
||||
|
@ -56,10 +60,14 @@ exclude_permissions = (
|
|||
('audits', 'passwordchangelog', 'add,change,delete', 'passwordchangelog'),
|
||||
('audits', 'userloginlog', 'add,change,delete,change', 'userloginlog'),
|
||||
('audits', 'ftplog', 'change,delete', 'ftplog'),
|
||||
('tickets', 'ticket', '*', '*'),
|
||||
('tickets', 'ticketassignee', '*', 'ticketassignee'),
|
||||
('tickets', 'ticketflow', 'add,delete', 'ticketflow'),
|
||||
('tickets', 'comment', 'change,delete', 'comment'),
|
||||
('tickets', 'ticket', 'delete', 'ticket'),
|
||||
('tickets', 'ticketstep', '*', '*'),
|
||||
('tickets', 'ticketapprovalrule', '*', '*'),
|
||||
('tickets', 'approvalrule', '*', '*'),
|
||||
('tickets', 'superticket', 'delete', 'superticket'),
|
||||
('tickets', 'ticketsession', 'delete', 'ticketsession'),
|
||||
('xpack', 'interface', '*', '*'),
|
||||
('xpack', 'license', '*', '*'),
|
||||
('xpack', 'syncinstancedetail', 'add,delete,change', 'syncinstancedetail'),
|
||||
|
@ -75,13 +83,13 @@ exclude_permissions = (
|
|||
|
||||
|
||||
only_system_permissions = (
|
||||
('assets', 'platform', '*', '*'),
|
||||
('users', 'user', 'delete', 'user'),
|
||||
('rbac', 'role', 'delete,add,change', 'role'),
|
||||
('rbac', 'systemrole', '*', '*'),
|
||||
('rbac', 'rolebinding', '*', '*'),
|
||||
('rbac', 'systemrolebinding', '*', '*'),
|
||||
('rbac', 'orgrole', 'delete,add,change', '*'),
|
||||
('rbac', 'orgrolebinding', 'delete,add,change', '*'),
|
||||
('orgs', 'organization', '*', '*'),
|
||||
('xpack', 'license', '*', '*'),
|
||||
('settings', 'setting', '*', '*'),
|
||||
|
|
|
@ -12,6 +12,6 @@ class Migration(migrations.Migration):
|
|||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='menupermission',
|
||||
options={'default_permissions': [], 'permissions': [('view_dashboard', 'Can view resource statistics'), ('view_console', 'Can view console view'), ('view_audit', 'Can view audit view'), ('view_workspace', 'Can view workspace view'), ('view_webterminal', 'Can view web terminal'), ('view_filemanager', 'Can view file manager')], 'verbose_name': 'Menu permission'},
|
||||
options={'default_permissions': [], 'permissions': [('view_console', 'Can view console view'), ('view_audit', 'Can view audit view'), ('view_workspace', 'Can view workspace view'), ('view_webterminal', 'Can view web terminal'), ('view_filemanager', 'Can view file manager')], 'verbose_name': 'Menu permission'},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -12,6 +12,6 @@ class Migration(migrations.Migration):
|
|||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='menupermission',
|
||||
options={'default_permissions': [], 'permissions': [('view_console', 'Can view console view'), ('view_audit', 'Can view audit view'), ('view_workspace', 'Can view workspace view'), ('view_webterminal', 'Can view web terminal'), ('view_filemanager', 'Can view file manager'), ('view_dashboard', 'Can view dashboard')], 'verbose_name': 'Menu permission'},
|
||||
options={'default_permissions': [], 'permissions': [('view_console', 'Can view console view'), ('view_audit', 'Can view audit view'), ('view_workspace', 'Can view workspace view'), ('view_webterminal', 'Can view web terminal'), ('view_filemanager', 'Can view file manager') ], 'verbose_name': 'Menu permission'},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -17,5 +17,4 @@ class MenuPermission(models.Model):
|
|||
('view_workspace', _('Can view workspace view')),
|
||||
('view_webterminal', _('Can view web terminal')),
|
||||
('view_filemanager', _('Can view file manager')),
|
||||
('view_dashboard', _('Can view dashboard')),
|
||||
]
|
||||
|
|
|
@ -98,7 +98,14 @@ special_pid_mapper = {
|
|||
"perms.view_mydatabaseapp": "my_apps",
|
||||
"perms.connect_mydatabaseapp": "my_apps",
|
||||
"xpack.interface": "view_setting",
|
||||
"settings.change_terminal": "terminal_node"
|
||||
"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",
|
||||
"rbac.view_webterminal": "view_workspace",
|
||||
"rbac.view_filemanager": "view_workspace",
|
||||
}
|
||||
|
||||
verbose_name_mapper = {
|
||||
|
@ -115,6 +122,32 @@ xpack_nodes = [
|
|||
]
|
||||
|
||||
|
||||
def _sort_action(node):
|
||||
value = 0
|
||||
|
||||
if 'view' in node.title:
|
||||
value += 2
|
||||
elif 'add' in node.title:
|
||||
value += 4
|
||||
elif 'change' in node.title:
|
||||
value += 6
|
||||
elif 'delete' in node.title:
|
||||
value += 8
|
||||
else:
|
||||
value += 10
|
||||
return value
|
||||
|
||||
|
||||
def sort_nodes(node):
|
||||
value = 0
|
||||
|
||||
if node.isParent:
|
||||
value += 50
|
||||
else:
|
||||
value += _sort_action(node)
|
||||
return value
|
||||
|
||||
|
||||
class PermissionTreeUtil:
|
||||
get_permissions: Callable
|
||||
|
||||
|
@ -122,7 +155,7 @@ class PermissionTreeUtil:
|
|||
self.permissions = self.prefetch_permissions(permissions)
|
||||
self.all_permissions = self.prefetch_permissions(
|
||||
Permission.get_permissions(scope)
|
||||
).order_by('-codename')
|
||||
)
|
||||
self.check_disabled = check_disabled
|
||||
self.total_counts = defaultdict(int)
|
||||
self.checked_counts = defaultdict(int)
|
||||
|
@ -272,7 +305,7 @@ class PermissionTreeUtil:
|
|||
# name 要特殊处理,解决 i18n 问题
|
||||
name = self._get_permission_name(p, content_types_name_mapper)
|
||||
if settings.DEBUG:
|
||||
name += '({})'.format(p.app_label_codename)
|
||||
name += '[{}]'.format(p.app_label_codename)
|
||||
|
||||
title = p.app_label_codename
|
||||
pid = model_id
|
||||
|
@ -320,9 +353,12 @@ class PermissionTreeUtil:
|
|||
},
|
||||
**data
|
||||
}
|
||||
if not node_data.get('title'):
|
||||
node_data['title'] = node_data['name']
|
||||
node_data['title'] = node_data['id']
|
||||
node = TreeNode(**node_data)
|
||||
if settings.DEBUG:
|
||||
node.name += ('[' + node.id + ']')
|
||||
if settings.DEBUG:
|
||||
node.name += ('-' + node.id)
|
||||
node.name += f'({checked_count}/{total_count})'
|
||||
return node
|
||||
|
||||
|
@ -367,12 +403,12 @@ class PermissionTreeUtil:
|
|||
return nodes
|
||||
|
||||
def create_tree_nodes(self):
|
||||
nodes = [self._create_root_tree_node()]
|
||||
perms_nodes = self._create_perms_nodes()
|
||||
models_nodes = self._create_models_nodes()
|
||||
apps_nodes = self.create_apps_nodes()
|
||||
extra_nodes = self._create_extra_nodes()
|
||||
views_nodes = self._create_views_node()
|
||||
nodes = self._create_perms_nodes()
|
||||
nodes += self._create_models_nodes()
|
||||
nodes += self.create_apps_nodes()
|
||||
nodes += self._create_extra_nodes()
|
||||
nodes += self._create_views_node()
|
||||
nodes += [self._create_root_tree_node()]
|
||||
|
||||
nodes += views_nodes + apps_nodes + models_nodes + perms_nodes + extra_nodes
|
||||
nodes.sort(key=sort_nodes)
|
||||
return nodes
|
||||
|
|
|
@ -11,6 +11,9 @@ from .. import serializers
|
|||
|
||||
class DingTalkTestingAPI(GenericAPIView):
|
||||
serializer_class = serializers.DingTalkSettingSerializer
|
||||
rbac_perms = {
|
||||
'POST': 'settings.change_auth'
|
||||
}
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
|
|
|
@ -43,7 +43,6 @@ class PublicSettingApi(generics.RetrieveAPIView):
|
|||
"XPACK_LICENSE_INFO": get_xpack_license_info(),
|
||||
"LOGIN_TITLE": self.get_login_title(),
|
||||
"LOGO_URLS": self.get_logo_urls(),
|
||||
"TICKETS_ENABLED": settings.TICKETS_ENABLED,
|
||||
"PASSWORD_RULE": {
|
||||
'SECURITY_PASSWORD_MIN_LENGTH': settings.SECURITY_PASSWORD_MIN_LENGTH,
|
||||
'SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH': settings.SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH,
|
||||
|
|
|
@ -41,9 +41,41 @@ class SettingsApi(generics.RetrieveUpdateAPIView):
|
|||
'tencent': serializers.TencentSMSSettingSerializer,
|
||||
}
|
||||
|
||||
rbac_category_permissions = {
|
||||
# 'all': 'view_setting',
|
||||
'basic': 'view_setting',
|
||||
'terminal': 'change_terminal',
|
||||
'security': 'change_security',
|
||||
'ldap': 'change_auth',
|
||||
'email': 'change_email',
|
||||
'email_content': 'change_email',
|
||||
'wecom': 'change_auth',
|
||||
'dingtalk': 'change_auth',
|
||||
'feishu': 'change_auth',
|
||||
'auth': 'change_auth',
|
||||
'oidc': 'change_auth',
|
||||
'keycloak': 'change_auth',
|
||||
'radius': 'change_auth',
|
||||
'cas': 'change_auth',
|
||||
'sso': 'change_auth',
|
||||
'saml2': 'change_auth',
|
||||
'clean': 'change_clean',
|
||||
'other': 'change_other',
|
||||
'sms': 'change_sms',
|
||||
'alibaba': 'change_sms',
|
||||
'tencent': 'change_sms',
|
||||
}
|
||||
|
||||
def get_queryset(self):
|
||||
return Setting.objects.all()
|
||||
|
||||
def check_permissions(self, request):
|
||||
category = request.query_params.get('category', 'basic')
|
||||
require_perm = self.rbac_category_permissions.get(category)
|
||||
if not request.user.has_perm(require_perm):
|
||||
self.permission_denied(request)
|
||||
return super().check_permissions(request)
|
||||
|
||||
def get_serializer_class(self):
|
||||
category = self.request.query_params.get('category', 'basic')
|
||||
default = serializers.BasicSettingSerializer
|
||||
|
|
|
@ -12,6 +12,6 @@ class Migration(migrations.Migration):
|
|||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='setting',
|
||||
options={'permissions': [('change_basic', 'Can change basic setting'), ('change_email', 'Can change email setting'), ('change_auth', 'Can change auth setting'), ('change_sms', 'Can change sms setting'), ('change_security', 'Can change security setting'), ('change_clean', 'Can change clean setting'), ('change_other', 'Can change other setting'), ('change_terminal_basic_setting', 'Can change terminal basic setting')], 'verbose_name': 'System 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'},
|
||||
),
|
||||
]
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
# Generated by Django 3.1.14 on 2022-03-10 11:52
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('settings', '0005_auto_20220310_0616'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='setting',
|
||||
options={'permissions': [('change_basic', 'Can change basic setting'), ('change_email', 'Can change email setting'), ('change_auth', 'Can change auth setting'), ('change_sms', 'Can change sms setting'), ('change_security', 'Can change security setting'), ('change_clean', 'Can change clean setting'), ('change_other', 'Can change other setting'), ('change_interface', 'Can change interface setting'), ('change_license', 'Can change license setting'), ('change_terminal_basic_setting', 'Can change terminal basic setting')], 'verbose_name': 'System setting'},
|
||||
),
|
||||
]
|
|
@ -1,17 +0,0 @@
|
|||
# Generated by Django 3.1.14 on 2022-03-10 12:06
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('settings', '0006_auto_20220310_1952'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='setting',
|
||||
options={'permissions': [('change_basic', 'Can change basic setting'), ('change_email', 'Can change email setting'), ('change_auth', 'Can change auth setting'), ('change_sys_msg_sub', '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'},
|
||||
),
|
||||
]
|
|
@ -139,7 +139,6 @@ class Setting(models.Model):
|
|||
db_table = "settings_setting"
|
||||
verbose_name = _("System setting")
|
||||
permissions = [
|
||||
('change_basic', _('Can change basic setting')),
|
||||
('change_email', _('Can change email setting')),
|
||||
('change_auth', _('Can change auth setting')),
|
||||
('change_systemmsgsubscription', _('Can sys msg sub setting')),
|
||||
|
|
|
@ -41,7 +41,6 @@ class BasicSettingSerializer(serializers.Serializer):
|
|||
required=False, max_length=1024, allow_blank=True, allow_null=True, label=_("Global organization name"),
|
||||
help_text=_('The name of global organization to display')
|
||||
)
|
||||
TICKETS_ENABLED = serializers.BooleanField(required=False, default=True, label=_("Enable tickets"))
|
||||
ANNOUNCEMENT_ENABLED = serializers.BooleanField(label=_('Enable announcement'), default=True)
|
||||
ANNOUNCEMENT = AnnouncementSerializer(label=_("Announcement"))
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
from rest_framework import viewsets, mixins
|
||||
from common.exceptions import JMSException
|
||||
from common.utils import lazyproperty
|
||||
from rbac.permissions import RBACPermission
|
||||
from tickets import serializers
|
||||
from tickets.models import Ticket
|
||||
from tickets.permissions.comment import IsAssignee, IsApplicant, IsSwagger
|
||||
|
@ -14,7 +15,7 @@ __all__ = ['CommentViewSet']
|
|||
|
||||
class CommentViewSet(mixins.CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
||||
serializer_class = serializers.CommentSerializer
|
||||
permission_classes = (IsSwagger | IsAssignee | IsApplicant,)
|
||||
permission_classes = (RBACPermission| IsSwagger | IsAssignee | IsApplicant)
|
||||
|
||||
@lazyproperty
|
||||
def ticket(self):
|
||||
|
|
|
@ -19,7 +19,6 @@ __all__ = ['TicketViewSet', 'TicketFlowViewSet']
|
|||
|
||||
|
||||
class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet):
|
||||
permission_classes = (IsValidUser,)
|
||||
serializer_class = serializers.TicketDisplaySerializer
|
||||
serializer_classes = {
|
||||
'open': serializers.TicketApplySerializer,
|
||||
|
|
|
@ -5,12 +5,13 @@ from django.db.models import F
|
|||
|
||||
from common.drf.api import JMSBulkRelationModelViewSet
|
||||
from .. import serializers
|
||||
from ..models import User
|
||||
from ..models import User, UserGroup
|
||||
|
||||
__all__ = ['UserUserGroupRelationViewSet']
|
||||
|
||||
|
||||
class UserUserGroupRelationViewSet(JMSBulkRelationModelViewSet):
|
||||
perm_model = UserGroup
|
||||
filterset_fields = ('user', 'usergroup')
|
||||
search_fields = filterset_fields
|
||||
serializer_class = serializers.UserUserGroupRelationSerializer
|
||||
|
|
|
@ -53,9 +53,11 @@ def clean_db_content_types():
|
|||
('applications', 'remoteapp', 'view_remoteapp'),
|
||||
|
||||
('settings', 'setting', 'change_terminal_basic_setting'),
|
||||
('rbac', 'menupermission', 'view_resourcestatistics'),
|
||||
|
||||
|
||||
('settings', 'setting', 'change_sys_msg_sub'),
|
||||
('settings', 'setting', 'change_basic'),
|
||||
('rbac', 'menupermission', 'view_userview'),
|
||||
('rbac', 'menupermission', 'view_adminview'),
|
||||
('rbac', 'menupermission', 'view_auditview'),
|
||||
]
|
||||
for app, model, codename in permissions_delete_required:
|
||||
print('delete {}.{} ({})'.format(app, codename, model))
|
||||
|
|
Loading…
Reference in New Issue