fix(housekeeping): harden people read boundaries

This commit is contained in:
Simo committed 2026-08-29 02:13:53 +02:00
1 parent e3f8b51d31
commit d1382c839e
12 files changed
+1635 -446

No files matched your search

@@ -75,11 +75,13 @@ export function createPeopleStaffQuery(
const authorization = authorizeHousekeeping(context, requirement);
if (!authorization.ok) return authorization;
const correlationId = authorization.correlationId;
const list = normalizePeopleListInput(
input.list,
["id", "name", "username", "createdAt"],
"id",
);
const allowedSorts =
input.routeId === "people.staff.applications"
? ["id", "username", "createdAt"]
: input.routeId === "people.staff.teams"
? ["id", "name"]
: ["id", "username"];
const list = normalizePeopleListInput(input.list, allowedSorts, "id");
try {
if (input.routeId === "people.staff.applications") {
@@ -87,13 +89,7 @@ export function createPeopleStaffQuery(
return ok(
{
kind: "applications" as const,
page: createPeoplePage(result.rows, result.total, list, (row) =>
list.sort === "username"
? (row.username ?? "")
: list.sort === "createdAt"
? (row.createdAt ?? "")
: row.id,
),
page: createPeoplePage(result.rows, result.total, list),
},
correlationId,
);
@@ -104,9 +100,7 @@ export function createPeopleStaffQuery(
return ok(
{
kind: "teams" as const,
page: createPeoplePage(result.rows, result.total, list, (row) =>
list.sort === "name" ? row.name : row.id,
),
page: createPeoplePage(result.rows, result.total, list),
},
correlationId,
);
@@ -116,9 +110,7 @@ export function createPeopleStaffQuery(
return ok(
{
kind: "moderation-team" as const,
page: createPeoplePage(result.rows, result.total, list, (row) =>
list.sort === "username" ? row.username : row.id,
),
page: createPeoplePage(result.rows, result.total, list),
},
correlationId,
);
@@ -134,11 +126,13 @@ export function createPeopleStaffQuery(
}
function resultRows<T>(result: unknown): T[] {
if (!Array.isArray(result)) return [];
return Array.isArray(result[0]) ? (result[0] as T[]) : [];
if (!Array.isArray(result) || !Array.isArray(result[0])) {
throw new Error("invalid People driver result");
}
return result[0] as T[];
}
export const peopleStaffAdapters: PeopleStaffAdapters = {
const peopleStaffAdapters: PeopleStaffAdapters = {
async loadApplications(input) {
const [{ sql }, { db }] = await Promise.all([
import("drizzle-orm"),
@@ -158,7 +152,7 @@ export const peopleStaffAdapters: PeopleStaffAdapters = {
ORDER BY ${input.sort === "username" ? sql`u.username` : input.sort === "createdAt" ? sql`a.created_at` : sql`a.id`} ${
input.order === "asc" ? sql`ASC` : sql`DESC`
}, a.id ASC
LIMIT ${input.offset + input.pageSize}
LIMIT ${input.pageSize} OFFSET ${input.offset}
`),
db.execute(sql`
SELECT COUNT(*) AS total
@@ -205,7 +199,7 @@ export const peopleStaffAdapters: PeopleStaffAdapters = {
ORDER BY ${input.sort === "name" ? sql`rank_name` : sql`id`} ${
input.order === "desc" ? sql`DESC` : sql`ASC`
}, id ASC
LIMIT ${input.offset + input.pageSize}
LIMIT ${input.pageSize} OFFSET ${input.offset}
`),
db.execute(sql`SELECT COUNT(*) AS total FROM website_teams ${where}`),
]);
@@ -248,7 +242,7 @@ export const peopleStaffAdapters: PeopleStaffAdapters = {
ORDER BY ${input.sort === "username" ? sql`u.username` : sql`u.id`} ${
input.order === "desc" ? sql`DESC` : sql`ASC`
}, u.id ASC
LIMIT ${input.offset + input.pageSize}
LIMIT ${input.pageSize} OFFSET ${input.offset}
`),
db.execute(sql`
SELECT COUNT(*) AS total FROM users u