From d32d3dcc61e0d9499012be6f4a71ba7ee99aa06a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1lint=20Kir=C3=A1ly?= Date: Tue, 24 Dec 2024 08:41:57 +0100 Subject: [PATCH] Add club membership synchronization logic to auth service Implemented logic to update or remove club membership information based on user profiles from AuthSch. Extended `.env.example` with new environment variables to support membership status checks. --- apps/backend/.env.example | 5 ++ apps/backend/src/auth/auth.service.ts | 83 +++++++++++++++++++++++ apps/backend/src/auth/authsch.strategy.ts | 3 +- 3 files changed, 90 insertions(+), 1 deletion(-) diff --git a/apps/backend/.env.example b/apps/backend/.env.example index 3e1ad0e..eefe107 100644 --- a/apps/backend/.env.example +++ b/apps/backend/.env.example @@ -4,3 +4,8 @@ AUTHSCH_CLIENT_SECRET="5KhIlDHGhxzLx3FK7L81FJ5CQSuyJTLVrW0hZnbzv4jbdOHU255HuOtBg JWT_SECRET="this is a secret" FRONTEND_URL="http://localhost:3000" BACKEND_PORT=3030 + +PEK_GROUP_NAME="Muzsika mívelő mérnökök klubja" +PEK_MEMBER_TITLE="tag" +PEK_NEWBIE_TITLE="újonc" +PEK_GATEKEEPER_TITLE="beengedő" diff --git a/apps/backend/src/auth/auth.service.ts b/apps/backend/src/auth/auth.service.ts index 333c34d..50d9422 100644 --- a/apps/backend/src/auth/auth.service.ts +++ b/apps/backend/src/auth/auth.service.ts @@ -33,4 +33,87 @@ export class AuthService { }, }); } + + async syncClubMembership(user: User, userProfile: AuthSchProfile): Promise { + // Skip if the user's PEK profile has not been updated since the last check + if (user.clubMembershipUpdatedAt && userProfile.pek.updatedAt < user.clubMembershipUpdatedAt.valueOf() / 1000) { + return this.prisma.user.update({ where: { id: user.id }, data: { clubMembershipUpdatedAt: new Date() } }); + } + + // If the user is not a member of MMMK + if ( + !( + userProfile.pek.activeMemberAt.some((membership) => membership.groupName === process.env.PEK_GROUP_NAME) || + userProfile.pek.alumniMemberAt.some((membership) => membership.groupName === process.env.MMMK_GROUP_NAME) || + userProfile.pek.executiveAt.some((membership) => membership.groupName === process.env.MMMK_GROUP_NAME) + ) + ) { + // If the user's membership has been terminated, remove their club membership record + this.prisma.clubMembership.delete({ where: { userId: user.id } }); + + return this.prisma.user.update({ where: { id: user.id }, data: { clubMembershipUpdatedAt: new Date() } }); + } + + // Active member at MMMK + for (const membership of userProfile.pek.activeMemberAt) { + if (membership.groupName === process.env.PEK_GROUP_NAME) { + const clubMembership = await this.prisma.clubMembership.upsert({ + where: { userId: user.id }, + update: { + status: membership.titles.includes(process.env.PEK_NEWBIE_TITLE) ? 'NEWBIE' : 'ACTIVE', + titles: membership.titles.filter( + (title) => title !== process.env.PEK_NEWBIE_TITLE && title !== process.env.PEK_MEMBER_TITLE + ), + isGateKeeper: membership.titles.includes(process.env.PEK_GATEKEEPER_TITLE), + }, + create: { + user: { connect: { id: user.id } }, + status: membership.titles.includes(process.env.PEK_NEWBIE_TITLE) ? 'NEWBIE' : 'ACTIVE', + titles: membership.titles.filter( + (title) => title !== process.env.PEK_NEWBIE_TITLE && title !== process.env.PEK_MEMBER_TITLE + ), + isGateKeeper: membership.titles.includes(process.env.PEK_GATEKEEPER_TITLE), + hasRoomAccess: false, + isLeadershipMember: false, + }, + }); + + return this.prisma.user.update({ + where: { id: user.id }, + data: { + clubMembership: { connect: { id: clubMembership.id } }, + clubMembershipUpdatedAt: new Date(), + }, + }); + } + } + + // Senior member at MMMK + for (const membership of userProfile.pek.alumniMemberAt) { + if (membership.groupName === process.env.MMMK_GROUP_NAME) { + const clubMembership = await this.prisma.clubMembership.upsert({ + where: { userId: user.id }, + update: { + status: 'SENIOR', + isGateKeeper: false, + }, + create: { + user: { connect: { id: user.id } }, + status: 'SENIOR', + isGateKeeper: false, + hasRoomAccess: false, + isLeadershipMember: false, + }, + }); + + return this.prisma.user.update({ + where: { id: user.id }, + data: { + clubMembership: { connect: { id: clubMembership.id } }, + clubMembershipUpdatedAt: new Date(), + }, + }); + } + } + } } diff --git a/apps/backend/src/auth/authsch.strategy.ts b/apps/backend/src/auth/authsch.strategy.ts index d925271..079a322 100644 --- a/apps/backend/src/auth/authsch.strategy.ts +++ b/apps/backend/src/auth/authsch.strategy.ts @@ -15,6 +15,7 @@ export class AuthSchStrategy extends PassportStrategy(Strategy) { } async validate(userProfile: AuthSchProfile): Promise { - return await this.authService.findOrCreateUser(userProfile); + const user = await this.authService.findOrCreateUser(userProfile); + return await this.authService.syncClubMembership(user, userProfile); } }