diff --git a/apps/notifications/signals_handler.py b/apps/notifications/signals_handler.py index 79964464a..fbe444345 100644 --- a/apps/notifications/signals_handler.py +++ b/apps/notifications/signals_handler.py @@ -85,9 +85,11 @@ def create_system_messages(app_config: AppConfig, **kwargs): @receiver(post_save, sender=User) def on_user_post_save(sender, instance, created, **kwargs): - if created: - receive_backends = [] - for backend in BACKEND: - if backend.get_account(instance): - receive_backends.append(backend) - UserMsgSubscription.objects.create(user=instance, receive_backends=receive_backends) + if not created: + return + receive_backends = [] + # Todo: IDE 识别不了 get_account + for backend in BACKEND: + if backend.get_account(instance): + receive_backends.append(backend) + UserMsgSubscription.objects.create(user=instance, receive_backends=receive_backends) diff --git a/apps/orgs/migrations/0010_auto_20210219_1241.py b/apps/orgs/migrations/0010_auto_20210219_1241.py index f5694d7bc..facc6a654 100644 --- a/apps/orgs/migrations/0010_auto_20210219_1241.py +++ b/apps/orgs/migrations/0010_auto_20210219_1241.py @@ -44,11 +44,12 @@ def migrate_default_org_id(apps, schema_editor): def add_all_user_to_default_org(apps, schema_editor): - User = apps.get_model('users', 'User') - Organization = apps.get_model('orgs', 'Organization') + user_model = apps.get_model('users', 'User') + org_model = apps.get_model('orgs', 'Organization') + org_members_model = apps.get_model('orgs', 'OrganizationMember') - users_qs = User.objects.all() - default_org = Organization.objects.get(id=default_id) + users_qs = user_model.objects.all() + default_org = org_model.objects.get(id=default_id) t_start = time.time() count = users_qs.count() @@ -57,7 +58,8 @@ def add_all_user_to_default_org(apps, schema_editor): batch_size = 1000 for i in range(0, count, batch_size): users = list(users_qs[i:i + batch_size]) - default_org.members.add(*users) + members = [org_members_model(user=user, org=default_org) for user in users] + org_members_model.objects.bulk_create(members, ignore_conflicts=True) print(f'Add users to default org: {i+1}-{i+len(users)}') interval = round((time.time() - t_start) * 1000, 2) print(f'done, use {interval} ms') diff --git a/apps/orgs/models.py b/apps/orgs/models.py index 7dd93c4ed..6a8fd4302 100644 --- a/apps/orgs/models.py +++ b/apps/orgs/models.py @@ -104,6 +104,18 @@ class Organization(models.Model): def get_members(self): return self.members.all().distinct() + def add_member(self, user, role=None): + from rbac.builtin import BuiltinRole + from .utils import tmp_to_org + role_id = BuiltinRole.org_user.id + if role: + role_id = role.id + with tmp_to_org(self): + self.members.through.objects.create( + user=user, role_id=role_id, + org_id=self.id, scope='org' + ) + def get_total_resources_amount(self): from django.apps import apps from orgs.mixins.models import OrgModelMixin diff --git a/apps/orgs/signals_handler/common.py b/apps/orgs/signals_handler/common.py index 84a807a87..dfd29955d 100644 --- a/apps/orgs/signals_handler/common.py +++ b/apps/orgs/signals_handler/common.py @@ -150,7 +150,8 @@ def on_user_created_set_default_org(sender, instance, created, **kwargs): return if instance.orgs.count() > 0: return - Organization.default().members.add(instance) + with tmp_to_org(Organization.default()): + Organization.default().add_member(instance) @receiver(post_user_leave_org) diff --git a/apps/rbac/builtin.py b/apps/rbac/builtin.py index 130b8e334..3a68fa563 100644 --- a/apps/rbac/builtin.py +++ b/apps/rbac/builtin.py @@ -80,8 +80,8 @@ class BuiltinRole: system_auditor = PreRole( '2', ugettext_noop('SystemAuditor'), Scope.system, auditor_perms ) - system_app = PreRole( - '4', ugettext_noop('SystemApp'), Scope.system, app_exclude_perms, 'exclude' + system_component = PreRole( + '4', ugettext_noop('SystemComponent'), Scope.system, app_exclude_perms, 'exclude' ) system_user = PreRole( '3', ugettext_noop('User'), Scope.system, [] @@ -108,7 +108,7 @@ class BuiltinRole: @classmethod def get_system_role_by_old_name(cls, name): mapper = { - 'App': cls.system_app, + 'App': cls.system_component, 'Admin': cls.system_admin, 'User': cls.system_user, 'Auditor': cls.system_auditor diff --git a/apps/settings/utils/ldap.py b/apps/settings/utils/ldap.py index 68f856da9..70f5a6323 100644 --- a/apps/settings/utils/ldap.py +++ b/apps/settings/utils/ldap.py @@ -376,8 +376,10 @@ class LDAPImportUtil(object): except Exception as e: errors.append({user['username']: str(e)}) logger.error(e) - if org and not org.is_root(): - org.members.add(*objs) + if org and org.is_root(): + return + for obj in objs: + org.add_member.add(obj) logger.info('End perform import ldap users') return errors diff --git a/apps/terminal/models/terminal.py b/apps/terminal/models/terminal.py index 1718dd808..8578ab599 100644 --- a/apps/terminal/models/terminal.py +++ b/apps/terminal/models/terminal.py @@ -157,15 +157,6 @@ class Terminal(StorageMixin, TerminalStatusMixin, models.Model): def service_account(self): return self.user - def create_app_user(self): - random = uuid.uuid4().hex[:6] - user, access_key = User.create_app_user( - name="{}-{}".format(self.name, random), comment=self.comment - ) - self.user = user - self.save() - return user, access_key - def delete(self, using=None, keep_parents=False): if self.user: self.user.delete() diff --git a/apps/terminal/serializers/terminal.py b/apps/terminal/serializers/terminal.py index 5c20f4d92..626529a5e 100644 --- a/apps/terminal/serializers/terminal.py +++ b/apps/terminal/serializers/terminal.py @@ -127,13 +127,14 @@ class TerminalRegistrationSerializer(serializers.ModelSerializer): valid = self.service_account.is_valid(raise_exception=True) return valid - def save(self, **kwargs): - instance = super().save(**kwargs) + def create(self, validated_data): + instance = super().create(validated_data) request = self.context.get('request') instance.is_accepted = True if request: instance.remote_addr = get_request_ip(request) - sa = self.service_account.save() + sa = self.service_account.create(validated_data) + sa.set_component_role() instance.user = sa instance.command_storage = CommandStorage.default().name instance.replay_storage = ReplayStorage.default().name diff --git a/apps/terminal/urls/api_urls.py b/apps/terminal/urls/api_urls.py index ebf6fa47f..b071e8134 100644 --- a/apps/terminal/urls/api_urls.py +++ b/apps/terminal/urls/api_urls.py @@ -25,6 +25,7 @@ router.register(r'session-join-records', api.SessionJoinRecordsViewSet, 'session urlpatterns = [ path('terminal-registrations/', api.TerminalRegistrationApi.as_view(), name='terminal-registration'), + path('registration/', api.TerminalRegistrationApi.as_view(), name='registration'), path('sessions/join/validate/', api.SessionJoinValidateAPI.as_view(), name='join-session-validate'), path('sessions//replay/', api.SessionReplayViewSet.as_view({'get': 'retrieve', 'post': 'create'}), diff --git a/apps/users/api/service_account.py b/apps/users/api/service_account.py index 6a2b30d65..26ecb9c1b 100644 --- a/apps/users/api/service_account.py +++ b/apps/users/api/service_account.py @@ -14,5 +14,5 @@ class ServiceAccountRegistrationViewSet(viewsets.ModelViewSet): def perform_create(self, serializer): app = serializer.save() - role = Role.BuiltinRole.system_app.get_role() + role = Role.BuiltinRole.system_component.get_role() RoleBinding.objects.create(user=app, role=role) diff --git a/apps/users/models/user.py b/apps/users/models/user.py index 3e927b1c2..4eedba48f 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -283,18 +283,20 @@ class RoleMixin: pass @classmethod - def create_app_user(cls, name, comment): - from rbac.models import Role + def create_service_account(cls, name, comment): app = cls.objects.create( username=name, name=name, email='{}@local.domain'.format(name), - is_active=False, comment=comment, is_first_login=False, created_by='System', - is_app=True, + is_active=False, comment=comment, is_first_login=False, + created_by='System', is_app=True, ) access_key = app.create_access_key() - role = Role.BuiltinRole.system_app.get_role() - app.system_roles.add(role) return app, access_key + def set_component_role(self): + from rbac.models import Role + role = Role.BuiltinRole.system_component.get_role() + self.system_roles.add(role) + def remove(self): if current_org.is_root(): return diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index 19ba886d7..a66211ba0 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- # -from copy import deepcopy from functools import partial from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers @@ -12,6 +11,7 @@ from rbac.models import OrgRoleBinding, SystemRoleBinding from ..models import User from ..const import PasswordStrategy from rbac.models import Role +from rbac.builtin import BuiltinRole __all__ = [ 'UserSerializer', 'MiniUserSerializer', @@ -280,13 +280,6 @@ class ServiceAccountSerializer(serializers.ModelSerializer): raise serializers.ValidationError(_('name not unique'), code='unique') return name - def save(self, **kwargs): - self.validated_data['email'] = self.get_email() - self.validated_data['username'] = self.get_username() - self.validated_data['is_app'] = True - return super().save(**kwargs) - def create(self, validated_data): - instance = super().create(validated_data) - instance.create_access_key() - return instance + user, ak = User.create_service_account(validated_data['name'], validated_data['comment']) + return user