@oj-module/cli 0.2.66 → 0.2.67
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/.oj-version +1 -0
- package/bin/oj +4 -0
- package/devkit/README.md +15 -7
- package/devkit/SKILL.md +30 -1
- package/devkit/framework-dev.md +10 -4
- package/devkit/manual.md +38 -12
- package/devkit/publish-walkthrough.md +110 -37
- package/devkit/wecom-internal-app.md +7 -2
- package/devkit/wecom-multi-corp-links.md +163 -0
- package/package.json +2 -2
- package/shell-dist/assets/{index.i0kqbxp050.js → index.6alqyx6ae0.js} +21 -1
- package/shell-dist/assets/{runtime.1xfsxcajj0.js → runtime.2dgstpjsu0.js} +3449 -3449
- package/shell-dist/index.html +4 -4
- package/shell-dist/versions.json +3 -3
- package/src/__tests__/publish-keygen.test.ts +157 -0
- package/src/__tests__/templates-migration-schema-parity.test.ts +540 -0
- package/src/__tests__/templates-schema-columns.test.ts +15 -2
- package/src/__tests__/templates-tenant-scope.test.ts +6 -2
- package/src/bundle.ts +8 -3
- package/src/cli.ts +17 -5
- package/src/dev.ts +15 -10
- package/src/install.ts +11 -4
- package/src/keygen.ts +54 -0
- package/src/lifecycle/__tests__/bundle.test.ts +21 -3
- package/src/lifecycle/__tests__/fixtures/fixture-valid/api/src/demo-solution/manifest.yaml +1 -1
- package/src/lifecycle/__tests__/fixtures/fixture-valid/api/src/demo-solution/migrations/0001__init.sql +2 -2
- package/src/lifecycle/__tests__/fixtures/fixture-valid/api/src/demo-solution/schema.yaml +5 -2
- package/src/lifecycle/__tests__/fixtures/fixture-valid/manifest.yaml +1 -1
- package/src/lifecycle/__tests__/manifest-contract.test.ts +75 -3
- package/src/lifecycle/__tests__/smoke.test.ts +2 -2
- package/src/manifest-contract.ts +91 -8
- package/src/market/bootstrap.ts +26 -2
- package/src/market/command.ts +1 -0
- package/src/market/publish.ts +5 -1
- package/src/market/walkthrough.ts +24 -8
- package/src/site.ts +2 -0
- package/src/usage.ts +8 -4
- package/src/vendor.ts +5 -1
- package/templates/config.yaml +4 -2
- package/templates/init.include.yaml +8 -3
- package/templates/openapi.json +460 -1
- package/templates/src/app/api/_platform/_lifecycle/compensate.ts +136 -0
- package/templates/src/app/api/_platform/_lifecycle/installer.ts +71 -22
- package/templates/src/app/api/_platform/_lifecycle/lock.ts +23 -0
- package/templates/src/app/api/_platform/_lifecycle/steps/deploy-web.ts +28 -0
- package/templates/src/app/api/_platform/_lifecycle/steps/preflight.ts +46 -0
- package/templates/src/app/api/_platform/_lifecycle/steps/reload.ts +100 -36
- package/templates/src/app/api/_platform/_lifecycle/steps/smoke.ts +7 -15
- package/templates/src/app/api/_platform/_lifecycle/text-edit.ts +71 -19
- package/templates/src/app/api/_platform/_lifecycle/types.ts +26 -2
- package/templates/src/app/api/_platform/_lifecycle/uninstall.ts +93 -14
- package/templates/src/app/api/_platform/_shared/service/domain/settings.ts +8 -4
- package/templates/src/app/api/_platform/manifest.yaml +1 -0
- package/templates/src/app/api/_platform/market/api.ts +235 -10
- package/templates/src/app/api/_platform/migrations/0001__baseline.mysql.sql +178 -0
- package/templates/src/app/api/_platform/migrations/0001__baseline.pg.sql +173 -0
- package/templates/src/app/api/_platform/migrations/0001__baseline.sql +188 -0
- package/templates/src/app/api/_platform/migrations/0002__market_release.mysql.sql +17 -0
- package/templates/src/app/api/_platform/migrations/0002__market_release.pg.sql +16 -0
- package/templates/src/app/api/_platform/migrations/0002__market_release.sql +33 -0
- package/templates/src/app/api/_platform/schema.yaml +18 -0
- package/templates/src/app/api/_platform/seed.mysql.sql +10 -0
- package/templates/src/app/api/_platform/seed.pg.sql +10 -0
- package/templates/src/app/api/auth/_shared/wecom/client.ts +24 -4
- package/templates/src/app/api/home/migrations/0001__create_home_tables.mysql.sql +14 -0
- package/templates/src/app/api/home/migrations/0001__create_home_tables.pg.sql +14 -0
- package/templates/src/app/api/home/migrations/0002__tenant.pg.sql +4 -0
- package/templates/src/app/api/home/seed.mysql.sql +71 -0
- package/templates/src/app/api/home/seed.pg.sql +71 -0
- package/templates/src/app/api/notification/_shared/notify.ts +6 -6
- package/templates/src/app/api/notification/migrations/0001__create_notifications.mysql.sql +11 -0
- package/templates/src/app/api/notification/migrations/0001__create_notifications.pg.sql +11 -0
- package/templates/src/app/api/notification/migrations/0002__notifications_user.mysql.sql +8 -0
- package/templates/src/app/api/notification/migrations/0003__notifications_broadcast.mysql.sql +21 -0
- package/templates/src/app/api/notification/migrations/0003__notifications_broadcast.pg.sql +22 -0
- package/templates/src/app/api/notification/migrations/0004__notifications_broadcast_hidden.mysql.sql +10 -0
- package/templates/src/app/api/notification/migrations/0004__notifications_broadcast_hidden.pg.sql +11 -0
- package/templates/src/app/api/notification/migrations/0005__tenant.pg.sql +6 -0
- package/templates/src/app/api/notification/seed.mysql.sql +8 -0
- package/templates/src/app/api/notification/seed.pg.sql +11 -0
- package/templates/src/app/api/publish/_shared/identity.ts +69 -0
- package/templates/src/app/api/publish/api.ts +349 -0
- package/templates/src/app/api/publish/manifest.yaml +8 -0
- package/templates/src/app/api/publish/migrations/0001__publish_credential.mysql.sql +23 -0
- package/templates/src/app/api/publish/migrations/0001__publish_credential.pg.sql +23 -0
- package/templates/src/app/api/publish/migrations/0001__publish_credential.sql +39 -0
- package/templates/src/app/api/publish/schema.yaml +33 -0
- package/templates/src/app/api/system/login-methods/api.ts +2 -1
- package/templates/src/app/web/_platform/__client/api.schemas.ts +15 -0
- package/templates/src/app/web/_platform/__client/index.ts +25 -1
- package/templates/src/app/web/entry.ts +9 -5
- package/templates/src/app/web/home/routes.ts +5 -0
- package/templates/src/app/web/login/locales/en-US.json +7 -1
- package/templates/src/app/web/login/locales/zh-CN.json +7 -1
- package/templates/src/app/web/login/pages/login.tsx +79 -86
- package/templates/src/app/web/login/routes.ts +54 -1
- package/templates/src/app/web/personal-center/locales/en-US.json +1 -0
- package/templates/src/app/web/personal-center/locales/zh-CN.json +1 -0
- package/templates/src/app/web/personal-center/pages/my-profile/index.tsx +5 -0
- package/templates/src/app/web/system/__client/api.schemas.ts +2 -1
- package/templates/src/app/web/system/locales/en-US.json +1 -8
- package/templates/src/app/web/system/locales/zh-CN.json +1 -8
- package/templates/src/app/web/system/pages/settings/index.tsx +17 -4
- package/templates/src/app/web/system/routes.ts +0 -6
- package/templates/src/oj-market/web/__tests__/CardGrid.test.tsx +33 -0
- package/templates/src/oj-market/web/__tests__/DetailDrawer.test.tsx +69 -0
- package/templates/src/oj-market/web/__tests__/marketClient.fake.ts +7 -1
- package/templates/src/oj-market/web/api/client.ts +3 -0
- package/templates/src/oj-market/web/api/defaultClient.ts +5 -0
- package/templates/src/oj-market/web/components/CardItem.tsx +44 -1
- package/templates/src/oj-market/web/components/DetailDrawer.tsx +17 -1
- package/templates/src/oj-market/web/entry.ts +31 -2
- package/templates/src/oj-market/web/locales/en-US.json +5 -1
- package/templates/src/oj-market/web/locales/zh-CN.json +5 -1
- package/templates/src/oj-market/web/publish/__client/api.schemas.ts +61 -0
- package/templates/src/oj-market/web/publish/__client/index.ts +164 -0
- package/templates/src/oj-market/web/publish/locales/en-US.json +80 -0
- package/templates/src/oj-market/web/publish/locales/zh-CN.json +80 -0
- package/templates/src/oj-market/web/publish/pages/history.tsx +112 -0
- package/templates/src/oj-market/web/publish/pages/index.tsx +196 -0
- package/templates/src/oj-market/web/publish/pages/model.ts +52 -0
- package/templates/src/oj-market/web/publish/pages/token-modal.tsx +82 -0
- package/templates/src/oj-market/web/publish/routes.ts +41 -0
- package/templates/src/oj-market/web/types.ts +30 -0
- package/templates/tests/lifecycle/compensate.spec.ts +207 -0
- package/templates/tests/lifecycle/deploy-smoke.spec.ts +38 -14
- package/templates/tests/lifecycle/installer.spec.ts +28 -9
- package/templates/tests/lifecycle/market-api.spec.ts +164 -12
- package/templates/tests/lifecycle/preflight.spec.ts +68 -0
- package/templates/tests/lifecycle/role-title-translate.spec.ts +2 -32
- package/templates/tests/lifecycle/text-edit.spec.ts +45 -27
- package/templates/tests/lifecycle/uninstall.spec.ts +36 -0
- package/templates/tests/publish-credential.spec.ts +354 -0
- package/templates/tests/publish-identity.spec.ts +44 -0
- package/templates/tests/wecom-client-timeout.spec.ts +33 -3
- package/templates/tests/wecom-landing.spec.ts +63 -1
- package/templates/tsconfig.paths.json +1 -0
- package/templates/web.config.ts +6 -4
- package/vendor/host-versions.json +3 -3
- package/templates/seed.mysql.sql +0 -6
- package/templates/seed.pg.sql +0 -6
- package/templates/src/app/api/_platform/migrations/0001__create_users.mysql.sql +0 -9
- package/templates/src/app/api/_platform/migrations/0001__create_users.pg.sql +0 -9
- package/templates/src/app/api/_platform/migrations/0001__create_users.sql +0 -7
- package/templates/src/app/api/_platform/migrations/0002__add_users_avatar_base64.mysql.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0002__add_users_avatar_base64.sql +0 -2
- package/templates/src/app/api/_platform/migrations/0003__users_source_display_name.mysql.sql +0 -5
- package/templates/src/app/api/_platform/migrations/0003__users_source_display_name.sql +0 -5
- package/templates/src/app/api/_platform/migrations/0004__sys_rbac.mysql.sql +0 -70
- package/templates/src/app/api/_platform/migrations/0004__sys_rbac.pg.sql +0 -67
- package/templates/src/app/api/_platform/migrations/0004__sys_rbac.sql +0 -67
- package/templates/src/app/api/_platform/migrations/0005__users_must_change.mysql.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0005__users_must_change.sql +0 -2
- package/templates/src/app/api/_platform/migrations/0006__users_is_forbidden.mysql.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0006__users_is_forbidden.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0007__users_email.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0008__sys_refresh_token.mysql.sql +0 -10
- package/templates/src/app/api/_platform/migrations/0008__sys_refresh_token.pg.sql +0 -10
- package/templates/src/app/api/_platform/migrations/0008__sys_refresh_token.sql +0 -11
- package/templates/src/app/api/_platform/migrations/0009__sys_throttle.mysql.sql +0 -12
- package/templates/src/app/api/_platform/migrations/0009__sys_throttle.pg.sql +0 -12
- package/templates/src/app/api/_platform/migrations/0009__sys_throttle.sql +0 -13
- package/templates/src/app/api/_platform/migrations/0010__sys_solution_route.mysql.sql +0 -17
- package/templates/src/app/api/_platform/migrations/0010__sys_solution_route.pg.sql +0 -16
- package/templates/src/app/api/_platform/migrations/0010__sys_solution_route.sql +0 -18
- package/templates/src/app/api/_platform/migrations/0011__sys_setting_group_label.mysql.sql +0 -2
- package/templates/src/app/api/_platform/migrations/0011__sys_setting_group_label.sql +0 -4
- package/templates/src/app/api/_platform/migrations/0012__market_history.mysql.sql +0 -13
- package/templates/src/app/api/_platform/migrations/0012__market_history.pg.sql +0 -12
- package/templates/src/app/api/_platform/migrations/0012__market_history.sql +0 -14
- package/templates/src/app/api/_platform/migrations/0013__users_profile.sql +0 -4
- package/templates/src/app/api/_platform/migrations/0014__reg_source_seq.mysql.sql +0 -9
- package/templates/src/app/api/_platform/migrations/0014__reg_source_seq.pg.sql +0 -7
- package/templates/src/app/api/_platform/migrations/0014__reg_source_seq.sql +0 -8
- package/templates/src/app/api/_platform/migrations/0015__tenant.mysql.sql +0 -12
- package/templates/src/app/api/_platform/migrations/0015__tenant.pg.sql +0 -11
- package/templates/src/app/api/_platform/migrations/0015__tenant.sql +0 -44
- package/templates/src/app/api/_platform/migrations/0016__org.mysql.sql +0 -41
- package/templates/src/app/api/_platform/migrations/0016__org.pg.sql +0 -40
- package/templates/src/app/api/_platform/migrations/0016__org.sql +0 -62
- package/templates/src/app/api/_platform/migrations/0017__users_employee_no.mysql.sql +0 -7
- package/templates/src/app/api/_platform/migrations/0017__users_employee_no.pg.sql +0 -4
- package/templates/src/app/api/_platform/migrations/0017__users_employee_no.sql +0 -8
- package/templates/src/app/api/_platform/migrations/0018__sys_role_title_key.mysql.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0018__sys_role_title_key.pg.sql +0 -3
- package/templates/src/app/api/_platform/migrations/0018__sys_role_title_key.sql +0 -8
- package/templates/src/app/web/system/pages/login-methods/index.tsx +0 -30
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
// 1. 无 AbortSignal 时调用照常工作(不抛 `AbortSignal is not defined`);
|
|
9
9
|
// 2. 不再把 `signal` 传给 fetch(旧 bug 的根);
|
|
10
10
|
// 3. tasks.sleep 存在 → 慢请求被软超时拦截并抛「超时」文案;
|
|
11
|
-
// 4. tasks 缺失 →
|
|
11
|
+
// 4. tasks 缺失 → 安全降级为「不超时」,快速请求正常返回;
|
|
12
|
+
// 5. 软超时只按短步长 sleep(企微工作台 5-6s 白屏回归)——早期实现挂一条
|
|
13
|
+
// sleep(5000) 做竞态,上游秒回时那条 sleep 仍在飞,oj 运行时要等请求上下文里
|
|
14
|
+
// 所有异步任务结束才 flush 响应,于是每个调企微接口的请求都被白拖到 5s。
|
|
12
15
|
|
|
13
16
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
14
17
|
import { runtimeHttp } from "../src/app/api/auth/_shared/wecom/client";
|
|
@@ -26,6 +29,7 @@ beforeEach(() => {
|
|
|
26
29
|
});
|
|
27
30
|
|
|
28
31
|
afterEach(() => {
|
|
32
|
+
vi.restoreAllMocks();
|
|
29
33
|
Object.defineProperty(globalThis, "AbortSignal", { value: savedAbortSignal, configurable: true, writable: true });
|
|
30
34
|
g.tasks = savedTasks;
|
|
31
35
|
g.fetch = savedFetch;
|
|
@@ -74,8 +78,16 @@ describe("wecom client:无 AbortSignal 的 isolate 不崩(回归)", () =>
|
|
|
74
78
|
|
|
75
79
|
describe("wecom client:软超时(tasks.sleep)", () => {
|
|
76
80
|
it("tasks.sleep 存在时,慢请求被软超时拦截并抛出「超时」文案", async () => {
|
|
77
|
-
//
|
|
78
|
-
|
|
81
|
+
// 假时钟:sleep 不真的等,只推进 Date.now()。软超时按墙钟 deadline 判定、
|
|
82
|
+
// 50ms 一个步长,故 100 步后到点抛超时(测试秒级完成)。
|
|
83
|
+
let now = 0;
|
|
84
|
+
vi.spyOn(Date, "now").mockImplementation(() => now);
|
|
85
|
+
g.tasks = {
|
|
86
|
+
sleep: (ms: number) => {
|
|
87
|
+
now += ms;
|
|
88
|
+
return Promise.resolve();
|
|
89
|
+
},
|
|
90
|
+
};
|
|
79
91
|
let resolveFetch: (v: unknown) => void = () => {};
|
|
80
92
|
const fetchMock = vi.fn(() => new Promise<unknown>((resolve) => {
|
|
81
93
|
resolveFetch = resolve;
|
|
@@ -96,4 +108,22 @@ describe("wecom client:软超时(tasks.sleep)", () => {
|
|
|
96
108
|
const data = await runtimeHttp().getJson("https://qyapi.weixin.qq.com/x");
|
|
97
109
|
expect(data.errcode).toBe(0);
|
|
98
110
|
});
|
|
111
|
+
|
|
112
|
+
it("快速上游只按短步长 sleep,不留 5s 悬挂任务拖住响应(企微工作台白屏回归)", async () => {
|
|
113
|
+
const sleeps: number[] = [];
|
|
114
|
+
g.tasks = {
|
|
115
|
+
sleep: (ms: number) => {
|
|
116
|
+
sleeps.push(ms);
|
|
117
|
+
return Promise.resolve();
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
g.fetch = vi.fn(async () => ({ ok: true, json: async () => ({ errcode: 0 }) }));
|
|
121
|
+
|
|
122
|
+
const data = await runtimeHttp().getJson("https://qyapi.weixin.qq.com/x");
|
|
123
|
+
expect(data.errcode).toBe(0);
|
|
124
|
+
// 旧实现这里会是 [5000]:race 由 fetch 赢,但那条 sleep 仍在请求上下文里飞,
|
|
125
|
+
// 响应只能等它走完才发出去。短步长后每次请求都 <=50ms,主链路结束即收尾。
|
|
126
|
+
expect(sleeps.length).toBeGreaterThan(0);
|
|
127
|
+
expect(Math.max(...sleeps)).toBeLessThanOrEqual(50);
|
|
128
|
+
});
|
|
99
129
|
});
|
|
@@ -4,9 +4,27 @@
|
|
|
4
4
|
// · 落地参数解析必须区分「企微回跳」与「普通打开登录页」(后者不能触发换票);
|
|
5
5
|
// · 参数要裁剪、要能容忍少了 tenant(此时沿用本地租户,不是登录失败);
|
|
6
6
|
// · 授权入口即使没填企业代码也要跳(后端会回 400 说明缺什么,比前端静默不动好排查)。
|
|
7
|
-
import { describe, expect, it } from "vitest";
|
|
7
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
8
|
+
import { getWecomBootError, onInit } from "../src/app/web/login/routes";
|
|
8
9
|
import { parseWecomLanding, wecomAuthorizePath } from "../src/app/web/login/wecom";
|
|
9
10
|
|
|
11
|
+
// p2-C:企微回跳的换票必须发生在首帧 render 之前,且成功后把 URL 改到首页——
|
|
12
|
+
// 否则宿主 shell(无 AuthGuard)会先把登录页画出来再跳,工作台进入时「闪一下」。
|
|
13
|
+
// 这里把 runtime 全部桩掉,只锁 onInit 的编排:谁被调用、顺序、URL 改没改。
|
|
14
|
+
const mocks = vi.hoisted(() => ({
|
|
15
|
+
login: vi.fn(),
|
|
16
|
+
setTenant: vi.fn(),
|
|
17
|
+
registerAuthProvider: vi.fn(),
|
|
18
|
+
replaceState: vi.fn(),
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
vi.mock("@oj-module/runtime", () => ({
|
|
22
|
+
useAuthStore: { getState: () => ({ login: mocks.login }), subscribe: vi.fn() },
|
|
23
|
+
useTenantStore: { getState: () => ({ setTenant: mocks.setTenant, clear: vi.fn() }) },
|
|
24
|
+
getRedirectPath: () => "/home",
|
|
25
|
+
resolveSiteBase: () => "/",
|
|
26
|
+
}));
|
|
27
|
+
|
|
10
28
|
describe("p2-A:回跳落地参数解析", () => {
|
|
11
29
|
it("带齐 ticket 与 tenant → 解析出两者", () => {
|
|
12
30
|
expect(parseWecomLanding("?wecom_ticket=tk_1&tenant=ww_corp_a")).toEqual({ ticket: "tk_1", tenant: "ww_corp_a" });
|
|
@@ -34,6 +52,50 @@ describe("p2-A:回跳落地参数解析", () => {
|
|
|
34
52
|
});
|
|
35
53
|
});
|
|
36
54
|
|
|
55
|
+
describe("p2-C:回跳换票提前到 onInit(登录页不闪)", () => {
|
|
56
|
+
const ctx = { register: { authProvider: mocks.registerAuthProvider } } as never;
|
|
57
|
+
const g = globalThis as any;
|
|
58
|
+
|
|
59
|
+
beforeEach(() => {
|
|
60
|
+
vi.clearAllMocks();
|
|
61
|
+
g.window = { location: { search: "" }, history: { replaceState: mocks.replaceState } };
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("无 ticket:不换票、不改 URL", async () => {
|
|
65
|
+
await onInit(ctx);
|
|
66
|
+
expect(mocks.login).not.toHaveBeenCalled();
|
|
67
|
+
expect(mocks.replaceState).not.toHaveBeenCalled();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("带 ticket:首帧前换票成功,URL 改到首页(登录页不挂载)", async () => {
|
|
71
|
+
g.window.location.search = "?wecom_ticket=tk_1&tenant=ww_corp_a";
|
|
72
|
+
mocks.login.mockResolvedValue(undefined);
|
|
73
|
+
await onInit(ctx);
|
|
74
|
+
expect(mocks.setTenant).toHaveBeenCalledWith("ww_corp_a");
|
|
75
|
+
expect(mocks.login).toHaveBeenCalledTimes(1);
|
|
76
|
+
expect(mocks.login).toHaveBeenCalledWith(expect.objectContaining({ method: "wecom", ticket: "tk_1" }));
|
|
77
|
+
expect(mocks.replaceState).toHaveBeenCalledWith(null, "", "/home");
|
|
78
|
+
expect(getWecomBootError()).toBe("");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("换票失败:错误留给登录页首帧显示表单,不改写 URL", async () => {
|
|
82
|
+
g.window.location.search = "?wecom_ticket=bad&tenant=ww_corp_a";
|
|
83
|
+
mocks.login.mockRejectedValue(new Error("登录票据无效或已使用"));
|
|
84
|
+
await onInit(ctx);
|
|
85
|
+
expect(mocks.replaceState).not.toHaveBeenCalled();
|
|
86
|
+
expect(getWecomBootError()).toContain("登录票据无效或已使用");
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe("p2-D:一键扫码登录路径(不要求用户填企业代码)", () => {
|
|
91
|
+
it("不带 corp/agent 时是纯入口路径,由后端 corpSelf() 自动解析本企业", () => {
|
|
92
|
+
// 登录页「企业微信一键登录」按钮走这条:点一次即跳,用户不必输企业代码。
|
|
93
|
+
// 带上 corp 就退回「先填企业代码再点」的两步式,锁住这个契约。
|
|
94
|
+
expect(wecomAuthorizePath("", "")).toBe("/auth/wecom/login");
|
|
95
|
+
expect(wecomAuthorizePath("", "")).not.toContain("corp=");
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
37
99
|
describe("p2-B:授权入口拼装", () => {
|
|
38
100
|
it("企业代码 → 站内路径(部署前缀由调用方 withSiteBase 拼)", () => {
|
|
39
101
|
expect(wecomAuthorizePath("ww_corp_a")).toBe("/auth/wecom/login?corp=ww_corp_a");
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"#/home/*": ["./src/app/api/home/*"],
|
|
12
12
|
"#/notification/*": ["./src/app/api/notification/*"],
|
|
13
13
|
"#/personal-center/*": ["./src/app/api/personal-center/*"],
|
|
14
|
+
"#/publish/*": ["./src/app/api/publish/*"],
|
|
14
15
|
"#/system/*": ["./src/app/api/system/*"],
|
|
15
16
|
"#/web/*": ["./src/app/api/web/*"]
|
|
16
17
|
}
|
package/templates/web.config.ts
CHANGED
|
@@ -20,7 +20,7 @@ const allModules = [
|
|
|
20
20
|
{ name: "app", entry: "src/app/web/entry.ts" },
|
|
21
21
|
// 解决方案市场:第一方能力(消费 _platform 编排面 /api/_platform/market/*,
|
|
22
22
|
// R29:第三方方案不得仿照此调用面),默认随脚手架下发。保持独立模块——
|
|
23
|
-
//
|
|
23
|
+
// 可选能力,删目录即可下线;发布管理页(/publish)也在这个模块里。
|
|
24
24
|
{ name: "oj-market", entry: "src/oj-market/web/entry.ts" },
|
|
25
25
|
// #region demo-only
|
|
26
26
|
// 以下为模板内置的演示模块(about/access/exception/outside/route-nest),
|
|
@@ -45,15 +45,17 @@ export default {
|
|
|
45
45
|
/**
|
|
46
46
|
* 生成 client 的归属模块:`api 前缀 → 承载其 __client 的 web 模块`。
|
|
47
47
|
*
|
|
48
|
-
*
|
|
49
|
-
* `src/app/web
|
|
50
|
-
*
|
|
48
|
+
* 框架内置后端收在 `src/app/api/<前缀>`(模块名即 URL 前缀),页面多数收在
|
|
49
|
+
* `src/app/web`;发布管理页已迁到方案市场,故 `publish` 的生成物跟页面一起落
|
|
50
|
+
* `src/oj-market/web/publish/__client`。不配则回落同名模块
|
|
51
|
+
* (`src/<api 前缀>/web/__client`,历史行为)。
|
|
51
52
|
*/
|
|
52
53
|
clientOwners: {
|
|
53
54
|
"_platform": "app",
|
|
54
55
|
"auth": "app",
|
|
55
56
|
"home": "app",
|
|
56
57
|
"personal-center": "app",
|
|
58
|
+
"publish": "oj-market",
|
|
57
59
|
"notification": "app",
|
|
58
60
|
"system": "app",
|
|
59
61
|
"web": "app",
|
|
@@ -8,9 +8,9 @@
|
|
|
8
8
|
"react-router": "7.18.2",
|
|
9
9
|
"react-router/dom": "7.18.2",
|
|
10
10
|
"@tanstack/react-query": "5.102.8",
|
|
11
|
-
"@oj-module/runtime": "0.2.
|
|
12
|
-
"@oj-module/runtime/contract": "0.2.
|
|
13
|
-
"@oj-module/runtime/contract/errors": "0.2.
|
|
11
|
+
"@oj-module/runtime": "0.2.67",
|
|
12
|
+
"@oj-module/runtime/contract": "0.2.67",
|
|
13
|
+
"@oj-module/runtime/contract/errors": "0.2.67",
|
|
14
14
|
"@plane/kit": "0.1.20",
|
|
15
15
|
"@plane/editor": "0.1.20",
|
|
16
16
|
"antd": "6.6.1",
|
package/templates/seed.mysql.sql
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
-- 系统设置默认值(PRD §4.3;注释内禁英文分号)
|
|
2
|
-
INSERT IGNORE INTO sys_setting (key, module, `group`, type, value, default_value, label_key, secret, update_time) VALUES ('framework.site_title', 'framework', 'general', 'string', 'React Antd Admin', 'React Antd Admin', 'system:setting.site_title', 0, 0);
|
|
3
|
-
-- 系统设置默认值(PRD §4.3;注释内禁英文分号;framework.market_cdn_url 缺省 /cdn = 本站点自供,免 setup)
|
|
4
|
-
INSERT IGNORE INTO sys_setting (key, module, `group`, type, value, default_value, label_key, secret, update_time) VALUES ('framework.market_cdn_url', 'framework', 'security', 'string', '/cdn', '/cdn', 'system:setting.market_cdn_url', 0, 0);
|
|
5
|
-
INSERT IGNORE INTO sys_setting (key, module, `group`, type, value, default_value, label_key, secret, update_time) VALUES ('ldap.enabled', 'ldap', 'login', 'bool', '0', '0', 'system:setting.ldap_enabled', 0, 0);
|
|
6
|
-
INSERT IGNORE INTO sys_setting (key, module, `group`, type, value, default_value, label_key, secret, update_time) VALUES ('sso.enabled', 'sso', 'login', 'bool', '0', '0', 'system:setting.sso_enabled', 0, 0);
|
package/templates/seed.pg.sql
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
-- 系统设置默认值(PRD §4.3;注释内禁英文分号)
|
|
2
|
-
INSERT INTO sys_setting (key, module, "group", type, value, default_value, label_key, secret, update_time) VALUES ('framework.site_title', 'framework', 'general', 'string', 'React Antd Admin', 'React Antd Admin', 'system:setting.site_title', 0, 0) ON CONFLICT DO NOTHING;
|
|
3
|
-
-- 系统设置默认值(PRD §4.3;注释内禁英文分号;framework.market_cdn_url 缺省 /cdn = 本站点自供,免 setup)
|
|
4
|
-
INSERT INTO sys_setting (key, module, "group", type, value, default_value, label_key, secret, update_time) VALUES ('framework.market_cdn_url', 'framework', 'security', 'string', '/cdn', '/cdn', 'system:setting.market_cdn_url', 0, 0) ON CONFLICT DO NOTHING;
|
|
5
|
-
INSERT INTO sys_setting (key, module, "group", type, value, default_value, label_key, secret, update_time) VALUES ('ldap.enabled', 'ldap', 'login', 'bool', '0', '0', 'system:setting.ldap_enabled', 0, 0) ON CONFLICT DO NOTHING;
|
|
6
|
-
INSERT INTO sys_setting (key, module, "group", type, value, default_value, label_key, secret, update_time) VALUES ('sso.enabled', 'sso', 'login', 'bool', '0', '0', 'system:setting.sso_enabled', 0, 0) ON CONFLICT DO NOTHING;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
-- users 表 mysql 方言覆盖(方言覆盖文件必胜,通用文件兜底,oj-bin docs/migration.md §3.1;约定同 oj-wiki 先例)。
|
|
2
|
-
-- 差异:AUTOINCREMENT → BIGINT AUTO_INCREMENT;username TEXT 改 VARCHAR(255)(mysql TEXT 不能带 UNIQUE);
|
|
3
|
-
-- roles TEXT 默认值写表达式 DEFAULT ('[]')(mysql ≥8.0.13 对 TEXT/BLOB 只允许表达式默认值)。
|
|
4
|
-
CREATE TABLE IF NOT EXISTS users (
|
|
5
|
-
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
6
|
-
username VARCHAR(255) NOT NULL UNIQUE,
|
|
7
|
-
password_hash TEXT NOT NULL,
|
|
8
|
-
roles TEXT NOT NULL DEFAULT ('[]')
|
|
9
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
-- users 表 pg 方言覆盖(方言覆盖文件必胜,oj-bin docs/migration.md §3.1;约定同 oj-wiki 先例)。
|
|
2
|
-
-- 差异:AUTOINCREMENT → BIGSERIAL(GENERATED ALWAYS 系显式插值受限,SERIAL 系允许 seed 显式 id);
|
|
3
|
-
-- username TEXT UNIQUE 在 pg 合法,保留 TEXT。
|
|
4
|
-
CREATE TABLE IF NOT EXISTS users (
|
|
5
|
-
id BIGSERIAL PRIMARY KEY,
|
|
6
|
-
username TEXT NOT NULL UNIQUE,
|
|
7
|
-
password_hash TEXT NOT NULL,
|
|
8
|
-
roles TEXT NOT NULL DEFAULT '[]'
|
|
9
|
-
);
|
package/templates/src/app/api/_platform/migrations/0003__users_source_display_name.mysql.sql
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
-- users 扩展列 mysql 方言覆盖(oj-wiki 0005/0006 先例同型)。
|
|
2
|
-
-- 差异:TEXT 默认值写表达式 DEFAULT ('local');DROP COLUMN mysql 8 原生支持,与基线同语法。
|
|
3
|
-
ALTER TABLE users ADD COLUMN source TEXT NOT NULL DEFAULT ('local');
|
|
4
|
-
ALTER TABLE users ADD COLUMN display_name TEXT;
|
|
5
|
-
ALTER TABLE users DROP COLUMN roles;
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
-- RBAC 地基:users 扩展列 + 移除 roles JSON 列(D10:sys_user_role 表为唯一权威源)
|
|
2
|
-
-- sqlite 方言(ALTER TABLE DROP COLUMN 需 sqlite ≥ 3.35,Node 22 内建满足)
|
|
3
|
-
ALTER TABLE users ADD COLUMN source TEXT NOT NULL DEFAULT 'local';
|
|
4
|
-
ALTER TABLE users ADD COLUMN display_name TEXT;
|
|
5
|
-
ALTER TABLE users DROP COLUMN roles;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
-- 框架 RBAC 六表 mysql 方言覆盖(sqlite 版见 0004__sys_rbac.sql;oj-wiki 先例同型)。
|
|
2
|
-
-- 差异:保留字反引号(mysql 默认 sql_mode 下双引号是字符串字面量);
|
|
3
|
-
-- AUTO_INCREMENT 替 AUTOINCREMENT,id 取 BIGINT(与 users 同宽度口径);
|
|
4
|
-
-- 主键/默认值 TEXT → VARCHAR(255) / 表达式默认值(mysql TEXT 不能作主键、不能直接带默认值)。
|
|
5
|
-
CREATE TABLE IF NOT EXISTS sys_setting (
|
|
6
|
-
`key` VARCHAR(255) PRIMARY KEY,
|
|
7
|
-
module TEXT NOT NULL,
|
|
8
|
-
`group` TEXT NOT NULL,
|
|
9
|
-
type TEXT NOT NULL DEFAULT ('string'),
|
|
10
|
-
value TEXT,
|
|
11
|
-
default_value TEXT,
|
|
12
|
-
label_key TEXT,
|
|
13
|
-
options TEXT,
|
|
14
|
-
secret BIGINT NOT NULL DEFAULT 0,
|
|
15
|
-
update_time BIGINT NOT NULL DEFAULT 0
|
|
16
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
17
|
-
|
|
18
|
-
CREATE TABLE IF NOT EXISTS sys_oplog (
|
|
19
|
-
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
|
20
|
-
create_time BIGINT NOT NULL,
|
|
21
|
-
user_id BIGINT NOT NULL DEFAULT 0,
|
|
22
|
-
username TEXT NOT NULL DEFAULT ('system'),
|
|
23
|
-
action TEXT NOT NULL,
|
|
24
|
-
module TEXT NOT NULL DEFAULT ('framework'),
|
|
25
|
-
version TEXT,
|
|
26
|
-
target TEXT,
|
|
27
|
-
detail TEXT,
|
|
28
|
-
level BIGINT NOT NULL DEFAULT 6
|
|
29
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
30
|
-
-- mysql 无 CREATE INDEX IF NOT EXISTS;迁移账本保证一次应用(oj-bin docs/migration.md 语义)
|
|
31
|
-
CREATE INDEX idx_sys_oplog_time ON sys_oplog (create_time, id);
|
|
32
|
-
|
|
33
|
-
CREATE TABLE IF NOT EXISTS sys_solution_route (
|
|
34
|
-
name VARCHAR(255) NOT NULL,
|
|
35
|
-
version VARCHAR(255) NOT NULL,
|
|
36
|
-
category TEXT NOT NULL,
|
|
37
|
-
path VARCHAR(255) NOT NULL,
|
|
38
|
-
`order` BIGINT NOT NULL DEFAULT 0,
|
|
39
|
-
title_key TEXT,
|
|
40
|
-
enabled BIGINT NOT NULL DEFAULT 1,
|
|
41
|
-
PRIMARY KEY (name, version, path)
|
|
42
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
43
|
-
|
|
44
|
-
CREATE TABLE IF NOT EXISTS sys_role (
|
|
45
|
-
name VARCHAR(255) PRIMARY KEY,
|
|
46
|
-
module TEXT NOT NULL,
|
|
47
|
-
title TEXT,
|
|
48
|
-
description TEXT,
|
|
49
|
-
builtin BIGINT NOT NULL DEFAULT 0,
|
|
50
|
-
deprecated BIGINT NOT NULL DEFAULT 0
|
|
51
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
52
|
-
|
|
53
|
-
CREATE TABLE IF NOT EXISTS sys_permission (
|
|
54
|
-
code VARCHAR(255) PRIMARY KEY,
|
|
55
|
-
module TEXT NOT NULL,
|
|
56
|
-
title_key TEXT,
|
|
57
|
-
deprecated BIGINT NOT NULL DEFAULT 0
|
|
58
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
59
|
-
|
|
60
|
-
CREATE TABLE IF NOT EXISTS sys_role_permission (
|
|
61
|
-
role_name VARCHAR(255) NOT NULL,
|
|
62
|
-
permission_code VARCHAR(255) NOT NULL,
|
|
63
|
-
PRIMARY KEY (role_name, permission_code)
|
|
64
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
65
|
-
|
|
66
|
-
CREATE TABLE IF NOT EXISTS sys_user_role (
|
|
67
|
-
user_id BIGINT NOT NULL,
|
|
68
|
-
role_name VARCHAR(255) NOT NULL,
|
|
69
|
-
PRIMARY KEY (user_id, role_name)
|
|
70
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
-- 框架 RBAC 六表 pg 方言覆盖(sqlite 版见 0004__sys_rbac.sql;oj-wiki 先例同型)。
|
|
2
|
-
-- 差异:双引号保留字与 TEXT 主键 pg 原生支持(与 sqlite 同语法);id 取 BIGSERIAL(同 0001.pg 先例)。
|
|
3
|
-
CREATE TABLE IF NOT EXISTS sys_setting (
|
|
4
|
-
key TEXT PRIMARY KEY,
|
|
5
|
-
module TEXT NOT NULL,
|
|
6
|
-
"group" TEXT NOT NULL,
|
|
7
|
-
type TEXT NOT NULL DEFAULT 'string',
|
|
8
|
-
value TEXT,
|
|
9
|
-
default_value TEXT,
|
|
10
|
-
label_key TEXT,
|
|
11
|
-
options TEXT,
|
|
12
|
-
secret INTEGER NOT NULL DEFAULT 0,
|
|
13
|
-
update_time INTEGER NOT NULL DEFAULT 0
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
CREATE TABLE IF NOT EXISTS sys_oplog (
|
|
17
|
-
id BIGSERIAL PRIMARY KEY,
|
|
18
|
-
create_time INTEGER NOT NULL,
|
|
19
|
-
user_id INTEGER NOT NULL DEFAULT 0,
|
|
20
|
-
username TEXT NOT NULL DEFAULT 'system',
|
|
21
|
-
action TEXT NOT NULL,
|
|
22
|
-
module TEXT NOT NULL DEFAULT 'framework',
|
|
23
|
-
version TEXT,
|
|
24
|
-
target TEXT,
|
|
25
|
-
detail TEXT,
|
|
26
|
-
level INTEGER NOT NULL DEFAULT 6
|
|
27
|
-
);
|
|
28
|
-
CREATE INDEX IF NOT EXISTS idx_sys_oplog_time ON sys_oplog (create_time, id);
|
|
29
|
-
|
|
30
|
-
CREATE TABLE IF NOT EXISTS sys_solution_route (
|
|
31
|
-
name TEXT NOT NULL,
|
|
32
|
-
version TEXT NOT NULL,
|
|
33
|
-
category TEXT NOT NULL,
|
|
34
|
-
path TEXT NOT NULL,
|
|
35
|
-
"order" INTEGER NOT NULL DEFAULT 0,
|
|
36
|
-
title_key TEXT,
|
|
37
|
-
enabled INTEGER NOT NULL DEFAULT 1,
|
|
38
|
-
PRIMARY KEY (name, version, path)
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
CREATE TABLE IF NOT EXISTS sys_role (
|
|
42
|
-
name TEXT PRIMARY KEY,
|
|
43
|
-
module TEXT NOT NULL,
|
|
44
|
-
title TEXT,
|
|
45
|
-
description TEXT,
|
|
46
|
-
builtin INTEGER NOT NULL DEFAULT 0,
|
|
47
|
-
deprecated INTEGER NOT NULL DEFAULT 0
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
CREATE TABLE IF NOT EXISTS sys_permission (
|
|
51
|
-
code TEXT PRIMARY KEY,
|
|
52
|
-
module TEXT NOT NULL,
|
|
53
|
-
title_key TEXT,
|
|
54
|
-
deprecated INTEGER NOT NULL DEFAULT 0
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
CREATE TABLE IF NOT EXISTS sys_role_permission (
|
|
58
|
-
role_name TEXT NOT NULL,
|
|
59
|
-
permission_code TEXT NOT NULL,
|
|
60
|
-
PRIMARY KEY (role_name, permission_code)
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
CREATE TABLE IF NOT EXISTS sys_user_role (
|
|
64
|
-
user_id INTEGER NOT NULL,
|
|
65
|
-
role_name TEXT NOT NULL,
|
|
66
|
-
PRIMARY KEY (user_id, role_name)
|
|
67
|
-
);
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
-- 框架 RBAC 六表(设计文档 §5.9.2;判权权威源 + 升级稳定性 deprecated 的地基)
|
|
2
|
-
-- sqlite 方言;mysql/pg 方言变体在阶段 A 冒烟时补齐
|
|
3
|
-
CREATE TABLE IF NOT EXISTS sys_setting (
|
|
4
|
-
key TEXT PRIMARY KEY,
|
|
5
|
-
module TEXT NOT NULL,
|
|
6
|
-
"group" TEXT NOT NULL,
|
|
7
|
-
type TEXT NOT NULL DEFAULT 'string',
|
|
8
|
-
value TEXT,
|
|
9
|
-
default_value TEXT,
|
|
10
|
-
label_key TEXT,
|
|
11
|
-
options TEXT,
|
|
12
|
-
secret INTEGER NOT NULL DEFAULT 0,
|
|
13
|
-
update_time INTEGER NOT NULL DEFAULT 0
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
CREATE TABLE IF NOT EXISTS sys_oplog (
|
|
17
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
18
|
-
create_time INTEGER NOT NULL,
|
|
19
|
-
user_id INTEGER NOT NULL DEFAULT 0,
|
|
20
|
-
username TEXT NOT NULL DEFAULT 'system',
|
|
21
|
-
action TEXT NOT NULL,
|
|
22
|
-
module TEXT NOT NULL DEFAULT 'framework',
|
|
23
|
-
version TEXT,
|
|
24
|
-
target TEXT,
|
|
25
|
-
detail TEXT,
|
|
26
|
-
level INTEGER NOT NULL DEFAULT 6
|
|
27
|
-
);
|
|
28
|
-
CREATE INDEX IF NOT EXISTS idx_sys_oplog_time ON sys_oplog (create_time, id);
|
|
29
|
-
|
|
30
|
-
CREATE TABLE IF NOT EXISTS sys_solution_route (
|
|
31
|
-
name TEXT NOT NULL,
|
|
32
|
-
version TEXT NOT NULL,
|
|
33
|
-
category TEXT NOT NULL,
|
|
34
|
-
path TEXT NOT NULL,
|
|
35
|
-
"order" INTEGER NOT NULL DEFAULT 0,
|
|
36
|
-
title_key TEXT,
|
|
37
|
-
enabled INTEGER NOT NULL DEFAULT 1,
|
|
38
|
-
PRIMARY KEY (name, version, path)
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
CREATE TABLE IF NOT EXISTS sys_role (
|
|
42
|
-
name TEXT PRIMARY KEY,
|
|
43
|
-
module TEXT NOT NULL,
|
|
44
|
-
title TEXT,
|
|
45
|
-
description TEXT,
|
|
46
|
-
builtin INTEGER NOT NULL DEFAULT 0,
|
|
47
|
-
deprecated INTEGER NOT NULL DEFAULT 0
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
CREATE TABLE IF NOT EXISTS sys_permission (
|
|
51
|
-
code TEXT PRIMARY KEY,
|
|
52
|
-
module TEXT NOT NULL,
|
|
53
|
-
title_key TEXT,
|
|
54
|
-
deprecated INTEGER NOT NULL DEFAULT 0
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
CREATE TABLE IF NOT EXISTS sys_role_permission (
|
|
58
|
-
role_name TEXT NOT NULL,
|
|
59
|
-
permission_code TEXT NOT NULL,
|
|
60
|
-
PRIMARY KEY (role_name, permission_code)
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
CREATE TABLE IF NOT EXISTS sys_user_role (
|
|
64
|
-
user_id INTEGER NOT NULL,
|
|
65
|
-
role_name TEXT NOT NULL,
|
|
66
|
-
PRIMARY KEY (user_id, role_name)
|
|
67
|
-
);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
-- refresh token 存储 mysql 方言覆盖(sqlite 版见 0008__sys_refresh_token.sql;oj-wiki 先例同型)。
|
|
2
|
-
-- 差异:整型列取 BIGINT;CREATE INDEX 无 IF NOT EXISTS(迁移账本一次应用语义兜底)。
|
|
3
|
-
CREATE TABLE IF NOT EXISTS sys_refresh_token (
|
|
4
|
-
token_hash VARCHAR(255) PRIMARY KEY,
|
|
5
|
-
user_id BIGINT NOT NULL,
|
|
6
|
-
expires_at BIGINT NOT NULL,
|
|
7
|
-
revoked BIGINT NOT NULL DEFAULT 0,
|
|
8
|
-
created_at BIGINT NOT NULL
|
|
9
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
10
|
-
CREATE INDEX idx_sys_refresh_token_user ON sys_refresh_token (user_id);
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
-- refresh token 存储 pg 方言覆盖(sqlite 版见 0008__sys_refresh_token.sql;oj-wiki 先例同型)。
|
|
2
|
-
-- 差异:无(TEXT 主键与 CREATE INDEX IF NOT EXISTS pg 原生支持,与 sqlite 同语法)。
|
|
3
|
-
CREATE TABLE IF NOT EXISTS sys_refresh_token (
|
|
4
|
-
token_hash TEXT PRIMARY KEY,
|
|
5
|
-
user_id INTEGER NOT NULL,
|
|
6
|
-
expires_at INTEGER NOT NULL,
|
|
7
|
-
revoked INTEGER NOT NULL DEFAULT 0,
|
|
8
|
-
created_at INTEGER NOT NULL
|
|
9
|
-
);
|
|
10
|
-
CREATE INDEX IF NOT EXISTS idx_sys_refresh_token_user ON sys_refresh_token (user_id);
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
-- refresh token 存储(设计 §3.1:不透明随机串,DB 存 SHA-256 哈希——A1 六表未含,B1 实现期补)。
|
|
2
|
-
-- 轮换作旧(revoked 标记);reuse 检测 = 已吊销串二次出现 → 按 user_id 全族吊销 + 审计;
|
|
3
|
-
-- is_forbidden=1 或重置口令 → 级联删该用户全部记录(§3.1 吊销联动)。
|
|
4
|
-
CREATE TABLE IF NOT EXISTS sys_refresh_token (
|
|
5
|
-
token_hash TEXT PRIMARY KEY,
|
|
6
|
-
user_id INTEGER NOT NULL,
|
|
7
|
-
expires_at INTEGER NOT NULL,
|
|
8
|
-
revoked INTEGER NOT NULL DEFAULT 0,
|
|
9
|
-
created_at INTEGER NOT NULL
|
|
10
|
-
);
|
|
11
|
-
CREATE INDEX IF NOT EXISTS idx_sys_refresh_token_user ON sys_refresh_token (user_id);
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
-- 限速/登录节流状态落库 mysql 方言覆盖(sqlite 版见 0009__sys_throttle.sql;oj-wiki 先例同型)。
|
|
2
|
-
-- 差异:整型列取 BIGINT;rate_key 避开 MySQL 保留字 key。
|
|
3
|
-
CREATE TABLE IF NOT EXISTS sys_rate_window (
|
|
4
|
-
rate_key VARCHAR(255) PRIMARY KEY,
|
|
5
|
-
window_start BIGINT NOT NULL,
|
|
6
|
-
count BIGINT NOT NULL
|
|
7
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
8
|
-
CREATE TABLE IF NOT EXISTS sys_login_throttle (
|
|
9
|
-
pair_key VARCHAR(255) PRIMARY KEY,
|
|
10
|
-
fail_count BIGINT NOT NULL,
|
|
11
|
-
blocked_until BIGINT NOT NULL DEFAULT 0
|
|
12
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
-- 限速/登录节流状态落库 pg 方言覆盖(sqlite 版见 0009__sys_throttle.sql;oj-wiki 先例同型)。
|
|
2
|
-
-- 差异:无(TEXT 主键三方言同语法)。
|
|
3
|
-
CREATE TABLE IF NOT EXISTS sys_rate_window (
|
|
4
|
-
rate_key TEXT PRIMARY KEY,
|
|
5
|
-
window_start INTEGER NOT NULL,
|
|
6
|
-
count INTEGER NOT NULL
|
|
7
|
-
);
|
|
8
|
-
CREATE TABLE IF NOT EXISTS sys_login_throttle (
|
|
9
|
-
pair_key TEXT PRIMARY KEY,
|
|
10
|
-
fail_count INTEGER NOT NULL,
|
|
11
|
-
blocked_until INTEGER NOT NULL DEFAULT 0
|
|
12
|
-
);
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
-- 限速/登录节流状态落库(反常识修正:oj 运行时每请求重建模块实例,进程内 Map 不跨请求存活——
|
|
2
|
-
-- B5 连败阈值与接口滑动窗口在真实运行时恒失效;状态持久化后重启保留、多实例天然同源,
|
|
3
|
-
-- 原先「多实例换 Redis」的已知上限就此消除)。
|
|
4
|
-
CREATE TABLE IF NOT EXISTS sys_rate_window (
|
|
5
|
-
rate_key TEXT PRIMARY KEY,
|
|
6
|
-
window_start INTEGER NOT NULL,
|
|
7
|
-
count INTEGER NOT NULL
|
|
8
|
-
);
|
|
9
|
-
CREATE TABLE IF NOT EXISTS sys_login_throttle (
|
|
10
|
-
pair_key TEXT PRIMARY KEY,
|
|
11
|
-
fail_count INTEGER NOT NULL,
|
|
12
|
-
blocked_until INTEGER NOT NULL DEFAULT 0
|
|
13
|
-
);
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
-- 方案注册路由表重构 mysql 方言覆盖(sqlite 版见 0010__sys_solution_route.sql)。
|
|
2
|
-
-- 差异:保留字反引号;整型列取 BIGINT;主键 TEXT → VARCHAR(255);
|
|
3
|
-
-- ALTER ADD COLUMN / CREATE INDEX 无 IF NOT EXISTS(迁移账本一次应用语义兜底,同 0008)。
|
|
4
|
-
ALTER TABLE sys_setting ADD COLUMN deprecated BIGINT NOT NULL DEFAULT 0;
|
|
5
|
-
|
|
6
|
-
DROP TABLE IF EXISTS sys_solution_route;
|
|
7
|
-
CREATE TABLE sys_solution_route (
|
|
8
|
-
path VARCHAR(255) PRIMARY KEY,
|
|
9
|
-
module TEXT NOT NULL,
|
|
10
|
-
category TEXT NOT NULL,
|
|
11
|
-
`order` BIGINT NOT NULL DEFAULT 0,
|
|
12
|
-
title_key TEXT,
|
|
13
|
-
required_permission TEXT,
|
|
14
|
-
deprecated BIGINT NOT NULL DEFAULT 0,
|
|
15
|
-
enabled BIGINT NOT NULL DEFAULT 1
|
|
16
|
-
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
17
|
-
CREATE INDEX idx_sys_solution_route_module ON sys_solution_route (module);
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
-- 方案注册路由表重构 pg 方言覆盖(sqlite 版见 0010__sys_solution_route.sql)。
|
|
2
|
-
-- 差异:无(ADD COLUMN / DROP TABLE / 双引号保留字 / CREATE INDEX IF NOT EXISTS pg 原生支持)。
|
|
3
|
-
ALTER TABLE sys_setting ADD COLUMN deprecated INTEGER NOT NULL DEFAULT 0;
|
|
4
|
-
|
|
5
|
-
DROP TABLE IF EXISTS sys_solution_route;
|
|
6
|
-
CREATE TABLE sys_solution_route (
|
|
7
|
-
path TEXT PRIMARY KEY,
|
|
8
|
-
module TEXT NOT NULL,
|
|
9
|
-
category TEXT NOT NULL,
|
|
10
|
-
"order" INTEGER NOT NULL DEFAULT 0,
|
|
11
|
-
title_key TEXT,
|
|
12
|
-
required_permission TEXT,
|
|
13
|
-
deprecated INTEGER NOT NULL DEFAULT 0,
|
|
14
|
-
enabled INTEGER NOT NULL DEFAULT 1
|
|
15
|
-
);
|
|
16
|
-
CREATE INDEX IF NOT EXISTS idx_sys_solution_route_module ON sys_solution_route (module);
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
-- 方案注册路由表重构(P1-8,D10 注册唯一出口的落点):0004 版以 (name, version, path) 为主键、
|
|
2
|
-
-- 无 module/required_permission/deprecated 列,与「站点级路由注册(path 唯一 + 声明消失标
|
|
3
|
-
-- deprecated,镜像 AC2-3/4)」的语义不兼容;旧表从未被运行时读写(仅存在性断言),DROP 重建零数据损失。
|
|
4
|
-
-- 同时为 sys_setting 补 deprecated 列:设置定义行声明消失同样保留标 deprecated(P1-8 register 语义)。
|
|
5
|
-
ALTER TABLE sys_setting ADD COLUMN deprecated INTEGER NOT NULL DEFAULT 0;
|
|
6
|
-
|
|
7
|
-
DROP TABLE IF EXISTS sys_solution_route;
|
|
8
|
-
CREATE TABLE sys_solution_route (
|
|
9
|
-
path TEXT PRIMARY KEY,
|
|
10
|
-
module TEXT NOT NULL,
|
|
11
|
-
category TEXT NOT NULL,
|
|
12
|
-
"order" INTEGER NOT NULL DEFAULT 0,
|
|
13
|
-
title_key TEXT,
|
|
14
|
-
required_permission TEXT,
|
|
15
|
-
deprecated INTEGER NOT NULL DEFAULT 0,
|
|
16
|
-
enabled INTEGER NOT NULL DEFAULT 1
|
|
17
|
-
);
|
|
18
|
-
CREATE INDEX IF NOT EXISTS idx_sys_solution_route_module ON sys_solution_route (module);
|