Files
leaudit-platform-frontend/app/api/db-client.server.ts
T

112 lines
3.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// app/api/db-client.server.ts
import { getUserSession } from '~/api/login/auth.server';
import { runWithContext } from './postgrest-client';
/**
* 在认证上下文中运行
*
* 所有在此上下文中调用的 postgrest 函数(postgrestGet/Post/Put/Delete
* 都会自动获取并添加 JWT Token 到 Authorization 头部
*
* @param request Remix Request 对象
* @param fn 要在认证上下文中执行的函数
* @returns 函数执行结果
* @throws 如果用户未登录则抛出错误
*
* @example
* ```typescript
* export async function loader({ request }: LoaderFunctionArgs) {
* return await runInAuthContext(request, async () => {
* // 所有 postgrest 调用自动带 JWT
* const users = await postgrestGet('users', { limit: 10 });
* const docs = await postgrestGet('documents', { filter: { status: 'eq.0' } });
*
* return json({ users: users.data, docs: docs.data });
* });
* }
* ```
*/
export async function runInAuthContext<T>(
request: Request,
fn: () => T | Promise<T>
): Promise<T> {
const { frontendJWT, isAuthenticated } = await getUserSession(request);
if (!isAuthenticated || !frontendJWT) {
throw new Error('用户未登录,无法执行需要认证的操作');
}
// 在上下文中设置 JWT,所有 postgrest 调用都会自动使用
return runWithContext({ jwt: frontendJWT }, fn);
}
/**
* 在公开上下文中运行(不需要认证)
*
* 用于公开数据访问,不会添加 JWT Token
*
* @param fn 要执行的函数
* @returns 函数执行结果
*
* @example
* ```typescript
* export async function loader() {
* return runInPublicContext(async () => {
* const articles = await postgrestGet('public_articles', {
* filter: { published: 'eq.true' }
* });
* return json({ articles: articles.data });
* });
* }
* ```
*/
export function runInPublicContext<T>(
fn: () => T | Promise<T>
): T | Promise<T> {
// 在空上下文中运行,不设置 JWT
return runWithContext({}, fn);
}
/**
* 在可选认证上下文中运行
*
* 如果用户已登录,会自动添加 JWT;
* 如果用户未登录,则不添加 JWT(不会抛出错误)
*
* @param request Remix Request 对象
* @param fn 要执行的函数
* @returns 函数执行结果
*
* @example
* ```typescript
* export async function loader({ request }: LoaderFunctionArgs) {
* return await runInOptionalAuthContext(request, async () => {
* // 如果用户登录,会带 JWT(可能看到更多内容)
* // 如果用户未登录,不带 JWT(看到基础内容)
* const content = await postgrestGet('content', { limit: 20 });
* return json({ content: content.data });
* });
* }
* ```
*/
export async function runInOptionalAuthContext<T>(
request: Request,
fn: () => T | Promise<T>
): Promise<T> {
try {
const { frontendJWT, isAuthenticated } = await getUserSession(request);
if (isAuthenticated && frontendJWT) {
// 用户已登录,使用 JWT
return runWithContext({ jwt: frontendJWT }, fn);
}
} catch (error) {
// 获取会话失败,继续以公开方式运行
console.warn('获取用户会话失败,以公开方式运行:', error);
}
// 用户未登录或获取会话失败,以公开方式运行
return runWithContext({}, fn);
}