Skip to content

Commit

Permalink
Merge pull request #803 from longguikeji/feature-scim
Browse files Browse the repository at this point in the history
Feature SCIM
  • Loading branch information
fanhe-lg authored May 1, 2022
2 parents 6112a32 + 83210e2 commit f0994f0
Show file tree
Hide file tree
Showing 60 changed files with 2,055 additions and 965 deletions.
2 changes: 2 additions & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ mkdocstrings = "*"
mkdocs = "*"
mkdocs-material = "*"
pyjwt = "*"
django-celery-beat = "*"
alibabacloud-dysmsapi20170525 = "*"
django-cors-headers = "*"

[requires]
Expand Down
516 changes: 439 additions & 77 deletions Pipfile.lock

Large diffs are not rendered by default.

190 changes: 159 additions & 31 deletions api/v1/views/scim_sync.py
Original file line number Diff line number Diff line change
@@ -1,39 +1,167 @@
from arkid.core.api import api
import json
from ninja import Schema
from ninja import ModelSchema
from arkid.core.translation import gettext_default as _
from arkid.core.extension.scim_sync import ScimSyncExtension
from arkid.extension.utils import import_extension
from arkid.extension.models import TenantExtensionConfig, Extension
from django_celery_beat.models import PeriodicTask, CrontabSchedule
from arkid.common.logger import logger
from typing import List
from ninja.pagination import paginate
from django.shortcuts import get_object_or_404
from uuid import UUID
from arkid.core.error import ErrorCode


@api.get("/tenant/{tenant_id}/scim_syncs/", tags=["用户数据同步配置"],auth=None)
class ScimSyncListSchemaOut(ModelSchema):
class Config:
model = TenantExtensionConfig
model_fields = ['id', 'name', 'type', 'config']

mode: str

@staticmethod
def resolve_mode(obj):
return obj.config.get("mode")


def update_or_create_periodic_task(extension_config):
crontab = extension_config.config.get('crontab')
if crontab:
try:
crontab = crontab.split(' ')
crontab.extend(['*'] * (5 - len(crontab)))

# create CrontabSchedule
schedule, _ = CrontabSchedule.objects.get_or_create(
minute=crontab[0],
hour=crontab[1],
day_of_week=crontab[2],
day_of_month=crontab[3],
month_of_year=crontab[4],
)

# create PeriodicTask
PeriodicTask.objects.update_or_create(
name=extension_config.id,
defaults={
'crontab': schedule,
'task': 'arkid.core.tasks.sync',
'args': json.dumps([extension_config.id.hex]),
'kwargs': json.dumps(extension_config.config),
},
)
except Exception as e:
logger.exception('add celery task failed %s' % e)


def delete_periodic_task(extension_config):
try:
# fake delete triggers post_save signal
PeriodicTask.objects.filter(name=extension_config.id).delete()
except Exception as e:
logger.exception('delete celery task failed %s' % e)


ScimSyncConfigSchemaIn = ScimSyncExtension.create_composite_config_schema(
'ScimSyncConfigSchemaIn'
)


class ScimSyncConfigSchemaOut(Schema):
id: UUID
type: str
name: str
config: dict


ScimSyncSchemaOut = ScimSyncExtension.create_composite_config_schema(
'ScimSyncSchemaOut'
)


@api.get(
"/tenant/{tenant_id}/scim_syncs/",
response=List[ScimSyncListSchemaOut],
tags=[_("用户数据同步配置")],
auth=None,
)
@paginate
def get_scim_syncs(request, tenant_id: str):
""" 用户数据同步配置列表,TODO
"""
return []
"""用户数据同步配置列表,TODO"""
configs = TenantExtensionConfig.valid_objects.filter(
tenant_id=tenant_id, type="scim_sync"
)
return configs


@api.get("/tenant/{tenant_id}/scim_syncs/{id}/", tags=["用户数据同步配置"],auth=None)
@api.get(
"/tenant/{tenant_id}/scim_syncs/{id}/",
response=ScimSyncConfigSchemaOut,
tags=[_("用户数据同步配置")],
auth=None,
)
def get_scim_sync(request, tenant_id: str, id: str):
""" 获取用户数据同步配置,TODO
"""
return {}

@api.post("/tenant/{tenant_id}/scim_syncs/", tags=["用户数据同步配置"],auth=None)
def create_scim_sync(request, tenant_id: str):
""" 创建用户数据同步配置,TODO
"""
return {}

@api.put("/tenant/{tenant_id}/scim_syncs/{id}/", tags=["用户数据同步配置"],auth=None)
def update_scim_sync(request, tenant_id: str, id: str):
""" 编辑用户数据同步配置,TODO
"""
return {}

@api.delete("/tenant/{tenant_id}/scim_syncs/{id}/", tags=["用户数据同步配置"],auth=None)
"""获取用户数据同步配置,TODO"""
config = get_object_or_404(TenantExtensionConfig, id=id, tenant=request.tenant)
return config


@api.post(
"/tenant/{tenant_id}/scim_syncs/",
tags=[_("用户数据同步配置")],
response=ScimSyncConfigSchemaOut,
auth=None,
)
def create_scim_sync(request, tenant_id: str, data: ScimSyncConfigSchemaIn):
"""创建用户数据同步配置,TODO"""

tenant = request.tenant
package = data.package
name = data.name
type = data.type
config = data.config
extension = Extension.active_objects.get(package=package)
extension = import_extension(extension.ext_dir)
extension_config = extension.create_tenant_config(
tenant, config.dict(), name=name, type=type
)
if config.mode == "client":
update_or_create_periodic_task(extension_config)
return extension_config


@api.put(
"/tenant/{tenant_id}/scim_syncs/{id}/",
tags=[_("用户数据同步配置")],
response=ScimSyncConfigSchemaOut,
auth=None,
)
def update_scim_sync(request, tenant_id: str, id: str, data: ScimSyncConfigSchemaIn):
"""编辑用户数据同步配置,TODO"""
extension_config = get_object_or_404(
TenantExtensionConfig, id=id, tenant=request.tenant
)
extension_config.package = data.package
extension_config.name = data.name
extension_config.type = data.type
extension_config.config = data.config

if data.config.mode == "client":
update_or_create_periodic_task(extension_config)

return extension_config


@api.delete("/tenant/{tenant_id}/scim_syncs/{id}/", tags=[_("用户数据同步配置")], auth=None)
def delete_scim_sync(request, tenant_id: str, id: str):
""" 删除用户数据同步配置,TODO
"""
return {}

@api.get("/tenant/{tenant_id}/scim_syncs/{id}/sync/", tags=["用户数据同步配置"],auth=None)
def scim_sync(request, tenant_id: str, id: str):
""" 同步权限数据,TODO
"""
return {}
"""删除用户数据同步配置,TODO"""
extension_config = get_object_or_404(
TenantExtensionConfig, id=id, tenant=request.tenant
)
extension_config.delete()
if extension_config.config["mode"] == "client":
delete_periodic_task(extension_config)
return {'error': ErrorCode.OK.value}
13 changes: 6 additions & 7 deletions arkid/core/extension/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,16 +435,15 @@ def get_tenant_configs(self, tenant):
def get_config_by_id(self, id):
return TenantExtensionConfig.valid_objects.get(id=id)

def update_tenant_config(self, id, config, name):
return TenantExtensionConfig.valid_objects.filter(id=id).update(config=config, name=name)
def update_tenant_config(self, id, config, name, type):
return TenantExtensionConfig.valid_objects.filter(id=id).update(config=config, name=name,type=type)

def create_tenant_config(self, tenant, config, name):
def create_tenant_config(self, tenant, config, name, type):
ext = ExtensionModel.valid_objects.filter(package=self.package).first()
return TenantExtensionConfig.objects.create(tenant=tenant, extension=ext, config=config, name=name)
return TenantExtensionConfig.objects.create(tenant=tenant, extension=ext, config=config, name=name, type=type)

def delete_tenant_config(self, tenant, config):
ext = ExtensionModel.valid_objects.filter(package=self.package).first()
return TenantExtensionConfig.objects.delete(tenant=tenant, extension=ext, config=config)
def delete_tenant_config(self, id):
return TenantExtensionConfig.objects.delete(id=id)

################################################################################

Expand Down
Loading

0 comments on commit f0994f0

Please sign in to comment.