64 lines
2.5 KiB
TypeScript
64 lines
2.5 KiB
TypeScript
import PocketBase from 'pocketbase';
|
|
import { redirect } from '@sveltejs/kit';
|
|
import type { RequestEvent } from '@sveltejs/kit';
|
|
import { SERVER_IP } from '$app/env/public';
|
|
import { PB_EMAIL, PB_PASSWORD } from '$app/env/private';
|
|
|
|
export const PB_ENDPOINT = import.meta.env.PROD ? '/pb' : `http://${SERVER_IP}:8090`;
|
|
|
|
// Server-side PB client, pre-authenticated as the given user's token.
|
|
// Used for CRUD as the authenticated user so PB collection rules apply
|
|
// (famId scoping) instead of running everything as superuser.
|
|
export function createPbClient(token?: string) {
|
|
const pb = new PocketBase(PB_ENDPOINT);
|
|
if (token) pb.authStore.save(token, null);
|
|
return pb;
|
|
}
|
|
|
|
// Authenticated PB client for the current request's admin/member session.
|
|
// Requires an active session; redirects to /login otherwise.
|
|
export function pbUser(event: RequestEvent) {
|
|
if (!event.locals.user || !event.locals.pbToken) {
|
|
throw redirect(303, '/login');
|
|
}
|
|
return createPbClient(event.locals.pbToken);
|
|
}
|
|
|
|
// Superuser PB client (memoized). Reserved for server-only privileged
|
|
// operations that must bypass collection rules: creating child users, minting
|
|
// OTP-login tokens, and verifying OTPs against the superuser-only otp.
|
|
let superClient: PocketBase | null = null;
|
|
export async function createSuperClient() {
|
|
if (superClient) return superClient;
|
|
const pb = new PocketBase(PB_ENDPOINT);
|
|
await pb.collection('_superusers').authWithPassword(String(PB_EMAIL), String(PB_PASSWORD));
|
|
superClient = pb;
|
|
return pb;
|
|
}
|
|
|
|
// Superuser CRUD facade, built on the memoized SDK superuser client. All
|
|
// server PB access (authenticated user + superuser) lives in this one module.
|
|
export const pbAdmin = {
|
|
async getList(collection: string, filter = '') {
|
|
const pb = await createSuperClient();
|
|
const options: { filter?: string } = {};
|
|
if (filter) options.filter = filter;
|
|
return pb.collection(collection).getFullList(options);
|
|
},
|
|
async getOne(collection: string, id: string) {
|
|
const pb = await createSuperClient();
|
|
return pb.collection(collection).getOne(id);
|
|
},
|
|
async create(collection: string, data: Record<string, unknown>) {
|
|
const pb = await createSuperClient();
|
|
return pb.collection(collection).create(data);
|
|
},
|
|
async update(collection: string, id: string, data: Record<string, unknown>) {
|
|
const pb = await createSuperClient();
|
|
return pb.collection(collection).update(id, data);
|
|
},
|
|
async remove(collection: string, id: string) {
|
|
const pb = await createSuperClient();
|
|
return pb.collection(collection).delete(id);
|
|
}
|
|
}; |