新增活跃会话管理与通行密钥、钱包登录
CI / test (push) Successful in 55s

This commit is contained in:
2026-07-30 12:23:05 +08:00
parent f1914880ac
commit 109c345e5e
49 changed files with 6468 additions and 336 deletions
+611 -7
View File
@@ -1044,11 +1044,23 @@ const docTemplate = `{
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"403": {
"description": "密码登录已禁用",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"428": {
"description": "需要两步验证码(totpRequired=true)",
"schema": {
"$ref": "#/definitions/internal_api.totpRequiredResponse"
}
},
"429": {
"description": "登录守卫锁定(无 code);全局 IP 限流时 code=RateLimited",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
@@ -1079,7 +1091,7 @@ const docTemplate = `{
"summary": "外部登录 provider 列表",
"responses": {
"200": {
"description": "providerspasswordLoginDisabled",
"description": "providerspasswordLoginDisabled 与 passkeyLogin",
"schema": {
"$ref": "#/definitions/internal_api.oauthProvidersResponse"
}
@@ -1114,6 +1126,24 @@ const docTemplate = `{
"schema": {
"$ref": "#/definitions/internal_api.urlResponse"
}
},
"401": {
"description": "bind 模式未携带有效 Bearer",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"404": {
"description": "未知 provider",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"409": {
"description": "provider 未配置 / 面板地址缺失 / 已禁用",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
@@ -1154,6 +1184,201 @@ const docTemplate = `{
}
}
},
"/api/v1/auth/passkey/login/begin": {
"post": {
"tags": [
"认证"
],
"summary": "发起通行密钥登录",
"responses": {
"200": {
"description": "sessionId 与 WebAuthn options",
"schema": {
"$ref": "#/definitions/internal_api.passkeyOptionsResponse"
}
},
"409": {
"description": "面板地址未设置",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
},
"/api/v1/auth/passkey/login/finish": {
"post": {
"tags": [
"认证"
],
"summary": "完成通行密钥登录",
"parameters": [
{
"description": "sessionId 与断言响应(name 忽略)",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_api.passkeyFinishRequest"
}
}
],
"responses": {
"200": {
"description": "token 与 expiresAt",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"400": {
"description": "请求体非法",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"401": {
"description": "校验失败",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"429": {
"description": "连续失败已锁定",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
},
"/api/v1/auth/passkey/register/begin": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"tags": [
"认证"
],
"summary": "发起通行密钥注册",
"responses": {
"200": {
"description": "sessionId 与 WebAuthn options",
"schema": {
"$ref": "#/definitions/internal_api.passkeyOptionsResponse"
}
},
"409": {
"description": "面板地址未设置或数量达上限",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
},
"/api/v1/auth/passkey/register/finish": {
"post": {
"security": [
{
"BearerAuth": []
}
],
"tags": [
"认证"
],
"summary": "完成通行密钥注册",
"parameters": [
{
"description": "sessionId、名称与凭据响应",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_api.passkeyFinishRequest"
}
}
],
"responses": {
"200": {
"description": "已注册,返回换发的新 token",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已注册但新 token 签发失败,需重新登录"
},
"400": {
"description": "请求体非法、会话过期或凭据校验失败",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
},
"/api/v1/auth/passkeys": {
"get": {
"security": [
{
"BearerAuth": []
}
],
"tags": [
"认证"
],
"summary": "通行密钥列表",
"responses": {
"200": {
"description": "items",
"schema": {
"$ref": "#/definitions/internal_api.itemsResponse-oci-portal_internal_model_UserPasskey"
}
}
}
}
},
"/api/v1/auth/passkeys/{id}": {
"delete": {
"security": [
{
"BearerAuth": []
}
],
"tags": [
"认证"
],
"summary": "删除通行密钥",
"parameters": [
{
"type": "integer",
"description": "凭据 ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "已删除,返回换发的新 token",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已删除但新 token 签发失败,需重新登录"
},
"409": {
"description": "密码登录已禁用且这是最后一个免密登录方式",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
},
"/api/v1/auth/password-login": {
"put": {
"security": [
@@ -1216,6 +1441,72 @@ const docTemplate = `{
}
}
},
"/api/v1/auth/sessions": {
"get": {
"security": [
{
"BearerAuth": []
}
],
"tags": [
"认证"
],
"summary": "活跃会话列表",
"responses": {
"200": {
"description": "items",
"schema": {
"$ref": "#/definitions/internal_api.itemsResponse-oci-portal_internal_service_SessionInfo"
}
}
}
}
},
"/api/v1/auth/sessions/{id}": {
"delete": {
"security": [
{
"BearerAuth": []
}
],
"tags": [
"认证"
],
"summary": "撤销单个会话",
"parameters": [
{
"type": "integer",
"description": "会话 ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"description": "已撤销"
},
"400": {
"description": "id 非法",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"404": {
"description": "会话不存在",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"409": {
"description": "不能撤销当前会话",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
},
"/api/v1/auth/totp": {
"get": {
"security": [
@@ -1266,8 +1557,11 @@ const docTemplate = `{
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已启用但新 token 签发失败,需重新登录"
"401": {
"description": "请求处理期间会话已撤销",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
@@ -1301,8 +1595,11 @@ const docTemplate = `{
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已停用但新 token 签发失败,需重新登录"
"401": {
"description": "请求处理期间会话已撤销",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
@@ -1334,6 +1631,108 @@ const docTemplate = `{
}
}
},
"/api/v1/auth/wallet/challenge": {
"post": {
"tags": [
"认证"
],
"summary": "发起钱包签名挑战",
"parameters": [
{
"description": "钱包地址与模式(bind 需 Bearer)",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_api.walletChallengeRequest"
}
}
],
"responses": {
"200": {
"description": "nonce 与待签名消息",
"schema": {
"$ref": "#/definitions/internal_api.walletChallengeResponse"
}
},
"400": {
"description": "地址格式不正确",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"401": {
"description": "bind 模式未登录",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"409": {
"description": "面板地址未设置",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
},
"/api/v1/auth/wallet/verify": {
"post": {
"tags": [
"认证"
],
"summary": "校验钱包签名",
"parameters": [
{
"description": "nonce 与签名",
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/internal_api.walletVerifyRequest"
}
}
],
"responses": {
"200": {
"description": "token 与 expiresAt(bind 模式为换发的新 token)",
"schema": {
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"400": {
"description": "挑战无效已过期,或 bind 模式签名校验失败",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"401": {
"description": "签名校验失败(login 模式)",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"403": {
"description": "地址未绑定账号",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"409": {
"description": "地址已绑定过",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"429": {
"description": "连续失败已锁定",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
},
"/api/v1/console-sessions/{sessionId}": {
"delete": {
"security": [
@@ -1579,7 +1978,7 @@ const docTemplate = `{
"BearerAuth": []
}
],
"description": "将刚创建的 key 设为本配置签名凭据:验证可用后落库,不删除旧 key;私钥为创建时下发的那份回传。",
"description": "将刚创建的 key 设为本配置签名凭据:验证可用后落库,不删除旧 key;私钥为创建时下发的那份回传。userId 给定且异于当前签名用户时,一并把签名用户切换为该用户。",
"tags": [
"租户 IAM"
],
@@ -1593,7 +1992,7 @@ const docTemplate = `{
"required": true
},
{
"description": "请求体:fingerprint 与 privateKey",
"description": "请求体:fingerprint 与 privateKey,可选 userId(切换签名用户)",
"name": "body",
"in": "body",
"required": true,
@@ -3467,6 +3866,12 @@ const docTemplate = `{
"responses": {
"204": {
"description": "无内容"
},
"409": {
"description": "该实例的生命周期操作正在处理中",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
@@ -3513,6 +3918,12 @@ const docTemplate = `{
"schema": {
"$ref": "#/definitions/oci-portal_internal_oci.Instance"
}
},
"409": {
"description": "该实例的生命周期操作正在处理中",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
@@ -7059,6 +7470,24 @@ const docTemplate = `{
"schema": {
"$ref": "#/definitions/oci-portal_internal_service.OAuthProvidersView"
}
},
"400": {
"description": "请求体非法",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"401": {
"description": "请求处理期间会话已撤销",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"409": {
"description": "密码登录禁用期间,该变更将移除最后可用登录方式",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
@@ -7110,6 +7539,24 @@ const docTemplate = `{
"schema": {
"$ref": "#/definitions/oci-portal_internal_service.SecuritySettings"
}
},
"400": {
"description": "字段越界或非法",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"401": {
"description": "请求处理期间会话已撤销",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
},
"409": {
"description": "密码登录禁用期间,面板地址变更将移除最后可用登录方式",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
@@ -8116,6 +8563,10 @@ const docTemplate = `{
"internal_api.errorResponse": {
"type": "object",
"properties": {
"code": {
"description": "Code 是机器可读错误码,多数错误不携带;当前仅全局 IP 限流的 429\n返回 \"RateLimited\",前端据此与登录守卫的 429(无 code)区分",
"type": "string"
},
"error": {
"type": "string"
}
@@ -8305,6 +8756,17 @@ const docTemplate = `{
}
}
},
"internal_api.itemsResponse-oci-portal_internal_model_UserPasskey": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/oci-portal_internal_model.UserPasskey"
}
}
}
},
"internal_api.itemsResponse-oci-portal_internal_service_AggregatedModel": {
"type": "object",
"properties": {
@@ -8349,6 +8811,17 @@ const docTemplate = `{
}
}
},
"internal_api.itemsResponse-oci-portal_internal_service_SessionInfo": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/oci-portal_internal_service.SessionInfo"
}
}
}
},
"internal_api.logWebhookStatusResponse": {
"type": "object",
"properties": {
@@ -8386,6 +8859,9 @@ const docTemplate = `{
"internal_api.oauthProvidersResponse": {
"type": "object",
"properties": {
"passkeyLogin": {
"type": "boolean"
},
"passwordLoginDisabled": {
"type": "boolean"
},
@@ -8394,6 +8870,9 @@ const docTemplate = `{
"items": {
"$ref": "#/definitions/oci-portal_internal_service.ProviderInfo"
}
},
"walletLogin": {
"type": "boolean"
}
}
},
@@ -8467,6 +8946,37 @@ const docTemplate = `{
}
}
},
"internal_api.passkeyFinishRequest": {
"type": "object",
"required": [
"credential",
"sessionId"
],
"properties": {
"credential": {
"$ref": "#/definitions/oci-portal_internal_aiwire.AnyJSON"
},
"name": {
"type": "string",
"maxLength": 64
},
"sessionId": {
"type": "string",
"maxLength": 64
}
}
},
"internal_api.passkeyOptionsResponse": {
"type": "object",
"properties": {
"options": {
"$ref": "#/definitions/oci-portal_internal_aiwire.AnyJSON"
},
"sessionId": {
"type": "string"
}
}
},
"internal_api.passwordResponse": {
"type": "object",
"properties": {
@@ -8773,6 +9283,53 @@ const docTemplate = `{
}
}
},
"internal_api.walletChallengeRequest": {
"type": "object",
"required": [
"address"
],
"properties": {
"address": {
"type": "string",
"maxLength": 64
},
"mode": {
"type": "string",
"enum": [
"login",
"bind"
]
}
}
},
"internal_api.walletChallengeResponse": {
"type": "object",
"properties": {
"message": {
"type": "string"
},
"nonce": {
"type": "string"
}
}
},
"internal_api.walletVerifyRequest": {
"type": "object",
"required": [
"nonce",
"signature"
],
"properties": {
"nonce": {
"type": "string",
"maxLength": 64
},
"signature": {
"type": "string",
"maxLength": 200
}
}
},
"internal_api.webConsoleSessionResponse": {
"type": "object",
"properties": {
@@ -10143,6 +10700,23 @@ const docTemplate = `{
}
}
},
"oci-portal_internal_model.UserPasskey": {
"type": "object",
"properties": {
"createdAt": {
"type": "string"
},
"id": {
"type": "integer"
},
"lastUsedAt": {
"type": "string"
},
"name": {
"type": "string"
}
}
},
"oci-portal_internal_oci.AuditEvent": {
"type": "object",
"properties": {
@@ -12014,6 +12588,36 @@ const docTemplate = `{
}
}
},
"oci-portal_internal_service.SessionInfo": {
"type": "object",
"properties": {
"clientIp": {
"type": "string"
},
"createdAt": {
"type": "string"
},
"current": {
"type": "boolean"
},
"expiresAt": {
"type": "string"
},
"id": {
"type": "integer"
},
"lastSeenAt": {
"type": "string"
},
"method": {
"description": "登录方式:password / oidc / github / passkey / wallet;接续换发保留原值",
"type": "string"
},
"userAgent": {
"type": "string"
}
}
},
"oci-portal_internal_service.TaskSettingsView": {
"type": "object",
"properties": {