Skip to content

Commit f5dd482

Browse files
committed
Commit entra and github seperately
1 parent e663459 commit f5dd482

File tree

1 file changed

+109
-116
lines changed

1 file changed

+109
-116
lines changed

src/api/routes/organizations.ts

Lines changed: 109 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -424,122 +424,52 @@ const organizationsPlugin: FastifyPluginAsync = async (fastify, _options) => {
424424
const grpDisplayName = `${request.params.orgId} Admin`;
425425
const grpShortName = `${OrganizationShortIdentifierMapping[request.params.orgId as keyof typeof OrganizationShortIdentifierMapping]}-adm`;
426426

427-
// Create external groups
428-
if (shouldCreateNewEntraGroup || !githubTeamId) {
429-
const timestamp = new Date().toISOString();
430-
const updates: Record<string, any> = { updatedAt: timestamp };
431-
const logStatements: TransactWriteItem[] = [];
432-
433-
// Create Entra group if needed
434-
if (shouldCreateNewEntraGroup) {
435-
request.log.info(
436-
`No Entra group exists for ${request.params.orgId}. Creating new group...`,
437-
);
427+
// Create Entra group if needed
428+
if (shouldCreateNewEntraGroup) {
429+
request.log.info(
430+
`No Entra group exists for ${request.params.orgId}. Creating new group...`,
431+
);
438432

439-
try {
440-
const memberUpns = add.map((u) =>
441-
u.username.replace("@illinois.edu", "@acm.illinois.edu"),
442-
);
443-
444-
entraGroupId = await createM365Group(
445-
entraIdToken,
446-
grpDisplayName,
447-
grpShortName,
448-
memberUpns,
449-
fastify.runEnvironment,
450-
);
451-
452-
request.log.info(
453-
`Created Entra group ${entraGroupId} for ${request.params.orgId}`,
454-
);
455-
456-
updates.leadsEntraGroupId = entraGroupId;
457-
const logStatement = buildAuditLogTransactPut({
458-
entry: {
459-
module: Modules.ORG_INFO,
460-
message: "Created Entra group for organization leads.",
461-
actor: request.username!,
462-
target: request.params.orgId,
463-
},
464-
});
465-
if (logStatement) {
466-
logStatements.push(logStatement);
467-
}
468-
469-
// Update dynamic membership query
470-
const newQuery = await getLeadsM365DynamicQuery({
471-
dynamoClient: fastify.dynamoClient,
472-
includeGroupIds: [entraGroupId],
473-
});
474-
if (newQuery) {
475-
const groupToUpdate =
476-
fastify.runEnvironment === "prod"
477-
? execCouncilGroupId
478-
: execCouncilTestingGroupId;
479-
request.log.info(
480-
"Changing Exec group membership dynamic query...",
481-
);
482-
await setGroupMembershipRule(
483-
entraIdToken,
484-
groupToUpdate,
485-
newQuery,
486-
);
487-
request.log.info("Changed Exec group membership dynamic query!");
488-
}
489-
} catch (e) {
490-
request.log.error(e, "Failed to create Entra group");
491-
throw new InternalServerError({
492-
message: "Failed to create Entra group for organization leads.",
493-
});
494-
}
495-
}
433+
try {
434+
const memberUpns = add.map((u) =>
435+
u.username.replace("@illinois.edu", "@acm.illinois.edu"),
436+
);
496437

497-
// Create GitHub team if needed
498-
if (!githubTeamId) {
499-
request.log.info(
500-
`No GitHub team exists for ${request.params.orgId}. Creating new team...`,
438+
entraGroupId = await createM365Group(
439+
entraIdToken,
440+
grpDisplayName,
441+
grpShortName,
442+
memberUpns,
443+
fastify.runEnvironment,
501444
);
502-
const suffix = fastify.environmentConfig.GroupEmailSuffix;
503-
githubTeamId = await createGithubTeam({
504-
orgId: fastify.environmentConfig.GithubOrgName,
505-
githubToken: fastify.secretConfig.github_pat,
506-
parentTeamId: fastify.environmentConfig.ExecGithubTeam,
507-
name: `${grpShortName}${suffix === "" ? "" : `-${suffix}`}`,
508-
description: grpDisplayName,
509-
logger: request.log,
510-
});
445+
511446
request.log.info(
512-
`Created GitHub team "${githubTeamId}" for ${request.params.orgId} leads.`,
447+
`Created Entra group ${entraGroupId} for ${request.params.orgId}`,
513448
);
514-
createdGithubTeam = true;
515-
updates.leadsGithubTeamId = githubTeamId;
449+
450+
// Store Entra group ID immediately
516451
const logStatement = buildAuditLogTransactPut({
517452
entry: {
518453
module: Modules.ORG_INFO,
519-
message: `Created GitHub team "${githubTeamId}" for organization leads.`,
454+
message: "Created Entra group for organization leads.",
520455
actor: request.username!,
521456
target: request.params.orgId,
522457
},
523458
});
524-
if (logStatement) {
525-
logStatements.push(logStatement);
526-
}
527-
}
528459

529-
// Store external group IDs if they were created
530-
if (Object.keys(updates).length > 0) {
531-
const storeIdsOperation = async () => {
460+
const storeEntraIdOperation = async () => {
532461
const commandTransaction = new TransactWriteItemsCommand({
533462
TransactItems: [
534-
...logStatements,
463+
...(logStatement ? [logStatement] : []),
535464
{
536465
Put: {
537466
TableName: genericConfig.SigInfoTableName,
538467
Item: marshall(
539468
{
540469
primaryKey: `DEFINE#${request.params.orgId}`,
541470
entryId: "0",
542-
...updates,
471+
leadsEntraGroupId: entraGroupId,
472+
updatedAt: new Date().toISOString(),
543473
},
544474
{ removeUndefinedValues: true },
545475
),
@@ -551,13 +481,92 @@ const organizationsPlugin: FastifyPluginAsync = async (fastify, _options) => {
551481
};
552482

553483
await retryDynamoTransactionWithBackoff(
554-
storeIdsOperation,
484+
storeEntraIdOperation,
555485
request.log,
556-
`Store group IDs for ${request.params.orgId}`,
486+
`Store Entra group ID for ${request.params.orgId}`,
557487
);
488+
489+
// Update dynamic membership query
490+
const newQuery = await getLeadsM365DynamicQuery({
491+
dynamoClient: fastify.dynamoClient,
492+
includeGroupIds: [entraGroupId],
493+
});
494+
if (newQuery) {
495+
const groupToUpdate =
496+
fastify.runEnvironment === "prod"
497+
? execCouncilGroupId
498+
: execCouncilTestingGroupId;
499+
request.log.info("Changing Exec group membership dynamic query...");
500+
await setGroupMembershipRule(entraIdToken, groupToUpdate, newQuery);
501+
request.log.info("Changed Exec group membership dynamic query!");
502+
}
503+
} catch (e) {
504+
request.log.error(e, "Failed to create Entra group");
505+
throw new InternalServerError({
506+
message: "Failed to create Entra group for organization leads.",
507+
});
558508
}
559509
}
560510

511+
// Create GitHub team if needed
512+
if (!githubTeamId) {
513+
request.log.info(
514+
`No GitHub team exists for ${request.params.orgId}. Creating new team...`,
515+
);
516+
const suffix = fastify.environmentConfig.GroupEmailSuffix;
517+
githubTeamId = await createGithubTeam({
518+
orgId: fastify.environmentConfig.GithubOrgName,
519+
githubToken: fastify.secretConfig.github_pat,
520+
parentTeamId: fastify.environmentConfig.ExecGithubTeam,
521+
name: `${grpShortName}${suffix === "" ? "" : `-${suffix}`}`,
522+
description: grpDisplayName,
523+
logger: request.log,
524+
});
525+
request.log.info(
526+
`Created GitHub team "${githubTeamId}" for ${request.params.orgId} leads.`,
527+
);
528+
createdGithubTeam = true;
529+
530+
// Store GitHub team ID immediately
531+
const logStatement = buildAuditLogTransactPut({
532+
entry: {
533+
module: Modules.ORG_INFO,
534+
message: `Created GitHub team "${githubTeamId}" for organization leads.`,
535+
actor: request.username!,
536+
target: request.params.orgId,
537+
},
538+
});
539+
540+
const storeGithubIdOperation = async () => {
541+
const commandTransaction = new TransactWriteItemsCommand({
542+
TransactItems: [
543+
...(logStatement ? [logStatement] : []),
544+
{
545+
Put: {
546+
TableName: genericConfig.SigInfoTableName,
547+
Item: marshall(
548+
{
549+
primaryKey: `DEFINE#${request.params.orgId}`,
550+
entryId: "0",
551+
leadsGithubTeamId: githubTeamId,
552+
updatedAt: new Date().toISOString(),
553+
},
554+
{ removeUndefinedValues: true },
555+
),
556+
},
557+
},
558+
],
559+
});
560+
return await clients.dynamoClient.send(commandTransaction);
561+
};
562+
563+
await retryDynamoTransactionWithBackoff(
564+
storeGithubIdOperation,
565+
request.log,
566+
`Store GitHub team ID for ${request.params.orgId}`,
567+
);
568+
}
569+
561570
const commonArgs = {
562571
orgId: request.params.orgId,
563572
actorUsername: request.username!,
@@ -574,26 +583,10 @@ const organizationsPlugin: FastifyPluginAsync = async (fastify, _options) => {
574583
removeLead({ ...commonArgs, username }),
575584
);
576585

577-
// Execute all add/remove operations sequentially to avoid transaction conflicts
578-
const results: PromiseSettledResult<SQSMessage | null>[] = [];
579-
580-
// Process adds
581-
for (const promise of addPromises) {
582-
const result = await promise.then(
583-
(value) => ({ status: "fulfilled" as const, value }),
584-
(reason) => ({ status: "rejected" as const, reason }),
585-
);
586-
results.push(result);
587-
}
588-
589-
// Process removes
590-
for (const promise of removePromises) {
591-
const result = await promise.then(
592-
(value) => ({ status: "fulfilled" as const, value }),
593-
(reason) => ({ status: "rejected" as const, reason }),
594-
);
595-
results.push(result);
596-
}
586+
const results = await Promise.allSettled([
587+
...addPromises,
588+
...removePromises,
589+
]);
597590

598591
const failures = results.filter((r) => r.status === "rejected");
599592
if (failures.length > 0) {

0 commit comments

Comments
 (0)