mirror of https://github.com/jumpserver/jumpserver
Merge pull request #9147 from jumpserver/pr@v3@fix_withdraw_acl_unfinished
fix: 删除掉连接方式控制半成品代码pull/9151/head
commit
21f91358cf
|
@ -1,52 +0,0 @@
|
|||
from rest_framework.views import APIView
|
||||
from rest_framework import status
|
||||
from django.http.response import JsonResponse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.drf.api import JMSBulkModelViewSet
|
||||
from common.const.choices import ConnectMethodChoices
|
||||
from ..models import ConnectACL
|
||||
from .. import serializers
|
||||
|
||||
__all__ = ['ConnectACLViewSet', 'ConnectMethodsAPI', 'ConnectMethodPermissionsAPI']
|
||||
|
||||
|
||||
class ConnectACLViewSet(JMSBulkModelViewSet):
|
||||
queryset = ConnectACL.objects.all()
|
||||
filterset_fields = ('name', )
|
||||
search_fields = ('name',)
|
||||
serializer_class = serializers.ConnectACLSerializer
|
||||
|
||||
|
||||
class ConnectMethodsAPI(APIView):
|
||||
rbac_perms = {
|
||||
'GET': 'acls.view_connnectacl',
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def get(request, *args, **kwargs):
|
||||
data = []
|
||||
for m in ConnectMethodChoices.choices:
|
||||
data.append({'label': m[1], 'value': m[0]})
|
||||
return JsonResponse(data, safe=False)
|
||||
|
||||
|
||||
class ConnectMethodPermissionsAPI(APIView):
|
||||
rbac_perms = {
|
||||
'GET': 'acls.view_connnectacl',
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def get(request, *args, **kwargs):
|
||||
login_type = request.query_params.get('login_type')
|
||||
if not login_type:
|
||||
rules = ConnectACL().all_rules(request.user)
|
||||
return JsonResponse({'rules': rules})
|
||||
|
||||
acl = ConnectACL.match(request.user, login_type)
|
||||
if acl:
|
||||
err = _('The current user is not allowed to login in this way')
|
||||
return JsonResponse({'error': err})
|
||||
else:
|
||||
return JsonResponse({'msg': 'ok'})
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
from django.db import models
|
||||
from django.core.cache import cache
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.utils.connection import get_redis_client
|
||||
from common.const.choices import ConnectMethodChoices
|
||||
from orgs.mixins.models import OrgManager, OrgModelMixin
|
||||
from .base import BaseACL, BaseACLQuerySet
|
||||
|
||||
|
||||
class ACLManager(OrgManager):
|
||||
|
||||
def valid(self):
|
||||
return self.get_queryset().valid()
|
||||
|
||||
|
||||
class ConnectACL(BaseACL, OrgModelMixin):
|
||||
ConnectACLUserCacheKey = 'CONNECT_ACL_USER_{}'
|
||||
ConnectACLUserCacheTTL = 600
|
||||
|
||||
class ActionChoices(models.TextChoices):
|
||||
reject = 'reject', _('Reject')
|
||||
|
||||
# 用户
|
||||
users = models.ManyToManyField(
|
||||
'users.User', related_name='connect_acls', blank=True,
|
||||
verbose_name=_("User")
|
||||
)
|
||||
user_groups = models.ManyToManyField(
|
||||
'users.UserGroup', related_name='connect_acls', blank=True,
|
||||
verbose_name=_("User group"),
|
||||
)
|
||||
rules = models.JSONField(default=list, verbose_name=_('Rule'))
|
||||
# 动作
|
||||
action = models.CharField(
|
||||
max_length=64, verbose_name=_('Action'),
|
||||
choices=ActionChoices.choices, default=ActionChoices.reject
|
||||
)
|
||||
|
||||
objects = ACLManager.from_queryset(BaseACLQuerySet)()
|
||||
|
||||
class Meta:
|
||||
ordering = ('priority', '-date_updated', 'name')
|
||||
verbose_name = _('Connect acl')
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def rules_display(self):
|
||||
return ', '.join(
|
||||
[ConnectMethodChoices.get_label(i) for i in self.rules]
|
||||
)
|
||||
|
||||
def is_action(self, action):
|
||||
return self.action == action
|
||||
|
||||
@staticmethod
|
||||
def match(user, connect_type):
|
||||
if not user:
|
||||
return
|
||||
|
||||
user_acls = user.connect_acls.all().valid().distinct()
|
||||
for acl in user_acls:
|
||||
if connect_type in acl.rules:
|
||||
return acl
|
||||
|
||||
for user_group in user.groups.all():
|
||||
acls = user_group.connect_acls.all().valid().distinct()
|
||||
for acl in acls:
|
||||
if connect_type in acl.rules:
|
||||
return acl
|
||||
|
||||
def _get_all_rules_from_cache(self, user):
|
||||
find = False
|
||||
cache_key = self.ConnectACLUserCacheKey.format(user.id)
|
||||
rules = cache.get(cache_key)
|
||||
if rules is not None:
|
||||
find = True
|
||||
return rules, find
|
||||
|
||||
@staticmethod
|
||||
def _get_all_rules_from_db(user):
|
||||
connect_rules = set()
|
||||
user_acls = user.connect_acls.all().valid()
|
||||
user_acl_rules = user_acls.values_list('id', 'rules')
|
||||
for r_id, rule in user_acl_rules:
|
||||
connect_rules.update(rule)
|
||||
|
||||
for ug in user.groups.all():
|
||||
user_group_acls = ug.connect_acls.all().valid()
|
||||
user_group_rules = user_group_acls.values_list('id', 'rules')
|
||||
for r_id, rule in user_group_rules:
|
||||
connect_rules.update(rule)
|
||||
return list(connect_rules)
|
||||
|
||||
def set_all_rules_to_cache(self, key, rules):
|
||||
cache.set(key, rules, self.ConnectACLUserCacheTTL)
|
||||
|
||||
def all_rules(self, user):
|
||||
rules, find = self._get_all_rules_from_cache(user)
|
||||
if not find:
|
||||
rules = self._get_all_rules_from_db(user)
|
||||
self.set_all_rules_to_cache(
|
||||
self.ConnectACLUserCacheKey.format(user.id), rules
|
||||
)
|
||||
return rules
|
||||
|
||||
def clear_rules_cache(self):
|
||||
cache.delete_pattern(
|
||||
self.ConnectACLUserCacheKey.format('*')
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.clear_rules_cache()
|
||||
return super().save(*args, **kwargs)
|
||||
|
||||
def delete(self, using=None, keep_parents=False):
|
||||
self.clear_rules_cache()
|
||||
return super().delete(using=using, keep_parents=keep_parents)
|
|
@ -1,36 +0,0 @@
|
|||
from django.utils.translation import ugettext as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.drf.serializers import BulkModelSerializer
|
||||
from common.const.choices import ConnectMethodChoices
|
||||
from ..models import ConnectACL
|
||||
|
||||
|
||||
__all__ = ['ConnectACLSerializer', ]
|
||||
|
||||
|
||||
class ConnectACLSerializer(BulkModelSerializer):
|
||||
action_display = serializers.ReadOnlyField(source='get_action_display', label=_('Action'))
|
||||
|
||||
class Meta:
|
||||
model = ConnectACL
|
||||
fields_mini = ['id', 'name']
|
||||
fields_small = fields_mini + [
|
||||
'priority', 'rules', 'rules_display', 'action', 'action_display', 'is_active',
|
||||
'date_created', 'date_updated', 'comment', 'created_by'
|
||||
]
|
||||
fields_m2m = ['users', 'user_groups']
|
||||
fields = fields_small + fields_m2m
|
||||
extra_kwargs = {
|
||||
'priority': {'default': 50},
|
||||
'is_active': {'default': True}
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def validate_rules(rules):
|
||||
for r in rules:
|
||||
label = ConnectMethodChoices.get_label(r)
|
||||
if not label:
|
||||
error = _('Invalid connection method: {}').format(r)
|
||||
raise serializers.ValidationError(error)
|
||||
return rules
|
Loading…
Reference in New Issue