Skip to content

Commit f7076ec

Browse files
authored
Merge pull request #45 from GeorgeXie2333/dev
feat: add Turnstile registration and image fixes
2 parents 7c6d285 + 884a9aa commit f7076ec

39 files changed

Lines changed: 1529 additions & 80 deletions

backend/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,19 @@ observability:
100100

101101
`APP_ENV` 未配置时默认 `prod`。`dev`/`development` 只用于本地开发;公网生产部署应保持 `APP_ENV=prod` 或 `APP_ENV=production` 并使用生产密钥。
102102

103+
## 邮箱注册 Turnstile
104+
105+
邮箱注册可选启用 Cloudflare Turnstile 人机验证,作用范围仅限邮箱注册;OAuth/OIDC 登录或注册不需要 Turnstile 校验。
106+
107+
相关运行时设置:
108+
109+
- `auth:turnstile_registration_enabled`:是否在邮箱注册时启用 Turnstile。
110+
- `auth:turnstile_site_key`:前端渲染 Turnstile 组件使用的 Site Key,会通过 `/api/v1/auth/login-options` 返回。
111+
- `auth:turnstile_secret_key`:后端调用 Cloudflare siteverify 使用的 Secret Key,属于敏感设置。
112+
- `TURNSTILE_SITEVERIFY_URL` / `security.turnstile_siteverify_url`:可选覆盖 siteverify 端点,默认使用 Cloudflare 官方地址。
113+
114+
启用 Turnstile 需要同时启用 `auth:email_registration_enabled`,并配置 Site Key 与 Secret Key。开启邮箱验证码注册时,前端在 `/api/v1/auth/register/email/start` 提交 `turnstileToken`;关闭邮箱验证码但允许邮箱注册时,前端在 `/api/v1/auth/register/email/complete` 提交 `turnstileToken`。
115+
103116
生产环境安全校验:
104117

105118
- `APP_ENV` 支持 `dev`/`development` 和 `prod`/`production`,其他值会启动失败。

backend/docs/docs.go

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3487,6 +3487,32 @@ const docTemplate = `{
34873487
}
34883488
}
34893489
},
3490+
"/auth/login-options": {
3491+
"get": {
3492+
"description": "获取用户名、邮箱、OAuth/OIDC 登录入口,以及邮箱注册 Turnstile 公共配置",
3493+
"produces": [
3494+
"application/json"
3495+
],
3496+
"tags": [
3497+
"auth"
3498+
],
3499+
"summary": "获取登录入口配置",
3500+
"responses": {
3501+
"200": {
3502+
"description": "OK",
3503+
"schema": {
3504+
"$ref": "#/definitions/internal_transport_http_auth.LoginOptionsResponseDoc"
3505+
}
3506+
},
3507+
"500": {
3508+
"description": "Internal Server Error",
3509+
"schema": {
3510+
"$ref": "#/definitions/internal_transport_http_auth.ErrorDoc"
3511+
}
3512+
}
3513+
}
3514+
}
3515+
},
34903516
"/auth/logout": {
34913517
"post": {
34923518
"security": [
@@ -3605,6 +3631,86 @@ const docTemplate = `{
36053631
}
36063632
}
36073633
},
3634+
"/auth/register/email/complete": {
3635+
"post": {
3636+
"description": "使用邮箱、密码和验证码完成注册;未开启邮箱验证码但启用 Turnstile 时需要提交 turnstileToken",
3637+
"consumes": [
3638+
"application/json"
3639+
],
3640+
"produces": [
3641+
"application/json"
3642+
],
3643+
"tags": [
3644+
"auth"
3645+
],
3646+
"summary": "完成邮箱注册",
3647+
"parameters": [
3648+
{
3649+
"description": "邮箱注册完成请求",
3650+
"name": "body",
3651+
"in": "body",
3652+
"required": true,
3653+
"schema": {
3654+
"$ref": "#/definitions/internal_transport_http_auth.EmailRegistrationCompleteRequest"
3655+
}
3656+
}
3657+
],
3658+
"responses": {
3659+
"200": {
3660+
"description": "OK",
3661+
"schema": {
3662+
"$ref": "#/definitions/internal_transport_http_auth.LoginResponseDoc"
3663+
}
3664+
},
3665+
"400": {
3666+
"description": "Bad Request",
3667+
"schema": {
3668+
"$ref": "#/definitions/internal_transport_http_auth.ErrorDoc"
3669+
}
3670+
}
3671+
}
3672+
}
3673+
},
3674+
"/auth/register/email/start": {
3675+
"post": {
3676+
"description": "邮箱验证码注册开启时发送验证码;启用 Turnstile 后需要提交 turnstileToken",
3677+
"consumes": [
3678+
"application/json"
3679+
],
3680+
"produces": [
3681+
"application/json"
3682+
],
3683+
"tags": [
3684+
"auth"
3685+
],
3686+
"summary": "发送邮箱注册验证码",
3687+
"parameters": [
3688+
{
3689+
"description": "邮箱注册验证码请求",
3690+
"name": "body",
3691+
"in": "body",
3692+
"required": true,
3693+
"schema": {
3694+
"$ref": "#/definitions/internal_transport_http_auth.EmailRegistrationStartRequest"
3695+
}
3696+
}
3697+
],
3698+
"responses": {
3699+
"200": {
3700+
"description": "OK",
3701+
"schema": {
3702+
"$ref": "#/definitions/internal_transport_http_auth.EmailRegistrationStartResponseDoc"
3703+
}
3704+
},
3705+
"400": {
3706+
"description": "Bad Request",
3707+
"schema": {
3708+
"$ref": "#/definitions/internal_transport_http_auth.ErrorDoc"
3709+
}
3710+
}
3711+
}
3712+
}
3713+
},
36083714
"/auth/sessions": {
36093715
"get": {
36103716
"security": [
@@ -7683,6 +7789,69 @@ const docTemplate = `{
76837789
}
76847790
}
76857791
},
7792+
"internal_transport_http_auth.EmailRegistrationCompleteRequest": {
7793+
"type": "object",
7794+
"required": [
7795+
"email",
7796+
"password"
7797+
],
7798+
"properties": {
7799+
"code": {
7800+
"type": "string"
7801+
},
7802+
"email": {
7803+
"type": "string",
7804+
"maxLength": 128
7805+
},
7806+
"password": {
7807+
"type": "string",
7808+
"maxLength": 128,
7809+
"minLength": 8
7810+
},
7811+
"turnstileToken": {
7812+
"type": "string",
7813+
"maxLength": 2048
7814+
}
7815+
}
7816+
},
7817+
"internal_transport_http_auth.EmailRegistrationStartRequest": {
7818+
"type": "object",
7819+
"required": [
7820+
"email"
7821+
],
7822+
"properties": {
7823+
"email": {
7824+
"type": "string",
7825+
"maxLength": 128
7826+
},
7827+
"turnstileToken": {
7828+
"type": "string",
7829+
"maxLength": 2048
7830+
}
7831+
}
7832+
},
7833+
"internal_transport_http_auth.EmailRegistrationStartResponse": {
7834+
"type": "object",
7835+
"properties": {
7836+
"expiresAt": {
7837+
"type": "string"
7838+
},
7839+
"sent": {
7840+
"type": "boolean"
7841+
}
7842+
}
7843+
},
7844+
"internal_transport_http_auth.EmailRegistrationStartResponseDoc": {
7845+
"type": "object",
7846+
"properties": {
7847+
"data": {
7848+
"$ref": "#/definitions/internal_transport_http_auth.EmailRegistrationStartResponse"
7849+
},
7850+
"errorMsg": {
7851+
"type": "string"
7852+
}
7853+
}
7854+
},
76867855
"internal_transport_http_auth.EmailVerificationStartResponse": {
76877856
"type": "object",
76887857
"properties": {
@@ -7730,6 +7899,120 @@ const docTemplate = `{
77307899
}
77317900
}
77327901
},
7902+
"internal_transport_http_auth.IdentityProviderResponse": {
7903+
"type": "object",
7904+
"properties": {
7905+
"authURL": {
7906+
"type": "string"
7907+
},
7908+
"avatarField": {
7909+
"type": "string"
7910+
},
7911+
"clientID": {
7912+
"type": "string"
7913+
},
7914+
"createdAt": {
7915+
"type": "string"
7916+
},
7917+
"defaultRole": {
7918+
"type": "string"
7919+
},
7920+
"discoveryURL": {
7921+
"type": "string"
7922+
},
7923+
"emailField": {
7924+
"type": "string"
7925+
},
7926+
"emailVerifiedField": {
7927+
"type": "string"
7928+
},
7929+
"issuerURL": {
7930+
"type": "string"
7931+
},
7932+
"jwksURL": {
7933+
"type": "string"
7934+
},
7935+
"loginEnabled": {
7936+
"type": "boolean"
7937+
},
7938+
"logoURL": {
7939+
"type": "string"
7940+
},
7941+
"name": {
7942+
"type": "string"
7943+
},
7944+
"nameField": {
7945+
"type": "string"
7946+
},
7947+
"publicID": {
7948+
"type": "string"
7949+
},
7950+
"registrationEnabled": {
7951+
"type": "boolean"
7952+
},
7953+
"scopes": {
7954+
"type": "string"
7955+
},
7956+
"slug": {
7957+
"type": "string"
7958+
},
7959+
"subjectField": {
7960+
"type": "string"
7961+
},
7962+
"tokenURL": {
7963+
"type": "string"
7964+
},
7965+
"type": {
7966+
"type": "string"
7967+
},
7968+
"updatedAt": {
7969+
"type": "string"
7970+
},
7971+
"userinfoURL": {
7972+
"type": "string"
7973+
}
7974+
}
7975+
},
7976+
"internal_transport_http_auth.LoginOptionsResponse": {
7977+
"type": "object",
7978+
"properties": {
7979+
"emailEnabled": {
7980+
"type": "boolean"
7981+
},
7982+
"emailRegistrationEnabled": {
7983+
"type": "boolean"
7984+
},
7985+
"emailVerificationEnabled": {
7986+
"type": "boolean"
7987+
},
7988+
"providers": {
7989+
"type": "array",
7990+
"items": {
7991+
"$ref": "#/definitions/internal_transport_http_auth.IdentityProviderResponse"
7992+
}
7993+
},
7994+
"turnstileRegistrationEnabled": {
7995+
"type": "boolean"
7996+
},
7997+
"turnstileSiteKey": {
7998+
"type": "string"
7999+
},
8000+
"usernameEnabled": {
8001+
"type": "boolean"
8002+
}
8003+
}
8004+
},
8005+
"internal_transport_http_auth.LoginOptionsResponseDoc": {
8006+
"type": "object",
8007+
"properties": {
8008+
"data": {
8009+
"$ref": "#/definitions/internal_transport_http_auth.LoginOptionsResponse"
8010+
},
8011+
"errorMsg": {
8012+
"type": "string"
8013+
}
8014+
}
8015+
},
77338016
"internal_transport_http_auth.LoginRequest": {
77348017
"type": "object",
77358018
"required": [

0 commit comments

Comments
 (0)