From 85c94b3516b52954ed424059b33edec607b32790 Mon Sep 17 00:00:00 2001 From: Dominik Korsa Date: Mon, 18 Jan 2021 13:26:09 +0100 Subject: [PATCH] Add students_mode field --- .idea/inspectionProfiles/Project_Default.xml | 1 + backend/src/routes/oauth2/authorize.ts | 28 +++++++++++++------ .../routes/website-api/models/prompt-info.ts | 4 +++ .../resolvers/prompt-info-resolver.ts | 1 + backend/src/types.ts | 12 ++++++++ 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 03d9549..832ccb8 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,5 +2,6 @@ \ No newline at end of file diff --git a/backend/src/routes/oauth2/authorize.ts b/backend/src/routes/oauth2/authorize.ts index d92cd78..a53089a 100644 --- a/backend/src/routes/oauth2/authorize.ts +++ b/backend/src/routes/oauth2/authorize.ts @@ -3,7 +3,8 @@ import { nanoid } from 'nanoid'; import { scopes } from '../../constants'; import database from '../../database/database'; import { ParamError, ScopeError } from '../../errors'; -import type { MyFastifyInstance } from '../../types'; +import type { MyFastifyInstance, StudentsMode } from '../../types'; + import { getSessionData, isObject, parseScopeParam, validateOptionalParam, validateParam, } from '../../utils'; @@ -39,22 +40,30 @@ export default function registerAuthorize(server: MyFastifyInstance): void { try { validateParam('response_type', request.query.response_type); if (request.query.response_type === 'code') { - const requestedScopes = _.uniq(parseScopeParam('scope', request.query.scope)); - requestedScopes.forEach((scope) => { - if (!scopes.includes(scope)) { - throw new ScopeError(`Unknown scope ${scope}`); - } - }); + validateParam('students_mode', request.query.students_mode); validateOptionalParam('state', request.query.state); validateOptionalParam('code_challenge', request.query.code_challenge); validateOptionalParam('code_challenge_method', request.query.code_challenge_method); const codeChallengeMethod = request.query.code_challenge_method ?? 'plain'; if (codeChallengeMethod !== 'plain' && codeChallengeMethod !== 'S256') { - await reply.redirect(`${request.query.redirect_uri}?error=invalid_request&error_description=${encodeURIComponent('code_challenge_method should be either plain or S256')}`); - return; + throw new ParamError('code_challenge_method should be either "plain" or "S256"'); } + if ( + !['none', 'one', 'many'].includes(request.query.students_mode) + ) { + throw new ParamError('students_mode should be either "none", "one" or "many"'); + } + const studentsMode = request.query.students_mode as StudentsMode; + + const requestedScopes = _.uniq(parseScopeParam('scope', request.query.scope)); + requestedScopes.forEach((scope) => { + if (!scopes.includes(scope)) { + throw new ScopeError(`Unknown scope ${scope}`); + } + }); + const promptId = nanoid(12); const sessionData = getSessionData(request.session); @@ -67,6 +76,7 @@ export default function registerAuthorize(server: MyFastifyInstance): void { method: codeChallengeMethod, value: request.query.code_challenge, }, + studentsMode, }); await reply.redirect(`/authenticate-prompt?prompt_id=${promptId}`); diff --git a/backend/src/routes/website-api/models/prompt-info.ts b/backend/src/routes/website-api/models/prompt-info.ts index 0fc787e..36898cb 100644 --- a/backend/src/routes/website-api/models/prompt-info.ts +++ b/backend/src/routes/website-api/models/prompt-info.ts @@ -1,4 +1,5 @@ import { Field, ObjectType } from 'type-graphql'; +import { StudentsMode } from '../../../types'; import PromptInfoApplication from './prompt-info-application'; @ObjectType() @@ -12,6 +13,9 @@ export default class PromptInfo { @Field(() => String) public clientId!: string; + @Field(() => StudentsMode) + public studentsMode!: StudentsMode; + @Field(() => PromptInfoApplication) public application!: PromptInfoApplication; } diff --git a/backend/src/routes/website-api/resolvers/prompt-info-resolver.ts b/backend/src/routes/website-api/resolvers/prompt-info-resolver.ts index 96df930..962fb39 100644 --- a/backend/src/routes/website-api/resolvers/prompt-info-resolver.ts +++ b/backend/src/routes/website-api/resolvers/prompt-info-resolver.ts @@ -22,6 +22,7 @@ export default class PromptInfoResolver implements ResolverInterface id: promptId, clientId: prompt.clientId, scopes: prompt.scopes, + studentsMode: prompt.studentsMode, }; } diff --git a/backend/src/types.ts b/backend/src/types.ts index c505fd4..753b14f 100644 --- a/backend/src/types.ts +++ b/backend/src/types.ts @@ -1,8 +1,19 @@ import type { FastifyInstance, FastifyRequest, RawReplyDefaultExpression, RawRequestDefaultExpression, RawServerDefault, } from 'fastify'; +import { registerEnumType } from 'type-graphql'; import type SessionData from './session-data'; +export enum StudentsMode { + None = 'none', + One = 'one', + Many = 'many', +} + +registerEnumType(StudentsMode, { + name: 'StudentsMode', +}); + export interface Prompt { clientId: string; redirectUri: string; @@ -12,6 +23,7 @@ export interface Prompt { value: string; method: 'plain' | 'S256'; }; + studentsMode: StudentsMode; loginInfo?: { host: string; username: string;