Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/api/routes/events.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import "zod-openapi/extend";
import { FastifyPluginAsync, FastifyRequest } from "fastify";

Check warning on line 2 in src/api/routes/events.ts

View workflow job for this annotation

GitHub Actions / Run Unit Tests

'FastifyRequest' is defined but never used. Allowed unused vars must match /^_/u
import { AppRoles } from "../../common/roles.js";
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";

Check warning on line 5 in src/api/routes/events.ts

View workflow job for this annotation

GitHub Actions / Run Unit Tests

'zodToJsonSchema' is defined but never used. Allowed unused vars must match /^_/u
import { OrganizationList } from "../../common/orgs.js";
import {
DeleteItemCommand,
Expand Down Expand Up @@ -56,6 +56,8 @@
host: "#host",
featured: "#featured",
id: "#id",
repeats: "#repeats",
repeatEnds: "#repeatEnds",
...(includeMetadata ? { metadata: "#metadata" } : {}),
};

Expand All @@ -76,7 +78,7 @@
expressionAttributeNames,
projectionExpression,
// Return function to destructure results if needed
getAttributes: <T>(item: any): T => item as T,

Check warning on line 81 in src/api/routes/events.ts

View workflow job for this annotation

GitHub Actions / Run Unit Tests

Unexpected any. Specify a different type
};
};

Expand Down Expand Up @@ -179,7 +181,7 @@
async (request, reply) => {
const upcomingOnly = request.query?.upcomingOnly || false;
const featuredOnly = request.query?.featuredOnly || false;
const includeMetadata = request.query.includeMetadata || true;
const includeMetadata = request.query.includeMetadata || false;
const host = request.query?.host;
const ts = request.query?.ts; // we only use this to disable cache control
const projection = createProjectionParams(includeMetadata);
Expand Down
18 changes: 8 additions & 10 deletions src/common/policies/definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { FastifyRequest } from "fastify";
import { hostRestrictionPolicy } from "./events.js";
import { z } from "zod";
import { AuthorizationPolicyResult } from "./evaluator.js";

type Policy<TParamsSchema extends z.ZodObject<any>> = {
name: string;
paramsSchema: TParamsSchema;
Expand All @@ -11,10 +12,8 @@ type Policy<TParamsSchema extends z.ZodObject<any>> = {
) => AuthorizationPolicyResult;
};

// Type to get parameters type from a policy
type PolicyParams<T> = T extends Policy<infer U> ? z.infer<U> : never;

// Type for a registry of policies
type PolicyRegistry = {
[key: string]: Policy<any>;
};
Expand All @@ -27,16 +26,15 @@ type TypedPolicyRegistry<T extends PolicyRegistry> = {
};
};

export const AuthorizationPoliciesRegistry: PolicyRegistry = {
EventsHostRestrictionPolicy: hostRestrictionPolicy,
} as const;

export type AvailableAuthorizationPolicies = TypedPolicyRegistry<
typeof AuthorizationPoliciesRegistry
>;
export const AuthorizationPoliciesRegistry = {
EventsHostRestrictionPolicy: hostRestrictionPolicy,
} as const;

export type AvailableAuthorizationPolicy = {
[K in keyof typeof AuthorizationPoliciesRegistry]: {
name: K;
params: PolicyParams<(typeof AuthorizationPoliciesRegistry)[K]>;
};
}[keyof typeof AuthorizationPoliciesRegistry];
name: keyof typeof AuthorizationPoliciesRegistry;
params: PolicyParams<typeof AuthorizationPoliciesRegistry[keyof typeof AuthorizationPoliciesRegistry]>;
};
27 changes: 24 additions & 3 deletions tests/live/events.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ test("getting events for a given host", async () => {
});

describe("Event lifecycle tests", async () => {
let createdEventUuid;
let createdEventUuid: string;
test("creating an event", { timeout: 30000 }, async () => {
const token = await createJwt();
const response = await fetch(`${baseEndpoint}/api/v1/events`, {
Expand All @@ -34,13 +34,14 @@ describe("Event lifecycle tests", async () => {
"Content-Type": "application/json",
},
body: JSON.stringify({
title: "Testing Event",
title: "Live Testing Event",
description: "An event of all time",
start: "2024-12-31T02:00:00",
end: "2024-12-31T03:30:00",
location: "ACM Room (Siebel 1104)",
host: "ACM",
featured: true,
repeats: "weekly",
}),
});
const responseJson = await response.json();
Expand All @@ -49,6 +50,26 @@ describe("Event lifecycle tests", async () => {
expect(responseJson).toHaveProperty("resource");
createdEventUuid = responseJson.id;
});
test("getting a created event", { timeout: 30000 }, async () => {
if (!createdEventUuid) {
throw new Error("Event UUID not found");
}
const response = await fetch(
`${baseEndpoint}/api/v1/events/${createdEventUuid}?ts=${Date.now()}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
},
);
const responseJson = await response.json();
expect(response.status).toBe(200);
expect(responseJson).toHaveProperty("id");
expect(responseJson).toHaveProperty("repeats");
expect(responseJson["repeatEnds"]).toBeUndefined();
createdEventUuid = responseJson.id;
});

test("deleting a previously-created event", { timeout: 30000 }, async () => {
if (!createdEventUuid) {
Expand All @@ -72,7 +93,7 @@ describe("Event lifecycle tests", async () => {
throw new Error("Event UUID not found");
}
const response = await fetch(
`${baseEndpoint}/api/v1/events/${createdEventUuid}`,
`${baseEndpoint}/api/v1/events/${createdEventUuid}?ts=${Date.now()}`,
{
method: "GET",
},
Expand Down
Loading