Merge pull request #10655 from jumpserver/pr@dev@fix_login_acl_uniq

perf: 优化 LoginACL 迁移,避免 uniq error
pull/10657/head
老广 2023-06-08 18:35:23 +08:00 committed by GitHub
commit 8f8e781376
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 18 additions and 10 deletions

View File

@ -1,4 +1,5 @@
# Generated by Django 3.2.17 on 2023-06-06 10:57 # Generated by Django 3.2.17 on 2023-06-06 10:57
from collections import defaultdict
from django.db import migrations, models from django.db import migrations, models
@ -7,7 +8,13 @@ import common.db.fields
def migrate_users_login_acls(apps, schema_editor): def migrate_users_login_acls(apps, schema_editor):
login_acl_model = apps.get_model('acls', 'LoginACL') login_acl_model = apps.get_model('acls', 'LoginACL')
name_used = defaultdict(int)
for login_acl in login_acl_model.objects.all(): for login_acl in login_acl_model.objects.all():
name = login_acl.name
if name_used[name] > 0:
login_acl.name += "_{}".format(name_used[name])
name_used[name] += 1
login_acl.users = { login_acl.users = {
"type": "ids", "ids": [str(login_acl.user_id)] "type": "ids", "ids": [str(login_acl.user_id)]
} }
@ -25,6 +32,7 @@ class Migration(migrations.Migration):
name='users', name='users',
field=common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users'), field=common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users'),
), ),
migrations.RunPython(migrate_users_login_acls),
migrations.RemoveField( migrations.RemoveField(
model_name='loginacl', model_name='loginacl',
name='user', name='user',

View File

@ -90,7 +90,7 @@ class UserBaseACL(BaseACL):
queryset = cls.objects.all() queryset = cls.objects.all()
q = cls.users.get_filter_q(user) q = cls.users.get_filter_q(user)
queryset = queryset.filter(q) queryset = queryset.filter(q)
return queryset.valid().distinct() return queryset.filter(is_active=True).distinct()
class UserAssetAccountBaseACL(OrgModelMixin, UserBaseACL): class UserAssetAccountBaseACL(OrgModelMixin, UserBaseACL):
@ -125,4 +125,4 @@ class UserAssetAccountBaseACL(OrgModelMixin, UserBaseACL):
kwargs['org_id'] = org_id kwargs['org_id'] = org_id
if kwargs: if kwargs:
queryset = queryset.filter(**kwargs) queryset = queryset.filter(**kwargs)
return queryset.valid().distinct().order_by('priority', 'date_created') return queryset.filter(is_active=True).distinct().order_by('priority', 'date_created')

View File

@ -20,22 +20,18 @@ class LoginACL(UserBaseACL):
def is_action(self, action): def is_action(self, action):
return self.action == action return self.action == action
@classmethod
def filter_acl(cls, user):
return user.login_acls.all().valid().distinct()
def create_confirm_ticket(self, request): def create_confirm_ticket(self, request):
from tickets import const from tickets import const
from tickets.models import ApplyLoginTicket from tickets.models import ApplyLoginTicket
from orgs.models import Organization from orgs.models import Organization
title = _('Login confirm') + ' {}'.format(self.user) title = _('Login confirm') + ' {}'.format(request.user)
login_ip = get_request_ip(request) if request else '' login_ip = get_request_ip(request) if request else ''
login_ip = login_ip or '0.0.0.0' login_ip = login_ip or '0.0.0.0'
login_city = get_ip_city(login_ip) login_city = get_ip_city(login_ip)
login_datetime = local_now_display() login_datetime = local_now_display()
data = { data = {
'title': title, 'title': title,
'applicant': self.user, 'applicant': request.user,
'apply_login_ip': login_ip, 'apply_login_ip': login_ip,
'org_id': Organization.ROOT_ID, 'org_id': Organization.ROOT_ID,
'apply_login_city': login_city, 'apply_login_city': login_city,

View File

@ -369,7 +369,7 @@ class AuthACLMixin:
logger.debug('Login confirm acl id: {}'.format(acl_id)) logger.debug('Login confirm acl id: {}'.format(acl_id))
if not acl_id: if not acl_id:
return return
acl = LoginACL.filter_acl(user).filter(id=acl_id).first() acl = LoginACL.get_user_acls(user).filter(id=acl_id).first()
if not acl: if not acl:
return return
if not acl.is_action(acl.ActionChoices.review): if not acl.is_action(acl.ActionChoices.review):

View File

@ -10,7 +10,7 @@ from django.apps import apps
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import MinValueValidator, MaxValueValidator from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models from django.db import models
from django.db.models import Q, Manager from django.db.models import Q, Manager, QuerySet
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework.utils.encoders import JSONEncoder from rest_framework.utils.encoders import JSONEncoder
@ -486,6 +486,10 @@ class JSONManyToManyDescriptor:
elif rule['match'] == 'm2m': elif rule['match'] == 'm2m':
if isinstance(value, Manager): if isinstance(value, Manager):
value = value.values_list('id', flat=True) value = value.values_list('id', flat=True)
elif isinstance(value, QuerySet):
value = value.values_list('id', flat=True)
elif isinstance(value, models.Model):
value = [value.id]
value = set(map(str, value)) value = set(map(str, value))
rule_value = set(map(str, rule_value)) rule_value = set(map(str, rule_value))
res &= rule_value.issubset(value) res &= rule_value.issubset(value)