Harden wechat summary and login input
This commit is contained in:
+101
-3
@@ -16,6 +16,11 @@ import type {
|
||||
SkillDefinition,
|
||||
SkillMap,
|
||||
UsageRecord,
|
||||
WechatAdminSummary,
|
||||
WechatBinding,
|
||||
WechatDeliveryLog,
|
||||
WechatDigestSubscription,
|
||||
WechatMessage,
|
||||
} from '../types';
|
||||
|
||||
export class ApiError extends Error {
|
||||
@@ -94,6 +99,7 @@ async function portalFetch<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
try {
|
||||
res = await fetch(path, {
|
||||
...init,
|
||||
credentials: 'include',
|
||||
headers: { 'Content-Type': 'application/json', ...init?.headers },
|
||||
});
|
||||
} catch (err) {
|
||||
@@ -119,7 +125,7 @@ async function portalFetch<T>(path: string, init?: RequestInit): Promise<T> {
|
||||
|
||||
export async function checkAuth(): Promise<AuthStatus> {
|
||||
try {
|
||||
const response = await fetch('/auth/status');
|
||||
const response = await fetch('/auth/status', { credentials: 'include' });
|
||||
if (!response.ok) return { authenticated: false };
|
||||
const status = (await response.json()) as AuthStatus;
|
||||
if (status.authenticated) resetUnauthorizedGuard();
|
||||
@@ -134,6 +140,7 @@ export async function login(username: string, password: string): Promise<PortalU
|
||||
try {
|
||||
response = await fetch('/auth/login', {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ username, password }),
|
||||
});
|
||||
@@ -152,8 +159,7 @@ export async function login(username: string, password: string): Promise<PortalU
|
||||
}
|
||||
|
||||
export async function logout(): Promise<void> {
|
||||
if (import.meta.env.DEV) return;
|
||||
await fetch('/auth/logout', { method: 'POST' });
|
||||
await fetch('/auth/logout', { method: 'POST', credentials: 'include' });
|
||||
}
|
||||
|
||||
// ── Pagination helpers ────────────────────────────────
|
||||
@@ -207,6 +213,98 @@ export async function listAdminLedger(params?: {
|
||||
return { items: result.entries ?? [], total, page: result.page ?? 1, pageSize, totalPages: Math.ceil(total / pageSize) };
|
||||
}
|
||||
|
||||
// ── WeChat MP ─────────────────────────────────────────
|
||||
|
||||
export async function getWechatAdminSummary(): Promise<WechatAdminSummary> {
|
||||
const summary = await portalFetch<Partial<WechatAdminSummary>>('/admin-api/wechat/summary');
|
||||
return {
|
||||
config: {
|
||||
mpEnabled: summary.config?.mpEnabled ?? false,
|
||||
scheduleEnabled: summary.config?.scheduleEnabled ?? false,
|
||||
reminderWorkerEnabled: summary.config?.reminderWorkerEnabled ?? false,
|
||||
appId: summary.config?.appId ?? null,
|
||||
publicBaseUrl: summary.config?.publicBaseUrl ?? null,
|
||||
bindPath: summary.config?.bindPath ?? null,
|
||||
tokenEndpointConfigured: summary.config?.tokenEndpointConfigured ?? false,
|
||||
customerServiceEndpointConfigured: summary.config?.customerServiceEndpointConfigured ?? false,
|
||||
},
|
||||
counts: {
|
||||
boundUsers: summary.counts?.boundUsers ?? 0,
|
||||
routes: {
|
||||
total: summary.counts?.routes?.total ?? 0,
|
||||
active: summary.counts?.routes?.active ?? 0,
|
||||
},
|
||||
recentMessages: summary.counts?.recentMessages ?? {},
|
||||
digests: summary.counts?.digests ?? {},
|
||||
recentDeliveries: summary.counts?.recentDeliveries ?? {},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function listWechatBindings(params?: {
|
||||
search?: string;
|
||||
limit?: number;
|
||||
}): Promise<WechatBinding[]> {
|
||||
const q = new URLSearchParams();
|
||||
if (params?.search) q.set('search', params.search);
|
||||
if (params?.limit) q.set('limit', String(params.limit));
|
||||
const result = await portalFetch<{ bindings: WechatBinding[] }>(
|
||||
`/admin-api/wechat/bindings${q.toString() ? `?${q}` : ''}`,
|
||||
);
|
||||
return result.bindings ?? [];
|
||||
}
|
||||
|
||||
export async function listWechatMessages(params?: {
|
||||
status?: string;
|
||||
limit?: number;
|
||||
}): Promise<WechatMessage[]> {
|
||||
const q = new URLSearchParams();
|
||||
if (params?.status) q.set('status', params.status);
|
||||
if (params?.limit) q.set('limit', String(params.limit));
|
||||
const result = await portalFetch<{ messages: WechatMessage[] }>(
|
||||
`/admin-api/wechat/messages${q.toString() ? `?${q}` : ''}`,
|
||||
);
|
||||
return result.messages ?? [];
|
||||
}
|
||||
|
||||
export async function listWechatDigests(params?: {
|
||||
status?: string;
|
||||
limit?: number;
|
||||
}): Promise<WechatDigestSubscription[]> {
|
||||
const q = new URLSearchParams();
|
||||
if (params?.status) q.set('status', params.status);
|
||||
if (params?.limit) q.set('limit', String(params.limit));
|
||||
const result = await portalFetch<{ digests: WechatDigestSubscription[] }>(
|
||||
`/admin-api/wechat/digests${q.toString() ? `?${q}` : ''}`,
|
||||
);
|
||||
return result.digests ?? [];
|
||||
}
|
||||
|
||||
export async function listWechatDeliveries(params?: {
|
||||
status?: string;
|
||||
limit?: number;
|
||||
}): Promise<WechatDeliveryLog[]> {
|
||||
const q = new URLSearchParams();
|
||||
if (params?.status) q.set('status', params.status);
|
||||
if (params?.limit) q.set('limit', String(params.limit));
|
||||
const result = await portalFetch<{ deliveries: WechatDeliveryLog[] }>(
|
||||
`/admin-api/wechat/deliveries${q.toString() ? `?${q}` : ''}`,
|
||||
);
|
||||
return result.deliveries ?? [];
|
||||
}
|
||||
|
||||
export async function clearWechatRoute(userId: string): Promise<{ ok: boolean; deleted: number }> {
|
||||
return portalFetch(`/admin-api/wechat/users/${userId}/route/clear`, { method: 'POST' });
|
||||
}
|
||||
|
||||
export async function cancelWechatDigest(id: string): Promise<{ ok: boolean }> {
|
||||
return portalFetch(`/admin-api/wechat/digests/${id}/cancel`, { method: 'POST' });
|
||||
}
|
||||
|
||||
export async function resumeWechatDigest(id: string): Promise<{ ok: boolean; nextRunAt: number }> {
|
||||
return portalFetch(`/admin-api/wechat/digests/${id}/resume`, { method: 'POST' });
|
||||
}
|
||||
|
||||
// ── Admin users ───────────────────────────────────────
|
||||
|
||||
export async function listAdminUsers(params?: {
|
||||
|
||||
Reference in New Issue
Block a user