From 5fd589815b61253f28335b790f6085c476be90d4 Mon Sep 17 00:00:00 2001 From: schnee Date: Tue, 12 Sep 2023 20:30:59 +0800 Subject: [PATCH] feat: add UserBuiltinField & TenantUserCustomField model (#1229) --- src/bk-user/bkuser/apps/tenant/constants.py | 11 +++- ..._tenantusercustomfield_userbuiltinfield.py | 61 +++++++++++++++++++ src/bk-user/bkuser/apps/tenant/models.py | 51 +++++++++------- .../apis/web/data_source/test_data_source.py | 4 ++ 4 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 src/bk-user/bkuser/apps/tenant/migrations/0002_tenantusercustomfield_userbuiltinfield.py diff --git a/src/bk-user/bkuser/apps/tenant/constants.py b/src/bk-user/bkuser/apps/tenant/constants.py index bb89ecd0a..6c4e7f464 100644 --- a/src/bk-user/bkuser/apps/tenant/constants.py +++ b/src/bk-user/bkuser/apps/tenant/constants.py @@ -9,7 +9,7 @@ specific language governing permissions and limitations under the License. """ import pytz -from blue_krill.data_types.enum import FeatureFlag, FeatureFlagField +from blue_krill.data_types.enum import EnumField, FeatureFlag, FeatureFlagField, StructuredEnum from django.utils.translation import gettext_lazy as _ TIME_ZONE_CHOICES = [(i, i) for i in list(pytz.common_timezones)] @@ -19,3 +19,12 @@ class TenantFeatureFlag(FeatureFlag): # type: ignore """租户特性标志""" USER_NUMBER_VISIBLE = FeatureFlagField(label=_("人员数量是否可见"), default=True) + + +class UserFieldDataType(str, StructuredEnum): + """租户用户自定义字段数据类型""" + + STRING = EnumField("string", label=_("字符串")) + NUMBER = EnumField("number", label=_("数字")) + ENUM = EnumField("enum", label=_("枚举")) + MULTI_ENUM = EnumField("multi_enum", label=_("多选枚举")) diff --git a/src/bk-user/bkuser/apps/tenant/migrations/0002_tenantusercustomfield_userbuiltinfield.py b/src/bk-user/bkuser/apps/tenant/migrations/0002_tenantusercustomfield_userbuiltinfield.py new file mode 100644 index 000000000..43fe56c35 --- /dev/null +++ b/src/bk-user/bkuser/apps/tenant/migrations/0002_tenantusercustomfield_userbuiltinfield.py @@ -0,0 +1,61 @@ +# -*- coding: utf-8 -*- +""" +TencentBlueKing is pleased to support the open source community by making 蓝鲸智云-用户管理(Bk-User) available. +Copyright (C) 2017-2021 THL A29 Limited, a Tencent company. All rights reserved. +Licensed under the MIT License (the "License"); you may not use this file except in compliance with the License. +You may obtain a copy of the License at http://opensource.org/licenses/MIT +Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on +an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +specific language governing permissions and limitations under the License. +""" +# Generated by Django 3.2.20 on 2023-09-12 11:19 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('tenant', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='UserBuiltinField', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='字段名称')), + ('display_name', models.CharField(max_length=128, verbose_name='展示用名称')), + ('data_type', models.CharField(choices=[('string', '字符串'), ('number', '数字'), ('datetime', '日期时间'), ('enum', '枚举'), ('multi_enum', '多选枚举')], max_length=32, verbose_name='数据类型')), + ('required', models.BooleanField(verbose_name='是否必填')), + ('unique', models.BooleanField(verbose_name='是否唯一')), + ('default', models.JSONField(default='', verbose_name='默认值')), + ('options', models.JSONField(default={}, verbose_name='配置项')), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='TenantUserCustomField', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('updated_at', models.DateTimeField(auto_now=True)), + ('name', models.CharField(max_length=128, verbose_name='字段名称')), + ('display_name', models.CharField(max_length=128, verbose_name='展示用名称')), + ('data_type', models.CharField(choices=[('string', '字符串'), ('number', '数字'), ('datetime', '日期时间'), ('enum', '枚举'), ('multi_enum', '多选枚举')], max_length=32, verbose_name='数据类型')), + ('required', models.BooleanField(verbose_name='是否必填')), + ('order', models.IntegerField(default=0, verbose_name='展示顺序')), + ('default', models.JSONField(default='', verbose_name='默认值')), + ('options', models.JSONField(default={}, verbose_name='配置项')), + ('tenant', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to='tenant.tenant')), + ], + options={ + 'unique_together': {('tenant', 'name'), ('tenant', 'display_name')}, + }, + ), + ] diff --git a/src/bk-user/bkuser/apps/tenant/models.py b/src/bk-user/bkuser/apps/tenant/models.py index 18f8701c6..6acdbe903 100644 --- a/src/bk-user/bkuser/apps/tenant/models.py +++ b/src/bk-user/bkuser/apps/tenant/models.py @@ -12,7 +12,7 @@ from django.db import models from bkuser.apps.data_source.models import DataSource, DataSourceDepartment, DataSourceUser -from bkuser.apps.tenant.constants import TenantFeatureFlag +from bkuser.apps.tenant.constants import TenantFeatureFlag, UserFieldDataType from bkuser.common.constants import PERMANENT_TIME, BkLanguageEnum from bkuser.common.models import TimestampedModel @@ -108,26 +108,35 @@ class Meta: ] -# TODO: 是否直接定义 TenantCommonConfig 表,DynamicFieldInfo是一个JSON字段 -# class DynamicFieldInfo(TimestampedModel): -# """动态的用户字段元信息""" -# -# tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, db_index=True) -# -# id = models.CharField("字段唯一标识", max_length=64) -# name = models.CharField("字段名称", max_length=64) -# # TODO: 需要枚举支持的数据类型 -# data_type = models.CharField("数据类型", max_length=32) -# require = models.BooleanField("是否必填", default=False) -# unique = models.BooleanField("是否唯一", default=False) -# editable = models.BooleanField("是否可b", default=False) -# # TODO:不同类型,可能有额外配置,比如枚举有key和value选项,是否配置为json_schema格式,便于校验呢??? -# -# class Meta: -# unique_together = [ -# ("tenant", "id"), -# ("tenant", "name"), -# ] +class UserBuiltinField(TimestampedModel): + """用户内置字段""" + + name = models.CharField("字段名称", unique=True, max_length=128) + display_name = models.CharField("展示用名称", max_length=128) + data_type = models.CharField("数据类型", choices=UserFieldDataType.get_choices(), max_length=32) + required = models.BooleanField("是否必填") + unique = models.BooleanField("是否唯一") + default = models.JSONField("默认值", default="") + options = models.JSONField("配置项", default={}) + + +class TenantUserCustomField(TimestampedModel): + """租户用户自定义字段""" + + tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, db_constraint=False) + name = models.CharField("字段名称", max_length=128) + display_name = models.CharField("展示用名称", max_length=128) + data_type = models.CharField("数据类型", choices=UserFieldDataType.get_choices(), max_length=32) + required = models.BooleanField("是否必填") + order = models.IntegerField("展示顺序", default=0) + default = models.JSONField("默认值", default="") + options = models.JSONField("配置项", default={}) + + class Meta: + unique_together = [ + ("tenant", "name"), + ("tenant", "display_name"), + ] # # TODO: 是否直接定义 TenantCommonConfig 表,AccountValidityPeriod是一个JSON字段? diff --git a/src/bk-user/tests/apis/web/data_source/test_data_source.py b/src/bk-user/tests/apis/web/data_source/test_data_source.py index 854b882e2..e59d2dec9 100644 --- a/src/bk-user/tests/apis/web/data_source/test_data_source.py +++ b/src/bk-user/tests/apis/web/data_source/test_data_source.py @@ -76,12 +76,14 @@ def local_ds_plugin_config() -> Dict[str, Any]: "scene": NotificationScene.USER_INITIALIZE, "sender": "蓝鲸智云", "content": "您的账户已经成功创建,请尽快修改密码", + "content_html": "

您的账户已经成功创建,请尽快修改密码

", }, { "method": NotificationMethod.SMS, "scene": NotificationScene.RESET_PASSWORD, "sender": "蓝鲸智云", "content": "点击以下链接以重置代码", + "content_html": "

点击以下链接以重置代码

", }, ], }, @@ -112,12 +114,14 @@ def local_ds_plugin_config() -> Dict[str, Any]: "scene": NotificationScene.PASSWORD_EXPIRING, "sender": "蓝鲸智云", "content": "您的密码即将到期!", + "content_html": "

您的密码即将到期!

", }, { "method": NotificationMethod.SMS, "scene": NotificationScene.PASSWORD_EXPIRED, "sender": "蓝鲸智云", "content": "您的密码已到期!", + "content_html": "

您的密码已到期!

", }, ], },