mirror of
https://github.com/SMNETSTUDIO/WeChat-AI.git
synced 2026-08-12 22:23:42 +08:00
fix: don't cache /api/v1/auth/config so LINUXDO_AUTH_ENABLED applies immediately; document local-only admin setup
This commit is contained in:
@@ -170,6 +170,8 @@ LINUXDO_ADMIN_IDS=12345,your_username
|
||||
# Per user: max INVITE_QUOTA_MAX codes every INVITE_QUOTA_WINDOW_HOURS hours
|
||||
# INVITE_QUOTA_WINDOW_HOURS=24
|
||||
# INVITE_QUOTA_MAX=3
|
||||
# 纯本地部署:LINUXDO_ADMIN_IDS 留空 + FIRST_USER_IS_ADMIN=true 时,
|
||||
# 第一个本地注册用户自动成为管理员(首个用户无需邀请码)。见 docs/oauth-linuxdo.md。
|
||||
|
||||
# Product
|
||||
DEFAULT_PERSONA_SLUG=catgirl
|
||||
|
||||
@@ -40,10 +40,6 @@ export const CC_PRIVATE_STICKER =
|
||||
*/
|
||||
export const CC_PRIVATE_QR = "private, no-store" as const;
|
||||
|
||||
/** Auth config (static-ish). */
|
||||
export const CC_AUTH_CONFIG = "public, max-age=60" as const;
|
||||
export const CDN_AUTH_CONFIG = "public, max-age=300" as const;
|
||||
|
||||
/** Default for authenticated / dynamic APIs. */
|
||||
export const CC_PRIVATE_NO_STORE = "private, no-store" as const;
|
||||
|
||||
|
||||
@@ -193,16 +193,15 @@ import {
|
||||
StickerSecurityError,
|
||||
} from "./sticker-security.js";
|
||||
import {
|
||||
CC_AUTH_CONFIG,
|
||||
CC_CDN_STICKER,
|
||||
CC_NO_STORE,
|
||||
CC_PRIVATE_NO_STORE,
|
||||
CC_PRIVATE_QR,
|
||||
CC_PRIVATE_STICKER,
|
||||
CDN_AUTH_CONFIG,
|
||||
CDN_CDN_STICKER,
|
||||
etagFromHash,
|
||||
ifNoneMatchHits,
|
||||
setPrivateNoStore,
|
||||
setPublicCache,
|
||||
} from "./cache-headers.js";
|
||||
import { qrSvg } from "./qrcode.js";
|
||||
@@ -645,7 +644,7 @@ export async function registerRoutes(
|
||||
const authInvitePeekLimiter = new RateLimiter(40, 60_000);
|
||||
|
||||
app.get("/api/v1/auth/config", async (_req, reply) => {
|
||||
setPublicCache(reply, CC_AUTH_CONFIG, CDN_AUTH_CONFIG);
|
||||
setPrivateNoStore(reply);
|
||||
const oauth = loadLinuxDoConfig();
|
||||
return {
|
||||
oauthEnabled: Boolean(oauth) && ctx.cfg.linuxdoAuthEnabled,
|
||||
|
||||
+4
-6
@@ -24,7 +24,7 @@
|
||||
| `/app` `/admin` | `public, max-age=60` | `max-age=3600, swr=86400` | 无(壳静态;数据走 API) |
|
||||
| `/og.jpg` | `public, max-age=86400, immutable` | `max-age=604800` | 无 |
|
||||
| `/cdn/s/:id?v=` | `public, max-age=31536000, immutable` | 同左 | **无**;仅 public+approved+enabled |
|
||||
| `/api/v1/auth/config` | `public, max-age=60` | `max-age=300` | 无 |
|
||||
| `/api/v1/auth/config` | `private, no-store` | — | 无(登录方式开关需实时) |
|
||||
| `/health` | `no-store` | — | 无 |
|
||||
| 其余 `/api/v1/**` | `private, no-store` | — | Cookie 会话 |
|
||||
| 鉴权表情图 | `private, no-store` | — | 登录 / admin |
|
||||
@@ -55,7 +55,7 @@ HTML 带 `ETag` + `Cache-Tag: html-shell`;公开表情带 `Cache-Tag: sticker-
|
||||
|
||||
- **Name:** `bypass-api-private`
|
||||
- **When:**
|
||||
`(starts_with(http.request.uri.path, "/api/v1/") and not http.request.uri.path eq "/api/v1/auth/config")`
|
||||
`starts_with(http.request.uri.path, "/api/v1/")`
|
||||
或方法为 `POST` / `PUT` / `PATCH` / `DELETE`
|
||||
- **Then:** Cache eligibility = **Bypass cache**
|
||||
|
||||
@@ -84,11 +84,9 @@ HTML 带 `ETag` + `Cache-Tag: html-shell`;公开表情带 `Cache-Tag: sticker-
|
||||
- **Then:** Eligible for cache;Edge TTL Respect origin;**Ignore cookies**
|
||||
- Cache key **保留 query string**(`v=` 内容哈希)
|
||||
|
||||
### Rule 5 — auth/config 短缓存
|
||||
### Rule 5 — ~~auth/config 短缓存~~(已移除)
|
||||
|
||||
- **Name:** `cache-auth-config`
|
||||
- **When:** `http.request.uri.path eq "/api/v1/auth/config"`
|
||||
- **Then:** Eligible for cache;Edge TTL 5 minutes 或 Respect origin;Ignore cookies
|
||||
> `/api/v1/auth/config` 现返回 `no-store`(登录方式开关需实时生效,不应缓存)。Cloudflare 默认尊重源站 `Cache-Control`,无 `public` 的响应不进共享缓存,故该路径**无需**任何缓存规则。
|
||||
|
||||
### 默认
|
||||
|
||||
|
||||
@@ -43,6 +43,39 @@ LINUXDO_AUTH_ENABLED=false
|
||||
- 即使 `LINUXDO_CLIENT_ID/SECRET` 仍配置着也不生效
|
||||
- 该开关可在 `/admin → 设置` 运行时切换,无需重启(`localAuthEnabled` 同理)
|
||||
|
||||
> 注意:如果**不重启服务**或浏览器/CDN 仍缓存旧的 `/api/v1/auth/config` 响应,
|
||||
> 前端按钮可能不会立即消失。此接口现在返回 `no-store`,但请确保已重启进程、
|
||||
> 并清除 Cloudflare 边缘缓存(`/api/v1/auth/config` 曾允许最长 5 分钟缓存)。
|
||||
>
|
||||
> **`linuxdoAuthEnabled` 是运行时设置**:`/admin → 设置` 页面存到 Redis 的
|
||||
> 覆盖值会**优先于 `.env`**。若曾在该页把开关切到 `true`(或 Redis 残留旧值),
|
||||
> 需回到 `/admin → 设置` 把它关闭(或「重置全部设置」),`.env` 的
|
||||
> `LINUXDO_AUTH_ENABLED=false` 才会生效。
|
||||
|
||||
### 完全不用 LINUX DO:纯本地管理员
|
||||
|
||||
不配置/不启用 LINUX DO,仅用「用户名+密码」管理,方法如下:
|
||||
|
||||
```env
|
||||
LINUXDO_AUTH_ENABLED=false
|
||||
LOCAL_AUTH_ENABLED=true # 用户名+密码登录(默认已开)
|
||||
FIRST_USER_IS_ADMIN=true # 首个注册用户自动成为管理员(默认)
|
||||
LINUXDO_ADMIN_IDS= # 留空,交给 FIRST_USER_IS_ADMIN 引导
|
||||
```
|
||||
|
||||
**步骤**:
|
||||
|
||||
1. 按上面配置后启动服务
|
||||
2. 打开 `/app` → **注册**(第一个注册用户因 `FIRST_USER_IS_ADMIN` 自动成为超管)
|
||||
- 若 `INVITE_REQUIRED_FOR_LOCAL=true` 且是第一个用户(库中尚无任何用户),
|
||||
`bootstrap` 逻辑会跳过邀请码要求,直接成为管理员
|
||||
3. 用该账号登录 `/admin`,进入 **用户** 页即可给其他账号「授予管理员」
|
||||
|
||||
> `LINUXDO_ADMIN_IDS` 为空且首个本地用户注册时,`createLocalUser` 的
|
||||
> `bootstrapAdmin` 分支(`firstUserIsAdmin && totalUsers===0 && adminIds.size===0`)
|
||||
> 会将其标记为管理员——这就是纯本地部署下第一位管理员的来源。
|
||||
> 之后新增管理员请在 `/admin → 用户` 手动授予。
|
||||
|
||||
## 3. 流程
|
||||
|
||||
1. 用户访问 `/app` → 可用 **用户名密码** 登录,或点「LINUX DO 登录」
|
||||
|
||||
Reference in New Issue
Block a user