diff --git a/src/platform-control/platform-control.service.ts b/src/platform-control/platform-control.service.ts index 2ab319c..f805bba 100644 --- a/src/platform-control/platform-control.service.ts +++ b/src/platform-control/platform-control.service.ts @@ -59,8 +59,7 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { async requestControl(accessToken: string | undefined, platformOptionId: string) { const { authUser, user } = await this.getStudent(accessToken); - const context = this.organizationContext(authUser); - const group = await this.findStudentGroup(user.id, context); + const { context, group } = await this.getStudentControlContext(user.id, authUser); const resource = await this.resolveResource(platformOptionId, context, group?.instructorPlatformId ?? null); await this.applyExpiredSessions(context); @@ -137,8 +136,7 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { async cancelQueue(accessToken: string | undefined, platformOptionId: string) { const { authUser, user } = await this.getStudent(accessToken); - const context = this.organizationContext(authUser); - const group = await this.findStudentGroup(user.id, context); + const { context, group } = await this.getStudentControlContext(user.id, authUser); const resource = await this.resolveResource(platformOptionId, context, group?.instructorPlatformId ?? null); await this.prisma.platformControlQueueEntry.updateMany({ @@ -158,8 +156,7 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { async getPlatformStatuses(accessToken: string | undefined, platformOptionIds: string[]) { const { authUser, user } = await this.getStudent(accessToken); - const context = this.organizationContext(authUser); - const group = await this.findStudentGroup(user.id, context); + const { context, group } = await this.getStudentControlContext(user.id, authUser); const uniqueIds = Array.from(new Set(platformOptionIds.map((id) => id.trim()).filter(Boolean))).slice(0, 30); const resources = await Promise.all(uniqueIds.map(async (platformOptionId) => { const resource = await this.resolveResource(platformOptionId, context, group?.instructorPlatformId ?? null).catch(() => null); @@ -230,8 +227,7 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { async releaseControl(accessToken: string | undefined, platformOptionId: string) { const { authUser, user } = await this.getStudent(accessToken); - const context = this.organizationContext(authUser); - const group = await this.findStudentGroup(user.id, context); + const { context, group } = await this.getStudentControlContext(user.id, authUser); const resource = await this.resolveResource(platformOptionId, context, group?.instructorPlatformId ?? null); const result = await this.prisma.$transaction(async (tx) => { @@ -286,8 +282,7 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { async extendControl(accessToken: string | undefined, platformOptionId: string) { const { authUser, user } = await this.getStudent(accessToken); - const context = this.organizationContext(authUser); - const group = await this.findStudentGroup(user.id, context); + const { context, group } = await this.getStudentControlContext(user.id, authUser); const resource = await this.resolveResource(platformOptionId, context, group?.instructorPlatformId ?? null); await this.applyExpiredSessions(context); @@ -357,8 +352,7 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { async connectPlatform(accessToken: string | undefined, platformOptionId: string) { const { authUser, user } = await this.getStudent(accessToken); - const context = this.organizationContext(authUser); - const group = await this.findStudentGroup(user.id, context); + const { context, group } = await this.getStudentControlContext(user.id, authUser); const resource = await this.resolveResource(platformOptionId, context, group?.instructorPlatformId ?? null); const active = await this.prisma.platformControlSession.findFirst({ @@ -434,8 +428,7 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { async getRemoteVisualizationStatus(accessToken: string | undefined, platformOptionId: string) { const { authUser, user } = await this.getStudent(accessToken); - const context = this.organizationContext(authUser); - const group = await this.findStudentGroup(user.id, context); + const { context, group } = await this.getStudentControlContext(user.id, authUser); const resource = await this.resolveResource(platformOptionId, context, group?.instructorPlatformId ?? null); await this.assertActiveControl(resource, user.id); const gatewayPlatformId = await this.resolveGatewayPlatformId(resource); @@ -449,8 +442,7 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { input: { stack?: string; rosDomainId?: string; profile?: unknown }, ) { const { authUser, user } = await this.getStudent(accessToken); - const context = this.organizationContext(authUser); - const group = await this.findStudentGroup(user.id, context); + const { context, group } = await this.getStudentControlContext(user.id, authUser); const resource = await this.resolveResource(platformOptionId, context, group?.instructorPlatformId ?? null); await this.assertActiveControl(resource, user.id); const gatewayPlatformId = await this.resolveGatewayPlatformId(resource); @@ -464,8 +456,7 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { input: { stack?: string; rosDomainId?: string; profile?: unknown }, ) { const { authUser, user } = await this.getStudent(accessToken); - const context = this.organizationContext(authUser); - const group = await this.findStudentGroup(user.id, context); + const { context, group } = await this.getStudentControlContext(user.id, authUser); const resource = await this.resolveResource(platformOptionId, context, group?.instructorPlatformId ?? null); await this.assertActiveControl(resource, user.id); const gatewayPlatformId = await this.resolveGatewayPlatformId(resource); @@ -475,8 +466,7 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { async listRemoteModules(accessToken: string | undefined, platformOptionId: string) { const { authUser, user } = await this.getStudent(accessToken); - const context = this.organizationContext(authUser); - const group = await this.findStudentGroup(user.id, context); + const { context, group } = await this.getStudentControlContext(user.id, authUser); const resource = await this.resolveResource(platformOptionId, context, group?.instructorPlatformId ?? null); const gatewayPlatformId = await this.resolveGatewayPlatformId(resource); if (!gatewayPlatformId) throw new BadRequestException('Remote platform is required'); @@ -490,8 +480,7 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { input: { folderName?: string | null; rosDomainId?: string | null }, ) { const { authUser, user } = await this.getStudent(accessToken); - const context = this.organizationContext(authUser); - const group = await this.findStudentGroup(user.id, context); + const { context, group } = await this.getStudentControlContext(user.id, authUser); const resource = await this.resolveResource(platformOptionId, context, group?.instructorPlatformId ?? null); await this.assertActiveControl(resource, user.id); const gatewayPlatformId = await this.resolveGatewayPlatformId(resource); @@ -510,8 +499,7 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { input: { containerKey?: string | null }, ) { const { authUser, user } = await this.getStudent(accessToken); - const context = this.organizationContext(authUser); - const group = await this.findStudentGroup(user.id, context); + const { context, group } = await this.getStudentControlContext(user.id, authUser); const resource = await this.resolveResource(platformOptionId, context, group?.instructorPlatformId ?? null); await this.assertActiveControl(resource, user.id); const gatewayPlatformId = await this.resolveGatewayPlatformId(resource); @@ -896,14 +884,16 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { private async findStudentGroup( userId: string, - context: { organizationId?: string; organizationName: string }, + context?: { organizationId?: string; organizationName: string } | null, ) { return this.prisma.studentGroup.findFirst({ where: { - ...this.organizationWhere( - context.organizationId, - context.organizationName, - ), + ...(context + ? this.organizationWhere( + context.organizationId, + context.organizationName, + ) + : {}), members: { some: { userId }, }, @@ -943,15 +933,34 @@ export class PlatformControlService implements OnModuleInit, OnModuleDestroy { private organizationContext(user: AuthResponseUser) { const organizationName = user.primaryAffiliation?.organizationName?.trim(); - if (!organizationName) { - throw new BadRequestException('Organization is required'); - } + if (!organizationName) return null; return { organizationId: user.primaryAffiliation?.organizationId, organizationName, }; } + private async getStudentControlContext(userId: string, authUser: AuthResponseUser) { + const group = await this.findStudentGroup(userId); + + if (group) { + return { + context: { + organizationId: group.organizationId ?? undefined, + organizationName: group.organizationName, + }, + group, + }; + } + + const primaryContext = this.organizationContext(authUser); + if (primaryContext) { + return { context: primaryContext, group: null }; + } + + throw new BadRequestException('Student group is required'); + } + private resourceWhere(resource: Pick) { return resource.instructorPlatformId ? { instructorPlatformId: resource.instructorPlatformId }