Skip to content

Commit e157578

Browse files
committed
basing security check on crawler and not event on refreshScheduleRequest endpoint, because event might not exist on first crawl
1 parent 9b0fa3b commit e157578

File tree

2 files changed

+48
-16
lines changed

2 files changed

+48
-16
lines changed

cloud/functions/src/functions/http/api/events-routes.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as z from "zod";
33
import {ISO_DATETIME_PARSER} from "../../../utils/zod-parsers";
44
import {Routes} from "./routes";
55
import {
6+
ensureHasCrawlerFamilyOrEventOrganizerToken,
67
ensureHasEventStatsValidToken,
78
ensureHasFamilyOrEventOrganizerToken,
89
ensureHasRoomStatsContributorValidToken,
@@ -58,7 +59,7 @@ export function declareEventHttpRoutes(app: Express) {
5859
eventId: z.string().min(3),
5960
})
6061
}),
61-
ensureHasFamilyOrEventOrganizerToken(),
62+
ensureHasCrawlerFamilyOrEventOrganizerToken(),
6263
async (res, path, query, body) =>
6364
(await import("../event/crawlEvent")).requestEventScheduleRefresh(res, path, query));
6465
Routes.get(app, '/events/:eventId/talkEditors',

cloud/functions/src/functions/http/api/route-access.ts

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ import {
66
} from "../../firestore/services/publicTokens-utils";
77
import {match, P} from "ts-pattern";
88
import {PublicToken} from "../../../../../../shared/public-tokens";
9+
import {getCrawlersMatching} from "../../firestore/services/crawlers-utils";
10+
import {FieldPath} from "firebase-admin/firestore";
11+
import {ConferenceDescriptor} from "../../../../../../shared/conference-descriptor.firestore";
12+
import {FIREBASE_CRAWLER_DESCRIPTOR_PARSER} from "../../../crawlers/crawler-parsers";
13+
import {z} from "zod";
914

1015

1116
export function publicEndpoint() {
@@ -21,27 +26,28 @@ export function ensureHasSuperAdminToken() {
2126
}
2227
}
2328

24-
function ensureEventBasedTokenPredicateIsValid<T extends PublicToken>(publicTokenResolver: (token: string) => Promise<T>) {
29+
function ensureEventBasedTokenPredicateIsValid<
30+
T extends PublicToken,
31+
E extends { eventFamily: string, eventName: string }
32+
>(
33+
entityResolver: (eventId: string) => Promise<E>,
34+
publicTokenResolver: (token: string) => Promise<T>
35+
) {
2536
return async (pathParams: { eventId: string }, queryParams: { token: string }) => {
2637
const token = queryParams.token;
2738

28-
const eventDescriptor = await getEventDescriptor(pathParams.eventId);
29-
30-
if(!eventDescriptor) {
31-
throw new Error(`No event found with id ${pathParams.eventId}`)
32-
}
33-
39+
const entity = await entityResolver(pathParams.eventId);
3440
const matchingPublicToken = await publicTokenResolver(token);
3541

3642
const validationErrorMessage = match(matchingPublicToken as PublicToken)
3743
.with({ eventFamilies: P.array(P.string) }, ({ eventFamilies: tokenEventFamilies }) => {
38-
if(!eventDescriptor.eventFamily || !tokenEventFamilies.includes(eventDescriptor.eventFamily)) {
39-
return `Provided event family-based token doesn't match with event ${eventDescriptor.id} family: [${eventDescriptor.eventFamily}]`;
44+
if(!entity.eventFamily || !tokenEventFamilies.includes(entity.eventFamily)) {
45+
return `Provided event family-based token doesn't match with event ${pathParams.eventId} family: [${entity.eventFamily}]`;
4046
}
4147
return undefined;
4248
}).with({ eventNames: P.array(P.string) }, ({ eventNames: tokenEventNames }) => {
43-
if(!eventDescriptor.eventName || !tokenEventNames.includes(eventDescriptor.eventName)) {
44-
return `Provided event-based token doesn't match with event ${eventDescriptor.id} name: [${eventDescriptor.eventName}]`
49+
if(!entity.eventName || !tokenEventNames.includes(entity.eventName)) {
50+
return `Provided event-based token doesn't match with event ${pathParams.eventId} name: [${entity.eventName}]`
4551
}
4652
return undefined;
4753
}).exhaustive();
@@ -50,18 +56,43 @@ function ensureEventBasedTokenPredicateIsValid<T extends PublicToken>(publicToke
5056
throw new Error(validationErrorMessage);
5157
}
5258

53-
return eventDescriptor;
59+
return entity;
60+
}
61+
}
62+
63+
async function resolveEventById(eventId: string): Promise<ConferenceDescriptor> {
64+
const eventDescriptor = await getEventDescriptor(eventId);
65+
66+
if(!eventDescriptor) {
67+
throw new Error(`No event found with id ${eventId}`)
68+
}
69+
70+
return eventDescriptor;
71+
}
72+
73+
async function resolveCrawlerById(eventId: string): Promise<z.infer<typeof FIREBASE_CRAWLER_DESCRIPTOR_PARSER> & {id: string}> {
74+
75+
const crawlerDescriptors = await getCrawlersMatching(crawlerColl => crawlerColl.where(FieldPath.documentId(), "==", eventId))
76+
77+
if(!crawlerDescriptors.length) {
78+
throw new Error(`No crawler found with id ${eventId}`)
5479
}
80+
81+
return crawlerDescriptors[0];
5582
}
5683

5784
export function ensureHasFamilyOrEventOrganizerToken() {
58-
return ensureEventBasedTokenPredicateIsValid((token) => getFamilyOrEventOrganizerToken(token))
85+
return ensureEventBasedTokenPredicateIsValid(resolveEventById, (token) => getFamilyOrEventOrganizerToken(token))
86+
}
87+
88+
export function ensureHasCrawlerFamilyOrEventOrganizerToken() {
89+
return ensureEventBasedTokenPredicateIsValid(resolveCrawlerById, (token) => getFamilyOrEventOrganizerToken(token))
5990
}
6091

6192
export function ensureHasEventStatsValidToken() {
62-
return ensureEventBasedTokenPredicateIsValid((token) => getEventStatsValidToken(token))
93+
return ensureEventBasedTokenPredicateIsValid(resolveEventById, (token) => getEventStatsValidToken(token))
6394
}
6495

6596
export function ensureHasRoomStatsContributorValidToken() {
66-
return ensureEventBasedTokenPredicateIsValid((token) => getRoomStatsContributorValidToken(token))
97+
return ensureEventBasedTokenPredicateIsValid(resolveEventById, (token) => getRoomStatsContributorValidToken(token))
6798
}

0 commit comments

Comments
 (0)