新增活跃会话管理与通行密钥、钱包登录
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": {
+611 -7
View File
@@ -1037,11 +1037,23 @@
"$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"
}
}
}
}
@@ -1072,7 +1084,7 @@
"summary": "外部登录 provider 列表",
"responses": {
"200": {
"description": "providerspasswordLoginDisabled",
"description": "providerspasswordLoginDisabled 与 passkeyLogin",
"schema": {
"$ref": "#/definitions/internal_api.oauthProvidersResponse"
}
@@ -1107,6 +1119,24 @@
"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"
}
}
}
}
@@ -1147,6 +1177,201 @@
}
}
},
"/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": [
@@ -1209,6 +1434,72 @@
}
}
},
"/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": [
@@ -1259,8 +1550,11 @@
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已启用但新 token 签发失败,需重新登录"
"401": {
"description": "请求处理期间会话已撤销",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
@@ -1294,8 +1588,11 @@
"$ref": "#/definitions/internal_api.tokenResponse"
}
},
"204": {
"description": "已停用但新 token 签发失败,需重新登录"
"401": {
"description": "请求处理期间会话已撤销",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
@@ -1327,6 +1624,108 @@
}
}
},
"/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": [
@@ -1572,7 +1971,7 @@
"BearerAuth": []
}
],
"description": "将刚创建的 key 设为本配置签名凭据:验证可用后落库,不删除旧 key;私钥为创建时下发的那份回传。",
"description": "将刚创建的 key 设为本配置签名凭据:验证可用后落库,不删除旧 key;私钥为创建时下发的那份回传。userId 给定且异于当前签名用户时,一并把签名用户切换为该用户。",
"tags": [
"租户 IAM"
],
@@ -1586,7 +1985,7 @@
"required": true
},
{
"description": "请求体:fingerprint 与 privateKey",
"description": "请求体:fingerprint 与 privateKey,可选 userId(切换签名用户)",
"name": "body",
"in": "body",
"required": true,
@@ -3460,6 +3859,12 @@
"responses": {
"204": {
"description": "无内容"
},
"409": {
"description": "该实例的生命周期操作正在处理中",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
@@ -3506,6 +3911,12 @@
"schema": {
"$ref": "#/definitions/oci-portal_internal_oci.Instance"
}
},
"409": {
"description": "该实例的生命周期操作正在处理中",
"schema": {
"$ref": "#/definitions/internal_api.errorResponse"
}
}
}
}
@@ -7052,6 +7463,24 @@
"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"
}
}
}
}
@@ -7103,6 +7532,24 @@
"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"
}
}
}
}
@@ -8109,6 +8556,10 @@
"internal_api.errorResponse": {
"type": "object",
"properties": {
"code": {
"description": "Code 是机器可读错误码,多数错误不携带;当前仅全局 IP 限流的 429\n返回 \"RateLimited\",前端据此与登录守卫的 429(无 code)区分",
"type": "string"
},
"error": {
"type": "string"
}
@@ -8298,6 +8749,17 @@
}
}
},
"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": {
@@ -8342,6 +8804,17 @@
}
}
},
"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": {
@@ -8379,6 +8852,9 @@
"internal_api.oauthProvidersResponse": {
"type": "object",
"properties": {
"passkeyLogin": {
"type": "boolean"
},
"passwordLoginDisabled": {
"type": "boolean"
},
@@ -8387,6 +8863,9 @@
"items": {
"$ref": "#/definitions/oci-portal_internal_service.ProviderInfo"
}
},
"walletLogin": {
"type": "boolean"
}
}
},
@@ -8460,6 +8939,37 @@
}
}
},
"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": {
@@ -8766,6 +9276,53 @@
}
}
},
"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": {
@@ -10136,6 +10693,23 @@
}
}
},
"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": {
@@ -12007,6 +12581,36 @@
}
}
},
"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": {
+396 -7
View File
@@ -401,6 +401,11 @@ definitions:
type: object
internal_api.errorResponse:
properties:
code:
description: |-
Code 是机器可读错误码,多数错误不携带;当前仅全局 IP 限流的 429
返回 "RateLimited",前端据此与登录守卫的 429(无 code)区分
type: string
error:
type: string
type: object
@@ -524,6 +529,13 @@ definitions:
$ref: '#/definitions/oci-portal_internal_model.UserIdentity'
type: array
type: object
internal_api.itemsResponse-oci-portal_internal_model_UserPasskey:
properties:
items:
items:
$ref: '#/definitions/oci-portal_internal_model.UserPasskey'
type: array
type: object
internal_api.itemsResponse-oci-portal_internal_service_AggregatedModel:
properties:
items:
@@ -552,6 +564,13 @@ definitions:
$ref: '#/definitions/oci-portal_internal_service.ProxyView'
type: array
type: object
internal_api.itemsResponse-oci-portal_internal_service_SessionInfo:
properties:
items:
items:
$ref: '#/definitions/oci-portal_internal_service.SessionInfo'
type: array
type: object
internal_api.logWebhookStatusResponse:
properties:
exists:
@@ -578,12 +597,16 @@ definitions:
type: object
internal_api.oauthProvidersResponse:
properties:
passkeyLogin:
type: boolean
passwordLoginDisabled:
type: boolean
providers:
items:
$ref: '#/definitions/oci-portal_internal_service.ProviderInfo'
type: array
walletLogin:
type: boolean
type: object
internal_api.pagedResponse-oci-portal_internal_model_AiCallLog:
properties:
@@ -630,6 +653,27 @@ definitions:
nextPage:
type: string
type: object
internal_api.passkeyFinishRequest:
properties:
credential:
$ref: '#/definitions/oci-portal_internal_aiwire.AnyJSON'
name:
maxLength: 64
type: string
sessionId:
maxLength: 64
type: string
required:
- credential
- sessionId
type: object
internal_api.passkeyOptionsResponse:
properties:
options:
$ref: '#/definitions/oci-portal_internal_aiwire.AnyJSON'
sessionId:
type: string
type: object
internal_api.passwordResponse:
properties:
password:
@@ -827,6 +871,38 @@ definitions:
$ref: '#/definitions/oci-portal_internal_service.UserApiKeyInfo'
type: array
type: object
internal_api.walletChallengeRequest:
properties:
address:
maxLength: 64
type: string
mode:
enum:
- login
- bind
type: string
required:
- address
type: object
internal_api.walletChallengeResponse:
properties:
message:
type: string
nonce:
type: string
type: object
internal_api.walletVerifyRequest:
properties:
nonce:
maxLength: 64
type: string
signature:
maxLength: 200
type: string
required:
- nonce
- signature
type: object
internal_api.webConsoleSessionResponse:
properties:
sessionId:
@@ -1737,6 +1813,17 @@ definitions:
provider:
type: string
type: object
oci-portal_internal_model.UserPasskey:
properties:
createdAt:
type: string
id:
type: integer
lastUsedAt:
type: string
name:
type: string
type: object
oci-portal_internal_oci.AuditEvent:
properties:
compartmentName:
@@ -2974,6 +3061,26 @@ definitions:
description: 真实IP请求头:空 = 直连(RemoteAddr);反代后必须选择与反代匹配的头
type: string
type: object
oci-portal_internal_service.SessionInfo:
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
type: object
oci-portal_internal_service.TaskSettingsView:
properties:
snatchAuthFailLimit:
@@ -3669,10 +3776,18 @@ paths:
description: 凭据错误
schema:
$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'
summary: 登录
tags:
- 认证
@@ -3703,6 +3818,18 @@ paths:
description: url
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'
summary: 外部登录授权跳转
tags:
- 认证
@@ -3734,12 +3861,132 @@ paths:
get:
responses:
"200":
description: providerspasswordLoginDisabled
description: providerspasswordLoginDisabled 与 passkeyLogin
schema:
$ref: '#/definitions/internal_api.oauthProvidersResponse'
summary: 外部登录 provider 列表
tags:
- 认证
/api/v1/auth/passkey/login/begin:
post:
responses:
"200":
description: sessionId 与 WebAuthn options
schema:
$ref: '#/definitions/internal_api.passkeyOptionsResponse'
"409":
description: 面板地址未设置
schema:
$ref: '#/definitions/internal_api.errorResponse'
summary: 发起通行密钥登录
tags:
- 认证
/api/v1/auth/passkey/login/finish:
post:
parameters:
- description: sessionId 与断言响应(name 忽略)
in: body
name: 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'
summary: 完成通行密钥登录
tags:
- 认证
/api/v1/auth/passkey/register/begin:
post:
responses:
"200":
description: sessionId 与 WebAuthn options
schema:
$ref: '#/definitions/internal_api.passkeyOptionsResponse'
"409":
description: 面板地址未设置或数量达上限
schema:
$ref: '#/definitions/internal_api.errorResponse'
security:
- BearerAuth: []
summary: 发起通行密钥注册
tags:
- 认证
/api/v1/auth/passkey/register/finish:
post:
parameters:
- description: sessionId、名称与凭据响应
in: body
name: 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'
security:
- BearerAuth: []
summary: 完成通行密钥注册
tags:
- 认证
/api/v1/auth/passkeys:
get:
responses:
"200":
description: items
schema:
$ref: '#/definitions/internal_api.itemsResponse-oci-portal_internal_model_UserPasskey'
security:
- BearerAuth: []
summary: 通行密钥列表
tags:
- 认证
/api/v1/auth/passkeys/{id}:
delete:
parameters:
- description: 凭据 ID
in: path
name: id
required: true
type: integer
responses:
"200":
description: 已删除,返回换发的新 token
schema:
$ref: '#/definitions/internal_api.tokenResponse'
"204":
description: 已删除但新 token 签发失败,需重新登录
"409":
description: 密码登录已禁用且这是最后一个免密登录方式
schema:
$ref: '#/definitions/internal_api.errorResponse'
security:
- BearerAuth: []
summary: 删除通行密钥
tags:
- 认证
/api/v1/auth/password-login:
put:
parameters:
@@ -3777,6 +4024,46 @@ paths:
summary: 撤销全部会话
tags:
- 认证
/api/v1/auth/sessions:
get:
responses:
"200":
description: items
schema:
$ref: '#/definitions/internal_api.itemsResponse-oci-portal_internal_service_SessionInfo'
security:
- BearerAuth: []
summary: 活跃会话列表
tags:
- 认证
/api/v1/auth/sessions/{id}:
delete:
parameters:
- description: 会话 ID
in: path
name: id
required: true
type: integer
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'
security:
- BearerAuth: []
summary: 撤销单个会话
tags:
- 认证
/api/v1/auth/totp:
get:
responses:
@@ -3803,8 +4090,10 @@ paths:
description: 已启用,返回换发的新 token
schema:
$ref: '#/definitions/internal_api.tokenResponse'
"204":
description: 已启用但新 token 签发失败,需重新登录
"401":
description: 请求处理期间会话已撤销
schema:
$ref: '#/definitions/internal_api.errorResponse'
security:
- BearerAuth: []
summary: 激活两步验证
@@ -3824,8 +4113,10 @@ paths:
description: 已停用,返回换发的新 token
schema:
$ref: '#/definitions/internal_api.tokenResponse'
"204":
description: 已停用但新 token 签发失败,需重新登录
"401":
description: 请求处理期间会话已撤销
schema:
$ref: '#/definitions/internal_api.errorResponse'
security:
- BearerAuth: []
summary: 停用两步验证
@@ -3847,6 +4138,72 @@ paths:
summary: 发起两步验证设置
tags:
- 认证
/api/v1/auth/wallet/challenge:
post:
parameters:
- description: 钱包地址与模式(bind 需 Bearer)
in: body
name: 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'
summary: 发起钱包签名挑战
tags:
- 认证
/api/v1/auth/wallet/verify:
post:
parameters:
- description: nonce 与签名
in: body
name: 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'
summary: 校验钱包签名
tags:
- 认证
/api/v1/console-sessions/{sessionId}:
delete:
parameters:
@@ -3994,14 +4351,14 @@ paths:
- 租户配置
/api/v1/oci-configs/{id}/activate-api-key:
post:
description: 将刚创建的 key 设为本配置签名凭据:验证可用后落库,不删除旧 key;私钥为创建时下发的那份回传。
description: 将刚创建的 key 设为本配置签名凭据:验证可用后落库,不删除旧 key;私钥为创建时下发的那份回传。userId 给定且异于当前签名用户时,一并把签名用户切换为该用户。
parameters:
- description: 配置 ID
in: path
name: id
required: true
type: integer
- description: 请求体:fingerprint 与 privateKey
- description: 请求体:fingerprint 与 privateKey,可选 userId(切换签名用户)
in: body
name: body
required: true
@@ -5134,6 +5491,10 @@ paths:
responses:
"204":
description: 无内容
"409":
description: 该实例的生命周期操作正在处理中
schema:
$ref: '#/definitions/internal_api.errorResponse'
security:
- BearerAuth: []
summary: 终止实例
@@ -5213,6 +5574,10 @@ paths:
description: OK
schema:
$ref: '#/definitions/oci-portal_internal_oci.Instance'
"409":
description: 该实例的生命周期操作正在处理中
schema:
$ref: '#/definitions/internal_api.errorResponse'
security:
- BearerAuth: []
summary: 实例电源操作(启停/重启)
@@ -7409,6 +7774,18 @@ paths:
description: OK
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'
security:
- BearerAuth: []
summary: 部分更新 OAuth provider 配置
@@ -7439,6 +7816,18 @@ paths:
description: OK
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'
security:
- BearerAuth: []
summary: 部分更新安全设置并返回最新值