Skip to content

Commit 7a44027

Browse files
Auto-update feature branch with changes from the main branch
2 parents db631a5 + 168c273 commit 7a44027

File tree

16 files changed

+60
-308
lines changed

16 files changed

+60
-308
lines changed

src/api/components/index.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,6 @@ export function withRoles<T extends FastifyZodOpenApiSchema>(
205205
...schema.response,
206206
};
207207
return {
208-
...schema,
209208
security,
210209
"x-required-roles": roles,
211210
"x-disable-api-key-auth": disableApiKeyAuth,
@@ -233,6 +232,7 @@ ${schema.description}
233232
<hr />
234233
${roles.length > 0 ? `Requires any of the following roles:\n\n${roles.map((item) => `* ${AppRoleHumanMapper[item]} (<code>${item}</code>)`).join("\n")}` : "Requires valid authentication but no specific authorization."}
235234
`,
235+
...schema,
236236
response: responses,
237237
};
238238
}
@@ -241,21 +241,11 @@ export function withTags<T extends FastifyZodOpenApiSchema>(
241241
tags: string[],
242242
schema: T,
243243
) {
244-
const cleanedResponse = schema.response
245-
? Object.fromEntries(
246-
Object.entries(schema.response).filter(([_, value]) => value !== null),
247-
)
248-
: {};
249244
const responses = {
250-
...(schema.response && schema.response["500"] !== null
251-
? { 500: internalServerError }
252-
: {}),
253-
...(schema.response && schema.response["429"] !== null
254-
? { 429: rateLimitExceededError }
255-
: {}),
256-
...(schema.response &&
257-
schema.response["400"] !== null && { 400: validationError }),
258-
...cleanedResponse,
245+
500: internalServerError,
246+
429: rateLimitExceededError,
247+
400: validationError,
248+
...schema.response,
259249
};
260250
return {
261251
tags,

src/api/index.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import {
2626
import { type ZodOpenApiVersion } from "zod-openapi";
2727
import { withTags } from "./components/index.js";
2828
import RedisModule from "ioredis";
29-
import * as z from "zod/v4";
3029

3130
/** BEGIN EXTERNAL PLUGINS */
3231
import fastifyIp from "fastify-ip";
@@ -345,21 +344,7 @@ Otherwise, email [[email protected]](mailto:[email protected]) for sup
345344
"/api/v1/healthz",
346345
{
347346
schema: withTags(["Generic"], {
348-
summary: "Get API server health status",
349-
response: {
350-
200: {
351-
description: "The API server is healthy.",
352-
content: {
353-
"application/json": {
354-
schema: z.object({
355-
message: z.literal("UP").meta({ example: "UP" }),
356-
}),
357-
},
358-
},
359-
},
360-
400: null,
361-
429: null,
362-
},
347+
summary: "Verify that the API server is healthy.",
363348
}),
364349
},
365350
async (_, reply) => {

src/api/routes/apiKey.ts

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -37,26 +37,8 @@ const apiKeyRoute: FastifyPluginAsync = async (fastify, _options) => {
3737
schema: withRoles(
3838
[AppRoles.MANAGE_ORG_API_KEYS],
3939
withTags(["API Keys"], {
40-
summary: "Create an organization API key",
41-
description:
42-
"Organization API keys are not tied to the permissions of a specific user, but rather are assigned their own permissions with optional restrictions.",
40+
summary: "Create an organization API key.",
4341
body: apiKeyPostBody,
44-
response: {
45-
201: {
46-
description: "The organization API key has been created.",
47-
content: {
48-
"application/json": {
49-
schema: z.object({
50-
apiKey: z.string().min(1).meta({
51-
description: "The API key.",
52-
example:
53-
"acmuiuc_sample435be_example244b8607e7665319c221496ad7282edbb09558f720e0e634ab77615b_d305c1",
54-
}),
55-
}),
56-
},
57-
},
58-
},
59-
},
6042
}),
6143
{ disableApiKeyAuth: true },
6244
),
@@ -161,23 +143,13 @@ If you did not create this API key, please secure your account and notify the AC
161143
schema: withRoles(
162144
[AppRoles.MANAGE_ORG_API_KEYS],
163145
withTags(["API Keys"], {
164-
summary: "Delete an organization API key",
146+
summary: "Delete an organization API key.",
165147
params: z.object({
166148
keyId: z.string().min(1).meta({
167149
description:
168150
"Key ID to delete. The key ID is the second segment of the API key.",
169151
}),
170152
}),
171-
response: {
172-
204: {
173-
description: "The organization API key has been deleted.",
174-
content: {
175-
"application/json": {
176-
schema: z.null(),
177-
},
178-
},
179-
},
180-
},
181153
}),
182154
{ disableApiKeyAuth: true },
183155
),
@@ -270,18 +242,7 @@ If you did not delete this API key, please secure your account and notify the AC
270242
schema: withRoles(
271243
[AppRoles.MANAGE_ORG_API_KEYS],
272244
withTags(["API Keys"], {
273-
summary: "Get all organization API keys",
274-
response: {
275-
200: {
276-
description:
277-
"The list of organization API keys has been retrieved.",
278-
content: {
279-
"application/json": {
280-
schema: z.array(apiKeyPostBody),
281-
},
282-
},
283-
},
284-
},
245+
summary: "Get all organization API keys.",
285246
}),
286247
{ disableApiKeyAuth: true },
287248
),

src/api/routes/iam.ts

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ import {
3131
groupModificationPatchSchema,
3232
EntraGroupActions,
3333
entraProfilePatchRequest,
34-
entraActionResponseSchema,
35-
entraGroupMembershipListResponse,
3634
} from "../../common/types/iam.js";
3735
import { clearAuthCache, getGroupRoles } from "../functions/authorization.js";
3836
import { getRoleCredentials } from "api/functions/sts.js";
@@ -222,17 +220,8 @@ const iamRoutes: FastifyPluginAsync = async (fastify, _options) => {
222220
[AppRoles.IAM_INVITE_ONLY, AppRoles.IAM_ADMIN],
223221
withTags(["IAM"], {
224222
body: invitePostRequestSchema,
225-
summary: "Invite users to the ACM @ UIUC Entra ID tenant",
226-
response: {
227-
202: {
228-
description: "At least one of the users have been invited.",
229-
content: {
230-
"application/json": {
231-
schema: entraActionResponseSchema,
232-
},
233-
},
234-
},
235-
},
223+
summary: "Invite a user to the ACM @ UIUC Entra ID tenant.",
224+
// response: { 202: entraActionResponseSchema },
236225
}),
237226
),
238227
onRequest: fastify.authorizeFromSchema,
@@ -301,12 +290,7 @@ const iamRoutes: FastifyPluginAsync = async (fastify, _options) => {
301290
}
302291
}
303292
await Promise.allSettled(logPromises);
304-
if (response.success.length > 0) {
305-
reply.status(202);
306-
} else {
307-
reply.status(500);
308-
}
309-
reply.send(response);
293+
reply.status(202).send(response);
310294
},
311295
);
312296
fastify.withTypeProvider<FastifyZodOpenApiTypeProvider>().patch(
@@ -569,16 +553,7 @@ No action is required from you at this time.
569553
schema: withRoles(
570554
[AppRoles.IAM_ADMIN],
571555
withTags(["IAM"], {
572-
response: {
573-
200: {
574-
description: "The members of the group have been retrieved.",
575-
content: {
576-
"application/json": {
577-
schema: entraGroupMembershipListResponse,
578-
},
579-
},
580-
},
581-
},
556+
// response: { 200: entraGroupMembershipListResponse },
582557
params: z.object({
583558
groupId,
584559
}),

src/api/routes/ics.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,21 +56,8 @@ const icalPlugin: FastifyPluginAsync = async (fastify, _options) => {
5656
description: "Organization to retrieve calendar for",
5757
}),
5858
}),
59-
summary: "Retrieve an organization's calendar",
60-
response: {
61-
200: {
62-
description: "The organization's calendar has been generated.",
63-
content: {
64-
"text/calendar": {
65-
schema: z.string().meta({
66-
description: "Calendar in iCalendar format.",
67-
example:
68-
"BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//sebbo.net//ical-generator//EN\nMETHOD:PUBLISH\nNAME:ACM@UIUC - Infrastructure Committee Events\nX-WR-CALNAME:ACM@UIUC - Infrastructure Committee Events\nTIMEZONE-ID:America/Chicago\nX-WR-TIMEZONE:America/Chicago\nEND:VCALENDAR",
69-
}),
70-
},
71-
},
72-
},
73-
},
59+
summary:
60+
"Retrieve the calendar for ACM @ UIUC or a specific sub-organization.",
7461
} satisfies FastifyZodOpenApiSchema),
7562
},
7663
async (request, reply) => {

src/api/routes/linkry.ts

Lines changed: 3 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,7 @@ import {
2626
getLinkryKvArn,
2727
setKey,
2828
} from "api/functions/cloudfrontKvStore.js";
29-
import {
30-
createRequest,
31-
linkryAccessList,
32-
linkryRecordWithOwner,
33-
linkryRedirectTarget,
34-
linkrySlug,
35-
} from "common/types/linkry.js";
29+
import { createRequest, linkrySlug } from "common/types/linkry.js";
3630
import {
3731
extractUniqueSlugs,
3832
fetchOwnerRecords,
@@ -88,40 +82,7 @@ const linkryRoutes: FastifyPluginAsync = async (fastify, _options) => {
8882
{
8983
schema: withRoles(
9084
[AppRoles.LINKS_MANAGER, AppRoles.LINKS_ADMIN],
91-
withTags(["Linkry"], {
92-
summary: "Get current user's links",
93-
description:
94-
"If the user has bypass permissions, all links will be returned. Otherwise, only links owned by the current user, or delegated to the current user, will be returned.",
95-
response: {
96-
200: {
97-
description: "The current user's links have been retrieved.",
98-
content: {
99-
"application/json": {
100-
schema: z.object({
101-
ownedLinks: z
102-
.array(
103-
z.object({
104-
slug: linkrySlug,
105-
createdAt: z.iso.datetime(),
106-
updatedAt: z.iso.datetime(),
107-
redirect: linkryRedirectTarget,
108-
access: linkryAccessList,
109-
}),
110-
)
111-
.meta({
112-
description:
113-
"A list of all links that the current user owns.",
114-
}),
115-
delegatedLinks: z.array(linkryRecordWithOwner).meta({
116-
description:
117-
"A list of all links that the current user has delegated access to (including superuser access).",
118-
}),
119-
}),
120-
},
121-
},
122-
},
123-
},
124-
}),
85+
withTags(["Linkry"], {}),
12586
),
12687
onRequest: fastify.authorizeFromSchema,
12788
},
@@ -216,27 +177,7 @@ const linkryRoutes: FastifyPluginAsync = async (fastify, _options) => {
216177
schema: withRoles(
217178
[AppRoles.LINKS_MANAGER, AppRoles.LINKS_ADMIN],
218179
withTags(["Linkry"], {
219-
summary: "Create short link record",
220180
body: createRequest,
221-
response: {
222-
201: {
223-
description: "The short link has been created.",
224-
headers: {
225-
Location: z
226-
.url()
227-
.min(1)
228-
.meta({
229-
description: "The resource URL for the shortened link.",
230-
example: `${fastify.environmentConfig.UserFacingUrl}/api/v1/linkry/redir/healthz`,
231-
}),
232-
},
233-
content: {
234-
"application/json": {
235-
schema: z.null(),
236-
},
237-
},
238-
},
239-
},
240181
}),
241182
),
242183
preValidation: async (request, reply) => {
@@ -509,13 +450,7 @@ const linkryRoutes: FastifyPluginAsync = async (fastify, _options) => {
509450
message: `Created redirect to "${request.body.redirect}"`,
510451
},
511452
});
512-
return reply
513-
.header(
514-
"Location",
515-
`${fastify.environmentConfig.UserFacingUrl}/api/v1/linkry/redir/${request.body.slug}`,
516-
)
517-
.status(201)
518-
.send();
453+
return reply.status(201).send();
519454
},
520455
);
521456

@@ -528,17 +463,6 @@ const linkryRoutes: FastifyPluginAsync = async (fastify, _options) => {
528463
params: z.object({
529464
slug: linkrySlug,
530465
}),
531-
summary: "Get a short link record",
532-
response: {
533-
200: {
534-
description: "The short link record has been retrieved.",
535-
content: {
536-
"application/json": {
537-
schema: linkryRecordWithOwner,
538-
},
539-
},
540-
},
541-
},
542466
}),
543467
),
544468
onRequest: fastify.authorizeFromSchema,
@@ -588,20 +512,9 @@ const linkryRoutes: FastifyPluginAsync = async (fastify, _options) => {
588512
schema: withRoles(
589513
[AppRoles.LINKS_MANAGER, AppRoles.LINKS_ADMIN],
590514
withTags(["Linkry"], {
591-
summary: "Delete a short link record",
592515
params: z.object({
593516
slug: linkrySlug,
594517
}),
595-
response: {
596-
204: {
597-
description: "The short link record has been deleted.",
598-
content: {
599-
"application/json": {
600-
schema: z.null(),
601-
},
602-
},
603-
},
604-
},
605518
}),
606519
),
607520
onRequest: async (request, reply) => {

0 commit comments

Comments
 (0)