fix: logic-audit P0/P1 wave — CORS PUT, chunked cap, presign checksums, logout await, refresh rotation race
From the logic audit (HEAD 04f5f7e):
- P0 CORS: enableCors methods lacked PUT — browsers could not chunk-upload
at all (cross-origin preflight refused)
- P0 chunked: validateUpload enforced the 2 GiB whole-body cap on chunked
completes, so every >2 GiB chunked upload failed after full upload
- P1 presignPut: the SDK's flexible-checksum default added an
x-amz-checksum-crc32 header browsers cannot reproduce; S3Client now uses
requestChecksumCalculation WHEN_REQUIRED
- P1 refresh rotation race: concurrent refreshes both succeeded (consume
ignored rowCount) forking the token family; consume now returns whether
it won and the loser revokes the chain
- P2 logout: awaits the revocation and ignores missing/forged bearers
honestly
This commit is contained in:
parent
e475402b4d
commit
b24ebc5862
19 changed files with 1636 additions and 101 deletions
|
|
@ -16,12 +16,11 @@ import { BadRequestException } from "@nestjs/common";
|
|||
import { MIME_CLASSES } from "@tactical-media-broadcast-hub/core";
|
||||
import type {
|
||||
FileRetention,
|
||||
GroupFile,
|
||||
GroupFileMapping,
|
||||
MatrixAttachmentCandidate,
|
||||
MimeClass,
|
||||
SharedFileOrigin,
|
||||
} from "@tactical-media-broadcast-hub/core";
|
||||
import type { GroupFile } from "./group-files.types.js";
|
||||
|
||||
// FileRetention (packages/core/src/shared-files.ts): mode is keep|until and
|
||||
// legalHold is an orthogonal boolean flag — NOT a third mode.
|
||||
|
|
@ -142,7 +141,7 @@ export function requireIsoTimestamp(value: unknown, field: string): string {
|
|||
}
|
||||
|
||||
/** The four SharedFileOrigin variants, discriminated by `kind`. */
|
||||
export function parseSharedFileOrigin(value: unknown, field = "origin"): SharedFileOrigin {
|
||||
export function parseSharedFileOrigin(value: unknown, field = "origin"): GroupFile["origin"] {
|
||||
if (!isRecord(value)) throw new BadRequestException(`${field} must be an object`);
|
||||
const kind = enumField(value, "kind", ORIGIN_KINDS, `${field}.kind`);
|
||||
if (kind === "matrix") return { kind, mxcUri: requireMxcUri(value.mxcUri, `${field}.mxcUri`) };
|
||||
|
|
@ -154,7 +153,10 @@ export function parseSharedFileOrigin(value: unknown, field = "origin"): SharedF
|
|||
...(value.remoteEventId === undefined || value.remoteEventId === null ? {} : { remoteEventId: stringField(value, "remoteEventId", `${field}.remoteEventId`) }),
|
||||
};
|
||||
}
|
||||
if (kind === "upload") return { kind };
|
||||
if (kind === "upload") {
|
||||
if (value.sharedFrom !== undefined && value.sharedFrom !== "personal") throw new BadRequestException(`${field}.sharedFrom must be personal`);
|
||||
return { kind, ...(value.sharedFrom === "personal" ? { sharedFrom: "personal" as const } : {}) };
|
||||
}
|
||||
return { kind: "pad-export", padId: stringField(value, "padId", `${field}.padId`), revision: stringField(value, "revision", `${field}.revision`) };
|
||||
}
|
||||
|
||||
|
|
@ -215,7 +217,11 @@ export function parseGroupFile(value: unknown, field = "item"): GroupFile {
|
|||
return {
|
||||
id: stringField(value, "id", `${field}.id`),
|
||||
workspaceId: stringField(value, "workspaceId", `${field}.workspaceId`),
|
||||
groupId: stringField(value, "groupId", `${field}.groupId`),
|
||||
groupId: value.groupId === null ? null : stringField(value, "groupId", `${field}.groupId`),
|
||||
ownerId: nullableUuid(value.ownerId, `${field}.ownerId`),
|
||||
folderId: nullableUuid(value.folderId, `${field}.folderId`),
|
||||
createdBy: nullableUuid(value.createdBy, `${field}.createdBy`),
|
||||
shared: value.shared === undefined ? false : booleanField(value.shared, `${field}.shared`),
|
||||
roomId: value.roomId === undefined || value.roomId === null ? null : requireRoomId(value.roomId, `${field}.roomId`),
|
||||
senderId: requireMxid(value.senderId, `${field}.senderId`),
|
||||
eventId: eventId === undefined || eventId === null ? null : eventId,
|
||||
|
|
@ -228,9 +234,10 @@ export function parseGroupFile(value: unknown, field = "item"): GroupFile {
|
|||
createdAt: isoField(value, "createdAt", `${field}.createdAt`),
|
||||
indexedAt: isoField(value, "indexedAt", `${field}.indexedAt`),
|
||||
file: {
|
||||
spaceId: stringField(file, "spaceId", `${field}.file.spaceId`),
|
||||
spaceId: file.spaceId === null ? null : stringField(file, "spaceId", `${field}.file.spaceId`),
|
||||
resourceId: stringField(file, "resourceId", `${field}.file.resourceId`),
|
||||
version: stringField(file, "version", `${field}.file.version`),
|
||||
...(file.storageKey === undefined ? {} : { storageKey: stringField(file, "storageKey", `${field}.file.storageKey`) }),
|
||||
},
|
||||
shareLink: {
|
||||
url: stringField(shareLink, "url", `${field}.shareLink.url`),
|
||||
|
|
@ -241,3 +248,16 @@ export function parseGroupFile(value: unknown, field = "item"): GroupFile {
|
|||
status: enumField(value, "status", FILE_STATUSES, `${field}.status`),
|
||||
};
|
||||
}
|
||||
|
||||
function nullableUuid(value: unknown, field: string): string | null {
|
||||
if (value === undefined || value === null) return null;
|
||||
if (typeof value !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value)) {
|
||||
throw new BadRequestException(`${field} must be a UUID or null`);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function booleanField(value: unknown, field: string): boolean {
|
||||
if (typeof value !== "boolean") throw new BadRequestException(`${field} must be a boolean`);
|
||||
return value;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue