fix: rbac 合并 (#7658)

* perf: 修复一些错误权限位

* Pr@fix rbac@fix rbac permissions (#7648)

* fix: 确保每次 migrate 执行更新 role permissions

* perf: 修改 choices

* feat: 兼容apple m1

* perf: 修改 migrations role permissions

* perf: pymysql 导入

* perf: admin 判断

* fix: 修复消息订阅权限

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: Aaron3S <chenyang@fit2cloud.com>
Co-authored-by: feng626 <1304903146@qq.com>
pull/7660/head
Jiangjie.Bai 2022-02-21 16:24:03 +08:00 committed by GitHub
parent 783c163324
commit 83ff8dbf26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 59 additions and 46 deletions

View File

@ -54,6 +54,6 @@ class ApplicationAccountSecretViewSet(ApplicationAccountViewSet):
permission_classes = [RBACPermission, NeedMFAVerify]
http_method_names = ['get', 'options']
rbac_perms = {
'retrieve': 'view_applicationaccountsecret',
'list': 'view_applicationaccountsecret',
'retrieve': 'applications.view_applicationaccountsecret',
'list': 'applications.view_applicationaccountsecret',
}

View File

@ -1,10 +1,10 @@
# coding: utf-8
#
from django.db.models import TextChoices
from django.db import models
from django.utils.translation import ugettext_lazy as _
class AppCategory(TextChoices):
class AppCategory(models.TextChoices):
db = 'db', _('Database')
remote_app = 'remote_app', _('Remote app')
cloud = 'cloud', 'Cloud'
@ -14,7 +14,7 @@ class AppCategory(TextChoices):
return dict(cls.choices).get(category, '')
class AppType(TextChoices):
class AppType(models.TextChoices):
# db category
mysql = 'mysql', 'MySQL'
redis = 'redis', 'Redis'

View File

@ -8,7 +8,6 @@ from functools import reduce
from collections import OrderedDict
from django.db import models
from common.db.models import TextChoices
from django.utils.translation import ugettext_lazy as _
from rest_framework.exceptions import ValidationError
@ -59,7 +58,7 @@ class AssetQuerySet(models.QuerySet):
class ProtocolsMixin:
protocols = ''
class Protocol(TextChoices):
class Protocol(models.TextChoices):
ssh = 'ssh', 'SSH'
rdp = 'rdp', 'RDP'
telnet = 'telnet', 'Telnet'

View File

@ -7,7 +7,6 @@ import random
from django.core.cache import cache
import paramiko
from django.db import models
from django.db.models import TextChoices
from django.utils.translation import ugettext_lazy as _
from common.utils import get_logger
@ -55,7 +54,7 @@ class Gateway(BaseUser):
UNCONNECTIVE_SILENCE_PERIOD_KEY_TMPL = 'asset_unconnective_gateway_silence_period_{}'
UNCONNECTIVE_SILENCE_PERIOD_BEGIN_VALUE = 60 * 5
class Protocol(TextChoices):
class Protocol(models.TextChoices):
ssh = 'ssh', 'SSH'
ip = models.CharField(max_length=128, verbose_name=_('IP'), db_index=True)

View File

@ -5,13 +5,11 @@
import logging
from django.db import models
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
from django.core.validators import MinValueValidator, MaxValueValidator
from django.core.cache import cache
from common.utils import signer, get_object_or_none
from common.db.models import TextChoices
from .base import BaseUser
from .asset import Asset
from .authbook import AuthBook
@ -24,7 +22,7 @@ logger = logging.getLogger(__name__)
class ProtocolMixin:
protocol: str
class Protocol(TextChoices):
class Protocol(models.TextChoices):
ssh = 'ssh', 'SSH'
rdp = 'rdp', 'RDP'
telnet = 'telnet', 'Telnet'
@ -217,7 +215,7 @@ class SystemUser(ProtocolMixin, AuthMixin, BaseUser):
(LOGIN_MANUAL, _('Manually input'))
)
class Type(TextChoices):
class Type(models.TextChoices):
common = 'common', _('Common user')
admin = 'admin', _('Admin user')

View File

@ -1,4 +1,10 @@
import os
import platform
if platform.system() == 'Darwin' and platform.machine() == 'arm64':
import pymysql
pymysql.version_info = (1, 4, 2, "final", 0)
pymysql.install_as_MySQLdb()
from django.urls import reverse_lazy
@ -68,10 +74,9 @@ INSTALLED_APPS = [
'django.contrib.messages',
'django.contrib.staticfiles',
'django.forms',
'simple_history',
'simple_history', # 这个要放到最后,别特么瞎改顺序
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
@ -92,7 +97,6 @@ MIDDLEWARE = [
'simple_history.middleware.HistoryRequestMiddleware',
]
ROOT_URLCONF = 'jumpserver.urls'
TEMPLATES = [
@ -158,13 +162,14 @@ DATABASES = {
'OPTIONS': DB_OPTIONS
}
}
DB_CA_PATH = os.path.join(PROJECT_DIR, 'data', 'certs', 'db_ca.pem')
if CONFIG.DB_ENGINE.lower() == 'mysql':
DB_OPTIONS['init_command'] = "SET sql_mode='STRICT_TRANS_TABLES'"
if os.path.isfile(DB_CA_PATH):
DB_OPTIONS['ssl'] = {'ca': DB_CA_PATH}
# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
#
@ -234,7 +239,6 @@ EMAIL_RECIPIENT = CONFIG.EMAIL_RECIPIENT
EMAIL_USE_SSL = CONFIG.EMAIL_USE_SSL
EMAIL_USE_TLS = CONFIG.EMAIL_USE_TLS
# Custom User Auth model
AUTH_USER_MODEL = 'users.User'

View File

@ -19,14 +19,15 @@ __all__ = (
class BackendListView(APIView):
permission_classes = [IsValidUser]
def get(self, request):
data = [
{
'name': backend,
'name_display': backend.label
}
for backend in BACKEND.choices
if backend.is_enable
for backend in BACKEND if backend.is_enable
]
return Response(data=data)
@ -91,7 +92,6 @@ class UserMsgSubscriptionViewSet(ListModelMixin,
return queryset
def get_all_test_messages(request):
import textwrap
from ..notifications import Message
@ -128,5 +128,3 @@ def get_all_test_messages(request):
<hr />
""").format(msg_cls.__name__, msg_text)
return HttpResponse(html_data + text_data)

View File

@ -13,7 +13,7 @@ class CeleryTaskLogView(PermissionsMixin, TemplateView):
template_name = 'ops/celery_task_log.html'
permission_classes = [RBACPermission]
rbac_perms = {
'GET': 'view_tasklog'
'GET': 'ops.view_tasklog'
}
def get_context_data(self, **kwargs):

View File

@ -56,7 +56,7 @@ class MyGrantedApplicationSystemUsersApi(RoleUserMixin, GrantedApplicationSystem
@method_decorator(tmp_to_root_org(), name='get')
class ValidateUserApplicationPermissionApi(APIView):
rbac_perms = {
'GET': 'view_applicationpermission'
'GET': 'ops.view_applicationpermission'
}
def get(self, request, *args, **kwargs):

View File

@ -123,7 +123,7 @@ class UserGroupGrantedNodeAssetsApi(ListAPIView):
class UserGroupGrantedNodesApi(ListAPIView):
serializer_class = serializers.NodeGrantedSerializer
rbac_perms = {
'list': 'view_userassets'
'list': 'perms.view_userassets'
}
def get_queryset(self):
@ -137,7 +137,7 @@ class UserGroupGrantedNodesApi(ListAPIView):
class UserGroupGrantedNodeChildrenAsTreeApi(SerializeToTreeNodeMixin, ListAPIView):
rbac_perms = {
'list': 'view_userassets'
'list': 'perms.view_userassets'
}
def get_children_nodes(self, parent_key):

View File

@ -1,9 +1,8 @@
import logging
from django.utils.translation import ugettext_lazy as _
from django.db.models import F
from django.db.models import F, TextChoices
from common.db.models import TextChoices
from orgs.mixins.models import OrgModelMixin
from common.db import models
from common.utils import lazyproperty

View File

@ -5,3 +5,7 @@ from django.utils.translation import ugettext_lazy as _
class RBACConfig(AppConfig):
name = 'rbac'
verbose_name = _('RBAC')
def ready(self):
from . import signal_handlers
super().ready()

View File

@ -64,11 +64,11 @@ class PredefineRole:
}
return defaults
def get_or_create_role(self):
def update_or_create_role(self):
from rbac.models import Role
defaults = self._get_defaults()
permissions = defaults.pop('permissions', [])
role, created = Role.objects.get_or_create(defaults, id=self.id)
role, created = Role.objects.update_or_create(defaults, id=self.id)
role.permissions.set(permissions)
return role, created
@ -125,10 +125,10 @@ class BuiltinRole:
return mapper[name].get_role()
@classmethod
def sync_to_db(cls):
def sync_to_db(cls, show_msg=False):
roles = cls.get_roles()
for pre_role in roles.values():
role, created = pre_role.get_or_create_role()
print("Create builtin Role: {} - {}".format(role.name, created))
role, created = pre_role.update_or_create_role()
if show_msg:
print("Update builtin Role: {} - {}".format(role.name, created))

View File

@ -5,7 +5,7 @@ from rbac.builtin import BuiltinRole
def create_builtin_roles(apps, schema_editor):
BuiltinRole.sync_to_db()
BuiltinRole.sync_to_db(show_msg=True)
class Migration(migrations.Migration):

View File

@ -1,7 +1,5 @@
import uuid
from typing import Callable
from django.db import models
from django.db.models import F, Count, Q
from django.apps import apps
from django.utils.translation import ugettext_lazy as _, ugettext

View File

@ -49,10 +49,10 @@ class Role(JMSModel):
return '%s(%s)' % (self.name, self.get_scope_display())
def is_system_admin(self):
return self.id == self.BuiltinRole.system_admin.id and self.builtin
return str(self.id) == self.BuiltinRole.system_admin.id and self.builtin
def is_org_admin(self):
return self.id == self.BuiltinRole.org_admin.id and self.builtin
return str(self.id) == self.BuiltinRole.org_admin.id and self.builtin
def is_admin(self):
yes = self.is_system_admin() or self.is_org_admin()

View File

@ -0,0 +1,14 @@
from django.dispatch import receiver
from django.db.models.signals import post_migrate
from django.apps import apps
from .builtin import BuiltinRole
@receiver(post_migrate)
def after_migrate_update_builtin_role_permissions(sender, app_config, **kwargs):
# 最后一个 app migrations 后执行, 更新内置角色的权限
last_app = list(apps.get_app_configs())[-1]
if app_config.name == last_app.name:
print("After migration, update builtin role permissions")
BuiltinRole.sync_to_db()

View File

@ -85,7 +85,7 @@ class TerminalViewSet(JMSBulkModelViewSet):
class TerminalConfig(APIView):
rbac_perms = {
'GET': 'view_terminalconfig'
'GET': 'terminal.view_terminalconfig'
}
def get(self, request):

View File

@ -13,7 +13,7 @@ from django.core.cache import cache
from assets.models import Asset
from users.models import User
from orgs.mixins.models import OrgModelMixin
from common.db.models import TextChoices
from django.db.models import TextChoices
from ..backends import get_multi_command_storage

View File

@ -21,7 +21,7 @@ from orgs.utils import current_org
from orgs.models import Organization
from common.utils import date_expired_default, get_logger, lazyproperty, random_string
from common import fields
from common.db.models import TextChoices
from django.db.models import TextChoices
from ..signals import post_user_change_password, post_user_leave_org, pre_user_leave_org
__all__ = ['User', 'UserPasswordHistory']

View File

@ -12,7 +12,7 @@ chardet==3.0.4
configparser==3.5.0
coreapi==2.3.3
coreschema==0.0.4
cryptography==3.3.2
cryptography==36.0.1
decorator==4.1.2
Django==3.1.13
django-auth-ldap==2.2.0
@ -52,8 +52,8 @@ passlib==1.7.1
Pillow==8.3.2
pyasn1==0.4.8
pycparser==2.19
pycryptodome==3.10.1
pycryptodomex==3.10.1
pycryptodome==3.12.0
pycryptodomex==3.12.0
pyotp==2.2.6
PyNaCl==1.2.1
python-dateutil==2.8.2