- New assertNotBlocked() helper (src/lib/assert-not-blocked.ts), mirroring assertPetOwnership. comments.create, reactions.toggle (create path), and reposts.create now reject direct interaction between blocked pets, not just feed visibility (product decision: enforce, matching messages.ts's existing DM block check). - videos.updateCaption and stories.getViewers now route through the shared assertPetOwnership helper instead of duplicating the inline ownership check. - ads.ts mutations (recordView, toggleReaction, addComment, toggleRepost) gain the same rate limiting their post-side equivalents already have. - follows.listFollowers/listFollowing/getPetsWithActiveStories now apply getSpiderExclusionId(), matching the established per-query pattern in feed.ts/explore.ts/search.ts. Remaining findings from the review are addressed: - timingSafeStringEqual's length short-circuit needs no fix (matches Node's own crypto.timingSafeEqual behavior).
31 lines
815 B
TypeScript
31 lines
815 B
TypeScript
import "server-only";
|
|
import { TRPCError } from "@trpc/server";
|
|
import type { PrismaClient } from "@prisma/client";
|
|
|
|
/**
|
|
* Blocks apply in both directions and must gate direct interaction
|
|
* (comments, reactions, reposts), not just feed visibility — see
|
|
* blocks.ts's own doc comment on why feed hydration alone isn't enough.
|
|
*/
|
|
export async function assertNotBlocked(
|
|
prisma: PrismaClient,
|
|
petIdA: string,
|
|
petIdB: string
|
|
) {
|
|
if (petIdA === petIdB) return;
|
|
const block = await prisma.block.findFirst({
|
|
where: {
|
|
OR: [
|
|
{ blockerPetId: petIdA, blockedPetId: petIdB },
|
|
{ blockerPetId: petIdB, blockedPetId: petIdA },
|
|
],
|
|
},
|
|
});
|
|
if (block) {
|
|
throw new TRPCError({
|
|
code: "FORBIDDEN",
|
|
message: "Cannot interact with this pet's content.",
|
|
});
|
|
}
|
|
}
|