Skip to content

Commit

Permalink
add timeout and skip provisioning
Browse files Browse the repository at this point in the history
  • Loading branch information
MarvinOehlerkingCap committed Dec 11, 2024
1 parent 545982e commit 7f36a8f
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export interface SchulconnexClientConfig {
SCHULCONNEX_CLIENT__PERSON_INFO_TIMEOUT_IN_MS: number;
SCHULCONNEX_CLIENT__PERSONEN_INFO_TIMEOUT_IN_MS: number;
SCHULCONNEX_CLIENT__POLICIES_INFO_TIMEOUT_IN_MS: number;
SCHULCONNEX_CLIENT__API_URL?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { SchulconnexRestClientOptions } from './schulconnex-rest-client-options'

@Module({})
export class SchulconnexClientModule {
static registerAsync(): DynamicModule {
public static registerAsync(): DynamicModule {
return {
imports: [HttpModule, LoggerModule],
module: SchulconnexClientModule,
Expand All @@ -27,6 +27,7 @@ export class SchulconnexClientModule {
tokenEndpoint: configService.get<string>('SCHULCONNEX_CLIENT__TOKEN_ENDPOINT'),
clientId: configService.get<string>('SCHULCONNEX_CLIENT__CLIENT_ID'),
clientSecret: configService.get<string>('SCHULCONNEX_CLIENT__CLIENT_SECRET'),
personInfoTimeoutInMs: configService.get<number>('SCHULCONNEX_CLIENT__PERSON_INFO_TIMEOUT_IN_MS'),
personenInfoTimeoutInMs: configService.get<number>('SCHULCONNEX_CLIENT__PERSONEN_INFO_TIMEOUT_IN_MS'),
policiesInfoTimeoutInMs: configService.get<number>('SCHULCONNEX_CLIENT__POLICIES_INFO_TIMEOUT_IN_MS'),
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export interface SchulconnexRestClientOptions {

clientSecret?: string;

personInfoTimeoutInMs?: number;

personenInfoTimeoutInMs?: number;

policiesInfoTimeoutInMs?: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ describe(SchulconnexRestClient.name, () => {
clientId: 'clientId',
clientSecret: 'clientSecret',
tokenEndpoint: 'https://schulconnex.url/token',
personenInfoTimeoutInMs: 30000,
policiesInfoTimeoutInMs: 30000,
personInfoTimeoutInMs: 30001,
personenInfoTimeoutInMs: 30002,
policiesInfoTimeoutInMs: 30003,
};

beforeAll(() => {
Expand Down Expand Up @@ -100,6 +101,7 @@ describe(SchulconnexRestClient.name, () => {
Authorization: `Bearer ${accessToken}`,
'Accept-Encoding': 'gzip',
},
timeout: options.personInfoTimeoutInMs,
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,14 @@ export class SchulconnexRestClient implements SchulconnexApiInterface {
this.SCHULCONNEX_API_BASE_URL = options.apiUrl || '';
}

public async getPersonInfo(accessToken: string, options?: { overrideUrl: string }): Promise<SchulconnexResponse> {
public getPersonInfo(accessToken: string, options?: { overrideUrl: string }): Promise<SchulconnexResponse> {
const url: URL = new URL(options?.overrideUrl ?? `${this.SCHULCONNEX_API_BASE_URL}/person-info`);

const response: Promise<SchulconnexResponse> = this.getRequest<SchulconnexResponse>(url, accessToken);
const response: Promise<SchulconnexResponse> = this.getRequest<SchulconnexResponse>(
url,
accessToken,
this.options.personInfoTimeoutInMs
);

return response;
}
Expand Down
13 changes: 8 additions & 5 deletions apps/server/src/modules/idp-console/idp-console.config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { Configuration } from '@hpi-schul-cloud/commons';
import { ConsoleWriterConfig } from '@infra/console';
import { LoggerConfig } from '@src/core/logger';
import { RabbitMqConfig } from '@infra/rabbitmq';
import { SchulconnexClientConfig } from '@infra/schulconnex-client';
import { AccountConfig } from '@modules/account';
import { UserConfig } from '@modules/user';
import { SynchronizationConfig } from '@modules/synchronization';
import { SchulconnexClientConfig } from '@infra/schulconnex-client';
import { Configuration } from '@hpi-schul-cloud/commons';
import { UserConfig } from '@modules/user';
import { LanguageType } from '@shared/domain/interface';
import { RabbitMqConfig } from '@infra/rabbitmq';
import { LoggerConfig } from '@src/core/logger';

export interface IdpConsoleConfig
extends ConsoleWriterConfig,
Expand All @@ -33,6 +33,9 @@ const config: IdpConsoleConfig = {
TEACHER_VISIBILITY_FOR_EXTERNAL_TEAM_INVITATION: Configuration.get(
'TEACHER_VISIBILITY_FOR_EXTERNAL_TEAM_INVITATION'
) as string,
SCHULCONNEX_CLIENT__PERSON_INFO_TIMEOUT_IN_MS: Configuration.get(
'SCHULCONNEX_CLIENT__PERSON_INFO_TIMEOUT_IN_MS'
) as number,
SCHULCONNEX_CLIENT__PERSONEN_INFO_TIMEOUT_IN_MS: Configuration.get(
'SCHULCONNEX_CLIENT__PERSONEN_INFO_TIMEOUT_IN_MS'
) as number,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export interface ProvisioningConfig {
FEATURE_SCHULCONNEX_COURSE_SYNC_ENABLED: boolean;
FEATURE_SCHULCONNEX_MEDIA_LICENSE_ENABLED: boolean;
PROVISIONING_SCHULCONNEX_POLICIES_INFO_URL: string;
PROVISIONING_SCHULCONNEX_GROUP_USERS_LIMIT?: number;
FEATURE_SANIS_GROUP_PROVISIONING_ENABLED: boolean;
FEATURE_OTHER_GROUPUSERS_PROVISIONING_ENABLED: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ describe(SchulconnexProvisioningStrategy.name, () => {
config.FEATURE_SANIS_GROUP_PROVISIONING_ENABLED = false;
config.FEATURE_SCHULCONNEX_COURSE_SYNC_ENABLED = false;
config.FEATURE_OTHER_GROUPUSERS_PROVISIONING_ENABLED = true;
config.PROVISIONING_SCHULCONNEX_GROUP_USERS_LIMIT = undefined;
});

afterAll(async () => {
Expand Down Expand Up @@ -336,6 +337,42 @@ describe(SchulconnexProvisioningStrategy.name, () => {
});
});

describe('when there are too many users in groups', () => {
const setup = () => {
config.PROVISIONING_SCHULCONNEX_GROUP_USERS_LIMIT = 1;

const externalUserId = 'externalUserId';
const externalGroups: ExternalGroupDto[] = externalGroupDtoFactory.buildList(2);
const oauthData: OauthDataDto = new OauthDataDto({
system: new ProvisioningSystemDto({
systemId: new ObjectId().toHexString(),
provisioningStrategy: SystemProvisioningStrategy.OIDC,
}),
externalSchool: externalSchoolDtoFactory.build(),
externalUser: externalUserDtoFactory.build({ externalId: externalUserId }),
externalGroups,
});

const user: UserDO = userDoFactory.withRoles([{ id: 'roleId', name: RoleName.USER }]).build({
externalId: externalUserId,
});

schulconnexUserProvisioningService.provisionExternalUser.mockResolvedValueOnce(user);

return {
oauthData,
};
};

it('should not run group provisioning', async () => {
const { oauthData } = setup();

await strategy.apply(oauthData);

expect(schulconnexGroupProvisioningService.provisionExternalGroup).not.toHaveBeenCalled();
});
});

describe('when group data is not provided', () => {
const setup = () => {
config.FEATURE_SANIS_GROUP_PROVISIONING_ENABLED = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,16 @@ export abstract class SchulconnexProvisioningStrategy extends ProvisioningStrate
);

if (this.configService.get('FEATURE_SANIS_GROUP_PROVISIONING_ENABLED')) {
await this.provisionGroups(data, school);
const usersInGroupsCount: number =
data.externalGroups?.reduce(
(count: number, group: ExternalGroupDto) => count + (group.otherUsers?.length ?? 0),
data.externalGroups?.length ?? 0
) ?? 0;

const limit: number | undefined = this.configService.get('PROVISIONING_SCHULCONNEX_GROUP_USERS_LIMIT');
if (!limit || usersInGroupsCount < limit) {
await this.provisionGroups(data, school);
}
}

if (this.configService.get('FEATURE_SCHULCONNEX_MEDIA_LICENSE_ENABLED') && user.id) {
Expand Down
6 changes: 6 additions & 0 deletions apps/server/src/modules/server/server.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,12 +267,18 @@ const config: ServerConfig = {
SCHULCONNEX_CLIENT__CLIENT_SECRET: Configuration.has('SCHULCONNEX_CLIENT__CLIENT_SECRET')
? (Configuration.get('SCHULCONNEX_CLIENT__CLIENT_SECRET') as string)
: undefined,
SCHULCONNEX_CLIENT__PERSON_INFO_TIMEOUT_IN_MS: Configuration.get(
'SCHULCONNEX_CLIENT__PERSON_INFO_TIMEOUT_IN_MS'
) as number,
SCHULCONNEX_CLIENT__PERSONEN_INFO_TIMEOUT_IN_MS: Configuration.get(
'SCHULCONNEX_CLIENT__PERSONEN_INFO_TIMEOUT_IN_MS'
) as number,
SCHULCONNEX_CLIENT__POLICIES_INFO_TIMEOUT_IN_MS: Configuration.get(
'SCHULCONNEX_CLIENT__POLICIES_INFO_TIMEOUT_IN_MS'
) as number,
PROVISIONING_SCHULCONNEX_GROUP_USERS_LIMIT: Configuration.has('PROVISIONING_SCHULCONNEX_GROUP_USERS_LIMIT')
? (Configuration.get('PROVISIONING_SCHULCONNEX_GROUP_USERS_LIMIT') as number)
: undefined,
FEATURE_SCHULCONNEX_COURSE_SYNC_ENABLED: Configuration.get('FEATURE_SCHULCONNEX_COURSE_SYNC_ENABLED') as boolean,
...getTldrawClientConfig(),
FEATURE_MEDIA_SHELF_ENABLED: Configuration.get('FEATURE_MEDIA_SHELF_ENABLED') as boolean,
Expand Down
Loading

0 comments on commit 7f36a8f

Please sign in to comment.