refactor(api): migrate to audience-scoped routes
This commit is contained in:
14
README.md
14
README.md
@@ -42,18 +42,18 @@ VITE_DEV_API_TARGET=http://localhost:5090
|
||||
| `/manage/*` | 必须通过租户 Backoffice Bootstrap;无 Permission 的账号统一显示 404 |
|
||||
| `/__demo` | 仅开发环境存在的生命周期启动器 |
|
||||
|
||||
后台菜单来自 `GET /api/backoffice/tenant/ui-bootstrap`。进入站点设计还必须包含 `tenant:settings:manage`,前端隐藏菜单不能替代后端 401/403。
|
||||
后台菜单来自 `GET /api/tenant/access/ui-bootstrap`。进入站点设计还必须包含 `tenant:settings:manage`,前端隐藏菜单不能替代后端 401/403。
|
||||
|
||||
## 前后端契约
|
||||
|
||||
当前前端 Facade 对齐以下接口:
|
||||
|
||||
- `GET /api/runtime/bootstrap`
|
||||
- `POST /api/browser-auth/activation/complete`
|
||||
- `POST /api/browser-auth/login/password`
|
||||
- `GET /api/backoffice/tenant/ui-bootstrap`
|
||||
- `GET /api/tenant-onboarding/status`
|
||||
- `GET|PUT|POST /api/tenant-admin/frontend-config/**`
|
||||
- `GET /api/public/runtime/bootstrap`
|
||||
- `POST /api/tenant/auth/browser/activation/complete`
|
||||
- `POST /api/tenant/auth/browser/login/password`
|
||||
- `GET /api/tenant/access/ui-bootstrap`
|
||||
- `GET /api/tenant/onboarding/status`
|
||||
- `GET|PUT|POST /api/tenant/frontend-config/**`
|
||||
|
||||
Browser Auth 激活接口会在完成密码设置后签发 HttpOnly Session Cookie;后续写请求从 `__Host-tiku-csrf` Cookie 读取双提交 Token,并发送 `X-CSRF-Token`。
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@ import { apiRequest } from './http';
|
||||
|
||||
export const authApi = {
|
||||
completeOwnerActivation: (request: BrowserOwnerActivationRequest) =>
|
||||
apiRequest<BrowserAuthenticationResult>('/api/browser-auth/activation/complete', {
|
||||
apiRequest<BrowserAuthenticationResult>('/api/tenant/auth/browser/activation/complete', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(request),
|
||||
}),
|
||||
login: (request: LoginRequest) => apiRequest<BrowserAuthenticationResult>('/api/browser-auth/login/password', {
|
||||
login: (request: LoginRequest) => apiRequest<BrowserAuthenticationResult>('/api/tenant/auth/browser/login/password', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ ...request, realm: 'Tenant' }),
|
||||
}),
|
||||
logout: () => apiRequest<void>('/api/browser-auth/logout', { method: 'POST' }),
|
||||
logout: () => apiRequest<void>('/api/tenant/auth/browser/logout', { method: 'POST' }),
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ const supportedMenuRoutes: Record<string, { path: string; requiresSiteSettings?:
|
||||
|
||||
export const backofficeApi = {
|
||||
bootstrap: async (): Promise<BackofficeBootstrap> => {
|
||||
const response = await apiRequest<BackofficeUiBootstrapResponse>('/api/backoffice/tenant/ui-bootstrap');
|
||||
const response = await apiRequest<BackofficeUiBootstrapResponse>('/api/tenant/access/ui-bootstrap');
|
||||
return {
|
||||
permissions: response.permissionCodes,
|
||||
enabledFeatures: response.enabledFeatures,
|
||||
|
||||
@@ -2,5 +2,5 @@ import type { TenantOnboardingStatus } from '../contracts';
|
||||
import { apiRequest } from './http';
|
||||
|
||||
export const onboardingApi = {
|
||||
status: () => apiRequest<TenantOnboardingStatus>('/api/tenant-onboarding/status'),
|
||||
status: () => apiRequest<TenantOnboardingStatus>('/api/tenant/onboarding/status'),
|
||||
};
|
||||
|
||||
@@ -2,5 +2,5 @@ import type { TenantRuntimeBootstrap } from '../contracts';
|
||||
import { apiRequest } from './http';
|
||||
|
||||
export const runtimeApi = {
|
||||
bootstrap: () => apiRequest<TenantRuntimeBootstrap>('/api/runtime/bootstrap'),
|
||||
bootstrap: () => apiRequest<TenantRuntimeBootstrap>('/api/public/runtime/bootstrap'),
|
||||
};
|
||||
|
||||
@@ -2,14 +2,14 @@ import type { TenantFrontendConfigDraft, TenantSiteConfig } from '../contracts';
|
||||
import { apiRequest } from './http';
|
||||
|
||||
export const siteConfigApi = {
|
||||
get: () => apiRequest<TenantSiteConfig>('/api/tenant-admin/frontend-config'),
|
||||
get: () => apiRequest<TenantSiteConfig>('/api/tenant/frontend-config'),
|
||||
saveDraft: (draft: TenantFrontendConfigDraft) =>
|
||||
apiRequest<TenantSiteConfig>('/api/tenant-admin/frontend-config/draft', {
|
||||
apiRequest<TenantSiteConfig>('/api/tenant/frontend-config/draft', {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(draft),
|
||||
}),
|
||||
publish: (expectedVersion: number) =>
|
||||
apiRequest<TenantSiteConfig>('/api/tenant-admin/frontend-config/publish', {
|
||||
apiRequest<TenantSiteConfig>('/api/tenant/frontend-config/publish', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ expectedVersion }),
|
||||
}),
|
||||
|
||||
@@ -23,9 +23,9 @@ function problem(error: unknown) {
|
||||
}
|
||||
|
||||
export const handlers = [
|
||||
http.get('/api/runtime/bootstrap', ({ request }) => HttpResponse.json(runtimeOf(ensureTenant(hostOf(request))))),
|
||||
http.get('/api/public/runtime/bootstrap', ({ request }) => HttpResponse.json(runtimeOf(ensureTenant(hostOf(request))))),
|
||||
|
||||
http.post('/api/browser-auth/activation/complete', async ({ request }) => {
|
||||
http.post('/api/tenant/auth/browser/activation/complete', async ({ request }) => {
|
||||
try {
|
||||
const body = await request.json() as BrowserOwnerActivationRequest;
|
||||
return HttpResponse.json({ status: 'Authenticated', user: activateOwner(hostOf(request), body) });
|
||||
@@ -34,7 +34,7 @@ export const handlers = [
|
||||
}
|
||||
}),
|
||||
|
||||
http.post('/api/browser-auth/login/password', async ({ request }) => {
|
||||
http.post('/api/tenant/auth/browser/login/password', async ({ request }) => {
|
||||
const host = hostOf(request);
|
||||
const body = await request.json() as LoginRequest;
|
||||
const state = ensureTenant(host);
|
||||
@@ -50,12 +50,12 @@ export const handlers = [
|
||||
return HttpResponse.json({ status: 'Authenticated', user: next.session!.user });
|
||||
}),
|
||||
|
||||
http.post('/api/browser-auth/logout', ({ request }) => {
|
||||
http.post('/api/tenant/auth/browser/logout', ({ request }) => {
|
||||
updateTenant(hostOf(request), state => { state.session = null; });
|
||||
return new HttpResponse(null, { status: 204 });
|
||||
}),
|
||||
|
||||
http.get('/api/backoffice/tenant/ui-bootstrap', ({ request }) => {
|
||||
http.get('/api/tenant/access/ui-bootstrap', ({ request }) => {
|
||||
try {
|
||||
const bootstrap = backofficeOf(ensureTenant(hostOf(request)));
|
||||
return HttpResponse.json({
|
||||
@@ -73,7 +73,7 @@ export const handlers = [
|
||||
}
|
||||
}),
|
||||
|
||||
http.get('/api/tenant-onboarding/status', ({ request }) => {
|
||||
http.get('/api/tenant/onboarding/status', ({ request }) => {
|
||||
try {
|
||||
const state = ensureTenant(hostOf(request));
|
||||
backofficeOf(state);
|
||||
@@ -83,7 +83,7 @@ export const handlers = [
|
||||
}
|
||||
}),
|
||||
|
||||
http.get('/api/tenant-admin/frontend-config', ({ request }) => {
|
||||
http.get('/api/tenant/frontend-config', ({ request }) => {
|
||||
try {
|
||||
const state = ensureTenant(hostOf(request));
|
||||
const bootstrap = backofficeOf(state);
|
||||
@@ -94,7 +94,7 @@ export const handlers = [
|
||||
}
|
||||
}),
|
||||
|
||||
http.put('/api/tenant-admin/frontend-config/draft', async ({ request }) => {
|
||||
http.put('/api/tenant/frontend-config/draft', async ({ request }) => {
|
||||
try {
|
||||
const host = hostOf(request);
|
||||
const state = ensureTenant(host);
|
||||
@@ -108,7 +108,7 @@ export const handlers = [
|
||||
}
|
||||
}),
|
||||
|
||||
http.post('/api/tenant-admin/frontend-config/publish', async ({ request }) => {
|
||||
http.post('/api/tenant/frontend-config/publish', async ({ request }) => {
|
||||
try {
|
||||
const host = hostOf(request);
|
||||
const state = ensureTenant(host);
|
||||
|
||||
Reference in New Issue
Block a user