Files
linumiq_net-web_app/lib/admin/sort.ts
T
Gerhard Scheikl d317e8c758 feat(admin): live redis kill-switch on tunnel actions, sortable columns + CSV export + bulk actions, Node 24 LTS
WS1: pin all Docker stages to node:24.16.0-alpine; add engines node>=20.
WS2: lib/redis.ts gains TTL-backed redisSet, redisDel, setTunnelActive (writes tunnel:active:<sub>=1/0 EX 30, TUNNEL_ACTIVE_TTL override, no-op without REDIS_URL); wired into tunnel active/delete/reassign routes.
WS3: sortable columns, CSV export routes (token excluded), and bulk actions (self-account guard) across users/tunnels/audit admin tables.
2026-05-31 14:46:22 +02:00

46 lines
1.2 KiB
TypeScript

/**
* Tiny helpers to parse + whitelist server-side sort parameters for the admin
* list/export endpoints. Anything not on the per-endpoint allow-list falls
* back to that endpoint's default column, so untrusted `sort`/`order` query
* params can never reach PostgREST verbatim.
*/
export type SortOrder = 'asc' | 'desc';
export function parseOrder(
v: string | null | undefined,
fallback: SortOrder = 'desc',
): SortOrder {
return v === 'asc' || v === 'desc' ? v : fallback;
}
export function parseSort<T extends string>(
v: string | null | undefined,
allowed: readonly T[],
fallback: T,
): T {
return v && (allowed as readonly string[]).includes(v) ? (v as T) : fallback;
}
export const USER_SORTS = [
'email',
'created_at',
'last_sign_in_at',
'role',
] as const;
export type UserSort = (typeof USER_SORTS)[number];
export const TUNNEL_SORTS = [
'subdomain',
'bytes_used',
'quota_bytes',
'is_active',
'created_at',
'last_seen_at',
'usage_pct',
] as const;
export type TunnelSort = (typeof TUNNEL_SORTS)[number];
export const AUDIT_SORTS = ['created_at', 'action', 'actor_email'] as const;
export type AuditSort = (typeof AUDIT_SORTS)[number];