diff --git a/src/bk-login/bklogin/authentication/manager.py b/src/bk-login/bklogin/authentication/manager.py index dc95d6b01..14eabe772 100644 --- a/src/bk-login/bklogin/authentication/manager.py +++ b/src/bk-login/bklogin/authentication/manager.py @@ -34,22 +34,22 @@ class BkTokenProcessor: """ - BKToken处理 - 生成并加密Token & 解密Token + BKToken 处理 + 生成并加密 Token & 解密 Token """ def __init__(self): - # 加密器,默认读取django settings里配置的加密密钥和加密类 + # 加密器,默认读取 django settings 里配置的加密密钥和加密类 self.crypter = EncryptHandler() @staticmethod def _salt(length: int = 8) -> str: - """生成长度为length 的随机字符串""" + """生成长度为 length 的随机字符串""" allow_chars = string.ascii_letters + string.digits return "".join([random.choice(allow_chars) for __ in range(length)]) def generate(self, username: str, expires_at: int) -> str: - """token生成""" + """token 生成""" # 加盐 plain_token = "%s|%s|%s" % (expires_at, username, self._salt()) @@ -58,7 +58,7 @@ def generate(self, username: str, expires_at: int) -> str: def parse(self, bk_token: str) -> Tuple[str, int]: """ - token解析 + token 解析 :return: username, expires_at """ try: @@ -88,7 +88,7 @@ def parse(self, bk_token: str) -> Tuple[str, int]: class BkTokenManager: def __init__(self): - # Token加密密钥 + # Token 加密密钥 self.bk_token_processor = BkTokenProcessor() # Token 过期间隔 self.cookie_age = settings.BK_TOKEN_COOKIE_AGE @@ -97,7 +97,7 @@ def __init__(self): # Token 校验时间允许误差 self.offset_error_age = settings.BK_TOKEN_OFFSET_ERROR_AGE - # Token生成失败的重试次数 + # Token 生成失败的重试次数 self.allowed_retry_count = 5 def generate(self, username: str) -> Tuple[str, datetime.datetime]: @@ -107,22 +107,22 @@ def generate(self, username: str) -> Tuple[str, datetime.datetime]: """ bk_token = "" expires_at = int(time.time()) - # 重试5次 + # 重试 5 次 retry_count = 0 while not bk_token and retry_count < self.allowed_retry_count: now_time = int(time.time()) - # Token过期时间 + # Token 过期时间 expires_at = now_time + self.cookie_age # Token 无操作失效时间 inactive_expires_at = now_time + self.inactive_age - # 生成bk_token + # 生成 bk_token bk_token = self.bk_token_processor.generate(username, expires_at) - # DB记录 + # DB 记录 try: BkToken.objects.create(token=bk_token, inactive_expires_at=inactive_expires_at) except Exception: # noqa: PERF203 logger.exception("Login ticket failed to be saved during ticket generation") - # 循环结束前将bk_token置空后重新生成 + # 循环结束前将 bk_token 置空后重新生成 bk_token = "" if retry_count + 1 < self.allowed_retry_count else bk_token retry_count += 1 # Note: quote_plus 是为了兼容 2.x 版本,保持一致,避免用于 Cookie 时调用方未进行 url encode @@ -136,15 +136,15 @@ def is_valid(self, bk_token: str) -> Tuple[bool, str, str]: if not bk_token: return False, "", _("参数 bk_token 缺失") - # Note: unquote_plus 是为了兼容 2.x 版本, 因为旧版本在设置 bk_token Cookie 时做了 quote_plus 转换编码 + # Note: unquote_plus 是为了兼容 2.x 版本,因为旧版本在设置 bk_token Cookie 时做了 quote_plus 转换编码 bk_token = unquote_plus(bk_token) - # 解析bk_token获取username和过期时间 + # 解析 bk_token 获取 username 和过期时间 try: username, expires_at = self.bk_token_processor.parse(bk_token) except ValueError as error: return False, "", str(error) - # 检查DB是存在 + # 检查 DB 是存在 try: bk_token_obj = BkToken.objects.get(token=bk_token) is_logout = bk_token_obj.is_logout @@ -152,16 +152,16 @@ def is_valid(self, bk_token: str) -> Tuple[bool, str, str]: except Exception: return False, "", _("不存在 bk_token[%s] 的记录").format(bk_token) - # token已注销 + # token 已注销 if is_logout: return False, "", _("登录态已注销") now = int(time.time()) - # token有效期已过 + # token 有效期已过 if now > expires_at + self.offset_error_age: return False, "", _("登录态已过期") - # token有效期大于当前时间的有效期 + # token 有效期大于当前时间的有效期 if expires_at - now > self.cookie_age + self.offset_error_age: return False, "", _("登录态有效期不合法") @@ -182,6 +182,6 @@ def set_invalid(bk_token: str): """ 设置登录态失效 """ - # Note: unquote_plus 是为了兼容 2.x 版本, 因为旧版本在设置 bk_token Cookie 时做了 quote_plus 转换编码 + # Note: unquote_plus 是为了兼容 2.x 版本,因为旧版本在设置 bk_token Cookie 时做了 quote_plus 转换编码 bk_token = unquote_plus(bk_token) BkToken.objects.filter(token=bk_token).update(is_logout=True) diff --git a/src/bk-login/bklogin/authentication/views.py b/src/bk-login/bklogin/authentication/views.py index 26285d857..45c7a75d8 100644 --- a/src/bk-login/bklogin/authentication/views.py +++ b/src/bk-login/bklogin/authentication/views.py @@ -49,7 +49,7 @@ logger = logging.getLogger(__name__) -# 确保无论何时,响应必然有CSRFToken Cookie +# 确保无论何时,响应必然有 CSRFToken Cookie @method_decorator(ensure_csrf_cookie, name="dispatch") class LoginView(View): """ @@ -61,11 +61,11 @@ class LoginView(View): template_name = "index.html" def _get_redirect_url(self, request): - """如果安全的话,返回用户发起的重定向URL""" - # 重定向URL + """如果安全的话,返回用户发起的重定向 URL""" + # 重定向 URL redirect_to = request.GET.get(REDIRECT_FIELD_NAME) or self.default_redirect_to - # 检查回调URL是否安全,防钓鱼 + # 检查回调 URL 是否安全,防钓鱼 url_is_safe = url_has_allowed_host_and_scheme( url=redirect_to, allowed_hosts={*settings.ALLOWED_REDIRECT_HOSTS}, @@ -77,7 +77,7 @@ def get(self, request, *args, **kwargs): """登录页面""" # 回调到业务系统的地址 redirect_url = self._get_redirect_url(request) - # 存储到当前session里,待认证成功后取出后重定向 + # 存储到当前 session 里,待认证成功后取出后重定向 request.session["redirect_uri"] = redirect_url # 返回登录页面 @@ -159,19 +159,19 @@ class PluginErrorContext(pydantic.BaseModel): http_method: str -# 先对所有请求豁免CSRF校验,由dispatch里根据需要手动执行CSRF校验 +# 先对所有请求豁免 CSRF 校验,由 dispatch 里根据需要手动执行 CSRF 校验 @method_decorator(csrf_exempt, name="dispatch") class IdpPluginDispatchView(View): def dispatch(self, request, *args, **kwargs): """ 根据路径参数 idp_id 和 action 将请求路由调度到各个插件 """ - # Session里获取当前登录的租户 + # Session 里获取当前登录的租户 sign_in_tenant_id = request.session.get(SIGN_IN_TENANT_ID_SESSION_KEY) # 路径优先 if kwargs.get("tenant_id"): sign_in_tenant_id = kwargs.get("tenant_id") - # session记录登录的租户 + # session 记录登录的租户 request.session[SIGN_IN_TENANT_ID_SESSION_KEY] = sign_in_tenant_id if not sign_in_tenant_id: raise error_codes.NO_PERMISSION.f(_("未选择需要登录的租户")) @@ -191,7 +191,7 @@ def dispatch(self, request, *args, **kwargs): plugin_cls = get_plugin_cls(idp.plugin.id) except NotImplementedError as error: raise error_codes.PLUGIN_SYSTEM_ERROR.f( - _("认证源[{}]获取插件[{}]失败, {}").format(idp.name, idp.plugin.name, error), + _("认证源 [{}] 获取插件 [{}] 失败,{}").format(idp.name, idp.plugin.name, error), ) # (2)初始化插件 @@ -200,19 +200,19 @@ def dispatch(self, request, *args, **kwargs): plugin = plugin_cls(cfg=plugin_cfg) except pydantic.ValidationError: logger.exception("idp(%s) init plugin(%s) config failed", idp.id, idp.plugin.id) - # Note: 不可将error对外,因为配置信息比较敏感 + # Note: 不可将 error 对外,因为配置信息比较敏感 raise error_codes.PLUGIN_SYSTEM_ERROR.f( - _("认证源[{}]初始化插件配置[{}]失败").format(idp.name, idp.plugin.name), + _("认证源 [{}] 初始化插件配置 [{}] 失败").format(idp.name, idp.plugin.name), ) except Exception as error: logger.exception("idp(%s) load plugin(%s) failed", idp.id, idp.plugin.id) raise error_codes.PLUGIN_SYSTEM_ERROR.f( - _("认证源[{}]加载插件[{}]失败, {}").format(idp.name, idp.plugin.name, error), + _("认证源 [{}] 加载插件 [{}] 失败,{}").format(idp.name, idp.plugin.name, error), ) idp_info = IdpBasicInfo(id=idp.id, name=idp.name, plugin_id=idp.plugin.id, plugin_name=idp.plugin.name) # (3)dispatch - # FIXME: 如何对身份凭证类的认证进行手动csrf校验,或者如何添加csrf_protect装饰器 + # FIXME: 如何对身份凭证类的认证进行手动 csrf 校验,或者如何添加 csrf_protect 装饰器 # 身份凭证类型 if isinstance(plugin, BaseCredentialIdpPlugin): return self._dispatch_credential_idp_plugin( @@ -246,7 +246,7 @@ def wrap_plugin_error(self, context: PluginErrorContext, func: Callable, *func_a context.idp.plugin_id, ) raise error_codes.PLUGIN_SYSTEM_ERROR.f( - _("认证源[{}]执行插件[{}]失败").format(context.idp.name, context.idp.plugin_name), + _("认证源 [{}] 执行插件 [{}] 失败").format(context.idp.name, context.idp.plugin_name), ) def _dispatch_credential_idp_plugin( @@ -303,8 +303,8 @@ def _dispatch_federation_idp_plugin( return HttpResponseRedirect(redirect_uri) # 第三方登录成功后回调回蓝鲸 - # Note: 大部分都是GET重定向,对于某些第三方登录,可能存在POST请求, - # 比如SAML的传输绑定有3种: HTTP Artifact、HTTP POST、和 HTTP Redirect + # Note: 大部分都是 GET 重定向,对于某些第三方登录,可能存在 POST 请求, + # 比如 SAML 的传输绑定有 3 种:HTTP Artifact、HTTP POST、和 HTTP Redirect if dispatch_cfs in [ (BuiltinActionEnum.CALLBACK, AllowedHttpMethodEnum.GET), (BuiltinActionEnum.CALLBACK, AllowedHttpMethodEnum.POST), @@ -337,7 +337,7 @@ def _auth_backend( tenant_users = bk_user_api.list_matched_tencent_user(sign_in_tenant_id, idp_id, user_infos) if not tenant_users: raise error_codes.OBJECT_NOT_FOUND.f( - _("认证成功,但用户在租户({})下未有对应账号").format(sign_in_tenant_id), + _("认证成功,但用户在租户 ({}) 下未有对应账号").format(sign_in_tenant_id), ) return [i.model_dump(include={"id", "username", "full_name"}) for i in tenant_users] @@ -361,9 +361,9 @@ def get(self, request, *args, **kwargs): user_id = tenant_users[0]["id"] response = HttpResponseRedirect(redirect_to=request.session.get("redirect_uri")) - # 生成Cookie + # 生成 Cookie bk_token, expired_at = BkTokenManager().generate(user_id) - # 设置Cookie + # 设置 Cookie response.set_cookie( settings.BK_TOKEN_COOKIE_NAME, bk_token, @@ -373,7 +373,7 @@ def get(self, request, *args, **kwargs): secure=False, ) - # 删除Session + # 删除 Session request.session.clear() return response @@ -384,12 +384,12 @@ def get(self, request, *args, **kwargs): """ 用户认证后,获取认证成功后的租户用户列表 """ - # Session里获取当前登录的租户 + # Session 里获取当前登录的租户 sign_in_tenant_id = request.session.get(SIGN_IN_TENANT_ID_SESSION_KEY) if not sign_in_tenant_id: raise error_codes.NO_PERMISSION.f(_("未选择需要登录的租户")) - # Session里获取已认证过的租户用户 + # Session 里获取已认证过的租户用户 tenant_users = request.session.get(ALLOWED_SIGN_IN_TENANT_USERS_SESSION_KEY) if not tenant_users: raise error_codes.NO_PERMISSION.f(_("未经过用户认证步骤")) @@ -402,7 +402,7 @@ def get(self, request, *args, **kwargs): class SignInTenantUserCreateApi(View): def post(self, request, *args, **kwargs): """ - 确认登录的用户,生成bk_token Cookie, 返回重定向业务系统的地址 + 确认登录的用户,生成 bk_token Cookie, 返回重定向业务系统的地址 """ request_body = parse_request_body_json(request.body) user_id = request_body.get("user_id") @@ -416,13 +416,13 @@ def post(self, request, *args, **kwargs): if user_id not in tenant_user_ids: raise error_codes.NO_PERMISSION.f(_("该用户不可登录")) - # TODO:支持MFA、首次登录强制修改密码登录操作 - # TODO: 首次登录强制修改密码登录 => 设置临时场景票据,类似登录态,比如bk_token_for_force_change_password + # TODO:支持 MFA、首次登录强制修改密码登录操作 + # TODO: 首次登录强制修改密码登录 => 设置临时场景票据,类似登录态,比如 bk_token_for_force_change_password response = APISuccessResponse({"redirect_uri": request.session.get("redirect_uri")}) - # 生成Cookie + # 生成 Cookie bk_token, expired_at = BkTokenManager().generate(user_id) - # 设置Cookie + # 设置 Cookie response.set_cookie( settings.BK_TOKEN_COOKIE_NAME, bk_token, @@ -432,7 +432,7 @@ def post(self, request, *args, **kwargs): secure=False, ) - # 删除Session + # 删除 Session request.session.clear() return response diff --git a/src/bk-login/bklogin/common/error_codes.py b/src/bk-login/bklogin/common/error_codes.py index 3a4434218..0134b3730 100644 --- a/src/bk-login/bklogin/common/error_codes.py +++ b/src/bk-login/bklogin/common/error_codes.py @@ -80,8 +80,8 @@ class ErrorCodes: ) NOT_SUPPORTED = ErrorCode(_("不支持")) - # 调用系统API异常 - REMOTE_REQUEST_ERROR = ErrorCode(_("调用系统API异常")) + # 调用系统 API 异常 + REMOTE_REQUEST_ERROR = ErrorCode(_("调用系统 API 异常")) # 实例化一个全局对象 diff --git a/src/bk-login/bklogin/common/middlewares.py b/src/bk-login/bklogin/common/middlewares.py index d809bb692..c2892d5dc 100644 --- a/src/bk-login/bklogin/common/middlewares.py +++ b/src/bk-login/bklogin/common/middlewares.py @@ -14,9 +14,14 @@ # # We undertake not to change the open source license (MIT license) applicable # to the current version of the project delivered to anyone in the future. +import base64 import json import logging +from collections import namedtuple +from typing import Any, Dict +import jwt +from django.conf import settings from django.db import connections from sentry_sdk import capture_exception @@ -41,8 +46,8 @@ def process_exception(self, request, exception): """ error = _handle_exception(request, exception) - # 根据蓝鲸新版HTTP API 协议, 处理响应数据 - # 开发者关注的,能自助排查, 快速定位问题 + # 根据蓝鲸新版 HTTP API 协议,处理响应数据 + # 开发者关注的,能自助排查,快速定位问题 detail = {"code": error.code, "message": ""} if error.detail and isinstance(error.detail, dict): detail.update(error.detail) @@ -80,7 +85,89 @@ def _handle_exception(request, exc) -> APIError: def _set_rollback(): - """DB事务回滚""" + """DB 事务回滚""" for db in connections.all(): if db.settings_dict["ATOMIC_REQUESTS"] and db.in_atomic_block: db.set_rollback(True) + + +class APIGatewayJWTMiddleware: + """ + 该中间件读取由 API 网关传输的 JWT 头信息,获取相应的公钥进行解密,将解密结果赋值给 request.app。 + 默认情况下,通过 settings.BK_APIGW_PUBLIC_KEY 读取 API 网关公钥 + """ + + JWT_KEY_HEADER_NAME = "HTTP_X_BKAPI_JWT" + ALGORITHM = "RS512" + App = namedtuple("App", ["bk_app_code", "verified"]) + + def __init__(self, get_response): + self.get_response = get_response + + self.public_key = self._get_public_key() + + def __call__(self, request): + # 解析 Header 头 APIGateway JWT + jwt_token = request.META.get(self.JWT_KEY_HEADER_NAME, "") + jwt_payload = self._decode_jwt(jwt_token) + if not jwt_payload: + return self.get_response(request) + + # App 信息 + jwt_app = jwt_payload.get("app") or {} + bk_app_code = jwt_app.get("bk_app_code", jwt_app.get("app_code", None)) + app_verified = jwt_app.get("verified", False) + + # 将 JWT App 信息赋值给 request.app + request.app = self._make_app(bk_app_code=bk_app_code, verified=app_verified) + + return self.get_response(request) + + @staticmethod + def _get_public_key() -> str: + """ + 获取 APIGW 的 Public Key + 由于配置文件里的 public key 是来自环境变量,且使用 base64 编码,因此需要解码 + """ + if not settings.BK_APIGW_PUBLIC_KEY: + logger.error("setting `BK_APIGW_PUBLIC_KEY` can not be empty") + return "" + + try: + return base64.b64decode(settings.BK_APIGW_PUBLIC_KEY).decode("utf-8") + except (TypeError, ValueError): + logger.exception( + "setting `BK_APIGW_PUBLIC_KEY` must be base64 string, BK_APIGW_PUBLIC_KEY=%s", + settings.BK_APIGW_PUBLIC_KEY, + ) + + return "" + + def _decode_jwt(self, jwt_token: str) -> Dict[str, Any] | None: + """ + 解析 JWT + :return + { + "app" : {"app_code" : "app-code-test", "verified" : true, ...}, + "user" : {"username" : "user-test", "verified" : false, ...} + } + """ + if not jwt_token: + return None + + if not self.public_key: + return None + + try: + # 从 JWT 里的 Header 字段里解析出未验证的信息,比如算法,然后用于后续解析 JWT 里的 Payload + jwt_header = jwt.get_unverified_header(jwt_token) + algorithm = jwt_header.get("alg") or self.ALGORITHM + # Note: bk apigw 目前的 issuer 不规范,所以这里不强校验 issuer + return jwt.decode(jwt_token, self.public_key, algorithms=[algorithm], options={"verify_iss": False}) + except jwt.PyJWTError: + logger.exception("jwt decode failed, jwt content: %s", jwt_token) + + return None + + def _make_app(self, bk_app_code: str | None = None, verified: bool = False): + return self.App(bk_app_code=bk_app_code, verified=verified) diff --git a/src/bk-login/bklogin/common/response.py b/src/bk-login/bklogin/common/response.py index 7a2c34399..b30f6a4f1 100644 --- a/src/bk-login/bklogin/common/response.py +++ b/src/bk-login/bklogin/common/response.py @@ -20,7 +20,7 @@ class APISuccessResponse(JsonResponse): - """遵循蓝鲸Http API协议返回""" + """遵循蓝鲸 Http API 协议返回""" def __init__(self, data: Any = None, status: Optional[int] = None): wrapped_data = {"data": data} diff --git a/src/bk-login/bklogin/component/bk_user/api.py b/src/bk-login/bklogin/component/bk_user/api.py index 93bb2ffa1..b89d28172 100644 --- a/src/bk-login/bklogin/component/bk_user/api.py +++ b/src/bk-login/bklogin/component/bk_user/api.py @@ -57,7 +57,7 @@ def _call_bk_user_api(http_func, url_path: str, allow_error_status_func: Callabl def _call_bk_user_api_20x(http_func, url_path: str, **kwargs): - """只允许20x的用户管理接口""" + """只允许 20x 的用户管理接口""" return _call_bk_user_api(http_func, url_path, allow_error_status_func=lambda s: False, **kwargs)["data"] @@ -86,13 +86,13 @@ def list_idp(tenant_id: str, idp_owner_tenant_id: str) -> List[IdpInfo]: def get_idp(idp_id: str) -> IdpDetail: - """获取IDP信息""" + """获取 IDP 信息""" data = _call_bk_user_api_20x(http_get, f"/api/v3/login/idps/{idp_id}/") return IdpDetail(**data) def list_matched_tencent_user(tenant_id: str, idp_id: str, idp_users: List[Dict[str, Any]]) -> List[TenantUserInfo]: - """根据IDP用户查询匹配的租户用户""" + """根据 IDP 用户查询匹配的租户用户""" data = _call_bk_user_api_20x( http_post, f"/api/v3/login/tenants/{tenant_id}/idps/{idp_id}/matched-tenant-users/", @@ -102,6 +102,6 @@ def list_matched_tencent_user(tenant_id: str, idp_id: str, idp_users: List[Dict[ def get_tenant_user(tenant_user_id: str) -> TenantUserDetailInfo: - """通过租户用户ID获取租户用户信息""" + """通过租户用户 ID 获取租户用户信息""" data = _call_bk_user_api_20x(http_get, f"/api/v3/login/tenant-users/{tenant_user_id}/") return TenantUserDetailInfo(**data) diff --git a/src/bk-login/bklogin/open_apis/compatibility/mixins.py b/src/bk-login/bklogin/open_apis/compatibility/mixins.py index 02e6b9c0d..41b676eb0 100644 --- a/src/bk-login/bklogin/open_apis/compatibility/mixins.py +++ b/src/bk-login/bklogin/open_apis/compatibility/mixins.py @@ -24,14 +24,14 @@ class CompatibilityApiMixin: - """兼容API Mixin""" + """兼容 API Mixin""" api_version = "v1" @staticmethod def is_request_from_esb(request): """ - 请求是否来自ESB + 请求是否来自 ESB """ x_app_token = request.META.get("HTTP_X_APP_TOKEN") x_app_code = request.META.get("HTTP_X_APP_CODE") diff --git a/src/bk-login/bklogin/open_apis/compatibility/views.py b/src/bk-login/bklogin/open_apis/compatibility/views.py index c567cc9f3..110ffc016 100644 --- a/src/bk-login/bklogin/open_apis/compatibility/views.py +++ b/src/bk-login/bklogin/open_apis/compatibility/views.py @@ -64,11 +64,11 @@ def get(self, request, *args, **kwargs): "language": user.language, "time_zone": user.time_zone, # 多租户版本新增 - "tenant_id": user.tenant_id, - "full_name": user.full_name, # 姓名 - "display_name": user.display_name, # 统一展示名 + # 规范所有 SaaS 统一展示名 + "display_name": user.display_name, # ----- 兼容 ------ # 兼容数据 + # 姓名 "chname": user.full_name, # 【兼容】固定或空值返回 "qq": "", diff --git a/src/bk-login/bklogin/open_apis/mixins.py b/src/bk-login/bklogin/open_apis/mixins.py new file mode 100644 index 000000000..8714e1c8e --- /dev/null +++ b/src/bk-login/bklogin/open_apis/mixins.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# TencentBlueKing is pleased to support the open source community by making +# 蓝鲸智云 - 用户管理 (bk-user) available. +# Copyright (C) 2017 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. +# +# We undertake not to change the open source license (MIT license) applicable +# to the current version of the project delivered to anyone in the future. +from bklogin.common.error_codes import error_codes + + +class APIGatewayAppVerifiedMixin: + """校验来源 APIGateway JWT 的应用是否认证""" + + # FIXME (nan): 待讨论清楚网关本身的用户认证与登录如何认证后再去除 + skip_app_verified = False + + def dispatch(self, request, *args, **kwargs): + if self.skip_app_verified: + return super().dispatch(request, *args, **kwargs) # type: ignore + + app = getattr(request, "app", None) + if app and app.verified: + return super().dispatch(request, *args, **kwargs) # type: ignore + + raise error_codes.UNAUTHENTICATED.f("the api must be verify app from api gateway") diff --git a/src/bk-login/bklogin/open_apis/urls.py b/src/bk-login/bklogin/open_apis/urls.py index 6f7475ac7..6ff191a55 100644 --- a/src/bk-login/bklogin/open_apis/urls.py +++ b/src/bk-login/bklogin/open_apis/urls.py @@ -16,16 +16,30 @@ # to the current version of the project delivered to anyone in the future. from django.urls import path +from . import views from .compatibility import views as compatibility_views urlpatterns = [ - # 兼容API, 兼容原有通过 ESB 和直接调用的两种方式 + # 兼容 API, 兼容原有通过 ESB 和直接调用的两种方式 path("accounts/is_login/", compatibility_views.TokenIntrospectCompatibilityApi.as_view(api_version="v1")), path("accounts/get_user/", compatibility_views.UserRetrieveCompatibilityApi.as_view(api_version="v1")), path("api/v2/is_login/", compatibility_views.TokenIntrospectCompatibilityApi.as_view(api_version="v2")), path("api/v2/get_user/", compatibility_views.UserRetrieveCompatibilityApi.as_view(api_version="v2")), path("api/v3/is_login/", compatibility_views.TokenIntrospectCompatibilityApi.as_view(api_version="v3")), path("api/v3/get_user/", compatibility_views.UserRetrieveCompatibilityApi.as_view(api_version="v3")), - # TODO: 新的 OpenAPI 后面统一接入 APIGateway,不支持直接调用, + # Note: 新的 OpenAPI 后面统一接入 APIGateway,不支持直接调用 # 同时只提供给 APIGateway 做用户认证的接口与通用 OpenAPI 区分开 + path("api/v3/open/bk-tokens/verify/", views.TokenVerifyApi.as_view(), name="v3_open.bk_token.verify"), + path( + "api/v3/open/bk-tokens/userinfo/", + views.TokenUserInfoRetrieveApi.as_view(), + name="v3_open.bk_token.userinfo_retrieve", + ), + path("api/v3/apigw/bk-tokens/verify/", views.TokenVerifyApi.as_view(skip_app_verified=True)), + # FIXME (nan): 临时兼容用户管理 SaaS 本地开发的登录 + path("api/v3/bkuser/bk-tokens/verify/", views.TokenVerifyApi.as_view(skip_app_verified=True)), + path( + "api/v3/bkuser/bk-tokens/userinfo/", + views.TokenUserInfoRetrieveApi.as_view(skip_app_verified=True), + ), ] diff --git a/src/bk-login/bklogin/open_apis/views.py b/src/bk-login/bklogin/open_apis/views.py new file mode 100644 index 000000000..4718f9f36 --- /dev/null +++ b/src/bk-login/bklogin/open_apis/views.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# TencentBlueKing is pleased to support the open source community by making +# 蓝鲸智云 - 用户管理 (bk-user) available. +# Copyright (C) 2017 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. +# +# We undertake not to change the open source license (MIT license) applicable +# to the current version of the project delivered to anyone in the future. +from django.conf import settings +from django.views.generic import View + +from bklogin.authentication.manager import BkTokenManager +from bklogin.common.error_codes import error_codes +from bklogin.common.response import APISuccessResponse +from bklogin.component.bk_user import api as bk_user_api + +from .mixins import APIGatewayAppVerifiedMixin + + +class TokenVerifyApi(APIGatewayAppVerifiedMixin, View): + """Token 解析""" + + def get(self, request, *args, **kwargs): + bk_token = request.GET.get(settings.BK_TOKEN_COOKIE_NAME) + + ok, username, msg = BkTokenManager().is_valid(bk_token) + if not ok: + raise error_codes.VALIDATION_ERROR.f(msg, replace=True) + + # FIXME (nan): 调整 bk_token 签发逻辑,DB BKToken 表额外添加 tenant_id / idp_id 等信息, + # 避免需频繁查询用户管理接口 + user = bk_user_api.get_tenant_user(username) + + return APISuccessResponse(data={"bk_username": user.id, "tenant_id": user.tenant_id}) + + +class TokenUserInfoRetrieveApi(APIGatewayAppVerifiedMixin, View): + """Token 用户信息解析""" + + def get(self, request, *args, **kwargs): + bk_token = request.GET.get(settings.BK_TOKEN_COOKIE_NAME) + + ok, username, msg = BkTokenManager().is_valid(bk_token) + if not ok: + raise error_codes.VALIDATION_ERROR.f(msg, replace=True) + + # 通过用户管理查询用户信息 + user = bk_user_api.get_tenant_user(username) + + return APISuccessResponse( + data={ + "bk_username": user.id, + "tenant_id": user.tenant_id, + # 基本信息 + "display_name": user.display_name, + "language": user.language, + "time_zone": user.time_zone, + } + ) diff --git a/src/bk-login/bklogin/settings.py b/src/bk-login/bklogin/settings.py index 13656b451..569e1029e 100644 --- a/src/bk-login/bklogin/settings.py +++ b/src/bk-login/bklogin/settings.py @@ -68,6 +68,7 @@ "django.middleware.clickjacking.XFrameOptionsMiddleware", "whitenoise.middleware.WhiteNoiseMiddleware", "bklogin.common.middlewares.ExceptionHandlerMiddleware", + "bklogin.common.middlewares.APIGatewayJWTMiddleware", "django_prometheus.middleware.PrometheusAfterMiddleware", ] @@ -123,7 +124,7 @@ # Static files (CSS, JavaScript, Images) STATIC_ROOT = BASE_DIR / "staticfiles" WHITENOISE_STATIC_PREFIX = os.path.join(SITE_URL, "staticfiles/") -# STATIC_URL 也可以是CDN地址 +# STATIC_URL 也可以是 CDN 地址 STATIC_URL = env.str("STATIC_URL", default=SITE_URL + "staticfiles/") # 登录服务的AppCode/AppSecret @@ -142,17 +143,17 @@ BK_CRYPTO_TYPE = env.str("BK_CRYPTO_TYPE", "CLASSIC") ENCRYPT_CIPHER_TYPE = "SM4CTR" if BK_CRYPTO_TYPE == "SHANGMI" else "FernetCipher" -# 蓝鲸统一的基础域和对外SCHEME +# 蓝鲸统一的基础域和对外 SCHEME BK_DOMAIN = env.str("BK_DOMAIN", "") BK_DOMAIN_SCHEME = env.str("BK_DOMAIN_SCHEME", default="http") -# 统一登录的外部访问地址,不包括http(s)协议 +# 统一登录的外部访问地址,不包括 http(s) 协议 BK_LOGIN_ADDR = env.str("BK_LOGIN_ADDR", "") BK_LOGIN_URL = f"{BK_DOMAIN_SCHEME}://{BK_LOGIN_ADDR}{SITE_URL}" AJAX_BASE_URL = env.str("AJAX_BASE_URL", SITE_URL) -# 蓝鲸公共的Cookie的Domain(比如 bk_token和blueking_language) +# 蓝鲸公共的 Cookie 的 Domain(比如 bk_token 和 blueking_language) BK_COOKIE_DOMAIN = f".{BK_DOMAIN}" -# 登录完成后允许重定向的HOST -# 支持匹配: +# 登录完成后允许重定向的 HOST +# 支持匹配: # (1) * 匹配任意域名 # (2) 泛域名匹配,比如 .example.com 可匹配 foo.example.com、example.com、foo.example.com:8000、example.com:8080 # (3) 精确域名匹配,比如 example.com 可匹配 example.com、example.com:8000 @@ -160,7 +161,7 @@ # 默认蓝鲸体系域名都可以匹配 ALLOWED_REDIRECT_HOSTS = env.list("BK_LOGIN_ALLOWED_REDIRECT_HOSTS", default=[BK_COOKIE_DOMAIN]) REDIRECT_URL_REQUIRE_HTTPS = env.bool("BK_LOGIN_REDIRECT_URL_REQUIRE_HTTPS", default=bool(BK_DOMAIN_SCHEME == "https")) -# 语言Cookie(蓝鲸体系共享) +# 语言 Cookie(蓝鲸体系共享) LANGUAGE_COOKIE_DOMAIN = BK_COOKIE_DOMAIN # session & csrf @@ -170,11 +171,11 @@ _BK_LOGIN_IS_SPECIAL_PORT = _BK_LOGIN_URL_PARSE_URL.port in [None, 80, 443] _BK_LOGIN_SCHEME = _BK_LOGIN_URL_PARSE_URL.scheme _BK_LOGIN_URL_MD5_16BIT = hashlib.md5(BK_LOGIN_URL.encode("utf-8")).hexdigest()[8:-8] -# 注意:Cookie Domain是不支持端口的 +# 注意:Cookie Domain 是不支持端口的 SESSION_COOKIE_DOMAIN = _BK_LOGIN_HOSTNAME CSRF_COOKIE_DOMAIN = SESSION_COOKIE_DOMAIN SESSION_COOKIE_NAME = f"bklogin_sessionid_{_BK_LOGIN_URL_MD5_16BIT}" -SESSION_COOKIE_AGE = 60 * 60 * 24 # 1天 +SESSION_COOKIE_AGE = 60 * 60 * 24 # 1 天 CSRF_COOKIE_NAME = f"bklogin_csrftoken_{_BK_LOGIN_URL_MD5_16BIT}" # 对于特殊端口,带端口和不带端口都得添加,其他只需要添加默认原生的即可 # Django 4.0 之后 CSRF_TRUSTED_ORIGINS 必须以 scheme (http:// 或 https://) 开头 @@ -192,13 +193,13 @@ CORS_ORIGIN_WHITELIST.extend(CORS_ORIGIN_ADDITIONAL_WHITELIST) # 登录票据 -# 登录票据Cookie名称 +# 登录票据 Cookie 名称 BK_TOKEN_COOKIE_NAME = env.str("BK_LOGIN_COOKIE_NAME", default="bk_token") -# 登录票据Cookie有效期,默认1天 +# 登录票据 Cookie 有效期,默认 1 天 BK_TOKEN_COOKIE_AGE = env.int("BK_LOGIN_COOKIE_AGE", default=60 * 60 * 24) -# 登录票据校验有效期时,校验时间允许误差,防止多台机器时间不同步,默认1分钟 +# 登录票据校验有效期时,校验时间允许误差,防止多台机器时间不同步,默认 1 分钟 BK_TOKEN_OFFSET_ERROR_AGE = env.int("BK_LOGIN_COOKIE_OFFSET_ERROR_AGE", default=60) -# 无操作的失效期,默认2个小时. 长时间无操作, BkToken自动过期(Note: 调整为) +# 无操作的失效期,默认 2 个小时。长时间无操作,BkToken 自动过期(Note: 调整为) BK_TOKEN_INACTIVE_AGE = env.int("BK_TOKEN_INACTIVE_AGE", default=60 * 60 * 2) # 用户管理相关信息 @@ -208,6 +209,9 @@ # bk apigw url tmpl BK_API_URL_TMPL = env.str("BK_API_URL_TMPL", default="") +# Open API 接入 BK APIGateway 后,需要对 APIGW 请求来源认证,使用公钥解开 jwt +# Note: 格式必须是 base64 字符串 +BK_APIGW_PUBLIC_KEY = env.str("BK_APIGW_PUBLIC_KEY", default="") # footer / logo / title 等全局配置存储的共享仓库地址 BK_SHARED_RES_URL = env.str("BK_SHARED_RES_URL", default="") diff --git a/src/bk-login/poetry.lock b/src/bk-login/poetry.lock index acaf1762d..04c84df6d 100644 --- a/src/bk-login/poetry.lock +++ b/src/bk-login/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. [[package]] name = "annotated-types" @@ -406,51 +406,53 @@ reference = "tencent" [[package]] name = "cryptography" -version = "43.0.3" +version = "44.0.0" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false -python-versions = ">=3.7" -files = [ - {file = "cryptography-43.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e"}, - {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e"}, - {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e1ce50266f4f70bf41a2c6dc4358afadae90e2a1e5342d3c08883df1675374f"}, - {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:443c4a81bb10daed9a8f334365fe52542771f25aedaf889fd323a853ce7377d6"}, - {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:74f57f24754fe349223792466a709f8e0c093205ff0dca557af51072ff47ab18"}, - {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9762ea51a8fc2a88b70cf2995e5675b38d93bf36bd67d91721c309df184f49bd"}, - {file = "cryptography-43.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:81ef806b1fef6b06dcebad789f988d3b37ccaee225695cf3e07648eee0fc6b73"}, - {file = "cryptography-43.0.3-cp37-abi3-win32.whl", hash = "sha256:cbeb489927bd7af4aa98d4b261af9a5bc025bd87f0e3547e11584be9e9427be2"}, - {file = "cryptography-43.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:f46304d6f0c6ab8e52770addfa2fc41e6629495548862279641972b6215451cd"}, - {file = "cryptography-43.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8ac43ae87929a5982f5948ceda07001ee5e83227fd69cf55b109144938d96984"}, - {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:846da004a5804145a5f441b8530b4bf35afbf7da70f82409f151695b127213d5"}, - {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f996e7268af62598f2fc1204afa98a3b5712313a55c4c9d434aef49cadc91d4"}, - {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f7b178f11ed3664fd0e995a47ed2b5ff0a12d893e41dd0494f406d1cf555cab7"}, - {file = "cryptography-43.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:c2e6fc39c4ab499049df3bdf567f768a723a5e8464816e8f009f121a5a9f4405"}, - {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e1be4655c7ef6e1bbe6b5d0403526601323420bcf414598955968c9ef3eb7d16"}, - {file = "cryptography-43.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:df6b6c6d742395dd77a23ea3728ab62f98379eff8fb61be2744d4679ab678f73"}, - {file = "cryptography-43.0.3-cp39-abi3-win32.whl", hash = "sha256:d56e96520b1020449bbace2b78b603442e7e378a9b3bd68de65c782db1507995"}, - {file = "cryptography-43.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:0c580952eef9bf68c4747774cde7ec1d85a6e61de97281f2dba83c7d2c806362"}, - {file = "cryptography-43.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d03b5621a135bffecad2c73e9f4deb1a0f977b9a8ffe6f8e002bf6c9d07b918c"}, - {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a2a431ee15799d6db9fe80c82b055bae5a752bef645bba795e8e52687c69efe3"}, - {file = "cryptography-43.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:281c945d0e28c92ca5e5930664c1cefd85efe80e5c0d2bc58dd63383fda29f83"}, - {file = "cryptography-43.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:f18c716be16bc1fea8e95def49edf46b82fccaa88587a45f8dc0ff6ab5d8e0a7"}, - {file = "cryptography-43.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4a02ded6cd4f0a5562a8887df8b3bd14e822a90f97ac5e544c162899bc467664"}, - {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:53a583b6637ab4c4e3591a15bc9db855b8d9dee9a669b550f311480acab6eb08"}, - {file = "cryptography-43.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:1ec0bcf7e17c0c5669d881b1cd38c4972fade441b27bda1051665faaa89bdcaa"}, - {file = "cryptography-43.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2ce6fae5bdad59577b44e4dfed356944fbf1d925269114c28be377692643b4ff"}, - {file = "cryptography-43.0.3.tar.gz", hash = "sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805"}, +python-versions = ">=3.7, !=3.9.0, !=3.9.1" +files = [ + {file = "cryptography-44.0.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:84111ad4ff3f6253820e6d3e58be2cc2a00adb29335d4cacb5ab4d4d34f2a123"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b15492a11f9e1b62ba9d73c210e2416724633167de94607ec6069ef724fad092"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831c3c4d0774e488fdc83a1923b49b9957d33287de923d58ebd3cec47a0ae43f"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:761817a3377ef15ac23cd7834715081791d4ec77f9297ee694ca1ee9c2c7e5eb"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3c672a53c0fb4725a29c303be906d3c1fa99c32f58abe008a82705f9ee96f40b"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4ac4c9f37eba52cb6fbeaf5b59c152ea976726b865bd4cf87883a7e7006cc543"}, + {file = "cryptography-44.0.0-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:60eb32934076fa07e4316b7b2742fa52cbb190b42c2df2863dbc4230a0a9b385"}, + {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ed3534eb1090483c96178fcb0f8893719d96d5274dfde98aa6add34614e97c8e"}, + {file = "cryptography-44.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f3f6fdfa89ee2d9d496e2c087cebef9d4fcbb0ad63c40e821b39f74bf48d9c5e"}, + {file = "cryptography-44.0.0-cp37-abi3-win32.whl", hash = "sha256:eb33480f1bad5b78233b0ad3e1b0be21e8ef1da745d8d2aecbb20671658b9053"}, + {file = "cryptography-44.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:abc998e0c0eee3c8a1904221d3f67dcfa76422b23620173e28c11d3e626c21bd"}, + {file = "cryptography-44.0.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:660cb7312a08bc38be15b696462fa7cc7cd85c3ed9c576e81f4dc4d8b2b31591"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1923cb251c04be85eec9fda837661c67c1049063305d6be5721643c22dd4e2b7"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:404fdc66ee5f83a1388be54300ae978b2efd538018de18556dde92575e05defc"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c5eb858beed7835e5ad1faba59e865109f3e52b3783b9ac21e7e47dc5554e289"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f53c2c87e0fb4b0c00fa9571082a057e37690a8f12233306161c8f4b819960b7"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9e6fc8a08e116fb7c7dd1f040074c9d7b51d74a8ea40d4df2fc7aa08b76b9e6c"}, + {file = "cryptography-44.0.0-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:9abcc2e083cbe8dde89124a47e5e53ec38751f0d7dfd36801008f316a127d7ba"}, + {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:d2436114e46b36d00f8b72ff57e598978b37399d2786fd39793c36c6d5cb1c64"}, + {file = "cryptography-44.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a01956ddfa0a6790d594f5b34fc1bfa6098aca434696a03cfdbe469b8ed79285"}, + {file = "cryptography-44.0.0-cp39-abi3-win32.whl", hash = "sha256:eca27345e1214d1b9f9490d200f9db5a874479be914199194e746c893788d417"}, + {file = "cryptography-44.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:708ee5f1bafe76d041b53a4f95eb28cdeb8d18da17e597d46d7833ee59b97ede"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:37d76e6863da3774cd9db5b409a9ecfd2c71c981c38788d3fcfaf177f447b731"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:f677e1268c4e23420c3acade68fac427fffcb8d19d7df95ed7ad17cdef8404f4"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f5e7cb1e5e56ca0933b4873c0220a78b773b24d40d186b6738080b73d3d0a756"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:8b3e6eae66cf54701ee7d9c83c30ac0a1e3fa17be486033000f2a73a12ab507c"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:be4ce505894d15d5c5037167ffb7f0ae90b7be6f2a98f9a5c3442395501c32fa"}, + {file = "cryptography-44.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:62901fb618f74d7d81bf408c8719e9ec14d863086efe4185afd07c352aee1d2c"}, + {file = "cryptography-44.0.0.tar.gz", hash = "sha256:cd4e834f340b4293430701e772ec543b0fbe6c2dea510a5286fe0acabe153a02"}, ] [package.dependencies] cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} [package.extras] -docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=1.1.1)"] -docstest = ["pyenchant (>=1.6.11)", "readme-renderer", "sphinxcontrib-spelling (>=4.0.1)"] -nox = ["nox"] -pep8test = ["check-sdist", "click", "mypy", "ruff"] -sdist = ["build"] +docs = ["sphinx (>=5.3.0)", "sphinx-rtd-theme (>=3.0.0)"] +docstest = ["pyenchant (>=3)", "readme-renderer (>=30.0)", "sphinxcontrib-spelling (>=7.3.1)"] +nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2)"] +pep8test = ["check-sdist", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"] +sdist = ["build (>=1.0.0)"] ssh = ["bcrypt (>=3.1.5)"] -test = ["certifi", "cryptography-vectors (==43.0.3)", "pretend", "pytest (>=6.2.0)", "pytest-benchmark", "pytest-cov", "pytest-xdist"] +test = ["certifi (>=2024)", "cryptography-vectors (==44.0.0)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"] test-randomorder = ["pytest-randomly"] [package.source] @@ -889,70 +891,70 @@ reference = "tencent" [[package]] name = "grpcio" -version = "1.68.0" +version = "1.68.1" description = "HTTP/2-based RPC framework" optional = false python-versions = ">=3.8" files = [ - {file = "grpcio-1.68.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:619b5d0f29f4f5351440e9343224c3e19912c21aeda44e0c49d0d147a8d01544"}, - {file = "grpcio-1.68.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:a59f5822f9459bed098ffbceb2713abbf7c6fd13f2b9243461da5c338d0cd6c3"}, - {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:c03d89df516128febc5a7e760d675b478ba25802447624edf7aa13b1e7b11e2a"}, - {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44bcbebb24363d587472089b89e2ea0ab2e2b4df0e4856ba4c0b087c82412121"}, - {file = "grpcio-1.68.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79f81b7fbfb136247b70465bd836fa1733043fdee539cd6031cb499e9608a110"}, - {file = "grpcio-1.68.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:88fb2925789cfe6daa20900260ef0a1d0a61283dfb2d2fffe6194396a354c618"}, - {file = "grpcio-1.68.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:99f06232b5c9138593ae6f2e355054318717d32a9c09cdc5a2885540835067a1"}, - {file = "grpcio-1.68.0-cp310-cp310-win32.whl", hash = "sha256:a6213d2f7a22c3c30a479fb5e249b6b7e648e17f364598ff64d08a5136fe488b"}, - {file = "grpcio-1.68.0-cp310-cp310-win_amd64.whl", hash = "sha256:15327ab81131ef9b94cb9f45b5bd98803a179c7c61205c8c0ac9aff9d6c4e82a"}, - {file = "grpcio-1.68.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:3b2b559beb2d433129441783e5f42e3be40a9e1a89ec906efabf26591c5cd415"}, - {file = "grpcio-1.68.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:e46541de8425a4d6829ac6c5d9b16c03c292105fe9ebf78cb1c31e8d242f9155"}, - {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:c1245651f3c9ea92a2db4f95d37b7597db6b246d5892bca6ee8c0e90d76fb73c"}, - {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f1931c7aa85be0fa6cea6af388e576f3bf6baee9e5d481c586980c774debcb4"}, - {file = "grpcio-1.68.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b0ff09c81e3aded7a183bc6473639b46b6caa9c1901d6f5e2cba24b95e59e30"}, - {file = "grpcio-1.68.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8c73f9fbbaee1a132487e31585aa83987ddf626426d703ebcb9a528cf231c9b1"}, - {file = "grpcio-1.68.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6b2f98165ea2790ea159393a2246b56f580d24d7da0d0342c18a085299c40a75"}, - {file = "grpcio-1.68.0-cp311-cp311-win32.whl", hash = "sha256:e1e7ed311afb351ff0d0e583a66fcb39675be112d61e7cfd6c8269884a98afbc"}, - {file = "grpcio-1.68.0-cp311-cp311-win_amd64.whl", hash = "sha256:e0d2f68eaa0a755edd9a47d40e50dba6df2bceda66960dee1218da81a2834d27"}, - {file = "grpcio-1.68.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:8af6137cc4ae8e421690d276e7627cfc726d4293f6607acf9ea7260bd8fc3d7d"}, - {file = "grpcio-1.68.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:4028b8e9a3bff6f377698587d642e24bd221810c06579a18420a17688e421af7"}, - {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:f60fa2adf281fd73ae3a50677572521edca34ba373a45b457b5ebe87c2d01e1d"}, - {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e18589e747c1e70b60fab6767ff99b2d0c359ea1db8a2cb524477f93cdbedf5b"}, - {file = "grpcio-1.68.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0d30f3fee9372796f54d3100b31ee70972eaadcc87314be369360248a3dcffe"}, - {file = "grpcio-1.68.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7e0a3e72c0e9a1acab77bef14a73a416630b7fd2cbd893c0a873edc47c42c8cd"}, - {file = "grpcio-1.68.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a831dcc343440969aaa812004685ed322cdb526cd197112d0db303b0da1e8659"}, - {file = "grpcio-1.68.0-cp312-cp312-win32.whl", hash = "sha256:5a180328e92b9a0050958ced34dddcb86fec5a8b332f5a229e353dafc16cd332"}, - {file = "grpcio-1.68.0-cp312-cp312-win_amd64.whl", hash = "sha256:2bddd04a790b69f7a7385f6a112f46ea0b34c4746f361ebafe9ca0be567c78e9"}, - {file = "grpcio-1.68.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:fc05759ffbd7875e0ff2bd877be1438dfe97c9312bbc558c8284a9afa1d0f40e"}, - {file = "grpcio-1.68.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:15fa1fe25d365a13bc6d52fcac0e3ee1f9baebdde2c9b3b2425f8a4979fccea1"}, - {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:32a9cb4686eb2e89d97022ecb9e1606d132f85c444354c17a7dbde4a455e4a3b"}, - {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dba037ff8d284c8e7ea9a510c8ae0f5b016004f13c3648f72411c464b67ff2fb"}, - {file = "grpcio-1.68.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0efbbd849867e0e569af09e165363ade75cf84f5229b2698d53cf22c7a4f9e21"}, - {file = "grpcio-1.68.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:4e300e6978df0b65cc2d100c54e097c10dfc7018b9bd890bbbf08022d47f766d"}, - {file = "grpcio-1.68.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:6f9c7ad1a23e1047f827385f4713b5b8c6c7d325705be1dd3e31fb00dcb2f665"}, - {file = "grpcio-1.68.0-cp313-cp313-win32.whl", hash = "sha256:3ac7f10850fd0487fcce169c3c55509101c3bde2a3b454869639df2176b60a03"}, - {file = "grpcio-1.68.0-cp313-cp313-win_amd64.whl", hash = "sha256:afbf45a62ba85a720491bfe9b2642f8761ff348006f5ef67e4622621f116b04a"}, - {file = "grpcio-1.68.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:f8f695d9576ce836eab27ba7401c60acaf9ef6cf2f70dfe5462055ba3df02cc3"}, - {file = "grpcio-1.68.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9fe1b141cda52f2ca73e17d2d3c6a9f3f3a0c255c216b50ce616e9dca7e3441d"}, - {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:4df81d78fd1646bf94ced4fb4cd0a7fe2e91608089c522ef17bc7db26e64effd"}, - {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:46a2d74d4dd8993151c6cd585594c082abe74112c8e4175ddda4106f2ceb022f"}, - {file = "grpcio-1.68.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a17278d977746472698460c63abf333e1d806bd41f2224f90dbe9460101c9796"}, - {file = "grpcio-1.68.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:15377bce516b1c861c35e18eaa1c280692bf563264836cece693c0f169b48829"}, - {file = "grpcio-1.68.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cc5f0a4f5904b8c25729a0498886b797feb817d1fd3812554ffa39551112c161"}, - {file = "grpcio-1.68.0-cp38-cp38-win32.whl", hash = "sha256:def1a60a111d24376e4b753db39705adbe9483ef4ca4761f825639d884d5da78"}, - {file = "grpcio-1.68.0-cp38-cp38-win_amd64.whl", hash = "sha256:55d3b52fd41ec5772a953612db4e70ae741a6d6ed640c4c89a64f017a1ac02b5"}, - {file = "grpcio-1.68.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:0d230852ba97654453d290e98d6aa61cb48fa5fafb474fb4c4298d8721809354"}, - {file = "grpcio-1.68.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:50992f214264e207e07222703c17d9cfdcc2c46ed5a1ea86843d440148ebbe10"}, - {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:14331e5c27ed3545360464a139ed279aa09db088f6e9502e95ad4bfa852bb116"}, - {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f84890b205692ea813653ece4ac9afa2139eae136e419231b0eec7c39fdbe4c2"}, - {file = "grpcio-1.68.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0cf343c6f4f6aa44863e13ec9ddfe299e0be68f87d68e777328bff785897b05"}, - {file = "grpcio-1.68.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:fd2c2d47969daa0e27eadaf15c13b5e92605c5e5953d23c06d0b5239a2f176d3"}, - {file = "grpcio-1.68.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:18668e36e7f4045820f069997834e94e8275910b1f03e078a6020bd464cb2363"}, - {file = "grpcio-1.68.0-cp39-cp39-win32.whl", hash = "sha256:2af76ab7c427aaa26aa9187c3e3c42f38d3771f91a20f99657d992afada2294a"}, - {file = "grpcio-1.68.0-cp39-cp39-win_amd64.whl", hash = "sha256:e694b5928b7b33ca2d3b4d5f9bf8b5888906f181daff6b406f4938f3a997a490"}, - {file = "grpcio-1.68.0.tar.gz", hash = "sha256:7e7483d39b4a4fddb9906671e9ea21aaad4f031cdfc349fec76bdfa1e404543a"}, + {file = "grpcio-1.68.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:d35740e3f45f60f3c37b1e6f2f4702c23867b9ce21c6410254c9c682237da68d"}, + {file = "grpcio-1.68.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:d99abcd61760ebb34bdff37e5a3ba333c5cc09feda8c1ad42547bea0416ada78"}, + {file = "grpcio-1.68.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:f8261fa2a5f679abeb2a0a93ad056d765cdca1c47745eda3f2d87f874ff4b8c9"}, + {file = "grpcio-1.68.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0feb02205a27caca128627bd1df4ee7212db051019a9afa76f4bb6a1a80ca95e"}, + {file = "grpcio-1.68.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:919d7f18f63bcad3a0f81146188e90274fde800a94e35d42ffe9eadf6a9a6330"}, + {file = "grpcio-1.68.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:963cc8d7d79b12c56008aabd8b457f400952dbea8997dd185f155e2f228db079"}, + {file = "grpcio-1.68.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ccf2ebd2de2d6661e2520dae293298a3803a98ebfc099275f113ce1f6c2a80f1"}, + {file = "grpcio-1.68.1-cp310-cp310-win32.whl", hash = "sha256:2cc1fd04af8399971bcd4f43bd98c22d01029ea2e56e69c34daf2bf8470e47f5"}, + {file = "grpcio-1.68.1-cp310-cp310-win_amd64.whl", hash = "sha256:ee2e743e51cb964b4975de572aa8fb95b633f496f9fcb5e257893df3be854746"}, + {file = "grpcio-1.68.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:55857c71641064f01ff0541a1776bfe04a59db5558e82897d35a7793e525774c"}, + {file = "grpcio-1.68.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4b177f5547f1b995826ef529d2eef89cca2f830dd8b2c99ffd5fde4da734ba73"}, + {file = "grpcio-1.68.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:3522c77d7e6606d6665ec8d50e867f13f946a4e00c7df46768f1c85089eae515"}, + {file = "grpcio-1.68.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9d1fae6bbf0816415b81db1e82fb3bf56f7857273c84dcbe68cbe046e58e1ccd"}, + {file = "grpcio-1.68.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:298ee7f80e26f9483f0b6f94cc0a046caf54400a11b644713bb5b3d8eb387600"}, + {file = "grpcio-1.68.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cbb5780e2e740b6b4f2d208e90453591036ff80c02cc605fea1af8e6fc6b1bbe"}, + {file = "grpcio-1.68.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ddda1aa22495d8acd9dfbafff2866438d12faec4d024ebc2e656784d96328ad0"}, + {file = "grpcio-1.68.1-cp311-cp311-win32.whl", hash = "sha256:b33bd114fa5a83f03ec6b7b262ef9f5cac549d4126f1dc702078767b10c46ed9"}, + {file = "grpcio-1.68.1-cp311-cp311-win_amd64.whl", hash = "sha256:7f20ebec257af55694d8f993e162ddf0d36bd82d4e57f74b31c67b3c6d63d8b2"}, + {file = "grpcio-1.68.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:8829924fffb25386995a31998ccbbeaa7367223e647e0122043dfc485a87c666"}, + {file = "grpcio-1.68.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:3aed6544e4d523cd6b3119b0916cef3d15ef2da51e088211e4d1eb91a6c7f4f1"}, + {file = "grpcio-1.68.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:4efac5481c696d5cb124ff1c119a78bddbfdd13fc499e3bc0ca81e95fc573684"}, + {file = "grpcio-1.68.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ab2d912ca39c51f46baf2a0d92aa265aa96b2443266fc50d234fa88bf877d8e"}, + {file = "grpcio-1.68.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95c87ce2a97434dffe7327a4071839ab8e8bffd0054cc74cbe971fba98aedd60"}, + {file = "grpcio-1.68.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e4842e4872ae4ae0f5497bf60a0498fa778c192cc7a9e87877abd2814aca9475"}, + {file = "grpcio-1.68.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:255b1635b0ed81e9f91da4fcc8d43b7ea5520090b9a9ad9340d147066d1d3613"}, + {file = "grpcio-1.68.1-cp312-cp312-win32.whl", hash = "sha256:7dfc914cc31c906297b30463dde0b9be48e36939575eaf2a0a22a8096e69afe5"}, + {file = "grpcio-1.68.1-cp312-cp312-win_amd64.whl", hash = "sha256:a0c8ddabef9c8f41617f213e527254c41e8b96ea9d387c632af878d05db9229c"}, + {file = "grpcio-1.68.1-cp313-cp313-linux_armv7l.whl", hash = "sha256:a47faedc9ea2e7a3b6569795c040aae5895a19dde0c728a48d3c5d7995fda385"}, + {file = "grpcio-1.68.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:390eee4225a661c5cd133c09f5da1ee3c84498dc265fd292a6912b65c421c78c"}, + {file = "grpcio-1.68.1-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:66a24f3d45c33550703f0abb8b656515b0ab777970fa275693a2f6dc8e35f1c1"}, + {file = "grpcio-1.68.1-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c08079b4934b0bf0a8847f42c197b1d12cba6495a3d43febd7e99ecd1cdc8d54"}, + {file = "grpcio-1.68.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8720c25cd9ac25dd04ee02b69256d0ce35bf8a0f29e20577427355272230965a"}, + {file = "grpcio-1.68.1-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:04cfd68bf4f38f5bb959ee2361a7546916bd9a50f78617a346b3aeb2b42e2161"}, + {file = "grpcio-1.68.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c28848761a6520c5c6071d2904a18d339a796ebe6b800adc8b3f474c5ce3c3ad"}, + {file = "grpcio-1.68.1-cp313-cp313-win32.whl", hash = "sha256:77d65165fc35cff6e954e7fd4229e05ec76102d4406d4576528d3a3635fc6172"}, + {file = "grpcio-1.68.1-cp313-cp313-win_amd64.whl", hash = "sha256:a8040f85dcb9830d8bbb033ae66d272614cec6faceee88d37a88a9bd1a7a704e"}, + {file = "grpcio-1.68.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:eeb38ff04ab6e5756a2aef6ad8d94e89bb4a51ef96e20f45c44ba190fa0bcaad"}, + {file = "grpcio-1.68.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8a3869a6661ec8f81d93f4597da50336718bde9eb13267a699ac7e0a1d6d0bea"}, + {file = "grpcio-1.68.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:2c4cec6177bf325eb6faa6bd834d2ff6aa8bb3b29012cceb4937b86f8b74323c"}, + {file = "grpcio-1.68.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12941d533f3cd45d46f202e3667be8ebf6bcb3573629c7ec12c3e211d99cfccf"}, + {file = "grpcio-1.68.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80af6f1e69c5e68a2be529990684abdd31ed6622e988bf18850075c81bb1ad6e"}, + {file = "grpcio-1.68.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e8dbe3e00771bfe3d04feed8210fc6617006d06d9a2679b74605b9fed3e8362c"}, + {file = "grpcio-1.68.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:83bbf5807dc3ee94ce1de2dfe8a356e1d74101e4b9d7aa8c720cc4818a34aded"}, + {file = "grpcio-1.68.1-cp38-cp38-win32.whl", hash = "sha256:8cb620037a2fd9eeee97b4531880e439ebfcd6d7d78f2e7dcc3726428ab5ef63"}, + {file = "grpcio-1.68.1-cp38-cp38-win_amd64.whl", hash = "sha256:52fbf85aa71263380d330f4fce9f013c0798242e31ede05fcee7fbe40ccfc20d"}, + {file = "grpcio-1.68.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:cb400138e73969eb5e0535d1d06cae6a6f7a15f2cc74add320e2130b8179211a"}, + {file = "grpcio-1.68.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a1b988b40f2fd9de5c820f3a701a43339d8dcf2cb2f1ca137e2c02671cc83ac1"}, + {file = "grpcio-1.68.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:96f473cdacfdd506008a5d7579c9f6a7ff245a9ade92c3c0265eb76cc591914f"}, + {file = "grpcio-1.68.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:37ea3be171f3cf3e7b7e412a98b77685eba9d4fd67421f4a34686a63a65d99f9"}, + {file = "grpcio-1.68.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ceb56c4285754e33bb3c2fa777d055e96e6932351a3082ce3559be47f8024f0"}, + {file = "grpcio-1.68.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:dffd29a2961f3263a16d73945b57cd44a8fd0b235740cb14056f0612329b345e"}, + {file = "grpcio-1.68.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:025f790c056815b3bf53da850dd70ebb849fd755a4b1ac822cb65cd631e37d43"}, + {file = "grpcio-1.68.1-cp39-cp39-win32.whl", hash = "sha256:1098f03dedc3b9810810568060dea4ac0822b4062f537b0f53aa015269be0a76"}, + {file = "grpcio-1.68.1-cp39-cp39-win_amd64.whl", hash = "sha256:334ab917792904245a028f10e803fcd5b6f36a7b2173a820c0b5b076555825e1"}, + {file = "grpcio-1.68.1.tar.gz", hash = "sha256:44a8502dd5de653ae6a73e2de50a401d84184f0331d0ac3daeb044e66d5c5054"}, ] [package.extras] -protobuf = ["grpcio-tools (>=1.68.0)"] +protobuf = ["grpcio-tools (>=1.68.1)"] [package.source] type = "legacy" @@ -1645,13 +1647,13 @@ reference = "tencent" [[package]] name = "prometheus-client" -version = "0.21.0" +version = "0.21.1" description = "Python client for the Prometheus monitoring system." optional = false python-versions = ">=3.8" files = [ - {file = "prometheus_client-0.21.0-py3-none-any.whl", hash = "sha256:4fa6b4dd0ac16d58bb587c04b1caae65b8c5043e85f778f42f5f632f6af2e166"}, - {file = "prometheus_client-0.21.0.tar.gz", hash = "sha256:96c83c606b71ff2b0a433c98889d275f51ffec6c5e267de37c7a2b5c9aa9233e"}, + {file = "prometheus_client-0.21.1-py3-none-any.whl", hash = "sha256:594b45c410d6f4f8888940fe80b5cc2521b305a1fafe1c58609ef715a001f301"}, + {file = "prometheus_client-0.21.1.tar.gz", hash = "sha256:252505a722ac04b0456be05c05f75f45d760c2911ffc45f2a06bcaed9f3ae3fb"}, ] [package.extras] @@ -1871,13 +1873,13 @@ reference = "tencent" [[package]] name = "pyjwt" -version = "2.10.0" +version = "2.10.1" description = "JSON Web Token implementation in Python" optional = false python-versions = ">=3.9" files = [ - {file = "PyJWT-2.10.0-py3-none-any.whl", hash = "sha256:543b77207db656de204372350926bed5a86201c4cbff159f623f79c7bb487a15"}, - {file = "pyjwt-2.10.0.tar.gz", hash = "sha256:7628a7eb7938959ac1b26e819a1df0fd3259505627b575e4bad6d08f76db695c"}, + {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, + {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, ] [package.extras] @@ -1913,13 +1915,13 @@ reference = "tencent" [[package]] name = "pytest" -version = "8.3.3" +version = "8.3.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.3.3-py3-none-any.whl", hash = "sha256:a6853c7375b2663155079443d2e45de913a911a11d669df02a50814944db57b2"}, - {file = "pytest-8.3.3.tar.gz", hash = "sha256:70b98107bd648308a7952b06e6ca9a50bc660be218d53c257cc1fc94fda10181"}, + {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, + {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, ] [package.dependencies] @@ -2136,23 +2138,23 @@ reference = "tencent" [[package]] name = "setuptools" -version = "75.5.0" +version = "75.6.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.9" files = [ - {file = "setuptools-75.5.0-py3-none-any.whl", hash = "sha256:87cb777c3b96d638ca02031192d40390e0ad97737e27b6b4fa831bea86f2f829"}, - {file = "setuptools-75.5.0.tar.gz", hash = "sha256:5c4ccb41111392671f02bb5f8436dfc5a9a7185e80500531b133f5775c4163ef"}, + {file = "setuptools-75.6.0-py3-none-any.whl", hash = "sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d"}, + {file = "setuptools-75.6.0.tar.gz", hash = "sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6"}, ] [package.extras] check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1)", "ruff (>=0.7.0)"] -core = ["importlib-metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more-itertools", "more-itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] +core = ["importlib_metadata (>=6)", "jaraco.collections", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1)", "wheel (>=0.43.0)"] cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] enabler = ["pytest-enabler (>=2.2)"] test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] -type = ["importlib-metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"] +type = ["importlib_metadata (>=7.0.2)", "jaraco.develop (>=7.21)", "mypy (>=1.12,<1.14)", "pytest-mypy"] [package.source] type = "legacy" @@ -2161,13 +2163,13 @@ reference = "tencent" [[package]] name = "six" -version = "1.16.0" +version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" files = [ - {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, - {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] [package.source] @@ -2454,81 +2456,76 @@ reference = "tencent" [[package]] name = "wrapt" -version = "1.16.0" +version = "1.17.0" description = "Module for decorators, wrappers and monkey patching." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "wrapt-1.16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ffa565331890b90056c01db69c0fe634a776f8019c143a5ae265f9c6bc4bd6d4"}, - {file = "wrapt-1.16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e4fdb9275308292e880dcbeb12546df7f3e0f96c6b41197e0cf37d2826359020"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb2dee3874a500de01c93d5c71415fcaef1d858370d405824783e7a8ef5db440"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2a88e6010048489cda82b1326889ec075a8c856c2e6a256072b28eaee3ccf487"}, - {file = "wrapt-1.16.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac83a914ebaf589b69f7d0a1277602ff494e21f4c2f743313414378f8f50a4cf"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73aa7d98215d39b8455f103de64391cb79dfcad601701a3aa0dddacf74911d72"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:807cc8543a477ab7422f1120a217054f958a66ef7314f76dd9e77d3f02cdccd0"}, - {file = "wrapt-1.16.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bf5703fdeb350e36885f2875d853ce13172ae281c56e509f4e6eca049bdfb136"}, - {file = "wrapt-1.16.0-cp310-cp310-win32.whl", hash = "sha256:f6b2d0c6703c988d334f297aa5df18c45e97b0af3679bb75059e0e0bd8b1069d"}, - {file = "wrapt-1.16.0-cp310-cp310-win_amd64.whl", hash = "sha256:decbfa2f618fa8ed81c95ee18a387ff973143c656ef800c9f24fb7e9c16054e2"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1a5db485fe2de4403f13fafdc231b0dbae5eca4359232d2efc79025527375b09"}, - {file = "wrapt-1.16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:75ea7d0ee2a15733684badb16de6794894ed9c55aa5e9903260922f0482e687d"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a452f9ca3e3267cd4d0fcf2edd0d035b1934ac2bd7e0e57ac91ad6b95c0c6389"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:43aa59eadec7890d9958748db829df269f0368521ba6dc68cc172d5d03ed8060"}, - {file = "wrapt-1.16.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72554a23c78a8e7aa02abbd699d129eead8b147a23c56e08d08dfc29cfdddca1"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d2efee35b4b0a347e0d99d28e884dfd82797852d62fcd7ebdeee26f3ceb72cf3"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:6dcfcffe73710be01d90cae08c3e548d90932d37b39ef83969ae135d36ef3956"}, - {file = "wrapt-1.16.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:eb6e651000a19c96f452c85132811d25e9264d836951022d6e81df2fff38337d"}, - {file = "wrapt-1.16.0-cp311-cp311-win32.whl", hash = "sha256:66027d667efe95cc4fa945af59f92c5a02c6f5bb6012bff9e60542c74c75c362"}, - {file = "wrapt-1.16.0-cp311-cp311-win_amd64.whl", hash = "sha256:aefbc4cb0a54f91af643660a0a150ce2c090d3652cf4052a5397fb2de549cd89"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5eb404d89131ec9b4f748fa5cfb5346802e5ee8836f57d516576e61f304f3b7b"}, - {file = "wrapt-1.16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9090c9e676d5236a6948330e83cb89969f433b1943a558968f659ead07cb3b36"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94265b00870aa407bd0cbcfd536f17ecde43b94fb8d228560a1e9d3041462d73"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2058f813d4f2b5e3a9eb2eb3faf8f1d99b81c3e51aeda4b168406443e8ba809"}, - {file = "wrapt-1.16.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98b5e1f498a8ca1858a1cdbffb023bfd954da4e3fa2c0cb5853d40014557248b"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:14d7dc606219cdd7405133c713f2c218d4252f2a469003f8c46bb92d5d095d81"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:49aac49dc4782cb04f58986e81ea0b4768e4ff197b57324dcbd7699c5dfb40b9"}, - {file = "wrapt-1.16.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:418abb18146475c310d7a6dc71143d6f7adec5b004ac9ce08dc7a34e2babdc5c"}, - {file = "wrapt-1.16.0-cp312-cp312-win32.whl", hash = "sha256:685f568fa5e627e93f3b52fda002c7ed2fa1800b50ce51f6ed1d572d8ab3e7fc"}, - {file = "wrapt-1.16.0-cp312-cp312-win_amd64.whl", hash = "sha256:dcdba5c86e368442528f7060039eda390cc4091bfd1dca41e8046af7c910dda8"}, - {file = "wrapt-1.16.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d462f28826f4657968ae51d2181a074dfe03c200d6131690b7d65d55b0f360f8"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a33a747400b94b6d6b8a165e4480264a64a78c8a4c734b62136062e9a248dd39"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3646eefa23daeba62643a58aac816945cadc0afaf21800a1421eeba5f6cfb9c"}, - {file = "wrapt-1.16.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ebf019be5c09d400cf7b024aa52b1f3aeebeff51550d007e92c3c1c4afc2a40"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:0d2691979e93d06a95a26257adb7bfd0c93818e89b1406f5a28f36e0d8c1e1fc"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:1acd723ee2a8826f3d53910255643e33673e1d11db84ce5880675954183ec47e"}, - {file = "wrapt-1.16.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:bc57efac2da352a51cc4658878a68d2b1b67dbe9d33c36cb826ca449d80a8465"}, - {file = "wrapt-1.16.0-cp36-cp36m-win32.whl", hash = "sha256:da4813f751142436b075ed7aa012a8778aa43a99f7b36afe9b742d3ed8bdc95e"}, - {file = "wrapt-1.16.0-cp36-cp36m-win_amd64.whl", hash = "sha256:6f6eac2360f2d543cc875a0e5efd413b6cbd483cb3ad7ebf888884a6e0d2e966"}, - {file = "wrapt-1.16.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a0ea261ce52b5952bf669684a251a66df239ec6d441ccb59ec7afa882265d593"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bd2d7ff69a2cac767fbf7a2b206add2e9a210e57947dd7ce03e25d03d2de292"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9159485323798c8dc530a224bd3ffcf76659319ccc7bbd52e01e73bd0241a0c5"}, - {file = "wrapt-1.16.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a86373cf37cd7764f2201b76496aba58a52e76dedfaa698ef9e9688bfd9e41cf"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:73870c364c11f03ed072dda68ff7aea6d2a3a5c3fe250d917a429c7432e15228"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b935ae30c6e7400022b50f8d359c03ed233d45b725cfdd299462f41ee5ffba6f"}, - {file = "wrapt-1.16.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:db98ad84a55eb09b3c32a96c576476777e87c520a34e2519d3e59c44710c002c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win32.whl", hash = "sha256:9153ed35fc5e4fa3b2fe97bddaa7cbec0ed22412b85bcdaf54aeba92ea37428c"}, - {file = "wrapt-1.16.0-cp37-cp37m-win_amd64.whl", hash = "sha256:66dfbaa7cfa3eb707bbfcd46dab2bc6207b005cbc9caa2199bcbc81d95071a00"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1dd50a2696ff89f57bd8847647a1c363b687d3d796dc30d4dd4a9d1689a706f0"}, - {file = "wrapt-1.16.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:44a2754372e32ab315734c6c73b24351d06e77ffff6ae27d2ecf14cf3d229202"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e9723528b9f787dc59168369e42ae1c3b0d3fadb2f1a71de14531d321ee05b0"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dbed418ba5c3dce92619656802cc5355cb679e58d0d89b50f116e4a9d5a9603e"}, - {file = "wrapt-1.16.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:941988b89b4fd6b41c3f0bfb20e92bd23746579736b7343283297c4c8cbae68f"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6a42cd0cfa8ffc1915aef79cb4284f6383d8a3e9dcca70c445dcfdd639d51267"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1ca9b6085e4f866bd584fb135a041bfc32cab916e69f714a7d1d397f8c4891ca"}, - {file = "wrapt-1.16.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5e49454f19ef621089e204f862388d29e6e8d8b162efce05208913dde5b9ad6"}, - {file = "wrapt-1.16.0-cp38-cp38-win32.whl", hash = "sha256:c31f72b1b6624c9d863fc095da460802f43a7c6868c5dda140f51da24fd47d7b"}, - {file = "wrapt-1.16.0-cp38-cp38-win_amd64.whl", hash = "sha256:490b0ee15c1a55be9c1bd8609b8cecd60e325f0575fc98f50058eae366e01f41"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9b201ae332c3637a42f02d1045e1d0cccfdc41f1f2f801dafbaa7e9b4797bfc2"}, - {file = "wrapt-1.16.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2076fad65c6736184e77d7d4729b63a6d1ae0b70da4868adeec40989858eb3fb"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5cd603b575ebceca7da5a3a251e69561bec509e0b46e4993e1cac402b7247b8"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b47cfad9e9bbbed2339081f4e346c93ecd7ab504299403320bf85f7f85c7d46c"}, - {file = "wrapt-1.16.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8212564d49c50eb4565e502814f694e240c55551a5f1bc841d4fcaabb0a9b8a"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5f15814a33e42b04e3de432e573aa557f9f0f56458745c2074952f564c50e664"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:db2e408d983b0e61e238cf579c09ef7020560441906ca990fe8412153e3b291f"}, - {file = "wrapt-1.16.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edfad1d29c73f9b863ebe7082ae9321374ccb10879eeabc84ba3b69f2579d537"}, - {file = "wrapt-1.16.0-cp39-cp39-win32.whl", hash = "sha256:ed867c42c268f876097248e05b6117a65bcd1e63b779e916fe2e33cd6fd0d3c3"}, - {file = "wrapt-1.16.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb1b046be06b0fce7249f1d025cd359b4b80fc1c3e24ad9eca33e0dcdb2e4a35"}, - {file = "wrapt-1.16.0-py3-none-any.whl", hash = "sha256:6906c4100a8fcbf2fa735f6059214bb13b97f75b1a61777fcf6432121ef12ef1"}, - {file = "wrapt-1.16.0.tar.gz", hash = "sha256:5f370f952971e7d17c7d1ead40e49f32345a7f7a5373571ef44d800d06b1899d"}, + {file = "wrapt-1.17.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a0c23b8319848426f305f9cb0c98a6e32ee68a36264f45948ccf8e7d2b941f8"}, + {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b1ca5f060e205f72bec57faae5bd817a1560fcfc4af03f414b08fa29106b7e2d"}, + {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e185ec6060e301a7e5f8461c86fb3640a7beb1a0f0208ffde7a65ec4074931df"}, + {file = "wrapt-1.17.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bb90765dd91aed05b53cd7a87bd7f5c188fcd95960914bae0d32c5e7f899719d"}, + {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:879591c2b5ab0a7184258274c42a126b74a2c3d5a329df16d69f9cee07bba6ea"}, + {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fce6fee67c318fdfb7f285c29a82d84782ae2579c0e1b385b7f36c6e8074fffb"}, + {file = "wrapt-1.17.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:0698d3a86f68abc894d537887b9bbf84d29bcfbc759e23f4644be27acf6da301"}, + {file = "wrapt-1.17.0-cp310-cp310-win32.whl", hash = "sha256:69d093792dc34a9c4c8a70e4973a3361c7a7578e9cd86961b2bbf38ca71e4e22"}, + {file = "wrapt-1.17.0-cp310-cp310-win_amd64.whl", hash = "sha256:f28b29dc158ca5d6ac396c8e0a2ef45c4e97bb7e65522bfc04c989e6fe814575"}, + {file = "wrapt-1.17.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:74bf625b1b4caaa7bad51d9003f8b07a468a704e0644a700e936c357c17dd45a"}, + {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f2a28eb35cf99d5f5bd12f5dd44a0f41d206db226535b37b0c60e9da162c3ed"}, + {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81b1289e99cf4bad07c23393ab447e5e96db0ab50974a280f7954b071d41b489"}, + {file = "wrapt-1.17.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f2939cd4a2a52ca32bc0b359015718472d7f6de870760342e7ba295be9ebaf9"}, + {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6a9653131bda68a1f029c52157fd81e11f07d485df55410401f745007bd6d339"}, + {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4e4b4385363de9052dac1a67bfb535c376f3d19c238b5f36bddc95efae15e12d"}, + {file = "wrapt-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bdf62d25234290db1837875d4dceb2151e4ea7f9fff2ed41c0fde23ed542eb5b"}, + {file = "wrapt-1.17.0-cp311-cp311-win32.whl", hash = "sha256:5d8fd17635b262448ab8f99230fe4dac991af1dabdbb92f7a70a6afac8a7e346"}, + {file = "wrapt-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:92a3d214d5e53cb1db8b015f30d544bc9d3f7179a05feb8f16df713cecc2620a"}, + {file = "wrapt-1.17.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:89fc28495896097622c3fc238915c79365dd0ede02f9a82ce436b13bd0ab7569"}, + {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:875d240fdbdbe9e11f9831901fb8719da0bd4e6131f83aa9f69b96d18fae7504"}, + {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5ed16d95fd142e9c72b6c10b06514ad30e846a0d0917ab406186541fe68b451"}, + {file = "wrapt-1.17.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18b956061b8db634120b58f668592a772e87e2e78bc1f6a906cfcaa0cc7991c1"}, + {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:daba396199399ccabafbfc509037ac635a6bc18510ad1add8fd16d4739cdd106"}, + {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4d63f4d446e10ad19ed01188d6c1e1bb134cde8c18b0aa2acfd973d41fcc5ada"}, + {file = "wrapt-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8a5e7cc39a45fc430af1aefc4d77ee6bad72c5bcdb1322cfde852c15192b8bd4"}, + {file = "wrapt-1.17.0-cp312-cp312-win32.whl", hash = "sha256:0a0a1a1ec28b641f2a3a2c35cbe86c00051c04fffcfcc577ffcdd707df3f8635"}, + {file = "wrapt-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:3c34f6896a01b84bab196f7119770fd8466c8ae3dfa73c59c0bb281e7b588ce7"}, + {file = "wrapt-1.17.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:714c12485aa52efbc0fc0ade1e9ab3a70343db82627f90f2ecbc898fdf0bb181"}, + {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da427d311782324a376cacb47c1a4adc43f99fd9d996ffc1b3e8529c4074d393"}, + {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba1739fb38441a27a676f4de4123d3e858e494fac05868b7a281c0a383c098f4"}, + {file = "wrapt-1.17.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e711fc1acc7468463bc084d1b68561e40d1eaa135d8c509a65dd534403d83d7b"}, + {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:140ea00c87fafc42739bd74a94a5a9003f8e72c27c47cd4f61d8e05e6dec8721"}, + {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:73a96fd11d2b2e77d623a7f26e004cc31f131a365add1ce1ce9a19e55a1eef90"}, + {file = "wrapt-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0b48554952f0f387984da81ccfa73b62e52817a4386d070c75e4db7d43a28c4a"}, + {file = "wrapt-1.17.0-cp313-cp313-win32.whl", hash = "sha256:498fec8da10e3e62edd1e7368f4b24aa362ac0ad931e678332d1b209aec93045"}, + {file = "wrapt-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:fd136bb85f4568fffca995bd3c8d52080b1e5b225dbf1c2b17b66b4c5fa02838"}, + {file = "wrapt-1.17.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:17fcf043d0b4724858f25b8826c36e08f9fb2e475410bece0ec44a22d533da9b"}, + {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4a557d97f12813dc5e18dad9fa765ae44ddd56a672bb5de4825527c847d6379"}, + {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0229b247b0fc7dee0d36176cbb79dbaf2a9eb7ecc50ec3121f40ef443155fb1d"}, + {file = "wrapt-1.17.0-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8425cfce27b8b20c9b89d77fb50e368d8306a90bf2b6eef2cdf5cd5083adf83f"}, + {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9c900108df470060174108012de06d45f514aa4ec21a191e7ab42988ff42a86c"}, + {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4e547b447073fc0dbfcbff15154c1be8823d10dab4ad401bdb1575e3fdedff1b"}, + {file = "wrapt-1.17.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:914f66f3b6fc7b915d46c1cc424bc2441841083de01b90f9e81109c9759e43ab"}, + {file = "wrapt-1.17.0-cp313-cp313t-win32.whl", hash = "sha256:a4192b45dff127c7d69b3bdfb4d3e47b64179a0b9900b6351859f3001397dabf"}, + {file = "wrapt-1.17.0-cp313-cp313t-win_amd64.whl", hash = "sha256:4f643df3d4419ea3f856c5c3f40fec1d65ea2e89ec812c83f7767c8730f9827a"}, + {file = "wrapt-1.17.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:69c40d4655e078ede067a7095544bcec5a963566e17503e75a3a3e0fe2803b13"}, + {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f495b6754358979379f84534f8dd7a43ff8cff2558dcdea4a148a6e713a758f"}, + {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:baa7ef4e0886a6f482e00d1d5bcd37c201b383f1d314643dfb0367169f94f04c"}, + {file = "wrapt-1.17.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8fc931382e56627ec4acb01e09ce66e5c03c384ca52606111cee50d931a342d"}, + {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8f8909cdb9f1b237786c09a810e24ee5e15ef17019f7cecb207ce205b9b5fcce"}, + {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:ad47b095f0bdc5585bced35bd088cbfe4177236c7df9984b3cc46b391cc60627"}, + {file = "wrapt-1.17.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:948a9bd0fb2c5120457b07e59c8d7210cbc8703243225dbd78f4dfc13c8d2d1f"}, + {file = "wrapt-1.17.0-cp38-cp38-win32.whl", hash = "sha256:5ae271862b2142f4bc687bdbfcc942e2473a89999a54231aa1c2c676e28f29ea"}, + {file = "wrapt-1.17.0-cp38-cp38-win_amd64.whl", hash = "sha256:f335579a1b485c834849e9075191c9898e0731af45705c2ebf70e0cd5d58beed"}, + {file = "wrapt-1.17.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d751300b94e35b6016d4b1e7d0e7bbc3b5e1751e2405ef908316c2a9024008a1"}, + {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7264cbb4a18dc4acfd73b63e4bcfec9c9802614572025bdd44d0721983fc1d9c"}, + {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:33539c6f5b96cf0b1105a0ff4cf5db9332e773bb521cc804a90e58dc49b10578"}, + {file = "wrapt-1.17.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c30970bdee1cad6a8da2044febd824ef6dc4cc0b19e39af3085c763fdec7de33"}, + {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:bc7f729a72b16ee21795a943f85c6244971724819819a41ddbaeb691b2dd85ad"}, + {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:6ff02a91c4fc9b6a94e1c9c20f62ea06a7e375f42fe57587f004d1078ac86ca9"}, + {file = "wrapt-1.17.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2dfb7cff84e72e7bf975b06b4989477873dcf160b2fd89959c629535df53d4e0"}, + {file = "wrapt-1.17.0-cp39-cp39-win32.whl", hash = "sha256:2399408ac33ffd5b200480ee858baa58d77dd30e0dd0cab6a8a9547135f30a88"}, + {file = "wrapt-1.17.0-cp39-cp39-win_amd64.whl", hash = "sha256:4f763a29ee6a20c529496a20a7bcb16a73de27f5da6a843249c7047daf135977"}, + {file = "wrapt-1.17.0-py3-none-any.whl", hash = "sha256:d2c63b93548eda58abf5188e505ffed0229bf675f7c3090f8e36ad55b8cbc371"}, + {file = "wrapt-1.17.0.tar.gz", hash = "sha256:16187aa2317c731170a88ef35e8937ae0f533c402872c1ee5e6d079fcf320801"}, ] [package.source] @@ -2585,48 +2582,48 @@ reference = "tencent" [[package]] name = "zope-interface" -version = "7.1.1" +version = "7.2" description = "Interfaces for Python" optional = false python-versions = ">=3.8" files = [ - {file = "zope.interface-7.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6650bd56ef350d37c8baccfd3ee8a0483ed6f8666e641e4b9ae1a1827b79f9e5"}, - {file = "zope.interface-7.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:84e87eba6b77a3af187bae82d8de1a7c208c2a04ec9f6bd444fd091b811ad92e"}, - {file = "zope.interface-7.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c4e1b4c06d9abd1037c088dae1566c85f344a3e6ae4350744c3f7f7259d9c67"}, - {file = "zope.interface-7.1.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7cd5e3d910ac87652a09f6e5db8e41bc3b49cf08ddd2d73d30afc644801492cd"}, - {file = "zope.interface-7.1.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca95594d936ee349620900be5b46c0122a1ff6ce42d7d5cb2cf09dc84071ef16"}, - {file = "zope.interface-7.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:ad339509dcfbbc99bf8e147db6686249c4032f26586699ec4c82f6e5909c9fe2"}, - {file = "zope.interface-7.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3e59f175e868f856a77c0a77ba001385c377df2104fdbda6b9f99456a01e102a"}, - {file = "zope.interface-7.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0de23bcb93401994ea00bc5c677ef06d420340ac0a4e9c10d80e047b9ce5af3f"}, - {file = "zope.interface-7.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5cdb7e7e5524b76d3ec037c1d81a9e2c7457b240fd4cb0a2476b65c3a5a6c81f"}, - {file = "zope.interface-7.1.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3603ef82a9920bd0bfb505423cb7e937498ad971ad5a6141841e8f76d2fd5446"}, - {file = "zope.interface-7.1.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f1d52d052355e0c5c89e0630dd2ff7c0b823fd5f56286a663e92444761b35e25"}, - {file = "zope.interface-7.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:179ad46ece518c9084cb272e4a69d266b659f7f8f48e51706746c2d8a426433e"}, - {file = "zope.interface-7.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e6503534b52bb1720ace9366ee30838a58a3413d3e197512f3338c8f34b5d89d"}, - {file = "zope.interface-7.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f85b290e5b8b11814efb0d004d8ce6c9a483c35c462e8d9bf84abb93e79fa770"}, - {file = "zope.interface-7.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d029fac6a80edae80f79c37e5e3abfa92968fe921886139b3ee470a1b177321a"}, - {file = "zope.interface-7.1.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5836b8fb044c6e75ba34dfaabc602493019eadfa0faf6ff25f4c4c356a71a853"}, - {file = "zope.interface-7.1.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7395f13533318f150ee72adb55b29284b16e73b6d5f02ab21f173b3e83f242b8"}, - {file = "zope.interface-7.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:1d0e23c6b746eb8ce04573cc47bcac60961ac138885d207bd6f57e27a1431ae8"}, - {file = "zope.interface-7.1.1-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:9fad9bd5502221ab179f13ea251cb30eef7cf65023156967f86673aff54b53a0"}, - {file = "zope.interface-7.1.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:55c373becbd36a44d0c9be1d5271422fdaa8562d158fb44b4192297b3c67096c"}, - {file = "zope.interface-7.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed1df8cc01dd1e3970666a7370b8bfc7457371c58ba88c57bd5bca17ab198053"}, - {file = "zope.interface-7.1.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99c14f0727c978639139e6cad7a60e82b7720922678d75aacb90cf4ef74a068c"}, - {file = "zope.interface-7.1.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b1eed7670d564f1025d7cda89f99f216c30210e42e95de466135be0b4a499d9"}, - {file = "zope.interface-7.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:3defc925c4b22ac1272d544a49c6ba04c3eefcce3200319ee1be03d9270306dd"}, - {file = "zope.interface-7.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8d0fe45be57b5219aa4b96e846631c04615d5ef068146de5a02ccd15c185321f"}, - {file = "zope.interface-7.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bcbeb44fc16e0078b3b68a95e43f821ae34dcbf976dde6985141838a5f23dd3d"}, - {file = "zope.interface-7.1.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8e7b05dc6315a193cceaec071cc3cf1c180cea28808ccded0b1283f1c38ba73"}, - {file = "zope.interface-7.1.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d553e02b68c0ea5a226855f02edbc9eefd99f6a8886fa9f9bdf999d77f46585"}, - {file = "zope.interface-7.1.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81744a7e61b598ebcf4722ac56a7a4f50502432b5b4dc7eb29075a89cf82d029"}, - {file = "zope.interface-7.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:7720322763aceb5e0a7cadcc38c67b839efe599f0887cbf6c003c55b1458c501"}, - {file = "zope.interface-7.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1a2ed0852c25950cf430067f058f8d98df6288502ac313861d9803fe7691a9b3"}, - {file = "zope.interface-7.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9595e478047ce752b35cfa221d7601a5283ccdaab40422e0dc1d4a334c70f580"}, - {file = "zope.interface-7.1.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2317e1d4dba68203a5227ea3057f9078ec9376275f9700086b8f0ffc0b358e1b"}, - {file = "zope.interface-7.1.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6821ef9870f32154da873fcde439274f99814ea452dd16b99fa0b66345c4b6b"}, - {file = "zope.interface-7.1.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:190eeec67e023d5aac54d183fa145db0b898664234234ac54643a441da434616"}, - {file = "zope.interface-7.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:d17e7fc814eaab93409b80819fd6d30342844345c27f3bc3c4b43c2425a8d267"}, - {file = "zope.interface-7.1.1.tar.gz", hash = "sha256:4284d664ef0ff7b709836d4de7b13d80873dc5faeffc073abdb280058bfac5e3"}, + {file = "zope.interface-7.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ce290e62229964715f1011c3dbeab7a4a1e4971fd6f31324c4519464473ef9f2"}, + {file = "zope.interface-7.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:05b910a5afe03256b58ab2ba6288960a2892dfeef01336dc4be6f1b9ed02ab0a"}, + {file = "zope.interface-7.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:550f1c6588ecc368c9ce13c44a49b8d6b6f3ca7588873c679bd8fd88a1b557b6"}, + {file = "zope.interface-7.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0ef9e2f865721553c6f22a9ff97da0f0216c074bd02b25cf0d3af60ea4d6931d"}, + {file = "zope.interface-7.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27f926f0dcb058211a3bb3e0e501c69759613b17a553788b2caeb991bed3b61d"}, + {file = "zope.interface-7.2-cp310-cp310-win_amd64.whl", hash = "sha256:144964649eba4c5e4410bb0ee290d338e78f179cdbfd15813de1a664e7649b3b"}, + {file = "zope.interface-7.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:1909f52a00c8c3dcab6c4fad5d13de2285a4b3c7be063b239b8dc15ddfb73bd2"}, + {file = "zope.interface-7.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:80ecf2451596f19fd607bb09953f426588fc1e79e93f5968ecf3367550396b22"}, + {file = "zope.interface-7.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:033b3923b63474800b04cba480b70f6e6243a62208071fc148354f3f89cc01b7"}, + {file = "zope.interface-7.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a102424e28c6b47c67923a1f337ede4a4c2bba3965b01cf707978a801fc7442c"}, + {file = "zope.interface-7.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:25e6a61dcb184453bb00eafa733169ab6d903e46f5c2ace4ad275386f9ab327a"}, + {file = "zope.interface-7.2-cp311-cp311-win_amd64.whl", hash = "sha256:3f6771d1647b1fc543d37640b45c06b34832a943c80d1db214a37c31161a93f1"}, + {file = "zope.interface-7.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:086ee2f51eaef1e4a52bd7d3111a0404081dadae87f84c0ad4ce2649d4f708b7"}, + {file = "zope.interface-7.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:21328fcc9d5b80768bf051faa35ab98fb979080c18e6f84ab3f27ce703bce465"}, + {file = "zope.interface-7.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6dd02ec01f4468da0f234da9d9c8545c5412fef80bc590cc51d8dd084138a89"}, + {file = "zope.interface-7.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e7da17f53e25d1a3bde5da4601e026adc9e8071f9f6f936d0fe3fe84ace6d54"}, + {file = "zope.interface-7.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cab15ff4832580aa440dc9790b8a6128abd0b88b7ee4dd56abacbc52f212209d"}, + {file = "zope.interface-7.2-cp312-cp312-win_amd64.whl", hash = "sha256:29caad142a2355ce7cfea48725aa8bcf0067e2b5cc63fcf5cd9f97ad12d6afb5"}, + {file = "zope.interface-7.2-cp313-cp313-macosx_10_9_x86_64.whl", hash = "sha256:3e0350b51e88658d5ad126c6a57502b19d5f559f6cb0a628e3dc90442b53dd98"}, + {file = "zope.interface-7.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:15398c000c094b8855d7d74f4fdc9e73aa02d4d0d5c775acdef98cdb1119768d"}, + {file = "zope.interface-7.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:802176a9f99bd8cc276dcd3b8512808716492f6f557c11196d42e26c01a69a4c"}, + {file = "zope.interface-7.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb23f58a446a7f09db85eda09521a498e109f137b85fb278edb2e34841055398"}, + {file = "zope.interface-7.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a71a5b541078d0ebe373a81a3b7e71432c61d12e660f1d67896ca62d9628045b"}, + {file = "zope.interface-7.2-cp313-cp313-win_amd64.whl", hash = "sha256:4893395d5dd2ba655c38ceb13014fd65667740f09fa5bb01caa1e6284e48c0cd"}, + {file = "zope.interface-7.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d3a8ffec2a50d8ec470143ea3d15c0c52d73df882eef92de7537e8ce13475e8a"}, + {file = "zope.interface-7.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:31d06db13a30303c08d61d5fb32154be51dfcbdb8438d2374ae27b4e069aac40"}, + {file = "zope.interface-7.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e204937f67b28d2dca73ca936d3039a144a081fc47a07598d44854ea2a106239"}, + {file = "zope.interface-7.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:224b7b0314f919e751f2bca17d15aad00ddbb1eadf1cb0190fa8175edb7ede62"}, + {file = "zope.interface-7.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baf95683cde5bc7d0e12d8e7588a3eb754d7c4fa714548adcd96bdf90169f021"}, + {file = "zope.interface-7.2-cp38-cp38-win_amd64.whl", hash = "sha256:7dc5016e0133c1a1ec212fc87a4f7e7e562054549a99c73c8896fa3a9e80cbc7"}, + {file = "zope.interface-7.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7bd449c306ba006c65799ea7912adbbfed071089461a19091a228998b82b1fdb"}, + {file = "zope.interface-7.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a19a6cc9c6ce4b1e7e3d319a473cf0ee989cbbe2b39201d7c19e214d2dfb80c7"}, + {file = "zope.interface-7.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72cd1790b48c16db85d51fbbd12d20949d7339ad84fd971427cf00d990c1f137"}, + {file = "zope.interface-7.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:52e446f9955195440e787596dccd1411f543743c359eeb26e9b2c02b077b0519"}, + {file = "zope.interface-7.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ad9913fd858274db8dd867012ebe544ef18d218f6f7d1e3c3e6d98000f14b75"}, + {file = "zope.interface-7.2-cp39-cp39-win_amd64.whl", hash = "sha256:1090c60116b3da3bfdd0c03406e2f14a1ff53e5771aebe33fec1edc0a350175d"}, + {file = "zope.interface-7.2.tar.gz", hash = "sha256:8b49f1a3d1ee4cdaf5b32d2e738362c7f5e40ac8b46dd7d1a65e82a4872728fe"}, ] [package.dependencies] @@ -2645,4 +2642,4 @@ reference = "tencent" [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.12" -content-hash = "d6eb47c333f2c0657689969177af19d1958a2fd50ee645507e30cff145ee32fd" +content-hash = "936a2062a7f9fc4491af10ac52bdf50dfbb99aceb82fe5c130266ba495dd8e22" diff --git a/src/bk-login/pyproject.toml b/src/bk-login/pyproject.toml index 66aaf510e..d1989c7ea 100644 --- a/src/bk-login/pyproject.toml +++ b/src/bk-login/pyproject.toml @@ -38,6 +38,7 @@ opentelemetry-instrumentation-requests = "0.46b0" opentelemetry-instrumentation-celery = "0.46b0" opentelemetry-instrumentation-logging = "0.46b0" bk-notice-sdk = "1.3.2" +pyjwt = {version = "2.10.1", extras = ["cryptography"]} [tool.poetry.group.dev.dependencies] ruff = "^0.7.1" @@ -117,6 +118,9 @@ ignore = [ "B904" ] +[tool.ruff.lint.per-file-ignores] +"**/tests/**.py" = ["PLR2004"] + [tool.ruff.lint.mccabe] # Unlike Flake8, default to a complexity level of 10. max-complexity = 10 diff --git a/src/bk-login/requirements.txt b/src/bk-login/requirements.txt index 811cd8bc9..c856fb137 100644 --- a/src/bk-login/requirements.txt +++ b/src/bk-login/requirements.txt @@ -12,7 +12,7 @@ charset-normalizer==3.4.0 ; python_version >= "3.11" and python_version < "3.12" click==8.1.7 ; python_version >= "3.11" and python_version < "3.12" colorama==0.4.6 ; python_version >= "3.11" and python_version < "3.12" and platform_system == "Windows" concurrent-log-handler==0.9.25 ; python_version >= "3.11" and python_version < "3.12" -cryptography==43.0.3 ; python_version >= "3.11" and python_version < "3.12" +cryptography==44.0.0 ; python_version >= "3.11" and python_version < "3.12" curlify==2.2.1 ; python_version >= "3.11" and python_version < "3.12" dacite==1.8.1 ; python_version >= "3.11" and python_version < "3.12" deprecated==1.2.15 ; python_version >= "3.11" and python_version < "3.12" @@ -23,7 +23,7 @@ django==4.2.16 ; python_version >= "3.11" and python_version < "3.12" gevent==24.11.1 ; python_version >= "3.11" and python_version < "3.12" googleapis-common-protos==1.66.0 ; python_version >= "3.11" and python_version < "3.12" greenlet==3.1.1 ; python_version >= "3.11" and python_version < "3.12" and platform_python_implementation == "CPython" -grpcio==1.68.0 ; python_version >= "3.11" and python_version < "3.12" +grpcio==1.68.1 ; python_version >= "3.11" and python_version < "3.12" gunicorn==23.0.0 ; python_version >= "3.11" and python_version < "3.12" idna==3.10 ; python_version >= "3.11" and python_version < "3.12" importlib-metadata==7.1.0 ; python_version >= "3.11" and python_version < "3.12" @@ -47,21 +47,22 @@ opentelemetry-semantic-conventions==0.46b0 ; python_version >= "3.11" and python opentelemetry-util-http==0.46b0 ; python_version >= "3.11" and python_version < "3.12" packaging==24.2 ; python_version >= "3.11" and python_version < "3.12" portalocker==3.0.0 ; python_version >= "3.11" and python_version < "3.12" -prometheus-client==0.21.0 ; python_version >= "3.11" and python_version < "3.12" +prometheus-client==0.21.1 ; python_version >= "3.11" and python_version < "3.12" protobuf==4.25.5 ; python_version >= "3.11" and python_version < "3.12" pycparser==2.22 ; python_version >= "3.11" and python_version < "3.12" pycryptodomex==3.21.0 ; python_version >= "3.11" and python_version < "3.12" pydantic-core==2.16.3 ; python_version >= "3.11" and python_version < "3.12" pydantic==2.6.4 ; python_version >= "3.11" and python_version < "3.12" -pyjwt==2.10.0 ; python_version >= "3.11" and python_version < "3.12" +pyjwt==2.10.1 ; python_version >= "3.11" and python_version < "3.12" +pyjwt[cryptography]==2.10.1 ; python_version >= "3.11" and python_version < "3.12" pymysql==1.1.1 ; python_version >= "3.11" and python_version < "3.12" python-editor==1.0.4 ; python_version >= "3.11" and python_version < "3.12" python-json-logger==2.0.7 ; python_version >= "3.11" and python_version < "3.12" pywin32==308 ; python_version >= "3.11" and python_version < "3.12" and platform_system == "Windows" requests==2.32.3 ; python_version >= "3.11" and python_version < "3.12" sentry-sdk==1.45.0 ; python_version >= "3.11" and python_version < "3.12" -setuptools==75.5.0 ; python_version >= "3.11" and python_version < "3.12" -six==1.16.0 ; python_version >= "3.11" and python_version < "3.12" +setuptools==75.6.0 ; python_version >= "3.11" and python_version < "3.12" +six==1.17.0 ; python_version >= "3.11" and python_version < "3.12" sqlparse==0.5.2 ; python_version >= "3.11" and python_version < "3.12" toml==0.10.2 ; python_version >= "3.11" and python_version < "3.12" tongsuopy-crayon==1.0.2b6 ; python_version >= "3.11" and python_version < "3.12" @@ -71,7 +72,7 @@ urllib3==1.26.20 ; python_version >= "3.11" and python_version < "3.12" watchdog==6.0.0 ; python_version >= "3.11" and python_version < "3.12" werkzeug==3.0.6 ; python_version >= "3.11" and python_version < "3.12" whitenoise==6.8.2 ; python_version >= "3.11" and python_version < "3.12" -wrapt==1.16.0 ; python_version >= "3.11" and python_version < "3.12" +wrapt==1.17.0 ; python_version >= "3.11" and python_version < "3.12" zipp==3.21.0 ; python_version >= "3.11" and python_version < "3.12" zope-event==5.0 ; python_version >= "3.11" and python_version < "3.12" -zope-interface==7.1.1 ; python_version >= "3.11" and python_version < "3.12" +zope-interface==7.2 ; python_version >= "3.11" and python_version < "3.12" diff --git a/src/bk-login/requirements_dev.txt b/src/bk-login/requirements_dev.txt index fce91575c..793522b76 100644 --- a/src/bk-login/requirements_dev.txt +++ b/src/bk-login/requirements_dev.txt @@ -12,7 +12,7 @@ charset-normalizer==3.4.0 ; python_version >= "3.11" and python_version < "3.12" click==8.1.7 ; python_version >= "3.11" and python_version < "3.12" colorama==0.4.6 ; python_version >= "3.11" and python_version < "3.12" and (sys_platform == "win32" or platform_system == "Windows") concurrent-log-handler==0.9.25 ; python_version >= "3.11" and python_version < "3.12" -cryptography==43.0.3 ; python_version >= "3.11" and python_version < "3.12" +cryptography==44.0.0 ; python_version >= "3.11" and python_version < "3.12" curlify==2.2.1 ; python_version >= "3.11" and python_version < "3.12" dacite==1.8.1 ; python_version >= "3.11" and python_version < "3.12" deprecated==1.2.15 ; python_version >= "3.11" and python_version < "3.12" @@ -24,7 +24,7 @@ gevent==24.11.1 ; python_version >= "3.11" and python_version < "3.12" googleapis-common-protos==1.66.0 ; python_version >= "3.11" and python_version < "3.12" greenlet==3.1.1 ; python_version >= "3.11" and python_version < "3.12" and platform_python_implementation == "CPython" grimp==3.5 ; python_version >= "3.11" and python_version < "3.12" -grpcio==1.68.0 ; python_version >= "3.11" and python_version < "3.12" +grpcio==1.68.1 ; python_version >= "3.11" and python_version < "3.12" gunicorn==23.0.0 ; python_version >= "3.11" and python_version < "3.12" idna==3.10 ; python_version >= "3.11" and python_version < "3.12" import-linter==2.1 ; python_version >= "3.11" and python_version < "3.12" @@ -53,24 +53,25 @@ opentelemetry-util-http==0.46b0 ; python_version >= "3.11" and python_version < packaging==24.2 ; python_version >= "3.11" and python_version < "3.12" pluggy==1.5.0 ; python_version >= "3.11" and python_version < "3.12" portalocker==3.0.0 ; python_version >= "3.11" and python_version < "3.12" -prometheus-client==0.21.0 ; python_version >= "3.11" and python_version < "3.12" +prometheus-client==0.21.1 ; python_version >= "3.11" and python_version < "3.12" protobuf==4.25.5 ; python_version >= "3.11" and python_version < "3.12" pycparser==2.22 ; python_version >= "3.11" and python_version < "3.12" pycryptodomex==3.21.0 ; python_version >= "3.11" and python_version < "3.12" pydantic-core==2.16.3 ; python_version >= "3.11" and python_version < "3.12" pydantic==2.6.4 ; python_version >= "3.11" and python_version < "3.12" -pyjwt==2.10.0 ; python_version >= "3.11" and python_version < "3.12" +pyjwt==2.10.1 ; python_version >= "3.11" and python_version < "3.12" +pyjwt[cryptography]==2.10.1 ; python_version >= "3.11" and python_version < "3.12" pymysql==1.1.1 ; python_version >= "3.11" and python_version < "3.12" pytest-django==4.9.0 ; python_version >= "3.11" and python_version < "3.12" -pytest==8.3.3 ; python_version >= "3.11" and python_version < "3.12" +pytest==8.3.4 ; python_version >= "3.11" and python_version < "3.12" python-editor==1.0.4 ; python_version >= "3.11" and python_version < "3.12" python-json-logger==2.0.7 ; python_version >= "3.11" and python_version < "3.12" pywin32==308 ; python_version >= "3.11" and python_version < "3.12" and platform_system == "Windows" requests==2.32.3 ; python_version >= "3.11" and python_version < "3.12" ruff==0.7.4 ; python_version >= "3.11" and python_version < "3.12" sentry-sdk==1.45.0 ; python_version >= "3.11" and python_version < "3.12" -setuptools==75.5.0 ; python_version >= "3.11" and python_version < "3.12" -six==1.16.0 ; python_version >= "3.11" and python_version < "3.12" +setuptools==75.6.0 ; python_version >= "3.11" and python_version < "3.12" +six==1.17.0 ; python_version >= "3.11" and python_version < "3.12" sqlparse==0.5.2 ; python_version >= "3.11" and python_version < "3.12" toml==0.10.2 ; python_version >= "3.11" and python_version < "3.12" tongsuopy-crayon==1.0.2b6 ; python_version >= "3.11" and python_version < "3.12" @@ -83,7 +84,7 @@ urllib3==1.26.20 ; python_version >= "3.11" and python_version < "3.12" watchdog==6.0.0 ; python_version >= "3.11" and python_version < "3.12" werkzeug==3.0.6 ; python_version >= "3.11" and python_version < "3.12" whitenoise==6.8.2 ; python_version >= "3.11" and python_version < "3.12" -wrapt==1.16.0 ; python_version >= "3.11" and python_version < "3.12" +wrapt==1.17.0 ; python_version >= "3.11" and python_version < "3.12" zipp==3.21.0 ; python_version >= "3.11" and python_version < "3.12" zope-event==5.0 ; python_version >= "3.11" and python_version < "3.12" -zope-interface==7.1.1 ; python_version >= "3.11" and python_version < "3.12" +zope-interface==7.2 ; python_version >= "3.11" and python_version < "3.12" diff --git a/src/bk-login/tests/open_apis/__init__.py b/src/bk-login/tests/open_apis/__init__.py new file mode 100644 index 000000000..95b0be489 --- /dev/null +++ b/src/bk-login/tests/open_apis/__init__.py @@ -0,0 +1,16 @@ +# -*- coding: utf-8 -*- +# TencentBlueKing is pleased to support the open source community by making +# 蓝鲸智云 - 用户管理 (bk-user) available. +# Copyright (C) 2017 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. +# +# We undertake not to change the open source license (MIT license) applicable +# to the current version of the project delivered to anyone in the future. diff --git a/src/bk-login/tests/open_apis/conftest.py b/src/bk-login/tests/open_apis/conftest.py new file mode 100644 index 000000000..aa086a6f3 --- /dev/null +++ b/src/bk-login/tests/open_apis/conftest.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- +# TencentBlueKing is pleased to support the open source community by making +# 蓝鲸智云 - 用户管理 (bk-user) available. +# Copyright (C) 2017 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. +# +# We undertake not to change the open source license (MIT license) applicable +# to the current version of the project delivered to anyone in the future. +from unittest import mock + +import pytest +from django.test import Client + + +@pytest.fixture +def open_api_client() -> Client: + client = Client() + + with mock.patch("bklogin.open_apis.mixins.APIGatewayAppVerifiedMixin.skip_app_verified", return_value=True): + yield client diff --git a/src/bk-login/tests/open_apis/test_bk_token.py b/src/bk-login/tests/open_apis/test_bk_token.py new file mode 100644 index 000000000..f228449a7 --- /dev/null +++ b/src/bk-login/tests/open_apis/test_bk_token.py @@ -0,0 +1,82 @@ +# -*- coding: utf-8 -*- +# TencentBlueKing is pleased to support the open source community by making +# 蓝鲸智云 - 用户管理 (bk-user) available. +# Copyright (C) 2017 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. +# +# We undertake not to change the open source license (MIT license) applicable +# to the current version of the project delivered to anyone in the future. +from unittest import mock + +import pytest +from bklogin.authentication.manager import BkTokenManager +from bklogin.component.bk_user.models import TenantUserDetailInfo +from django.urls import reverse + +pytestmark = pytest.mark.django_db + + +@pytest.fixture +def bk_token() -> str: + bk_token, _ = BkTokenManager().generate("test_username") + + return bk_token + + +class TestTokenIntrospect: + @pytest.fixture(autouse=True) + def _mock_bk_user_component(self): + with mock.patch( + "bklogin.component.bk_user.api.get_tenant_user", + return_value=TenantUserDetailInfo( + id="test_username", + username="test_username", + full_name="test_fullname", + display_name="test_display_name", + tenant_id="test_tenant_id", + language="zh-CN", + time_zone="Asia/Shanghai", + ), + ): + yield + + def test_standard(self, open_api_client, bk_token): + resp = open_api_client.get(reverse("v3_open.bk_token.verify"), data={"bk_token": bk_token}) + + assert resp.status_code == 200 + + data = resp.json()["data"] + assert data["bk_username"] == "test_username" + assert data["tenant_id"] == "test_tenant_id" + + def test_invalid(self, open_api_client, bk_token): + resp = open_api_client.get(reverse("v3_open.bk_token.verify"), data={"bk_token": f"invalid_{bk_token}"}) + + assert resp.status_code == 400 + + def test_userinfo_standard(self, open_api_client, bk_token): + resp = open_api_client.get(reverse("v3_open.bk_token.userinfo_retrieve"), data={"bk_token": bk_token}) + + assert resp.status_code == 200 + + data = resp.json()["data"] + assert data["bk_username"] == "test_username" + assert data["tenant_id"] == "test_tenant_id" + assert data["display_name"] == "test_display_name" + assert data["language"] == "zh-CN" + assert data["time_zone"] == "Asia/Shanghai" + + def test_userinfo_invalid(self, open_api_client, bk_token): + resp = open_api_client.get( + reverse("v3_open.bk_token.userinfo_retrieve"), data={"bk_token": f"invalid_{bk_token}"} + ) + + assert resp.status_code == 400 diff --git a/src/bk-user/bkuser/auth/backends.py b/src/bk-user/bkuser/auth/backends.py index 0fda27e19..a95ca4289 100644 --- a/src/bk-user/bkuser/auth/backends.py +++ b/src/bk-user/bkuser/auth/backends.py @@ -29,12 +29,12 @@ class TokenBackend(BaseBackend): def authenticate(self, request=None, bk_token=None): logger.debug("Enter in TokenBackend") - # 判断是否传入验证所需的bk_token,没传入则返回None + # 判断是否传入验证所需的 bk_token,没传入则返回 None if not bk_token: return None verify_result, username = self.verify_bk_token(bk_token) - # 判断bk_token是否验证通过,不通过则返回None + # 判断 bk_token 是否验证通过,不通过则返回 None if not verify_result: return None @@ -43,7 +43,7 @@ def authenticate(self, request=None, bk_token=None): try: user, _ = user_model.objects.get_or_create(username=username) get_user_info_result, user_info = self.get_user_info(bk_token) - # 判断是否获取到用户信息,获取不到则返回None + # 判断是否获取到用户信息,获取不到则返回 None if not get_user_info_result: return None user.set_property(key="language", value=user_info.get("language", "")) @@ -65,7 +65,7 @@ def authenticate(self, request=None, bk_token=None): @staticmethod def get_user_info(bk_token): """ - 请求平台ESB接口获取用户信息 + 请求平台 ESB 接口获取用户信息 @param bk_token: bk_token @type bk_token: str @return:True, { @@ -93,7 +93,7 @@ def get_user_info(bk_token): @staticmethod def verify_bk_token(bk_token): """ - 请求VERIFY_URL,认证bk_token是否正确 + 请求 VERIFY_URL,认证 bk_token 是否正确 @param bk_token: "_FrcQiMNevOD05f8AY0tCynWmubZbWz86HslzmOqnhk" @type bk_token: str @return: False,None True,username diff --git a/src/bk-user/bkuser/component/login.py b/src/bk-user/bkuser/component/login.py index d7140724f..9457851f6 100644 --- a/src/bk-user/bkuser/component/login.py +++ b/src/bk-user/bkuser/component/login.py @@ -28,7 +28,7 @@ logger = logging.getLogger("component") -# FIXME: 后续登录OpenAPI接入APIGateway需重新调整 +# FIXME: 后续登录 OpenAPI 接入 APIGateway 需重新调整 def _call_login_api(http_func, url_path, **kwargs): request_id = local.request_id @@ -59,31 +59,12 @@ def _call_login_api(http_func, url_path, **kwargs): f"error={resp_data['error']}" ) - code = resp_data.get("bk_error_code", -1) - message = resp_data.get("bk_error_msg", "unknown") - if code == 0: - return resp_data["data"] - - logger.error( - "login api error! %s %s, kwargs: %s, request_id: %s, code: %s, message: %s", - http_func.__name__, - url, - kwargs, - request_id, - code, - message, - ) - - raise error_codes.REMOTE_REQUEST_ERROR.format( - f"request login error! " - f"Request=[{http_func.__name__} {urlparse(url).path} request_id={request_id}] " - f"Response[code={code}, message={message}]" - ) + return resp_data["data"] def verify_bk_token(bk_token: str): - """验证bk_token""" - url_path = "/api/v2/is_login/" + """验证 bk_token""" + url_path = "api/v3/bkuser/bk-tokens/verify/" return _call_login_api(http_get, url_path, params={"bk_token": bk_token}) @@ -91,5 +72,5 @@ def get_user_info(bk_token: str): """ 获取用户信息 """ - url_path = "/api/v2/get_user/" + url_path = "api/v3/bkuser/bk-tokens/userinfo/" return _call_login_api(http_get, url_path, params={"bk_token": bk_token})