From 546ca9f4622397715f417cede0373ce3918757bf Mon Sep 17 00:00:00 2001 From: inji-hanbin Date: Tue, 31 May 2022 18:37:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=BA=86celery=E5=90=AF=E5=8A=A8=E7=9A=84=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E5=92=8Cslug=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/v1/schema/child_manager.py | 8 ++ api/v1/views/child_manager.py | 53 ++++--- api/v1/views/permission.py | 12 +- arkid/core/apps.py | 2 +- .../core/migrations/0007_alter_tenant_slug.py | 18 +++ arkid/core/models.py | 4 +- arkid/core/perm/permission_data.py | 132 +++++++++++++++++- arkid/core/tasks/celery.py | 29 ++-- arkid/core/tasks/tasks.py | 20 +-- .../com_longgui_oauth2_server/__init__.py | 2 +- 10 files changed, 230 insertions(+), 50 deletions(-) create mode 100644 api/v1/schema/child_manager.py create mode 100644 arkid/core/migrations/0007_alter_tenant_slug.py diff --git a/api/v1/schema/child_manager.py b/api/v1/schema/child_manager.py new file mode 100644 index 000000000..76f5fdbe7 --- /dev/null +++ b/api/v1/schema/child_manager.py @@ -0,0 +1,8 @@ +from ninja import ModelSchema +from arkid.core.models import User + +class ChildManagerListOut(ModelSchema): + + class Config: + model = User + model_fields = ["id","username", "avatar"] \ No newline at end of file diff --git a/api/v1/views/child_manager.py b/api/v1/views/child_manager.py index 6781cfdcd..5d8bb47e7 100644 --- a/api/v1/views/child_manager.py +++ b/api/v1/views/child_manager.py @@ -1,30 +1,47 @@ -from arkid.core.api import api + +from api.v1.schema.child_manager import * +from arkid.core.models import User +from arkid.core.api import api, operation +from ninja.pagination import paginate +from typing import Union, Literal, List +from arkid.core.pagenation import CustomPagination from arkid.core.translation import gettext_default as _ +from arkid.core.constants import NORMAL_USER, TENANT_ADMIN, PLATFORM_ADMIN -@api.get("/tenant/{tenant_id}/child_managers/", tags=["子管理员"],auth=None) +@api.get("/tenant/{tenant_id}/child_managers/", response=List[ChildManagerListOut], tags=["子管理员"],auth=None) +@operation(roles=[TENANT_ADMIN, PLATFORM_ADMIN]) +@paginate(CustomPagination) def get_child_managers(request, tenant_id: str): """ 子管理员列表,TODO """ - return [] - -@api.get("/tenant/{tenant_id}/child_managers/{id}/", tags=["子管理员"],auth=None) + from arkid.core.perm.permission_data import PermissionData + tenant = request.tenant + users = User.valid_objects.filter(tenant=tenant) + permissiondata = PermissionData() + child_mans = permissiondata.get_child_mans(users, tenant) + return child_mans + +@api.get("/tenant/{tenant_id}/child_managers/{id}/", response=ChildManagerListOut, tags=["子管理员"],auth=None) +@operation(roles=[TENANT_ADMIN, PLATFORM_ADMIN, NORMAL_USER]) def get_child_manager(request, tenant_id: str, id: str): """ 获取子管理员,TODO """ - return {} - -@api.post("/tenant/{tenant_id}/child_managers/", tags=["子管理员"],auth=None) -def create_child_manager(request, tenant_id: str): - """ 创建子管理员,TODO - """ - return {} - -@api.put("/tenant/{tenant_id}/child_managers/{id}/", tags=["子管理员"],auth=None) -def update_child_manager(request, tenant_id: str, id: str): - """ 编辑子管理员,TODO - """ - return {} + tenant = request.tenant + user = User.valid_objects.filter(tenant=tenant, id=id).first() + return user + +# @api.post("/tenant/{tenant_id}/child_managers/", tags=["子管理员"],auth=None) +# def create_child_manager(request, tenant_id: str): +# """ 创建子管理员,TODO +# """ +# return {} + +# @api.put("/tenant/{tenant_id}/child_managers/{id}/", tags=["子管理员"],auth=None) +# def update_child_manager(request, tenant_id: str, id: str): +# """ 编辑子管理员,TODO +# """ +# return {} @api.delete("/tenant/{tenant_id}/child_managers/{id}/", tags=["子管理员"],auth=None) def delete_child_manager(request, tenant_id: str, id: str): diff --git a/api/v1/views/permission.py b/api/v1/views/permission.py index 693bb8258..2c15d7a6a 100644 --- a/api/v1/views/permission.py +++ b/api/v1/views/permission.py @@ -153,6 +153,16 @@ def get_permission_str(request, tenant_id: str, app_id: str = None): return permissiondata.get_permission_str(user, tenant_id, app_id) +@api.get("/app/permission_result", tags=['权限'], response=PermissionStrSchemaOut, auth=None) +def get_arkstore_permission_str(request): + ''' + 获取应用权限字符串 + ''' + from arkid.core.perm.permission_data import PermissionData + permissiondata = PermissionData() + return permissiondata.id_token_to_permission_str(request) + + @api.get("/tenant/{tenant_id}/permission/{permission_id}/user/{user_id}/add_permission", tags=['权限'], auth=None) @operation(roles=[TENANT_ADMIN, PLATFORM_ADMIN]) def user_add_permission(request, tenant_id: str, permission_id: str, user_id: str): @@ -206,4 +216,4 @@ def permission_set_close(request, tenant_id: str, permission_id: str): permission.save() return {'error': ErrorCode.OK.value} else: - return {'error': ErrorCode.PERMISSION_EXISTS_ERROR.value} \ No newline at end of file + return {'error': ErrorCode.PERMISSION_EXISTS_ERROR.value} diff --git a/arkid/core/apps.py b/arkid/core/apps.py index 167886f92..17f0c8135 100644 --- a/arkid/core/apps.py +++ b/arkid/core/apps.py @@ -15,7 +15,7 @@ def ready(self): try: from arkid.core.models import Tenant, User tenant, _ = Tenant.objects.get_or_create( - # slug='', + slug='', name="platform tenant", ) user, _ = User.objects.get_or_create( diff --git a/arkid/core/migrations/0007_alter_tenant_slug.py b/arkid/core/migrations/0007_alter_tenant_slug.py new file mode 100644 index 000000000..4d2757120 --- /dev/null +++ b/arkid/core/migrations/0007_alter_tenant_slug.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.13 on 2022-05-31 10:36 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0006_merge_20220526_1647'), + ] + + operations = [ + migrations.AlterField( + model_name='tenant', + name='slug', + field=models.SlugField(default='', unique=True, verbose_name='slug'), + ), + ] diff --git a/arkid/core/models.py b/arkid/core/models.py index be322c767..0203e1040 100644 --- a/arkid/core/models.py +++ b/arkid/core/models.py @@ -23,7 +23,7 @@ class Meta(object): verbose_name_plural = _("tenant", "租户") name = models.CharField(verbose_name=_('name', '名字'), max_length=128) - slug = models.SlugField(verbose_name=_('slug', '短链接标识'), blank=True, null=True, default='' ,unique=True) + slug = models.SlugField(verbose_name=_('slug', '短链接标识'), default='', unique=True) icon = models.URLField(verbose_name=_('icon', '图标'), blank=True, null=True) token_duration_minutes = models.IntegerField( @@ -63,7 +63,7 @@ def is_platform_tenant(self): ''' 是否是平台租户 ''' - tenant = Tenant.valid_objects.order_by('id').first() + tenant = Tenant.valid_objects.order_by('created').first() if tenant.id == self.id: return True else: diff --git a/arkid/core/perm/permission_data.py b/arkid/core/perm/permission_data.py index 53bdaf143..66649c4f9 100644 --- a/arkid/core/perm/permission_data.py +++ b/arkid/core/perm/permission_data.py @@ -11,6 +11,7 @@ import collections import requests import uuid +import jwt import re from oauth2_provider.models import Application @@ -70,6 +71,7 @@ def get_platfrom_tenant(self): 获取平台租户 ''' tenant, _ = Tenant.objects.get_or_create( + slug='', name="platform tenant", ) return tenant @@ -109,7 +111,7 @@ def add_system_permission_to_user(self, tenant_id, user_id, permission_id): tenant = Tenant.valid_objects.filter(id=tenant_id).first() user = User.valid_objects.filter(id=user_id).first() permission = SystemPermission.valid_objects.filter(id=permission_id).first() - if tenant and user: + if tenant: self.update_arkid_single_user_permission(tenant, user, permission, 1) else: print('不存在租户或者用户无法更新') @@ -1168,6 +1170,41 @@ def check_app_entry_permission(self, request, type, kwargs): return True + def id_token_reverse(self, id_token): + ''' + id token转换 + ''' + try: + payload = jwt.decode(id_token, options={"verify_signature": False}) + return payload + except Exception: + raise Exception("unable to parse id_token") + + def id_token_to_permission_str(self, request): + id_token = request.META.get('HTTP_ID_TOKEN', '') + payload = self.id_token_reverse(id_token) + client_id = payload.get('aud', None) + user_id = payload.get('sub_id', '') + tenant_id = payload.get('tenant_id', '') + + apps = App.valid_objects.filter( + type__in=['OIDC-Platform'], + tenant_id=tenant_id, + ) + app_temp = None + for app in apps: + data = app.config.config + app_client_id = data.get('client_id', '') + if app_client_id == client_id: + app_temp = app + break + user = User.valid_objects.filter(id=user_id).first() + if user and app_temp and tenant_id: + self.get_permission_str(user, tenant_id, app_temp.id) + else: + print('不存在用户或者应用或者租户') + return {'result': ''} + def permission_check_by_sortid(self, permission, user, app, tenant_id): ''' 根据权限检查用户身份 @@ -1220,4 +1257,95 @@ def get_open_appids(self): app_id = permission.app_id if app_id not in app_ids: app_ids.append(app_id) - return app_ids \ No newline at end of file + return app_ids + + def get_default_system_permission(self): + ''' + 获取默认的系统权限 + ''' + systempermission = SystemPermission.valid_objects.filter( + name='normal-user', + category='group', + ).first() + if systempermission: + describe = systempermission.describe + sort_ids = describe.get('sort_ids', []) + return sort_ids + else: + return [] + + def get_user_system_permission_arr(self, auth_users, tenant): + ''' + 获取用户的系统权限 + ''' + # 取得当前用户权限数据 + userpermissionresults = UserPermissionResult.valid_objects.filter( + user__in=auth_users, + tenant=tenant, + app=None, + ) + compress = Compress() + list_user = [] + for userpermissionresult in userpermissionresults: + temp_user = userpermissionresult.user + if userpermissionresult: + permission_result = compress.decrypt(userpermissionresult.result) + permission_result_arr = list(permission_result) + temp_user.arr = permission_result_arr + else: + temp_user.arr = [] + list_user.append(temp_user) + return list_user + + def get_child_mans(self, auth_users, tenant): + ''' + 获取子管理员 + ''' + sort_ids = self.get_default_system_permission() + list_user = self.get_user_system_permission_arr(auth_users, tenant) + exclude_id = [] + for item_user in list_user: + user_arr = item_user.arr + for index, user_arr_item in enumerate(user_arr): + if index not in sort_ids and user_arr_item == 1: + exclude_id.append(item_user.id) + break + auth_users = auth_users.exclude(id__in=exclude_id) + # 区分出那些人是管理员 + systempermission = SystemPermission.valid_objects.filter(tenant=tenant, code=tenant.admin_perm_code, is_system=True).first() + # 管理权限在arkidpermission表里 + system_userpermissionresults = UserPermissionResult.valid_objects.filter( + user__in=auth_users, + tenant=tenant, + app=None, + ) + system_userpermissionresults_dict = {} + for system_userpermissionresult in system_userpermissionresults: + system_userpermissionresults_dict[system_userpermissionresult.user.id.hex] = system_userpermissionresult + ids = [] + compress = Compress() + for auth_user in auth_users: + # 权限鉴定 + if auth_user.is_superuser: + auth_user.is_tenant_admin = True + else: + if auth_user.id.hex in system_userpermissionresults_dict: + system_userpermissionresults_obj = system_userpermissionresults_dict.get(auth_user.id.hex) + auth_user_permission_result = compress.decrypt(system_userpermissionresults_obj.result) + + auth_user_permission_result_arr = list(auth_user_permission_result) + check_result = int(auth_user_permission_result_arr[systempermission.sort_id]) + + if check_result == 1: + auth_user.is_tenant_admin = True + else: + ids.append(auth_user.id) + auth_user.is_tenant_admin = False + else: + ids.append(auth_user.id) + auth_user.is_tenant_admin = False + + if ids: + return User.valid_objects.filter(id__in=ids) + else: + return [] \ No newline at end of file diff --git a/arkid/core/tasks/celery.py b/arkid/core/tasks/celery.py index e568aba06..02d6131f8 100644 --- a/arkid/core/tasks/celery.py +++ b/arkid/core/tasks/celery.py @@ -2,7 +2,8 @@ import os -from celery import Celery +from celery import Celery, bootsteps +from click import Option # set the default Django settings module for the 'celery' program. os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'arkid.settings') @@ -15,22 +16,20 @@ # should have a `CELERY_` prefix. app.config_from_object('django.conf:settings', namespace='CELERY') -# Load task modules from all registered Django app configs. -app.autodiscover_tasks() +app.user_options['worker'].add(Option(('--is-init-permission',), is_flag=False, help='init permission option.')) +class MyBootstep(bootsteps.Step): -from arkid.core.tasks import tasks + def __init__(self, parent, is_init_permission=False, **options): + super().__init__(parent, **options) + if is_init_permission: + from arkid.core.tasks.tasks import update_system_permission + update_system_permission.delay() + +app.steps['worker'].add(MyBootstep) -# class ReadyCelery(object): +# Load task modules from all registered Django app configs. +app.autodiscover_tasks() -# def __init__(self): -# print('你被执行了') -# from arkid.core.models import Tenant -# from arkid.core.event import Event, dispatch_event, APP_START -# tenant, _ = Tenant.objects.get_or_create( -# slug='', -# name="platform tenant", -# ) -# dispatch_event(Event(tag=APP_START, tenant=tenant)) -# ReadyCelery() +from arkid.core.tasks import tasks diff --git a/arkid/core/tasks/tasks.py b/arkid/core/tasks/tasks.py index 87101c87a..75923eb71 100644 --- a/arkid/core/tasks/tasks.py +++ b/arkid/core/tasks/tasks.py @@ -285,16 +285,16 @@ def check_extensions_expired(self, *args, **kwargs): pass -class ReadyCelery(object): +# class ReadyCelery(object): - def __init__(self, *args, **kwargs): - pass +# def __init__(self, *args, **kwargs): +# pass - @classmethod - def instance(cls, *args, **kwargs): - if not hasattr(ReadyCelery, "_instance"): - ReadyCelery._instance = ReadyCelery(*args, **kwargs) - update_system_permission.delay() - return ReadyCelery._instance +# @classmethod +# def instance(cls, *args, **kwargs): +# if not hasattr(ReadyCelery, "_instance"): +# ReadyCelery._instance = ReadyCelery(*args, **kwargs) +# update_system_permission.delay() +# return ReadyCelery._instance -ReadyCelery.instance() +# ReadyCelery.instance() diff --git a/extension_root/com_longgui_oauth2_server/__init__.py b/extension_root/com_longgui_oauth2_server/__init__.py index a738fe189..cc0da9f77 100644 --- a/extension_root/com_longgui_oauth2_server/__init__.py +++ b/extension_root/com_longgui_oauth2_server/__init__.py @@ -11,7 +11,7 @@ import uuid -package='com.longgui.auth.oauth2_server' +package='com.longgui.auth.oauth2server' OIDCConfigSchema = create_extension_schema('OIDCConfigSchema',package, base_schema=OIDCConfigSchema) Oauth2ConfigSchema = create_extension_schema('Oauth2ConfigSchema',package, base_schema=Oauth2ConfigSchema)