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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"test:e2e-ui": "playwright test --ui"
},
"dependencies": {
"@acm-uiuc/js-shared": "^2.4.0"
"@acm-uiuc/js-shared": "^3.1.0"
},
"devDependencies": {
"@eslint/compat": "^1.3.2",
Expand Down
4 changes: 2 additions & 2 deletions src/api/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AppRoleHumanMapper, AppRoles } from "common/roles.js";
import { FastifyZodOpenApiSchema } from "fastify-zod-openapi";
import * as z from "zod/v4";
import { AllOrganizationList } from "@acm-uiuc/js-shared";
import { AllOrganizationNameList } from "@acm-uiuc/js-shared";
export {
illinoisSemesterId as semesterId,
illinoisNetId,
Expand All @@ -21,7 +21,7 @@
});

export const acmCoreOrganization = z
.enum(AllOrganizationList as [string, ...string[]])
.enum(AllOrganizationNameList as [string, ...string[]])
.meta({
description: "ACM Organization",
id: "AcmOrganization",
Expand Down Expand Up @@ -196,7 +196,7 @@
schema: T,
{ disableApiKeyAuth, notes }: RolesConfig = { disableApiKeyAuth: false },
): T & RoleSchema {
const security = [{ httpBearer: [] }] as any;

Check warning on line 199 in src/api/components/index.ts

View workflow job for this annotation

GitHub Actions / Run Unit Tests

Unexpected any. Specify a different type
if (!disableApiKeyAuth) {
security.push({ apiKeyHeader: [] });
}
Expand Down
6 changes: 3 additions & 3 deletions src/api/functions/organizations.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AllOrganizationList } from "@acm-uiuc/js-shared";
import { AllOrganizationNameList, OrganizationName } from "@acm-uiuc/js-shared";
import {
QueryCommand,
ScanCommand,
Expand Down Expand Up @@ -154,14 +154,14 @@ export async function getUserOrgRoles({
logger.warn(`Invalid role in role definition: ${JSON.stringify(item)}`);
continue;
}
if (!AllOrganizationList.includes(org)) {
if (!AllOrganizationNameList.includes(org as OrganizationName)) {
logger.warn(`Invalid org in role definition: ${JSON.stringify(item)}`);
continue;
}
cleanedRoles.push({
org,
role,
} as { org: (typeof AllOrganizationList)[number]; role: OrgRole });
} as { org: OrganizationName; role: OrgRole });
}
return cleanedRoles;
} catch (e) {
Expand Down
6 changes: 3 additions & 3 deletions src/api/routes/ics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import ical, {
} from "ical-generator";
import moment from "moment";
import { getVtimezoneComponent } from "@touch4it/ical-timezones";
import { CoreOrganizationList } from "@acm-uiuc/js-shared";
import { AllOrganizationNameList, OrganizationName } from "@acm-uiuc/js-shared";
import { CLIENT_HTTP_CACHE_POLICY, EventRepeatOptions } from "./events.js";
import rateLimiter from "api/plugins/rateLimiter.js";
import { getCacheCounter } from "api/functions/cache.js";
Expand Down Expand Up @@ -43,7 +43,7 @@ function generateHostName(host: string) {

const icalPlugin: FastifyPluginAsync = async (fastify, _options) => {
fastify.register(rateLimiter, {
limit: CoreOrganizationList.length,
limit: AllOrganizationNameList.length,
duration: 30,
rateLimitIdentifier: "ical",
});
Expand Down Expand Up @@ -87,7 +87,7 @@ const icalPlugin: FastifyPluginAsync = async (fastify, _options) => {
reply.header("etag", etag);
}
if (host) {
if (!CoreOrganizationList.includes(host)) {
if (!AllOrganizationNameList.includes(host as OrganizationName)) {
throw new ValidationError({
message: `Invalid host parameter "${host}" in path.`,
});
Expand Down
24 changes: 15 additions & 9 deletions src/api/routes/organizations.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { FastifyError, FastifyPluginAsync } from "fastify";
import {
ACMOrganization,
AllOrganizationList,
OrganizationShortIdentifierMapping,
AllOrganizationNameList,
getOrgByName,
Organizations,
} from "@acm-uiuc/js-shared";
import rateLimiter from "api/plugins/rateLimiter.js";
import { withRoles, withTags } from "api/components/index.js";
Expand Down Expand Up @@ -142,7 +142,7 @@ const organizationsPlugin: FastifyPluginAsync = async (fastify, _options) => {
isAuthenticated = false;
}
}
const promises = AllOrganizationList.map((x) =>
const promises = AllOrganizationNameList.map((x) =>
getOrgInfo({
id: x,
dynamoClient: fastify.dynamoClient,
Expand All @@ -161,7 +161,7 @@ const organizationsPlugin: FastifyPluginAsync = async (fastify, _options) => {
leadsEntraGroupId: undefined,
}));
}
const unknownIds = AllOrganizationList.filter(
const unknownIds = AllOrganizationNameList.filter(
(x) => !successIds.includes(x),
).map((x) => ({ id: x }));
return reply.send([...successOnly, ...unknownIds]);
Expand All @@ -185,7 +185,7 @@ const organizationsPlugin: FastifyPluginAsync = async (fastify, _options) => {
"Get information about a specific ACM @ UIUC sub-organization.",
params: z.object({
orgId: z
.enum(AllOrganizationList)
.enum(AllOrganizationNameList)
.meta({ description: "ACM @ UIUC organization to query." }),
}),
response: {
Expand Down Expand Up @@ -236,7 +236,7 @@ const organizationsPlugin: FastifyPluginAsync = async (fastify, _options) => {
summary: "Set metadata for an ACM @ UIUC sub-organization.",
params: z.object({
orgId: z
.enum(AllOrganizationList)
.enum(AllOrganizationNameList)
.meta({ description: "ACM @ UIUC organization to modify." }),
}),
body: setOrganizationMetaBody,
Expand Down Expand Up @@ -325,7 +325,7 @@ const organizationsPlugin: FastifyPluginAsync = async (fastify, _options) => {
summary: "Set leads for an ACM @ UIUC sub-organization.",
params: z.object({
orgId: z
.enum(AllOrganizationList)
.enum(AllOrganizationNameList)
.meta({ description: "ACM @ UIUC organization to modify." }),
}),
body: patchOrganizationLeadsBody,
Expand Down Expand Up @@ -424,7 +424,13 @@ const organizationsPlugin: FastifyPluginAsync = async (fastify, _options) => {

const shouldCreateNewEntraGroup = !entraGroupId;
const grpDisplayName = `${request.params.orgId} Admin`;
const grpShortName = `${OrganizationShortIdentifierMapping[request.params.orgId as keyof typeof OrganizationShortIdentifierMapping]}-adm`;
const orgInfo = getOrgByName(request.params.orgId);
if (!orgInfo) {
throw new InternalServerError({
message: `Organization ${request.params.orgId} could not be resolved.`,
});
}
const grpShortName = `${orgInfo?.shortcode}-adm`;

// Create Entra group if needed
if (shouldCreateNewEntraGroup) {
Expand Down
12 changes: 6 additions & 6 deletions src/common/policies/events.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import * as z from "zod/v4";
import { createPolicy } from "./evaluator.js";
import { CoreOrganizationList } from "@acm-uiuc/js-shared";
import { AllOrganizationNameList, OrganizationName } from "@acm-uiuc/js-shared";
import { FastifyRequest } from "fastify";

export const hostRestrictionPolicy = createPolicy(
"EventsHostRestrictionPolicy",
z.object({ host: z.array(z.enum(CoreOrganizationList)) }),
(request: FastifyRequest & {username?: string;}, params) => {
z.object({ host: z.array(z.enum(AllOrganizationNameList)) }),
(request: FastifyRequest & { username?: string; }, params) => {
if (request.method === "GET") {
return {
allowed: true,
Expand All @@ -21,7 +21,7 @@ export const hostRestrictionPolicy = createPolicy(
cacheKey: null
};
}
const typedBody = request.body as {host: string;featured: boolean;};
const typedBody = request.body as { host: string; featured: boolean; };
if (!typedBody || !typedBody["host"]) {
return {
allowed: true,
Expand All @@ -36,7 +36,7 @@ export const hostRestrictionPolicy = createPolicy(
cacheKey: request.username || null
};
}
if (!params.host.includes(typedBody["host"])) {
if (!params.host.includes(typedBody["host"] as OrganizationName)) {
return {
allowed: false,
message: `Denied by policy "EventsHostRestrictionPolicy". Host must be one of: ${params.host.toString()}.`,
Expand All @@ -49,4 +49,4 @@ export const hostRestrictionPolicy = createPolicy(
cacheKey: request.username || null
};
}
);
);
4 changes: 2 additions & 2 deletions src/common/roles.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AllOrganizationList } from "@acm-uiuc/js-shared";
import { AllOrganizationNameList } from "@acm-uiuc/js-shared";

/* eslint-disable import/prefer-default-export */
export const runEnvironments = ["dev", "prod"] as const;
Expand Down Expand Up @@ -27,7 +27,7 @@ export const PSUEDO_ROLES = [AppRoles.AT_LEAST_ONE_ORG_MANAGER]
export const orgRoles = ["LEAD", "MEMBER"] as const;
export type OrgRole = typeof orgRoles[number];
export type OrgRoleDefinition = {
org: typeof AllOrganizationList[number],
org: typeof AllOrganizationNameList[number],
role: OrgRole
}

Expand Down
4 changes: 2 additions & 2 deletions src/common/types/organizations.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AllOrganizationList } from "@acm-uiuc/js-shared";
import { AllOrganizationNameList } from "@acm-uiuc/js-shared";
import { AppRoleHumanMapper, AppRoles } from "../roles.js";
import { z } from "zod/v4";

Expand Down Expand Up @@ -28,7 +28,7 @@ export const orgLinkEntry = z.object({
export const enforcedOrgLeadEntry = orgLeadEntry.extend({ name: z.string().min(1), title: z.string().min(1) })

export const getOrganizationInfoResponse = z.object({
id: z.enum(AllOrganizationList),
id: z.enum(AllOrganizationNameList),
description: z.optional(z.string()),
website: z.optional(z.url()),
leads: z.optional(z.array(orgLeadEntry)),
Expand Down
4 changes: 2 additions & 2 deletions src/common/types/roomRequest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as z from "zod/v4";
import { AllOrganizationList } from "@acm-uiuc/js-shared";
import { AllOrganizationNameList } from "@acm-uiuc/js-shared";
import { illinoisSemesterId } from "./generic.js"

export const eventThemeOptions = [
Expand Down Expand Up @@ -146,7 +146,7 @@ export const roomRequestPostResponse = z.object({
});

export const roomRequestBaseSchema = z.object({
host: z.enum(AllOrganizationList),
host: z.enum(AllOrganizationNameList),
title: z.string().min(2, "Title must have at least 2 characters"),
semester: illinoisSemesterId
});
Expand Down
4 changes: 2 additions & 2 deletions src/ui/pages/events/ManageEvent.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { useNavigate, useParams } from "react-router-dom";
import * as z from "zod/v4";
import { AuthGuard } from "@ui/components/AuthGuard";
import { useApi } from "@ui/util/api";
import { AllOrganizationList as orgList } from "@acm-uiuc/js-shared";
import { AllOrganizationNameList as orgList } from "@acm-uiuc/js-shared";
import { AppRoles } from "@common/roles";
import { EVENT_CACHED_DURATION } from "@common/config";
import {
Expand Down Expand Up @@ -176,7 +176,7 @@ export const ManageEventPage: React.FC = () => {
end: new Date(startDate + 3.6e6),
location: "ACM Room (Siebel CS 1104)",
locationLink: "https://maps.app.goo.gl/dwbBBBkfjkgj8gvA8",
host: userPrimaryOrg,
host: userPrimaryOrg || "",
featured: false,
repeats: undefined,
repeatEnds: undefined,
Expand Down
29 changes: 17 additions & 12 deletions src/ui/pages/organization/OrgInfo.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { AppRoles } from "@common/roles";
import { notifications } from "@mantine/notifications";
import { IconAlertCircle } from "@tabler/icons-react";
import FullScreenLoader from "@ui/components/AuthContext/LoadingScreen";
import { AllOrganizationList } from "@acm-uiuc/js-shared";
import { AllOrganizationNameList, OrganizationName } from "@acm-uiuc/js-shared";
import { useAuth } from "@ui/components/AuthContext";
import { ManageOrganizationForm } from "./ManageOrganizationForm";
import {
Expand All @@ -17,21 +17,24 @@ import {
import * as z from "zod/v4";
import { useSearchParams } from "react-router-dom";

type AcmOrg = (typeof AllOrganizationList)[number];
type OrganizationData = z.infer<typeof setOrganizationMetaBody>;

export const OrgInfoPage = () => {
const api = useApi("core");
const { orgRoles } = useAuth();
const [searchParams, setSearchParams] = useSearchParams();
const [manageableOrgs, setManagableOrgs] = useState<AcmOrg[] | null>(null);
const [manageableOrgs, setManagableOrgs] = useState<
OrganizationName[] | null
>(null);

// Get org from URL query parameter
const orgFromUrl = searchParams.get("org") as AcmOrg | null;
const [selectedOrg, setSelectedOrg] = useState<AcmOrg | null>(orgFromUrl);
const orgFromUrl = searchParams.get("org") as OrganizationName | null;
const [selectedOrg, setSelectedOrg] = useState<OrganizationName | null>(
orgFromUrl,
);

const getOrganizationData = async (
org: AcmOrg,
org: OrganizationName,
): Promise<OrganizationData> => {
try {
const response = await api.get(
Expand All @@ -51,7 +54,7 @@ export const OrgInfoPage = () => {
};

const updateOrganizationData = async (
org: AcmOrg,
org: OrganizationName,
data: OrganizationData,
): Promise<void> => {
try {
Expand All @@ -78,7 +81,7 @@ export const OrgInfoPage = () => {
}
};
const updateLeads = async (
org: AcmOrg,
org: OrganizationName,
toAdd: LeadEntry[],
toRemove: string[],
): Promise<void> => {
Expand Down Expand Up @@ -110,7 +113,7 @@ export const OrgInfoPage = () => {
(async () => {
const appRoles = await getUserRoles("core");
if (appRoles?.includes(AppRoles.ALL_ORG_MANAGER)) {
setManagableOrgs(AllOrganizationList);
setManagableOrgs(AllOrganizationNameList);
return;
}
setManagableOrgs(
Expand All @@ -120,7 +123,7 @@ export const OrgInfoPage = () => {
}, [orgRoles]);

// Update URL when selected org changes
const handleOrgChange = (org: AcmOrg | null) => {
const handleOrgChange = (org: OrganizationName | null) => {
setSelectedOrg(org);
if (org) {
setSearchParams({ org });
Expand Down Expand Up @@ -182,7 +185,7 @@ export const OrgInfoPage = () => {
placeholder="Select organization"
data={manageableOrgs}
value={selectedOrg}
onChange={handleOrgChange}
onChange={(i) => handleOrgChange(i as OrganizationName)}
mt="md"
searchable
maw={400}
Expand All @@ -192,7 +195,9 @@ export const OrgInfoPage = () => {
{selectedOrg && (
<ManageOrganizationForm
organizationId={selectedOrg}
getOrganizationData={getOrganizationData}
getOrganizationData={(i) =>
getOrganizationData(i as OrganizationName)
}
updateOrganizationData={(data) =>
updateOrganizationData(selectedOrg, data)
}
Expand Down
4 changes: 2 additions & 2 deletions src/ui/pages/roomRequest/NewRoomRequest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
} from "@mantine/core";
import { useForm } from "@mantine/form";
import { DateInput, DateTimePicker } from "@mantine/dates";
import { AllOrganizationList } from "@acm-uiuc/js-shared";
import { AllOrganizationNameList } from "@acm-uiuc/js-shared";
import {
eventThemeOptions,
spaceTypeOptions,
Expand Down Expand Up @@ -405,7 +405,7 @@ const NewRoomRequest: React.FC<NewRoomRequestProps> = ({
placeholder="Select host organization"
withAsterisk
searchable
data={AllOrganizationList.map((org) => ({
data={AllOrganizationNameList.map((org) => ({
value: org,
label: org,
}))}
Expand Down
3 changes: 2 additions & 1 deletion src/ui/pages/roomRequest/RoomRequestLanding.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
RoomRequestPostResponse,
type RoomRequestStatus,
} from "@common/types/roomRequest";
import { OrganizationName } from "@acm-uiuc/js-shared";

export const ManageRoomRequestsPage: React.FC = () => {
const api = useApi("core");
Expand All @@ -34,7 +35,7 @@ export const ManageRoomRequestsPage: React.FC = () => {
{
requestId: string;
title: string;
host: string;
host: OrganizationName;
status: RoomRequestStatus;
}[]
>(
Expand Down
Loading
Loading