Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(bkuser): adjust local data source config model #1652

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/bk-user/bkuser/apis/web/data_source/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ def validate(self, attrs):
raise ValidationError(_("指定数据源不存在"))

plugin_config = data_source.get_plugin_cfg()
if not plugin_config.enable_account_password_login:
if not plugin_config.enable_password:
raise ValidationError(_("无法使用该数据源生成随机密码"))

attrs["password_rule"] = plugin_config.password_rule.to_rule()
Expand Down
4 changes: 2 additions & 2 deletions src/bk-user/bkuser/apis/web/data_source_organization/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ def put(self, request, *args, **kwargs):
data_source = user.data_source
plugin_config = data_source.get_plugin_cfg()

if not (data_source.is_local and plugin_config.enable_account_password_login):
if not (data_source.is_local and plugin_config.enable_password):
raise error_codes.DATA_SOURCE_OPERATION_UNSUPPORTED.f(
_("仅可以重置 已经启用账密登录功能 的 本地数据源 的用户密码")
nannan00 marked this conversation as resolved.
Show resolved Hide resolved
)
Expand All @@ -292,7 +292,7 @@ def put(self, request, *args, **kwargs):
DataSourceUserHandler.update_password(
data_source_user=user,
password=raw_password,
valid_days=plugin_config.password_rule.valid_time,
valid_days=plugin_config.password_expire.valid_time,
operator=request.user.username,
)

Expand Down
2 changes: 1 addition & 1 deletion src/bk-user/bkuser/apis/web/password/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ def post(self, request, *args, **kwargs):
DataSourceUserHandler.update_password(
data_source_user=data_source_user,
password=password,
valid_days=plugin_cfg.password_rule.valid_time,
valid_days=plugin_cfg.password_expire.valid_time,
operator="AnonymousByResetToken",
)
# 成功修改完用户密码后,需要及时禁用 Token
Expand Down
6 changes: 3 additions & 3 deletions src/bk-user/bkuser/apis/web/personal_center/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ def get(self, request, *args, **kwargs):

feature_flags = {
PersonalCenterFeatureFlag.CAN_CHANGE_PASSWORD: bool(
data_source.is_local and data_source.plugin_config.get("enable_account_password_login", False)
data_source.is_local and data_source.plugin_config.get("enable_password", False)
)
}
return Response(TenantUserFeatureFlagOutputSLZ(feature_flags).data)
Expand All @@ -279,7 +279,7 @@ def put(self, request, *args, **kwargs):
data_source = data_source_user.data_source
plugin_config = data_source.get_plugin_cfg()

if not (data_source.is_local and plugin_config.enable_account_password_login):
if not (data_source.is_local and plugin_config.enable_password):
raise error_codes.DATA_SOURCE_OPERATION_UNSUPPORTED.f(
_("仅可以重置 已经启用账密登录功能 的 本地数据源 的用户密码")
nannan00 marked this conversation as resolved.
Show resolved Hide resolved
)
Expand All @@ -298,7 +298,7 @@ def put(self, request, *args, **kwargs):
DataSourceUserHandler.update_password(
data_source_user=data_source_user,
password=new_password,
valid_days=plugin_config.password_rule.valid_time,
valid_days=plugin_config.password_expire.valid_time,
operator=request.user.username,
)

Expand Down
4 changes: 2 additions & 2 deletions src/bk-user/bkuser/apis/web/platform_management/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ def put(self, request, *args, **kwargs):
plugin_config = data_source.get_plugin_cfg()
assert isinstance(plugin_config, LocalDataSourcePluginConfig)
assert plugin_config.password_initial is not None
assert plugin_config.password_rule is not None
assert plugin_config.password_expire is not None

# 输入参数校验
slz = TenantBuiltinManagerUpdateInputSLZ(
Expand All @@ -329,7 +329,7 @@ def put(self, request, *args, **kwargs):
DataSourceUserHandler.update_password(
data_source_user=user,
password=fixed_password,
valid_days=plugin_config.password_rule.valid_time,
valid_days=plugin_config.password_expire.valid_time,
operator=request.user.username,
)

Expand Down
10 changes: 5 additions & 5 deletions src/bk-user/bkuser/apis/web/tenant_info/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def get(self, request, *args, **kwargs):
TenantBuiltinManagerRetrieveOutputSLZ(
{
"username": user.username,
"enable_account_password_login": data_source.plugin_config["enable_account_password_login"],
"enable_account_password_login": data_source.plugin_config["enable_password"],
nannan00 marked this conversation as resolved.
Show resolved Hide resolved
}
).data
)
Expand Down Expand Up @@ -126,8 +126,8 @@ def patch(self, request, *args, **kwargs):

# 更新是否启用登录
enable = data.get("enable_account_password_login")
if enable is not None and plugin_config.enable_account_password_login != enable:
plugin_config.enable_account_password_login = enable
if enable is not None and plugin_config.enable_password != enable:
plugin_config.enable_password = enable
data_source.set_plugin_cfg(plugin_config)

return Response(status=status.HTTP_204_NO_CONTENT)
Expand All @@ -151,7 +151,7 @@ def put(self, request, *args, **kwargs):
# 数据源配置
plugin_config = data_source.get_plugin_cfg()
assert isinstance(plugin_config, LocalDataSourcePluginConfig)
assert plugin_config.password_rule is not None
assert plugin_config.password_expire is not None

# 数据校验
slz = TenantBuiltinManagerPasswordUpdateInputSLZ(
Expand All @@ -164,7 +164,7 @@ def put(self, request, *args, **kwargs):
DataSourceUserHandler.update_password(
data_source_user=user,
password=raw_password,
valid_days=plugin_config.password_rule.valid_time,
valid_days=plugin_config.password_expire.valid_time,
operator=request.user.username,
)

Expand Down
2 changes: 1 addition & 1 deletion src/bk-user/bkuser/apis/web/virtual_user/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def get_current_virtual_data_source(self):
type=DataSourceTypeEnum.VIRTUAL,
defaults={
"plugin": DataSourcePlugin.objects.get(id=DataSourcePluginEnum.LOCAL),
"plugin_config": LocalDataSourcePluginConfig(enable_account_password_login=False),
"plugin_config": LocalDataSourcePluginConfig(enable_password=False),
},
)

Expand Down
6 changes: 3 additions & 3 deletions src/bk-user/bkuser/apps/data_source/initializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def __init__(self, data_source: DataSource):
self.plugin_cfg = data_source.get_plugin_cfg()
assert isinstance(self.plugin_cfg, LocalDataSourcePluginConfig)

if not self.plugin_cfg.enable_account_password_login:
if not self.plugin_cfg.enable_password:
return

self.password_provider = PasswordProvider(
Expand Down Expand Up @@ -91,7 +91,7 @@ def _can_skip(self) -> bool:
return True

# 是本地数据源,但是没开启账密登录的,不需要初始化
if not self.plugin_cfg.enable_account_password_login: # type: ignore
if not self.plugin_cfg.enable_password: # type: ignore
return True

return False
Expand Down Expand Up @@ -121,7 +121,7 @@ def _init_users_identity_info(self, users: List[DataSourceUser]) -> Dict[int, st

def _get_password_expired_at(self) -> datetime.datetime:
"""获取密码过期的具体时间"""
valid_time: int = self.plugin_cfg.password_rule.valid_time # type: ignore
valid_time: int = self.plugin_cfg.password_expire.valid_time # type: ignore
# 有效时间 -1 表示永远有效
if valid_time < 0:
return PERMANENT_TIME
Expand Down
6 changes: 3 additions & 3 deletions src/bk-user/bkuser/apps/idp/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def _update_local_idp_of_tenant(data_source: DataSource):
"""
更新租户的本地账密登录认证源
对于每个租户,如果有本地数据源,则必须有本地账密认证源
该函数主要是根据本地数据源(status和enable_account_password_login)的变化更新租户的本地账密认证源配置和状态
该函数主要是根据本地数据源(status 和 enable_password )的变化更新租户的本地账密认证源配置和状态
"""
# 非本地数据源不需要默认认证源
if not data_source.is_local:
Expand All @@ -45,11 +45,11 @@ def _update_local_idp_of_tenant(data_source: DataSource):
owner_tenant_id=data_source.owner_tenant_id, plugin=plugin, defaults={"name": _("本地账密")}
)

# 判断数据源 status和enable_account_password_login ,确定是否使用账密登录
# 判断数据源 status 和 enable_password ,确定是否使用账密登录
plugin_cfg = data_source.get_plugin_cfg()
assert isinstance(plugin_cfg, LocalDataSourcePluginConfig)

enable_login = plugin_cfg.enable_account_password_login
enable_login = plugin_cfg.enable_password

# 根据数据源是否使用账密登录,修改认证源配置
idp_plugin_cfg: LocalIdpPluginConfig = idp.get_plugin_cfg()
Expand Down
4 changes: 2 additions & 2 deletions src/bk-user/bkuser/apps/notification/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ def build_and_run_notify_password_expiring_users_task():
logger.info("data source's owner tenant %s not enabled, skip notify...", data_source.id)
continue

if data_source.plugin_config.get("enable_account_password_login", False):
if data_source.plugin_config.get("enable_password", False):
notify_password_expiring_users.delay(data_source.id)


Expand Down Expand Up @@ -122,7 +122,7 @@ def build_and_run_notify_password_expired_users_task():
logger.info("data source's owner tenant %s not enabled, skip notify...", data_source.id)
continue

if data_source.plugin_config.get("enable_account_password_login", False):
if data_source.plugin_config.get("enable_password", False):
notify_password_expired_users.delay(data_source.id)


Expand Down
13 changes: 8 additions & 5 deletions src/bk-user/bkuser/plugins/local/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
)
from bkuser.plugins.local.models import (
LocalDataSourcePluginConfig,
LoginLimitConfig,
NotificationConfig,
NotificationTemplate,
PasswordExpireConfig,
Expand All @@ -24,7 +25,7 @@

# 本地数据源插件默认配置
DEFAULT_PLUGIN_CONFIG = LocalDataSourcePluginConfig(
enable_account_password_login=True,
enable_password=False,
password_rule=PasswordRuleConfig(
min_length=12,
contain_lowercase=True,
Expand All @@ -36,12 +37,8 @@
not_continuous_letter=False,
not_continuous_digit=False,
not_repeated_symbol=False,
valid_time=90,
max_retries=3,
lock_time=60 * 60,
),
password_initial=PasswordInitialConfig(
force_change_at_first_login=True,
cannot_use_previous_password=True,
reserved_previous_password_count=3,
generate_method=PasswordGenerateMethod.RANDOM,
Expand Down Expand Up @@ -129,6 +126,7 @@
),
),
password_expire=PasswordExpireConfig(
valid_time=90,
remind_before_expire=[1, 7, 15],
notification=NotificationConfig(
enabled_methods=[NotificationMethod.EMAIL],
Expand Down Expand Up @@ -200,4 +198,9 @@
],
),
),
login_limit=LoginLimitConfig(
force_change_at_first_login=True,
max_retries=3,
lock_time=60 * 60,
),
)
34 changes: 20 additions & 14 deletions src/bk-user/bkuser/plugins/local/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,6 @@ class PasswordRuleConfig(BaseModel):
# 不允许重复字母,数字,特殊字符
not_repeated_symbol: bool

# 密码有效期(单位:天)
valid_time: int = Field(ge=NEVER_EXPIRE_TIME, le=MAX_PASSWORD_VALID_TIME)
# 密码试错次数
max_retries: int = Field(ge=0, le=PASSWORD_MAX_RETRIES)
# 锁定时间(单位:秒)
lock_time: int = Field(ge=NEVER_EXPIRE_TIME, le=MAX_LOCK_TIME)

def to_rule(self) -> PasswordRule:
"""转换成密码工具可用的规则"""
return PasswordRule(
Expand Down Expand Up @@ -120,8 +113,6 @@ class NotificationConfig(BaseModel):
class PasswordInitialConfig(BaseModel):
"""初始密码设置"""

# 首次登录后强制修改密码
force_change_at_first_login: bool
# 修改密码时候不能使用之前的密码
cannot_use_previous_password: bool
# 之前的 N 个密码不能被本次修改使用,仅当 cannot_use_previous_password 为 True 时有效
Expand All @@ -135,14 +126,27 @@ class PasswordInitialConfig(BaseModel):


class PasswordExpireConfig(BaseModel):
"""密码到期相关配置"""
"""密码有效期相关配置"""

# 密码有效期(单位:天)
valid_time: int = Field(ge=NEVER_EXPIRE_TIME, le=MAX_PASSWORD_VALID_TIME)
# 在密码到期多久前提醒,单位:天,多个值表示多次提醒
remind_before_expire: List[int]
# 通知相关配置
notification: NotificationConfig


class LoginLimitConfig(BaseModel):
"""登录限制配置"""

# 首次登录后强制修改密码
force_change_at_first_login: bool
# 密码试错次数
max_retries: int = Field(ge=0, le=PASSWORD_MAX_RETRIES)
# 锁定时间(单位:秒)
lock_time: int = Field(ge=NEVER_EXPIRE_TIME, le=MAX_LOCK_TIME)


class LocalDataSourcePluginConfig(BasePluginConfig):
"""本地数据源插件配置"""

Expand All @@ -151,20 +155,22 @@ class LocalDataSourcePluginConfig(BasePluginConfig):
"password_initial.fixed_password",
]

# 是否允许使用账密登录
enable_account_password_login: bool
# 是否启用密码,即用户是否添加密码数据
enable_password: bool
# 密码生成规则
password_rule: Optional[PasswordRuleConfig] = None
# 密码初始化/修改规则
password_initial: Optional[PasswordInitialConfig] = None
# 密码到期规则
password_expire: Optional[PasswordExpireConfig] = None
# 登录限制
login_limit: Optional[LoginLimitConfig] = None

@model_validator(mode="after")
def validate_attrs(self) -> "LocalDataSourcePluginConfig":
"""插件配置合法性检查"""
# 如果没有开启账密登录,则不需要检查配置
if not self.enable_account_password_login:
# 如果没有开启密码,则不需要检查配置
if not self.enable_password:
return self

# 若启用账密登录,则各字段都需要配置上
Expand Down
14 changes: 7 additions & 7 deletions src/bk-user/tests/apis/web/data_source/test_data_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def test_create_with_minimal_plugin_config(self, api_client, random_tenant):
reverse("data_source.list_create"),
data={
"plugin_id": DataSourcePluginEnum.LOCAL,
"plugin_config": {"enable_account_password_login": False},
"plugin_config": {"enable_password": False},
},
)
assert resp.status_code == status.HTTP_201_CREATED
Expand Down Expand Up @@ -126,7 +126,7 @@ def test_create_with_invalid_notification_template(self, api_client, random_tena
assert "邮件通知模板需要提供标题" in resp.data["message"]

def test_create_with_invalid_plugin_config(self, api_client, random_tenant, local_ds_plugin_cfg):
local_ds_plugin_cfg.pop("enable_account_password_login")
local_ds_plugin_cfg.pop("enable_password")
resp = api_client.post(
reverse("data_source.list_create"),
data={
Expand All @@ -135,7 +135,7 @@ def test_create_with_invalid_plugin_config(self, api_client, random_tenant, loca
},
)
assert resp.status_code == status.HTTP_400_BAD_REQUEST
assert "插件配置不合法:enable_account_password_login: Field required" in resp.data["message"]
assert "插件配置不合法:enable_password: Field required" in resp.data["message"]

def test_create_general_data_source(
self, api_client, random_tenant, general_ds_plugin_cfg, tenant_user_custom_fields, field_mapping, sync_config
Expand Down Expand Up @@ -253,21 +253,21 @@ def test_list_with_type(self, api_client, data_source):
class TestDataSourceUpdateApi:
def test_update_local_data_source(self, api_client, data_source, local_ds_plugin_cfg):
url = reverse("data_source.retrieve_update_destroy", kwargs={"id": data_source.id})
local_ds_plugin_cfg["enable_account_password_login"] = False
local_ds_plugin_cfg["enable_password"] = False
resp = api_client.put(url, data={"plugin_config": local_ds_plugin_cfg})
assert resp.status_code == status.HTTP_204_NO_CONTENT

resp = api_client.get(url)
assert resp.data["plugin_config"]["enable_account_password_login"] is False
assert resp.data["plugin_config"]["enable_password"] is False

def test_update_with_invalid_plugin_config(self, api_client, data_source, local_ds_plugin_cfg):
local_ds_plugin_cfg.pop("enable_account_password_login")
local_ds_plugin_cfg.pop("enable_password")
resp = api_client.put(
reverse("data_source.retrieve_update_destroy", kwargs={"id": data_source.id}),
data={"plugin_config": local_ds_plugin_cfg},
)
assert resp.status_code == status.HTTP_400_BAD_REQUEST
assert "插件配置不合法:enable_account_password_login: Field required" in resp.data["message"]
assert "插件配置不合法:enable_password: Field required" in resp.data["message"]

def test_update_general_data_source(
self, api_client, bare_general_data_source, general_ds_plugin_cfg, field_mapping, sync_config
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,4 @@ def test_list(self, api_client, tenant_user):
resp = api_client.get(reverse("personal_center.tenant_users.feature_flag.list", kwargs={"id": tenant_user.id}))

assert resp.status_code == status.HTTP_200_OK
assert resp.data["can_change_password"] is True
assert resp.data["can_change_password"] is False
2 changes: 1 addition & 1 deletion src/bk-user/tests/apps/data_source/test_initializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def test_skip_not_local_data_source(self, full_general_data_source):

def test_skip_not_account_password_login_data_source(self, full_local_data_source):
"""没有启用账密登录的,同步不会生效"""
full_local_data_source.plugin_config["enable_account_password_login"] = False
full_local_data_source.plugin_config["enable_password"] = False
full_local_data_source.save()

LocalDataSourceIdentityInfoInitializer(full_local_data_source).initialize()
Expand Down
Loading