diff --git a/apps/server/src/infra/schulconnex-client/index.ts b/apps/server/src/infra/schulconnex-client/index.ts index 1bc03b95236..9249683024a 100644 --- a/apps/server/src/infra/schulconnex-client/index.ts +++ b/apps/server/src/infra/schulconnex-client/index.ts @@ -2,20 +2,20 @@ export { SchulconnexRestClientOptions } from './schulconnex-rest-client-options' export { SchulconnexClientModule } from './schulconnex-client.module'; export { SchulconnexRestClient } from './schulconnex-rest-client'; export { - SanisResponse, - SanisRole, - SanisGroupRole, - SanisGroupType, - SanisGruppenResponse, - SanisResponseValidationGroups, - SanisPersonResponse, - SanisAnschriftResponse, - SanisGruppenzugehoerigkeitResponse, - SanisGruppeResponse, - SanisNameResponse, - SanisOrganisationResponse, - SanisPersonenkontextResponse, - SanisSonstigeGruppenzugehoerigeResponse, + SchulconnexResponse, + SchulconnexRole, + SchulconnexGroupRole, + SchulconnexGroupType, + SchulconnexGruppenResponse, + SchulconnexResponseValidationGroups, + SchulconnexPersonResponse, + SchulconnexAnschriftResponse, + SchulconnexGruppenzugehoerigkeitResponse, + SchulconnexGruppeResponse, + SchulconnexNameResponse, + SchulconnexOrganisationResponse, + SchulconnexPersonenkontextResponse, + SchulconnexSonstigeGruppenzugehoerigeResponse, } from './response'; export { schulconnexResponseFactory } from './testing/schulconnex-response-factory'; export { SchulconnexClientConfig } from './schulconnex-client-config'; diff --git a/apps/server/src/infra/schulconnex-client/response/index.ts b/apps/server/src/infra/schulconnex-client/response/index.ts index f01d0e33ed5..fed85ea47fa 100644 --- a/apps/server/src/infra/schulconnex-client/response/index.ts +++ b/apps/server/src/infra/schulconnex-client/response/index.ts @@ -1,17 +1,17 @@ -export * from './sanis.response'; -export * from './sanis-role'; -export * from './sanis-group-role'; -export * from './sanis-group-type'; -export * from './sanis-name-response'; -export * from './sanis-gruppe-response'; -export * from './sanis-gruppen-response'; -export * from './sanis-organisation-response'; -export * from './sanis-personenkontext-response'; -export * from './sanis-gruppenzugehoerigkeit-response'; -export * from './sanis-person-response'; -export * from './sanis-sonstige-gruppenzugehoerige-response'; -export * from './sanis-anschrift-response'; -export * from './sanis-response-validation-groups'; -export { SanisErreichbarkeitenResponse } from './sanis-erreichbarkeiten-response'; +export { SchulconnexResponse } from './schulconnex.response'; +export { SchulconnexRole } from './schulconnex-role'; +export { SchulconnexGroupRole } from './schulconnex-group-role'; +export { SchulconnexGroupType } from './schulconnex-group-type'; +export { SchulconnexNameResponse } from './schulconnex-name-response'; +export { SchulconnexGruppeResponse } from './schulconnex-gruppe-response'; +export { SchulconnexGruppenResponse } from './schulconnex-gruppen-response'; +export { SchulconnexOrganisationResponse } from './schulconnex-organisation-response'; +export { SchulconnexPersonenkontextResponse } from './schulconnex-personenkontext-response'; +export { SchulconnexGruppenzugehoerigkeitResponse } from './schulconnex-gruppenzugehoerigkeit-response'; +export { SchulconnexPersonResponse } from './schulconnex-person-response'; +export { SchulconnexSonstigeGruppenzugehoerigeResponse } from './schulconnex-sonstige-gruppenzugehoerige-response'; +export { SchulconnexAnschriftResponse } from './schulconnex-anschrift-response'; +export { SchulconnexResponseValidationGroups } from './schulconnex-response-validation-groups'; +export { SchulconnexErreichbarkeitenResponse } from './schulconnex-erreichbarkeiten-response'; export { SchulconnexCommunicationType } from './schulconnex-communication-type'; export * from './lizenz-info'; diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-gruppe-response.ts b/apps/server/src/infra/schulconnex-client/response/sanis-gruppe-response.ts deleted file mode 100644 index 0a785f73633..00000000000 --- a/apps/server/src/infra/schulconnex-client/response/sanis-gruppe-response.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { IsEnum, IsString } from 'class-validator'; -import { SanisGroupType } from './sanis-group-type'; - -export class SanisGruppeResponse { - @IsString() - id!: string; - - @IsString() - bezeichnung!: string; - - @IsEnum(SanisGroupType) - typ!: SanisGroupType; -} diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-gruppen-response.ts b/apps/server/src/infra/schulconnex-client/response/sanis-gruppen-response.ts deleted file mode 100644 index ce48cc90120..00000000000 --- a/apps/server/src/infra/schulconnex-client/response/sanis-gruppen-response.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Type } from 'class-transformer'; -import { IsArray, IsObject, IsOptional, ValidateNested } from 'class-validator'; -import { SanisGruppeResponse } from './sanis-gruppe-response'; -import { SanisGruppenzugehoerigkeitResponse } from './sanis-gruppenzugehoerigkeit-response'; -import { SanisSonstigeGruppenzugehoerigeResponse } from './sanis-sonstige-gruppenzugehoerige-response'; - -export class SanisGruppenResponse { - @IsObject() - @ValidateNested() - @Type(() => SanisGruppeResponse) - gruppe!: SanisGruppeResponse; - - @IsObject() - @ValidateNested() - @Type(() => SanisGruppenzugehoerigkeitResponse) - gruppenzugehoerigkeit!: SanisGruppenzugehoerigkeitResponse; - - @IsOptional() - @IsArray() - @ValidateNested({ each: true }) - @Type(() => SanisSonstigeGruppenzugehoerigeResponse) - sonstige_gruppenzugehoerige?: SanisSonstigeGruppenzugehoerigeResponse[]; -} diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-gruppenzugehoerigkeit-response.ts b/apps/server/src/infra/schulconnex-client/response/sanis-gruppenzugehoerigkeit-response.ts deleted file mode 100644 index 44e45d3c7df..00000000000 --- a/apps/server/src/infra/schulconnex-client/response/sanis-gruppenzugehoerigkeit-response.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IsArray, IsEnum, IsOptional } from 'class-validator'; -import { SanisGroupRole } from './sanis-group-role'; - -export class SanisGruppenzugehoerigkeitResponse { - @IsOptional() - @IsArray() - @IsEnum(SanisGroupRole, { each: true }) - rollen?: SanisGroupRole[]; -} diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-person-response.ts b/apps/server/src/infra/schulconnex-client/response/sanis-person-response.ts deleted file mode 100644 index 0e6dbcfb472..00000000000 --- a/apps/server/src/infra/schulconnex-client/response/sanis-person-response.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Type } from 'class-transformer'; -import { IsObject, IsOptional, ValidateNested } from 'class-validator'; -import { SanisGeburtResponse } from './sanis-geburt-response'; -import { SanisNameResponse } from './sanis-name-response'; - -export class SanisPersonResponse { - @IsObject() - @ValidateNested() - @Type(() => SanisNameResponse) - name!: SanisNameResponse; - - @IsOptional() - @IsObject() - @ValidateNested() - @Type(() => SanisGeburtResponse) - geburt?: SanisGeburtResponse; -} diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-personenkontext-response.ts b/apps/server/src/infra/schulconnex-client/response/sanis-personenkontext-response.ts deleted file mode 100644 index dc5ba40eea9..00000000000 --- a/apps/server/src/infra/schulconnex-client/response/sanis-personenkontext-response.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Type } from 'class-transformer'; -import { IsArray, IsEnum, IsObject, IsOptional, IsString, ValidateNested } from 'class-validator'; -import { SanisErreichbarkeitenResponse } from './sanis-erreichbarkeiten-response'; -import { SanisGruppenResponse } from './sanis-gruppen-response'; -import { SanisOrganisationResponse } from './sanis-organisation-response'; -import { SanisResponseValidationGroups } from './sanis-response-validation-groups'; -import { SanisRole } from './sanis-role'; - -export class SanisPersonenkontextResponse { - @IsString({ groups: [SanisResponseValidationGroups.USER, SanisResponseValidationGroups.GROUPS] }) - id!: string; - - @IsEnum(SanisRole, { groups: [SanisResponseValidationGroups.USER] }) - rolle!: SanisRole; - - @IsObject({ groups: [SanisResponseValidationGroups.SCHOOL] }) - @ValidateNested({ groups: [SanisResponseValidationGroups.SCHOOL] }) - @Type(() => SanisOrganisationResponse) - organisation!: SanisOrganisationResponse; - - @IsOptional({ groups: [SanisResponseValidationGroups.GROUPS] }) - @IsArray({ groups: [SanisResponseValidationGroups.GROUPS] }) - @ValidateNested({ each: true, groups: [SanisResponseValidationGroups.GROUPS] }) - @Type(() => SanisGruppenResponse) - gruppen?: SanisGruppenResponse[]; - - @IsOptional() - @IsArray() - @ValidateNested({ each: true }) - @Type(() => SanisErreichbarkeitenResponse) - erreichbarkeiten?: SanisErreichbarkeitenResponse[]; -} diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-sonstige-gruppenzugehoerige-response.ts b/apps/server/src/infra/schulconnex-client/response/sanis-sonstige-gruppenzugehoerige-response.ts deleted file mode 100644 index 68644ff3337..00000000000 --- a/apps/server/src/infra/schulconnex-client/response/sanis-sonstige-gruppenzugehoerige-response.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { IsArray, IsEnum, IsOptional, IsString } from 'class-validator'; -import { SanisGroupRole } from './sanis-group-role'; - -export class SanisSonstigeGruppenzugehoerigeResponse { - @IsString() - ktid!: string; - - @IsOptional() - @IsArray() - @IsEnum(SanisGroupRole, { each: true }) - rollen?: SanisGroupRole[]; -} diff --git a/apps/server/src/infra/schulconnex-client/response/sanis.response.ts b/apps/server/src/infra/schulconnex-client/response/sanis.response.ts deleted file mode 100644 index 193390df8bc..00000000000 --- a/apps/server/src/infra/schulconnex-client/response/sanis.response.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Type } from 'class-transformer'; -import { ArrayMinSize, IsArray, IsObject, IsString, ValidateNested } from 'class-validator'; -import { SanisPersonResponse } from './sanis-person-response'; -import { SanisPersonenkontextResponse } from './sanis-personenkontext-response'; -import { SanisResponseValidationGroups } from './sanis-response-validation-groups'; - -export class SanisResponse { - @IsString({ groups: [SanisResponseValidationGroups.USER] }) - pid!: string; - - @IsObject({ groups: [SanisResponseValidationGroups.USER] }) - @ValidateNested({ groups: [SanisResponseValidationGroups.USER] }) - @Type(() => SanisPersonResponse) - person!: SanisPersonResponse; - - @IsArray() - @ArrayMinSize(1) - @ValidateNested({ each: true }) - @Type(() => SanisPersonenkontextResponse) - personenkontexte!: SanisPersonenkontextResponse[]; -} diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-anschrift-response.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-anschrift-response.ts similarity index 69% rename from apps/server/src/infra/schulconnex-client/response/sanis-anschrift-response.ts rename to apps/server/src/infra/schulconnex-client/response/schulconnex-anschrift-response.ts index 429bb7b937d..ae1fad59a96 100644 --- a/apps/server/src/infra/schulconnex-client/response/sanis-anschrift-response.ts +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-anschrift-response.ts @@ -1,6 +1,6 @@ import { IsOptional, IsString } from 'class-validator'; -export class SanisAnschriftResponse { +export class SchulconnexAnschriftResponse { @IsString() @IsOptional() ort?: string; diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-erreichbarkeiten-response.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-erreichbarkeiten-response.ts similarity index 67% rename from apps/server/src/infra/schulconnex-client/response/sanis-erreichbarkeiten-response.ts rename to apps/server/src/infra/schulconnex-client/response/schulconnex-erreichbarkeiten-response.ts index 0a3c386c4fd..61318bcbc78 100644 --- a/apps/server/src/infra/schulconnex-client/response/sanis-erreichbarkeiten-response.ts +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-erreichbarkeiten-response.ts @@ -1,6 +1,6 @@ import { IsString } from 'class-validator'; -export class SanisErreichbarkeitenResponse { +export class SchulconnexErreichbarkeitenResponse { @IsString() typ!: string; diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-geburt-response.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-geburt-response.ts similarity index 71% rename from apps/server/src/infra/schulconnex-client/response/sanis-geburt-response.ts rename to apps/server/src/infra/schulconnex-client/response/schulconnex-geburt-response.ts index 0f3834fba6c..8617c2e9ca0 100644 --- a/apps/server/src/infra/schulconnex-client/response/sanis-geburt-response.ts +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-geburt-response.ts @@ -1,6 +1,6 @@ import { IsOptional, IsString } from 'class-validator'; -export class SanisGeburtResponse { +export class SchulconnexGeburtResponse { @IsOptional() @IsString() datum?: string; diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-group-role.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-group-role.ts similarity index 82% rename from apps/server/src/infra/schulconnex-client/response/sanis-group-role.ts rename to apps/server/src/infra/schulconnex-client/response/schulconnex-group-role.ts index 358333ffe56..1ce90fbc9e4 100644 --- a/apps/server/src/infra/schulconnex-client/response/sanis-group-role.ts +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-group-role.ts @@ -1,4 +1,4 @@ -export enum SanisGroupRole { +export enum SchulconnexGroupRole { TEACHER = 'Lehr', STUDENT = 'Lern', CLASS_LEADER = 'KlLeit', diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-group-type.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-group-type.ts similarity index 62% rename from apps/server/src/infra/schulconnex-client/response/sanis-group-type.ts rename to apps/server/src/infra/schulconnex-client/response/schulconnex-group-type.ts index 1af634d511b..d0af009e04e 100644 --- a/apps/server/src/infra/schulconnex-client/response/sanis-group-type.ts +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-group-type.ts @@ -1,4 +1,4 @@ -export enum SanisGroupType { +export enum SchulconnexGroupType { CLASS = 'Klasse', COURSE = 'Kurs', OTHER = 'Sonstig', diff --git a/apps/server/src/infra/schulconnex-client/response/schulconnex-gruppe-response.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-gruppe-response.ts new file mode 100644 index 00000000000..4a9a754b71a --- /dev/null +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-gruppe-response.ts @@ -0,0 +1,13 @@ +import { IsEnum, IsString } from 'class-validator'; +import { SchulconnexGroupType } from './schulconnex-group-type'; + +export class SchulconnexGruppeResponse { + @IsString() + id!: string; + + @IsString() + bezeichnung!: string; + + @IsEnum(SchulconnexGroupType) + typ!: SchulconnexGroupType; +} diff --git a/apps/server/src/infra/schulconnex-client/response/schulconnex-gruppen-response.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-gruppen-response.ts new file mode 100644 index 00000000000..ba0439d8543 --- /dev/null +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-gruppen-response.ts @@ -0,0 +1,23 @@ +import { Type } from 'class-transformer'; +import { IsArray, IsObject, IsOptional, ValidateNested } from 'class-validator'; +import { SchulconnexGruppeResponse } from './schulconnex-gruppe-response'; +import { SchulconnexGruppenzugehoerigkeitResponse } from './schulconnex-gruppenzugehoerigkeit-response'; +import { SchulconnexSonstigeGruppenzugehoerigeResponse } from './schulconnex-sonstige-gruppenzugehoerige-response'; + +export class SchulconnexGruppenResponse { + @IsObject() + @ValidateNested() + @Type(() => SchulconnexGruppeResponse) + gruppe!: SchulconnexGruppeResponse; + + @IsObject() + @ValidateNested() + @Type(() => SchulconnexGruppenzugehoerigkeitResponse) + gruppenzugehoerigkeit!: SchulconnexGruppenzugehoerigkeitResponse; + + @IsOptional() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => SchulconnexSonstigeGruppenzugehoerigeResponse) + sonstige_gruppenzugehoerige?: SchulconnexSonstigeGruppenzugehoerigeResponse[]; +} diff --git a/apps/server/src/infra/schulconnex-client/response/schulconnex-gruppenzugehoerigkeit-response.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-gruppenzugehoerigkeit-response.ts new file mode 100644 index 00000000000..653201ade6a --- /dev/null +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-gruppenzugehoerigkeit-response.ts @@ -0,0 +1,9 @@ +import { IsArray, IsEnum, IsOptional } from 'class-validator'; +import { SchulconnexGroupRole } from './schulconnex-group-role'; + +export class SchulconnexGruppenzugehoerigkeitResponse { + @IsOptional() + @IsArray() + @IsEnum(SchulconnexGroupRole, { each: true }) + rollen?: SchulconnexGroupRole[]; +} diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-name-response.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-name-response.ts similarity index 75% rename from apps/server/src/infra/schulconnex-client/response/sanis-name-response.ts rename to apps/server/src/infra/schulconnex-client/response/schulconnex-name-response.ts index ab6dda48ece..7cf7d9f5f54 100644 --- a/apps/server/src/infra/schulconnex-client/response/sanis-name-response.ts +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-name-response.ts @@ -1,6 +1,6 @@ import { IsString } from 'class-validator'; -export class SanisNameResponse { +export class SchulconnexNameResponse { @IsString() familienname!: string; diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-organisation-response.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-organisation-response.ts similarity index 55% rename from apps/server/src/infra/schulconnex-client/response/sanis-organisation-response.ts rename to apps/server/src/infra/schulconnex-client/response/schulconnex-organisation-response.ts index 6b623cdbb3b..27b2c67fd88 100644 --- a/apps/server/src/infra/schulconnex-client/response/sanis-organisation-response.ts +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-organisation-response.ts @@ -1,8 +1,8 @@ import { Type } from 'class-transformer'; import { IsObject, IsOptional, IsString, ValidateNested } from 'class-validator'; -import { SanisAnschriftResponse } from './sanis-anschrift-response'; +import { SchulconnexAnschriftResponse } from './schulconnex-anschrift-response'; -export class SanisOrganisationResponse { +export class SchulconnexOrganisationResponse { @IsString() id!: string; @@ -15,6 +15,6 @@ export class SanisOrganisationResponse { @IsOptional() @IsObject() @ValidateNested() - @Type(() => SanisAnschriftResponse) - anschrift?: SanisAnschriftResponse; + @Type(() => SchulconnexAnschriftResponse) + anschrift?: SchulconnexAnschriftResponse; } diff --git a/apps/server/src/infra/schulconnex-client/response/schulconnex-person-response.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-person-response.ts new file mode 100644 index 00000000000..2bbf3057ce6 --- /dev/null +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-person-response.ts @@ -0,0 +1,17 @@ +import { Type } from 'class-transformer'; +import { IsObject, IsOptional, ValidateNested } from 'class-validator'; +import { SchulconnexGeburtResponse } from './schulconnex-geburt-response'; +import { SchulconnexNameResponse } from './schulconnex-name-response'; + +export class SchulconnexPersonResponse { + @IsObject() + @ValidateNested() + @Type(() => SchulconnexNameResponse) + name!: SchulconnexNameResponse; + + @IsOptional() + @IsObject() + @ValidateNested() + @Type(() => SchulconnexGeburtResponse) + geburt?: SchulconnexGeburtResponse; +} diff --git a/apps/server/src/infra/schulconnex-client/response/schulconnex-personenkontext-response.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-personenkontext-response.ts new file mode 100644 index 00000000000..f127688af59 --- /dev/null +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-personenkontext-response.ts @@ -0,0 +1,32 @@ +import { Type } from 'class-transformer'; +import { IsArray, IsEnum, IsObject, IsOptional, IsString, ValidateNested } from 'class-validator'; +import { SchulconnexErreichbarkeitenResponse } from './schulconnex-erreichbarkeiten-response'; +import { SchulconnexGruppenResponse } from './schulconnex-gruppen-response'; +import { SchulconnexOrganisationResponse } from './schulconnex-organisation-response'; +import { SchulconnexResponseValidationGroups } from './schulconnex-response-validation-groups'; +import { SchulconnexRole } from './schulconnex-role'; + +export class SchulconnexPersonenkontextResponse { + @IsString({ groups: [SchulconnexResponseValidationGroups.USER, SchulconnexResponseValidationGroups.GROUPS] }) + id!: string; + + @IsEnum(SchulconnexRole, { groups: [SchulconnexResponseValidationGroups.USER] }) + rolle!: SchulconnexRole; + + @IsObject({ groups: [SchulconnexResponseValidationGroups.SCHOOL] }) + @ValidateNested({ groups: [SchulconnexResponseValidationGroups.SCHOOL] }) + @Type(() => SchulconnexOrganisationResponse) + organisation!: SchulconnexOrganisationResponse; + + @IsOptional({ groups: [SchulconnexResponseValidationGroups.GROUPS] }) + @IsArray({ groups: [SchulconnexResponseValidationGroups.GROUPS] }) + @ValidateNested({ each: true, groups: [SchulconnexResponseValidationGroups.GROUPS] }) + @Type(() => SchulconnexGruppenResponse) + gruppen?: SchulconnexGruppenResponse[]; + + @IsOptional() + @IsArray() + @ValidateNested({ each: true }) + @Type(() => SchulconnexErreichbarkeitenResponse) + erreichbarkeiten?: SchulconnexErreichbarkeitenResponse[]; +} diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-response-validation-groups.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-response-validation-groups.ts similarity index 53% rename from apps/server/src/infra/schulconnex-client/response/sanis-response-validation-groups.ts rename to apps/server/src/infra/schulconnex-client/response/schulconnex-response-validation-groups.ts index 9977965c752..bc4896dc6be 100644 --- a/apps/server/src/infra/schulconnex-client/response/sanis-response-validation-groups.ts +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-response-validation-groups.ts @@ -1,4 +1,4 @@ -export enum SanisResponseValidationGroups { +export enum SchulconnexResponseValidationGroups { USER = 'user', SCHOOL = 'school', GROUPS = 'groups', diff --git a/apps/server/src/infra/schulconnex-client/response/sanis-role.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-role.ts similarity index 71% rename from apps/server/src/infra/schulconnex-client/response/sanis-role.ts rename to apps/server/src/infra/schulconnex-client/response/schulconnex-role.ts index bd3c71f0826..4316182d792 100644 --- a/apps/server/src/infra/schulconnex-client/response/sanis-role.ts +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-role.ts @@ -1,4 +1,4 @@ -export enum SanisRole { +export enum SchulconnexRole { LEHR = 'Lehr', LERN = 'Lern', LEIT = 'Leit', diff --git a/apps/server/src/infra/schulconnex-client/response/schulconnex-sonstige-gruppenzugehoerige-response.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex-sonstige-gruppenzugehoerige-response.ts new file mode 100644 index 00000000000..e9c297d8c30 --- /dev/null +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex-sonstige-gruppenzugehoerige-response.ts @@ -0,0 +1,12 @@ +import { IsArray, IsEnum, IsOptional, IsString } from 'class-validator'; +import { SchulconnexGroupRole } from './schulconnex-group-role'; + +export class SchulconnexSonstigeGruppenzugehoerigeResponse { + @IsString() + ktid!: string; + + @IsOptional() + @IsArray() + @IsEnum(SchulconnexGroupRole, { each: true }) + rollen?: SchulconnexGroupRole[]; +} diff --git a/apps/server/src/infra/schulconnex-client/response/schulconnex.response.ts b/apps/server/src/infra/schulconnex-client/response/schulconnex.response.ts new file mode 100644 index 00000000000..b513edb2316 --- /dev/null +++ b/apps/server/src/infra/schulconnex-client/response/schulconnex.response.ts @@ -0,0 +1,21 @@ +import { Type } from 'class-transformer'; +import { ArrayMinSize, IsArray, IsObject, IsString, ValidateNested } from 'class-validator'; +import { SchulconnexPersonResponse } from './schulconnex-person-response'; +import { SchulconnexPersonenkontextResponse } from './schulconnex-personenkontext-response'; +import { SchulconnexResponseValidationGroups } from './schulconnex-response-validation-groups'; + +export class SchulconnexResponse { + @IsString({ groups: [SchulconnexResponseValidationGroups.USER] }) + pid!: string; + + @IsObject({ groups: [SchulconnexResponseValidationGroups.USER] }) + @ValidateNested({ groups: [SchulconnexResponseValidationGroups.USER] }) + @Type(() => SchulconnexPersonResponse) + person!: SchulconnexPersonResponse; + + @IsArray() + @ArrayMinSize(1) + @ValidateNested({ each: true }) + @Type(() => SchulconnexPersonenkontextResponse) + personenkontexte!: SchulconnexPersonenkontextResponse[]; +} diff --git a/apps/server/src/infra/schulconnex-client/schulconnex-api.interface.ts b/apps/server/src/infra/schulconnex-client/schulconnex-api.interface.ts index 488635881ee..dbbdbf8a62e 100644 --- a/apps/server/src/infra/schulconnex-client/schulconnex-api.interface.ts +++ b/apps/server/src/infra/schulconnex-client/schulconnex-api.interface.ts @@ -1,10 +1,10 @@ import { SchulconnexPersonenInfoParams } from './request'; -import { SanisResponse, SchulconnexLizenzInfoResponse } from './response'; +import { SchulconnexLizenzInfoResponse, SchulconnexResponse } from './response'; export interface SchulconnexApiInterface { - getPersonInfo(accessToken: string, options?: { overrideUrl: string }): Promise; + getPersonInfo(accessToken: string, options?: { overrideUrl: string }): Promise; - getPersonenInfo(params: SchulconnexPersonenInfoParams): Promise; + getPersonenInfo(params: SchulconnexPersonenInfoParams): Promise; getLizenzInfo(accessToken: string, options?: { overrideUrl: string }): Promise; } diff --git a/apps/server/src/infra/schulconnex-client/schulconnex-rest-client.spec.ts b/apps/server/src/infra/schulconnex-client/schulconnex-rest-client.spec.ts index 5a14e88b03c..35d871c8ab6 100644 --- a/apps/server/src/infra/schulconnex-client/schulconnex-rest-client.spec.ts +++ b/apps/server/src/infra/schulconnex-client/schulconnex-rest-client.spec.ts @@ -5,7 +5,7 @@ import { axiosResponseFactory } from '@shared/testing'; import { Logger } from '@src/core/logger'; import { of } from 'rxjs'; import { SchulconnexConfigurationMissingLoggable } from './loggable'; -import { SanisResponse, SchulconnexLizenzInfoResponse } from './response'; +import { SchulconnexLizenzInfoResponse, SchulconnexResponse } from './response'; import { SchulconnexRestClient } from './schulconnex-rest-client'; import { SchulconnexRestClientOptions } from './schulconnex-rest-client-options'; import { schulconnexResponseFactory } from './testing'; @@ -75,7 +75,7 @@ describe(SchulconnexRestClient.name, () => { describe('when requesting person-info', () => { const setup = () => { const accessToken = 'accessToken'; - const response: SanisResponse = schulconnexResponseFactory.build(); + const response: SchulconnexResponse = schulconnexResponseFactory.build(); httpService.get.mockReturnValueOnce(of(axiosResponseFactory.build({ data: response }))); @@ -101,7 +101,7 @@ describe(SchulconnexRestClient.name, () => { it('should return the response', async () => { const { accessToken, response } = setup(); - const result: SanisResponse = await client.getPersonInfo(accessToken); + const result: SchulconnexResponse = await client.getPersonInfo(accessToken); expect(result).toEqual(response); }); @@ -111,7 +111,7 @@ describe(SchulconnexRestClient.name, () => { const setup = () => { const accessToken = 'accessToken'; const customUrl = 'https://override.url/person-info'; - const response: SanisResponse = schulconnexResponseFactory.build(); + const response: SchulconnexResponse = schulconnexResponseFactory.build(); httpService.get.mockReturnValueOnce(of(axiosResponseFactory.build({ data: response }))); @@ -139,7 +139,7 @@ describe(SchulconnexRestClient.name, () => { accessToken: 'access_token', refreshToken: 'refresh_token', }); - const response: SanisResponse[] = schulconnexResponseFactory.buildList(2); + const response: SchulconnexResponse[] = schulconnexResponseFactory.buildList(2); const optionsWithTimeout: SchulconnexRestClientOptions = { ...options, @@ -189,7 +189,7 @@ describe(SchulconnexRestClient.name, () => { it('should return the response', async () => { const { response } = setup(); - const result: SanisResponse[] = await client.getPersonenInfo({ 'organisation.id': '1234' }); + const result: SchulconnexResponse[] = await client.getPersonenInfo({ 'organisation.id': '1234' }); expect(result).toEqual(response); }); diff --git a/apps/server/src/infra/schulconnex-client/schulconnex-rest-client.ts b/apps/server/src/infra/schulconnex-client/schulconnex-rest-client.ts index f1b8835bedb..8fe17ecde1b 100644 --- a/apps/server/src/infra/schulconnex-client/schulconnex-rest-client.ts +++ b/apps/server/src/infra/schulconnex-client/schulconnex-rest-client.ts @@ -8,7 +8,7 @@ import QueryString from 'qs'; import { lastValueFrom, Observable } from 'rxjs'; import { SchulconnexConfigurationMissingLoggable } from './loggable'; import { SchulconnexPersonenInfoParams } from './request'; -import { SanisResponse, SchulconnexLizenzInfoResponse } from './response'; +import { SchulconnexLizenzInfoResponse, SchulconnexResponse } from './response'; import { SchulconnexApiInterface } from './schulconnex-api.interface'; import { SchulconnexRestClientOptions } from './schulconnex-rest-client-options'; @@ -25,22 +25,21 @@ export class SchulconnexRestClient implements SchulconnexApiInterface { this.SCHULCONNEX_API_BASE_URL = options.apiUrl || ''; } - // TODO: N21-1678 use this in provisioning module - public async getPersonInfo(accessToken: string, options?: { overrideUrl: string }): Promise { + public async getPersonInfo(accessToken: string, options?: { overrideUrl: string }): Promise { const url: URL = new URL(options?.overrideUrl ?? `${this.SCHULCONNEX_API_BASE_URL}/person-info`); - const response: Promise = this.getRequest(url, accessToken); + const response: Promise = this.getRequest(url, accessToken); return response; } - public async getPersonenInfo(params: SchulconnexPersonenInfoParams): Promise { + public async getPersonenInfo(params: SchulconnexPersonenInfoParams): Promise { const token: OAuthTokenDto = await this.requestClientCredentialToken(); const url: URL = new URL(`${this.SCHULCONNEX_API_BASE_URL}/personen-info`); url.search = QueryString.stringify(params, { arrayFormat: 'comma' }); - const response: Promise = this.getRequest( + const response: Promise = this.getRequest( url, token.accessToken, this.options.personenInfoTimeoutInMs diff --git a/apps/server/src/infra/schulconnex-client/testing/schulconnex-response-factory.ts b/apps/server/src/infra/schulconnex-client/testing/schulconnex-response-factory.ts index 931281287d2..2cb7dcb5ece 100644 --- a/apps/server/src/infra/schulconnex-client/testing/schulconnex-response-factory.ts +++ b/apps/server/src/infra/schulconnex-client/testing/schulconnex-response-factory.ts @@ -1,8 +1,8 @@ import { UUID } from 'bson'; import { Factory } from 'fishery'; -import { SanisGroupRole, SanisGroupType, SanisResponse, SanisRole } from '../response'; +import { SchulconnexGroupRole, SchulconnexGroupType, SchulconnexResponse, SchulconnexRole } from '../response'; -export const schulconnexResponseFactory = Factory.define(() => { +export const schulconnexResponseFactory = Factory.define(() => { return { pid: 'aef1f4fd-c323-466e-962b-a84354c0e713', person: { @@ -17,7 +17,7 @@ export const schulconnexResponseFactory = Factory.define(() => { personenkontexte: [ { id: new UUID().toString(), - rolle: SanisRole.LEIT, + rolle: SchulconnexRole.LEIT, organisation: { id: new UUID('df66c8e6-cfac-40f7-b35b-0da5d8ee680e').toString(), name: 'schoolName', @@ -37,14 +37,14 @@ export const schulconnexResponseFactory = Factory.define(() => { gruppe: { id: new UUID().toString(), bezeichnung: 'bezeichnung', - typ: SanisGroupType.CLASS, + typ: SchulconnexGroupType.CLASS, }, gruppenzugehoerigkeit: { - rollen: [SanisGroupRole.TEACHER], + rollen: [SchulconnexGroupRole.TEACHER], }, sonstige_gruppenzugehoerige: [ { - rollen: [SanisGroupRole.STUDENT], + rollen: [SchulconnexGroupRole.STUDENT], ktid: 'ktid', }, ], diff --git a/apps/server/src/modules/idp-console/uc/synchronization.uc.spec.ts b/apps/server/src/modules/idp-console/uc/synchronization.uc.spec.ts index bd530547648..892708bf090 100644 --- a/apps/server/src/modules/idp-console/uc/synchronization.uc.spec.ts +++ b/apps/server/src/modules/idp-console/uc/synchronization.uc.spec.ts @@ -1,24 +1,24 @@ -import { Test, TestingModule } from '@nestjs/testing'; import { createMock, DeepMocked } from '@golevelup/ts-jest'; -import { setupEntities } from '@shared/testing'; -import { ObjectId } from 'bson'; -import { Logger } from '@src/core/logger'; -import { UserService } from '@modules/user'; -import { SanisResponse, schulconnexResponseFactory, SchulconnexRestClient } from '@infra/schulconnex-client'; -import { ConfigModule } from '@nestjs/config'; -import { createConfigModuleOptions } from '@src/config'; +import { SchulconnexResponse, schulconnexResponseFactory, SchulconnexRestClient } from '@infra/schulconnex-client'; import { Synchronization, + synchronizationFactory, SynchronizationService, SynchronizationStatusModel, - synchronizationFactory, } from '@modules/synchronization'; -import { SynchronizationUc } from './synchronization.uc'; -import { synchronizationTestConfig } from './testing'; +import { UserService } from '@modules/user'; +import { ConfigModule } from '@nestjs/config'; +import { Test, TestingModule } from '@nestjs/testing'; +import { setupEntities } from '@shared/testing'; +import { createConfigModuleOptions } from '@src/config'; +import { Logger } from '@src/core/logger'; +import { ObjectId } from 'bson'; import { FailedUpdateLastSyncedAtLoggableException, NoUsersToSynchronizationLoggableException, } from './loggable-exception'; +import { SynchronizationUc } from './synchronization.uc'; +import { synchronizationTestConfig } from './testing'; describe(SynchronizationUc.name, () => { let module: TestingModule; @@ -256,7 +256,7 @@ describe(SynchronizationUc.name, () => { describe('when users was found', () => { const setup = () => { const systemId = new ObjectId().toHexString(); - const externalUserData: SanisResponse = schulconnexResponseFactory.build(); + const externalUserData: SchulconnexResponse = schulconnexResponseFactory.build(); schulconnexRestClient.getPersonenInfo.mockResolvedValueOnce([externalUserData]); diff --git a/apps/server/src/modules/idp-console/uc/synchronization.uc.ts b/apps/server/src/modules/idp-console/uc/synchronization.uc.ts index a2de4db850c..edd53a3aa11 100644 --- a/apps/server/src/modules/idp-console/uc/synchronization.uc.ts +++ b/apps/server/src/modules/idp-console/uc/synchronization.uc.ts @@ -1,17 +1,17 @@ +import { SchulconnexResponse, SchulconnexRestClient } from '@infra/schulconnex-client'; +import { Synchronization, SynchronizationService, SynchronizationStatusModel } from '@modules/synchronization'; import { UserService } from '@modules/user'; import { Injectable } from '@nestjs/common'; -import { Logger } from '@src/core/logger'; -import { SanisResponse, SchulconnexRestClient } from '@infra/schulconnex-client'; import { ConfigService } from '@nestjs/config'; +import { Logger } from '@src/core/logger'; import { ErrorLogMessage } from '@src/core/logger/types'; -import { Synchronization, SynchronizationService, SynchronizationStatusModel } from '@modules/synchronization'; +import { SynchronizationConfig } from '../interface'; import { StartSynchronizationLoggable, SucessSynchronizationLoggable } from './loggable'; import { FailedUpdateLastSyncedAtLoggableException, NoUsersToSynchronizationLoggableException, SynchronizationUnknownErrorLoggableException, } from './loggable-exception'; -import { SynchronizationConfig } from '../interface'; @Injectable() export class SynchronizationUc { @@ -58,7 +58,7 @@ export class SynchronizationUc { public async findUsersToSynchronize(systemId: string): Promise { let usersToCheck: string[] = []; - const usersDownloaded: SanisResponse[] = await this.schulconnexRestClient.getPersonenInfo({}); + const usersDownloaded: SchulconnexResponse[] = await this.schulconnexRestClient.getPersonenInfo({}); if (usersDownloaded.length === 0) { throw new NoUsersToSynchronizationLoggableException(systemId); diff --git a/apps/server/src/modules/provisioning/loggable/group-role-unknown.loggable.spec.ts b/apps/server/src/modules/provisioning/loggable/group-role-unknown.loggable.spec.ts index 9c0c9560f8a..6a6931542c6 100644 --- a/apps/server/src/modules/provisioning/loggable/group-role-unknown.loggable.spec.ts +++ b/apps/server/src/modules/provisioning/loggable/group-role-unknown.loggable.spec.ts @@ -1,12 +1,12 @@ -import { SanisGroupRole, SanisSonstigeGruppenzugehoerigeResponse } from '@infra/schulconnex-client'; +import { SchulconnexGroupRole, SchulconnexSonstigeGruppenzugehoerigeResponse } from '@infra/schulconnex-client'; import { GroupRoleUnknownLoggable } from './group-role-unknown.loggable'; describe('GroupRoleUnknownLoggable', () => { describe('getLogMessage', () => { const setup = () => { - const sanisSonstigeGruppenzugehoerigeResponse: SanisSonstigeGruppenzugehoerigeResponse = { + const sanisSonstigeGruppenzugehoerigeResponse: SchulconnexSonstigeGruppenzugehoerigeResponse = { ktid: 'ktid', - rollen: [SanisGroupRole.TEACHER], + rollen: [SchulconnexGroupRole.TEACHER], }; const loggable = new GroupRoleUnknownLoggable(sanisSonstigeGruppenzugehoerigeResponse); diff --git a/apps/server/src/modules/provisioning/loggable/group-role-unknown.loggable.ts b/apps/server/src/modules/provisioning/loggable/group-role-unknown.loggable.ts index dd44dd8b7e7..a425ad168b2 100644 --- a/apps/server/src/modules/provisioning/loggable/group-role-unknown.loggable.ts +++ b/apps/server/src/modules/provisioning/loggable/group-role-unknown.loggable.ts @@ -1,8 +1,8 @@ +import { SchulconnexSonstigeGruppenzugehoerigeResponse } from '@infra/schulconnex-client'; import { ErrorLogMessage, Loggable, LogMessage, ValidationErrorLogMessage } from '@src/core/logger'; -import { SanisSonstigeGruppenzugehoerigeResponse } from '@infra/schulconnex-client'; export class GroupRoleUnknownLoggable implements Loggable { - constructor(private readonly relation: SanisSonstigeGruppenzugehoerigeResponse) {} + constructor(private readonly relation: SchulconnexSonstigeGruppenzugehoerigeResponse) {} getLogMessage(): LogMessage | ErrorLogMessage | ValidationErrorLogMessage { return { diff --git a/apps/server/src/modules/provisioning/provisioning.module.ts b/apps/server/src/modules/provisioning/provisioning.module.ts index 11dd7cfeb89..d7f9c168a54 100644 --- a/apps/server/src/modules/provisioning/provisioning.module.ts +++ b/apps/server/src/modules/provisioning/provisioning.module.ts @@ -5,7 +5,6 @@ import { LegacySchoolModule } from '@modules/legacy-school'; import { RoleModule } from '@modules/role'; import { SystemModule } from '@modules/system/system.module'; import { UserModule } from '@modules/user'; -import { HttpModule } from '@nestjs/axios'; import { Module } from '@nestjs/common'; import { LoggerModule } from '@src/core/logger'; import { SchulconnexClientModule } from '@src/infra/schulconnex-client'; @@ -16,7 +15,7 @@ import { IservProvisioningStrategy, OidcMockProvisioningStrategy, SanisProvisioningStrategy, - SanisResponseMapper, + SchulconnexResponseMapper, } from './strategy'; import { SchulconnexCourseSyncService, @@ -34,7 +33,6 @@ import { UserModule, RoleModule, SystemModule, - HttpModule, LoggerModule, GroupModule, LearnroomModule, @@ -43,7 +41,7 @@ import { ], providers: [ ProvisioningService, - SanisResponseMapper, + SchulconnexResponseMapper, SchulconnexSchoolProvisioningService, SchulconnexUserProvisioningService, SchulconnexGroupProvisioningService, diff --git a/apps/server/src/modules/provisioning/strategy/sanis/index.ts b/apps/server/src/modules/provisioning/strategy/sanis/index.ts index 39c4c4272ac..f1c634c3ee9 100644 --- a/apps/server/src/modules/provisioning/strategy/sanis/index.ts +++ b/apps/server/src/modules/provisioning/strategy/sanis/index.ts @@ -1,2 +1,2 @@ export * from './sanis.strategy'; -export * from './sanis-response.mapper'; +export { SchulconnexResponseMapper } from './schulconnex-response-mapper.service'; diff --git a/apps/server/src/modules/provisioning/strategy/sanis/sanis.strategy.spec.ts b/apps/server/src/modules/provisioning/strategy/sanis/sanis.strategy.spec.ts index 4fc0c390535..e0e34f9690d 100644 --- a/apps/server/src/modules/provisioning/strategy/sanis/sanis.strategy.spec.ts +++ b/apps/server/src/modules/provisioning/strategy/sanis/sanis.strategy.spec.ts @@ -1,25 +1,22 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; import { - SanisGruppenResponse, - SanisResponse, - SanisResponseValidationGroups, + SchulconnexGruppenResponse, + SchulconnexResponse, schulconnexResponseFactory, + SchulconnexResponseValidationGroups, SchulconnexRestClient, } from '@infra/schulconnex-client'; import { SchulconnexLizenzInfoResponse } from '@infra/schulconnex-client/response'; import { schulconnexLizenzInfoResponseFactory } from '@infra/schulconnex-client/testing/schulconnex-lizenz-info-response-factory'; import { GroupService } from '@modules/group'; import { GroupTypes } from '@modules/group/domain'; -import { HttpService } from '@nestjs/axios'; import { InternalServerErrorException } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; import { ValidationErrorLoggableException } from '@shared/common/loggable-exception'; import { RoleName } from '@shared/domain/interface'; import { SystemProvisioningStrategy } from '@shared/domain/interface/system-provisioning.strategy'; -import { axiosResponseFactory } from '@shared/testing'; import * as classValidator from 'class-validator'; -import { of } from 'rxjs'; import { IProvisioningFeatures, ProvisioningFeatures } from '../../config'; import { ExternalGroupDto, @@ -38,22 +35,16 @@ import { SchulconnexSchoolProvisioningService, SchulconnexUserProvisioningService, } from '../oidc/service'; -import { SanisResponseMapper } from './sanis-response.mapper'; import { SanisProvisioningStrategy } from './sanis.strategy'; +import { SchulconnexResponseMapper } from './schulconnex-response-mapper.service'; import ArgsType = jest.ArgsType; import SpyInstance = jest.SpyInstance; -const createAxiosResponse = (data: SanisResponse) => - axiosResponseFactory.build({ - data, - }); - describe(SanisProvisioningStrategy.name, () => { let module: TestingModule; let strategy: SanisProvisioningStrategy; - let mapper: DeepMocked; - let httpService: DeepMocked; + let mapper: DeepMocked; let validationFunction: SpyInstance< ReturnType, @@ -69,12 +60,8 @@ describe(SanisProvisioningStrategy.name, () => { providers: [ SanisProvisioningStrategy, { - provide: SanisResponseMapper, - useValue: createMock(), - }, - { - provide: HttpService, - useValue: createMock(), + provide: SchulconnexResponseMapper, + useValue: createMock(), }, { provide: SchulconnexSchoolProvisioningService, @@ -116,8 +103,7 @@ describe(SanisProvisioningStrategy.name, () => { }).compile(); strategy = module.get(SanisProvisioningStrategy); - mapper = module.get(SanisResponseMapper); - httpService = module.get(HttpService); + mapper = module.get(SchulconnexResponseMapper); provisioningFeatures = module.get(ProvisioningFeatures); schulconnexRestClient = module.get(SchulconnexRestClient); configService = module.get(ConfigService); @@ -135,7 +121,7 @@ describe(SanisProvisioningStrategy.name, () => { jest.resetAllMocks(); }); - const setupSanisResponse = (): SanisResponse => schulconnexResponseFactory.build(); + const setupschulconnexResponse = (): SchulconnexResponse => schulconnexResponseFactory.build(); describe('getType is called', () => { describe('when it is called', () => { @@ -160,7 +146,7 @@ describe(SanisProvisioningStrategy.name, () => { idToken: 'sanisIdToken', accessToken: 'sanisAccessToken', }); - const sanisResponse: SanisResponse = setupSanisResponse(); + const schulconnexResponse: SchulconnexResponse = setupschulconnexResponse(); const user: ExternalUserDto = new ExternalUserDto({ externalId: 'externalUserId', }); @@ -168,14 +154,14 @@ describe(SanisProvisioningStrategy.name, () => { externalId: 'externalSchoolId', name: 'schoolName', }); - const sanisGruppeResponse: SanisGruppenResponse = sanisResponse.personenkontexte[0].gruppen![0]!; + const sanisGruppeResponse: SchulconnexGruppenResponse = schulconnexResponse.personenkontexte[0].gruppen![0]!; const groups: ExternalGroupDto[] = [ new ExternalGroupDto({ name: sanisGruppeResponse.gruppe.bezeichnung, externalId: sanisGruppeResponse.gruppe.id, type: GroupTypes.CLASS, user: { - externalUserId: sanisResponse.personenkontexte[0].id, + externalUserId: schulconnexResponse.personenkontexte[0].id, roleName: RoleName.TEACHER, }, }), @@ -190,7 +176,7 @@ describe(SanisProvisioningStrategy.name, () => { }), ]; - httpService.get.mockReturnValue(of(createAxiosResponse(sanisResponse))); + schulconnexRestClient.getPersonInfo.mockResolvedValueOnce(schulconnexResponse); mapper.mapToExternalUserDto.mockReturnValue(user); mapper.mapToExternalSchoolDto.mockReturnValue(school); mapper.mapToExternalGroupDtos.mockReturnValue(groups); @@ -207,60 +193,42 @@ describe(SanisProvisioningStrategy.name, () => { school, groups, licenses, - sanisResponse, + schulconnexResponse, schulconnexLizenzInfoResponse, }; }; - it('should make a Http-GET-Request to the provisioning url of sanis with an access token', async () => { + it('should call the rest client of sanis with an access token', async () => { const { input, provisioningUrl } = setup(); await strategy.getData(input); - expect(httpService.get).toHaveBeenCalledWith( - provisioningUrl, - expect.objectContaining({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - headers: expect.objectContaining({ Authorization: 'Bearer sanisAccessToken', 'Accept-Encoding': 'gzip' }), - }) - ); - }); - - it('should accept gzip compressed data', async () => { - const { input, provisioningUrl } = setup(); - - await strategy.getData(input); - - expect(httpService.get).toHaveBeenCalledWith( - provisioningUrl, - expect.objectContaining({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - headers: expect.objectContaining({ 'Accept-Encoding': 'gzip' }), - }) - ); + expect(schulconnexRestClient.getPersonInfo).toHaveBeenCalledWith(input.accessToken, { + overrideUrl: provisioningUrl, + }); }); it('should validate the response for user and school', async () => { - const { input, sanisResponse } = setup(); + const { input, schulconnexResponse } = setup(); await strategy.getData(input); - expect(validationFunction).toHaveBeenCalledWith(sanisResponse, { + expect(validationFunction).toHaveBeenCalledWith(schulconnexResponse, { always: true, forbidUnknownValues: false, - groups: [SanisResponseValidationGroups.USER, SanisResponseValidationGroups.SCHOOL], + groups: [SchulconnexResponseValidationGroups.USER, SchulconnexResponseValidationGroups.SCHOOL], }); }); it('should validate the response for groups', async () => { - const { input, sanisResponse } = setup(); + const { input, schulconnexResponse } = setup(); await strategy.getData(input); - expect(validationFunction).toHaveBeenCalledWith(sanisResponse, { + expect(validationFunction).toHaveBeenCalledWith(schulconnexResponse, { always: true, forbidUnknownValues: false, - groups: [SanisResponseValidationGroups.GROUPS], + groups: [SchulconnexResponseValidationGroups.GROUPS], }); }); @@ -302,7 +270,7 @@ describe(SanisProvisioningStrategy.name, () => { idToken: 'sanisIdToken', accessToken: 'sanisAccessToken', }); - const sanisResponse: SanisResponse = setupSanisResponse(); + const schulconnexResponse: SchulconnexResponse = setupschulconnexResponse(); const user: ExternalUserDto = new ExternalUserDto({ externalId: 'externalUserId', }); @@ -311,7 +279,7 @@ describe(SanisProvisioningStrategy.name, () => { name: 'schoolName', }); - httpService.get.mockReturnValue(of(createAxiosResponse(sanisResponse))); + schulconnexRestClient.getPersonInfo.mockResolvedValueOnce(schulconnexResponse); mapper.mapToExternalUserDto.mockReturnValue(user); mapper.mapToExternalSchoolDto.mockReturnValue(school); validationFunction.mockResolvedValueOnce([]); @@ -320,18 +288,18 @@ describe(SanisProvisioningStrategy.name, () => { return { input, - sanisResponse, + schulconnexResponse, }; }; it('should not validate the response for groups', async () => { - const { input, sanisResponse } = setup(); + const { input, schulconnexResponse } = setup(); await strategy.getData(input); expect(validationFunction).not.toHaveBeenCalledWith( - sanisResponse, - expect.objectContaining({ groups: [SanisResponseValidationGroups.GROUPS] }) + schulconnexResponse, + expect.objectContaining({ groups: [SchulconnexResponseValidationGroups.GROUPS] }) ); }); @@ -356,7 +324,7 @@ describe(SanisProvisioningStrategy.name, () => { idToken: 'sanisIdToken', accessToken: 'sanisAccessToken', }); - const sanisResponse: SanisResponse = setupSanisResponse(); + const schulconnexResponse: SchulconnexResponse = setupschulconnexResponse(); const user: ExternalUserDto = new ExternalUserDto({ externalId: 'externalUserId', }); @@ -365,7 +333,7 @@ describe(SanisProvisioningStrategy.name, () => { name: 'schoolName', }); - httpService.get.mockReturnValue(of(createAxiosResponse(sanisResponse))); + schulconnexRestClient.getPersonInfo.mockResolvedValueOnce(schulconnexResponse); mapper.mapToExternalUserDto.mockReturnValue(user); mapper.mapToExternalSchoolDto.mockReturnValue(school); validationFunction.mockResolvedValueOnce([]); @@ -375,7 +343,7 @@ describe(SanisProvisioningStrategy.name, () => { return { input, - sanisResponse, + schulconnexResponse, }; }; @@ -399,7 +367,7 @@ describe(SanisProvisioningStrategy.name, () => { idToken: 'sanisIdToken', accessToken: 'sanisAccessToken', }); - const sanisResponse: SanisResponse = setupSanisResponse(); + const schulconnexResponse: SchulconnexResponse = setupschulconnexResponse(); const user: ExternalUserDto = new ExternalUserDto({ externalId: 'externalUserId', }); @@ -407,20 +375,20 @@ describe(SanisProvisioningStrategy.name, () => { externalId: 'externalSchoolId', name: 'schoolName', }); - const sanisGruppeResponse: SanisGruppenResponse = sanisResponse.personenkontexte[0].gruppen![0]!; + const sanisGruppeResponse: SchulconnexGruppenResponse = schulconnexResponse.personenkontexte[0].gruppen![0]!; const groups: ExternalGroupDto[] = [ new ExternalGroupDto({ name: sanisGruppeResponse.gruppe.bezeichnung, externalId: sanisGruppeResponse.gruppe.id, type: GroupTypes.CLASS, user: { - externalUserId: sanisResponse.personenkontexte[0].id, + externalUserId: schulconnexResponse.personenkontexte[0].id, roleName: RoleName.TEACHER, }, }), ]; - httpService.get.mockReturnValue(of(createAxiosResponse(sanisResponse))); + schulconnexRestClient.getPersonInfo.mockResolvedValueOnce(schulconnexResponse); mapper.mapToExternalUserDto.mockReturnValue(user); mapper.mapToExternalSchoolDto.mockReturnValue(school); mapper.mapToExternalGroupDtos.mockReturnValue(groups); @@ -451,7 +419,7 @@ describe(SanisProvisioningStrategy.name, () => { idToken: 'sanisIdToken', accessToken: 'sanisAccessToken', }); - const sanisResponse: SanisResponse = setupSanisResponse(); + const schulconnexResponse: SchulconnexResponse = setupschulconnexResponse(); const user = new ExternalUserDto({ externalId: 'externalSchoolId', roles: [RoleName.ADMINISTRATOR], @@ -460,20 +428,20 @@ describe(SanisProvisioningStrategy.name, () => { externalId: 'externalSchoolId', name: 'schoolName', }); - const sanisGruppeResponse: SanisGruppenResponse = sanisResponse.personenkontexte[0].gruppen![0]!; + const sanisGruppeResponse: SchulconnexGruppenResponse = schulconnexResponse.personenkontexte[0].gruppen![0]!; const groups: ExternalGroupDto[] = [ new ExternalGroupDto({ name: sanisGruppeResponse.gruppe.bezeichnung, externalId: sanisGruppeResponse.gruppe.id, type: GroupTypes.CLASS, user: { - externalUserId: sanisResponse.personenkontexte[0].id, + externalUserId: schulconnexResponse.personenkontexte[0].id, roleName: RoleName.TEACHER, }, }), ]; - httpService.get.mockReturnValue(of(createAxiosResponse(sanisResponse))); + schulconnexRestClient.getPersonInfo.mockResolvedValueOnce(schulconnexResponse); mapper.mapToExternalUserDto.mockReturnValue(user); mapper.mapToExternalSchoolDto.mockReturnValue(school); mapper.mapToExternalGroupDtos.mockReturnValue(groups); @@ -506,16 +474,16 @@ describe(SanisProvisioningStrategy.name, () => { idToken: 'sanisIdToken', accessToken: 'sanisAccessToken', }); - const sanisResponse: SanisResponse = setupSanisResponse(); + const schulconnexResponse: SchulconnexResponse = setupschulconnexResponse(); const validationError: classValidator.ValidationError = new classValidator.ValidationError(); - httpService.get.mockReturnValue(of(createAxiosResponse(sanisResponse))); + schulconnexRestClient.getPersonInfo.mockResolvedValueOnce(schulconnexResponse); validationFunction.mockResolvedValueOnce([validationError]); return { input, provisioningUrl, - sanisResponse, + schulconnexResponse, }; }; diff --git a/apps/server/src/modules/provisioning/strategy/sanis/sanis.strategy.ts b/apps/server/src/modules/provisioning/strategy/sanis/sanis.strategy.ts index f4e757f0610..5a41b9ae7f8 100644 --- a/apps/server/src/modules/provisioning/strategy/sanis/sanis.strategy.ts +++ b/apps/server/src/modules/provisioning/strategy/sanis/sanis.strategy.ts @@ -1,20 +1,17 @@ import { - SanisResponse, - SanisResponseValidationGroups, SchulconnexLizenzInfoResponse, + SchulconnexResponse, + SchulconnexResponseValidationGroups, } from '@infra/schulconnex-client/response'; import { SchulconnexRestClient } from '@infra/schulconnex-client/schulconnex-rest-client'; import { GroupService } from '@modules/group/service/group.service'; -import { HttpService } from '@nestjs/axios'; import { Inject, Injectable, InternalServerErrorException } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { ValidationErrorLoggableException } from '@shared/common/loggable-exception'; import { RoleName } from '@shared/domain/interface'; import { SystemProvisioningStrategy } from '@shared/domain/interface/system-provisioning.strategy'; -import { AxiosRequestConfig, AxiosResponse } from 'axios'; import { plainToClass } from 'class-transformer'; import { validate, ValidationError } from 'class-validator'; -import { firstValueFrom } from 'rxjs'; import { IProvisioningFeatures, ProvisioningFeatures } from '../../config'; import { ExternalGroupDto, @@ -33,7 +30,7 @@ import { SchulconnexSchoolProvisioningService, SchulconnexUserProvisioningService, } from '../oidc/service'; -import { SanisResponseMapper } from './sanis-response.mapper'; +import { SchulconnexResponseMapper } from './schulconnex-response-mapper.service'; @Injectable() export class SanisProvisioningStrategy extends SchulconnexProvisioningStrategy { @@ -45,8 +42,7 @@ export class SanisProvisioningStrategy extends SchulconnexProvisioningStrategy { protected readonly schulconnexCourseSyncService: SchulconnexCourseSyncService, protected readonly groupService: GroupService, protected readonly schulconnexLicenseProvisioningService: SchulconnexLicenseProvisioningService, - private readonly responseMapper: SanisResponseMapper, - private readonly httpService: HttpService, + private readonly responseMapper: SchulconnexResponseMapper, private readonly schulconnexRestClient: SchulconnexRestClient, protected readonly configService: ConfigService ) { @@ -73,35 +69,27 @@ export class SanisProvisioningStrategy extends SchulconnexProvisioningStrategy { ); } - // TODO: N21-1678 use the schulconnex rest client - const axiosConfig: AxiosRequestConfig = { - headers: { - Authorization: `Bearer ${input.accessToken}`, - 'Accept-Encoding': 'gzip', - }, - }; - - const sanisAxiosResponse: AxiosResponse = await firstValueFrom( - this.httpService.get(input.system.provisioningUrl, axiosConfig) - ); + const sanisAxiosResponse: SchulconnexResponse = await this.schulconnexRestClient.getPersonInfo(input.accessToken, { + overrideUrl: input.system.provisioningUrl, + }); - const sanisResponse: SanisResponse = plainToClass(SanisResponse, sanisAxiosResponse.data); + const sanisResponse: SchulconnexResponse = plainToClass(SchulconnexResponse, sanisAxiosResponse); await this.checkResponseValidation(sanisResponse, [ - SanisResponseValidationGroups.USER, - SanisResponseValidationGroups.SCHOOL, + SchulconnexResponseValidationGroups.USER, + SchulconnexResponseValidationGroups.SCHOOL, ]); - const externalUser: ExternalUserDto = this.responseMapper.mapToExternalUserDto(sanisAxiosResponse.data); + const externalUser: ExternalUserDto = this.responseMapper.mapToExternalUserDto(sanisResponse); this.addTeacherRoleIfAdmin(externalUser); - const externalSchool: ExternalSchoolDto = this.responseMapper.mapToExternalSchoolDto(sanisAxiosResponse.data); + const externalSchool: ExternalSchoolDto = this.responseMapper.mapToExternalSchoolDto(sanisResponse); let externalGroups: ExternalGroupDto[] | undefined; if (this.provisioningFeatures.schulconnexGroupProvisioningEnabled) { - await this.checkResponseValidation(sanisResponse, [SanisResponseValidationGroups.GROUPS]); + await this.checkResponseValidation(sanisResponse, [SchulconnexResponseValidationGroups.GROUPS]); - externalGroups = this.responseMapper.mapToExternalGroupDtos(sanisAxiosResponse.data); + externalGroups = this.responseMapper.mapToExternalGroupDtos(sanisResponse); } let externalLicenses: ExternalLicenseDto[] | undefined; @@ -117,7 +105,7 @@ export class SanisProvisioningStrategy extends SchulconnexProvisioningStrategy { ); await this.checkResponseValidation(schulconnexLizenzInfoResponses); - externalLicenses = SanisResponseMapper.mapToExternalLicenses(schulconnexLizenzInfoResponses); + externalLicenses = SchulconnexResponseMapper.mapToExternalLicenses(schulconnexLizenzInfoResponses); } const oauthData: OauthDataDto = new OauthDataDto({ @@ -132,8 +120,8 @@ export class SanisProvisioningStrategy extends SchulconnexProvisioningStrategy { } private async checkResponseValidation( - response: SanisResponse | SchulconnexLizenzInfoResponse | SchulconnexLizenzInfoResponse[], - groups?: SanisResponseValidationGroups[] + response: SchulconnexResponse | SchulconnexLizenzInfoResponse | SchulconnexLizenzInfoResponse[], + groups?: SchulconnexResponseValidationGroups[] ): Promise { const responsesArray = Array.isArray(response) ? response : [response]; diff --git a/apps/server/src/modules/provisioning/strategy/sanis/sanis-response.mapper.ts b/apps/server/src/modules/provisioning/strategy/sanis/schulconnex-response-mapper.service.ts similarity index 62% rename from apps/server/src/modules/provisioning/strategy/sanis/sanis-response.mapper.ts rename to apps/server/src/modules/provisioning/strategy/sanis/schulconnex-response-mapper.service.ts index ba072041846..06cfef99e98 100644 --- a/apps/server/src/modules/provisioning/strategy/sanis/sanis-response.mapper.ts +++ b/apps/server/src/modules/provisioning/strategy/sanis/schulconnex-response-mapper.service.ts @@ -1,16 +1,16 @@ import { - SanisGruppenResponse, - SanisResponse, - SanisSonstigeGruppenzugehoerigeResponse, + SchulconnexGruppenResponse, + SchulconnexResponse, + SchulconnexSonstigeGruppenzugehoerigeResponse, } from '@infra/schulconnex-client'; import { - SanisErreichbarkeitenResponse, SchulconnexCommunicationType, + SchulconnexErreichbarkeitenResponse, SchulconnexLizenzInfoResponse, } from '@infra/schulconnex-client/response'; -import { SanisGroupRole } from '@infra/schulconnex-client/response/sanis-group-role'; -import { SanisGroupType } from '@infra/schulconnex-client/response/sanis-group-type'; -import { SanisRole } from '@infra/schulconnex-client/response/sanis-role'; +import { SchulconnexGroupRole } from '@infra/schulconnex-client/response/schulconnex-group-role'; +import { SchulconnexGroupType } from '@infra/schulconnex-client/response/schulconnex-group-type'; +import { SchulconnexRole } from '@infra/schulconnex-client/response/schulconnex-role'; import { GroupTypes } from '@modules/group'; import { Inject, Injectable } from '@nestjs/common'; import { RoleName } from '@shared/domain/interface'; @@ -25,26 +25,26 @@ import { } from '../../dto'; import { GroupRoleUnknownLoggable } from '../../loggable'; -const RoleMapping: Record = { - [SanisRole.LEHR]: RoleName.TEACHER, - [SanisRole.LERN]: RoleName.STUDENT, - [SanisRole.LEIT]: RoleName.ADMINISTRATOR, - [SanisRole.ORGADMIN]: RoleName.ADMINISTRATOR, +const RoleMapping: Record = { + [SchulconnexRole.LEHR]: RoleName.TEACHER, + [SchulconnexRole.LERN]: RoleName.STUDENT, + [SchulconnexRole.LEIT]: RoleName.ADMINISTRATOR, + [SchulconnexRole.ORGADMIN]: RoleName.ADMINISTRATOR, }; -const GroupRoleMapping: Partial> = { - [SanisGroupRole.TEACHER]: RoleName.TEACHER, - [SanisGroupRole.STUDENT]: RoleName.STUDENT, +const GroupRoleMapping: Partial> = { + [SchulconnexGroupRole.TEACHER]: RoleName.TEACHER, + [SchulconnexGroupRole.STUDENT]: RoleName.STUDENT, }; -const GroupTypeMapping: Partial> = { - [SanisGroupType.CLASS]: GroupTypes.CLASS, - [SanisGroupType.COURSE]: GroupTypes.COURSE, - [SanisGroupType.OTHER]: GroupTypes.OTHER, +const GroupTypeMapping: Partial> = { + [SchulconnexGroupType.CLASS]: GroupTypes.CLASS, + [SchulconnexGroupType.COURSE]: GroupTypes.COURSE, + [SchulconnexGroupType.OTHER]: GroupTypes.OTHER, }; @Injectable() -export class SanisResponseMapper { +export class SchulconnexResponseMapper { SCHOOLNUMBER_PREFIX_REGEX = /^NI_/; constructor( @@ -52,7 +52,7 @@ export class SanisResponseMapper { private readonly logger: Logger ) {} - mapToExternalSchoolDto(source: SanisResponse): ExternalSchoolDto { + mapToExternalSchoolDto(source: SchulconnexResponse): ExternalSchoolDto { const officialSchoolNumber: string = source.personenkontexte[0].organisation.kennung.replace( this.SCHOOLNUMBER_PREFIX_REGEX, '' @@ -68,19 +68,20 @@ export class SanisResponseMapper { return mapped; } - mapToExternalUserDto(source: SanisResponse): ExternalUserDto { + mapToExternalUserDto(source: SchulconnexResponse): ExternalUserDto { let email: string | undefined; if (source.personenkontexte[0].erreichbarkeiten?.length) { - const emailContact: SanisErreichbarkeitenResponse | undefined = source.personenkontexte[0].erreichbarkeiten.find( - (contact: SanisErreichbarkeitenResponse): boolean => contact.typ === SchulconnexCommunicationType.EMAIL - ); + const emailContact: SchulconnexErreichbarkeitenResponse | undefined = + source.personenkontexte[0].erreichbarkeiten.find( + (contact: SchulconnexErreichbarkeitenResponse): boolean => contact.typ === SchulconnexCommunicationType.EMAIL + ); email = emailContact?.kennung; } const mapped = new ExternalUserDto({ firstName: source.person.name.vorname, lastName: source.person.name.familienname, - roles: [SanisResponseMapper.mapSanisRoleToRoleName(source)], + roles: [SchulconnexResponseMapper.mapSanisRoleToRoleName(source)], externalId: source.pid, birthday: source.person.geburt?.datum ? new Date(source.person.geburt?.datum) : undefined, email, @@ -89,22 +90,22 @@ export class SanisResponseMapper { return mapped; } - public static mapSanisRoleToRoleName(source: SanisResponse): RoleName { + public static mapSanisRoleToRoleName(source: SchulconnexResponse): RoleName { return RoleMapping[source.personenkontexte[0].rolle]; } - public static mapToGroupNameList(groups: SanisGruppenResponse[]): string[] { + public static mapToGroupNameList(groups: SchulconnexGruppenResponse[]): string[] { const groupNames: string[] = []; - groups.forEach((group: SanisGruppenResponse) => { + groups.forEach((group: SchulconnexGruppenResponse) => { groupNames.push(group.gruppe.bezeichnung); }); return groupNames; } - public mapToExternalGroupDtos(source: SanisResponse): ExternalGroupDto[] | undefined { - const groups: SanisGruppenResponse[] | undefined = source.personenkontexte[0].gruppen; + public mapToExternalGroupDtos(source: SchulconnexResponse): ExternalGroupDto[] | undefined { + const groups: SchulconnexGruppenResponse[] | undefined = source.personenkontexte[0].gruppen; if (!groups) { return undefined; @@ -117,7 +118,7 @@ export class SanisResponseMapper { return mapped; } - private mapExternalGroup(source: SanisResponse, group: SanisGruppenResponse): ExternalGroupDto | null { + private mapExternalGroup(source: SchulconnexResponse, group: SchulconnexGruppenResponse): ExternalGroupDto | null { const groupType: GroupTypes | undefined = GroupTypeMapping[group.gruppe.typ]; if (!groupType) { @@ -151,7 +152,7 @@ export class SanisResponseMapper { }); } - private mapToExternalGroupUser(relation: SanisSonstigeGruppenzugehoerigeResponse): ExternalGroupUserDto | null { + private mapToExternalGroupUser(relation: SchulconnexSonstigeGruppenzugehoerigeResponse): ExternalGroupUserDto | null { if (!relation.rollen?.length) { return null; } diff --git a/apps/server/src/modules/provisioning/strategy/sanis/sanis-response.mapper.spec.ts b/apps/server/src/modules/provisioning/strategy/sanis/schulconnex-response.mapper.spec.ts similarity index 89% rename from apps/server/src/modules/provisioning/strategy/sanis/sanis-response.mapper.spec.ts rename to apps/server/src/modules/provisioning/strategy/sanis/schulconnex-response.mapper.spec.ts index 1bea7896289..3140aa960e4 100644 --- a/apps/server/src/modules/provisioning/strategy/sanis/sanis-response.mapper.spec.ts +++ b/apps/server/src/modules/provisioning/strategy/sanis/schulconnex-response.mapper.spec.ts @@ -1,12 +1,12 @@ import { createMock } from '@golevelup/ts-jest'; import { - SanisGroupRole, - SanisGroupType, - SanisGruppenResponse, - SanisPersonenkontextResponse, - SanisResponse, - SanisSonstigeGruppenzugehoerigeResponse, + SchulconnexGroupRole, + SchulconnexGroupType, + SchulconnexGruppenResponse, + SchulconnexPersonenkontextResponse, + SchulconnexResponse, schulconnexResponseFactory, + SchulconnexSonstigeGruppenzugehoerigeResponse, } from '@infra/schulconnex-client'; import { GroupTypes } from '@modules/group'; import { Test, TestingModule } from '@nestjs/testing'; @@ -14,18 +14,18 @@ import { RoleName } from '@shared/domain/interface'; import { Logger } from '@src/core/logger'; import { IProvisioningFeatures, ProvisioningFeatures } from '../../config'; import { ExternalGroupDto, ExternalSchoolDto, ExternalUserDto } from '../../dto'; -import { SanisResponseMapper } from './sanis-response.mapper'; +import { SchulconnexResponseMapper } from './schulconnex-response-mapper.service'; -describe('SanisResponseMapper', () => { +describe(SchulconnexResponseMapper.name, () => { let module: TestingModule; - let mapper: SanisResponseMapper; + let mapper: SchulconnexResponseMapper; let provisioningFeatures: IProvisioningFeatures; beforeAll(async () => { module = await Test.createTestingModule({ providers: [ - SanisResponseMapper, + SchulconnexResponseMapper, { provide: Logger, useValue: createMock(), @@ -37,7 +37,7 @@ describe('SanisResponseMapper', () => { ], }).compile(); - mapper = module.get(SanisResponseMapper); + mapper = module.get(SchulconnexResponseMapper); provisioningFeatures = module.get(ProvisioningFeatures); }); @@ -45,7 +45,7 @@ describe('SanisResponseMapper', () => { const externalUserId = 'aef1f4fd-c323-466e-962b-a84354c0e713'; const externalSchoolId = 'df66c8e6-cfac-40f7-b35b-0da5d8ee680e'; - const sanisResponse: SanisResponse = schulconnexResponseFactory.build(); + const sanisResponse: SchulconnexResponse = schulconnexResponseFactory.build(); return { externalUserId, @@ -117,9 +117,9 @@ describe('SanisResponseMapper', () => { }); const { sanisResponse } = setupSanisResponse(); - const personenkontext: SanisPersonenkontextResponse = sanisResponse.personenkontexte[0]; - const group: SanisGruppenResponse = personenkontext.gruppen![0]; - const otherParticipant: SanisSonstigeGruppenzugehoerigeResponse = group.sonstige_gruppenzugehoerige![0]; + const personenkontext: SchulconnexPersonenkontextResponse = sanisResponse.personenkontexte[0]; + const group: SchulconnexGruppenResponse = personenkontext.gruppen![0]; + const otherParticipant: SchulconnexSonstigeGruppenzugehoerigeResponse = group.sonstige_gruppenzugehoerige![0]; return { sanisResponse, @@ -155,7 +155,7 @@ describe('SanisResponseMapper', () => { describe('when group type other is provided', () => { const setup = () => { const { sanisResponse } = setupSanisResponse(); - sanisResponse.personenkontexte[0].gruppen![0]!.gruppe.typ = SanisGroupType.OTHER; + sanisResponse.personenkontexte[0].gruppen![0]!.gruppe.typ = SchulconnexGroupType.OTHER; return { sanisResponse, @@ -178,7 +178,7 @@ describe('SanisResponseMapper', () => { describe('when group type course is provided', () => { const setup = () => { const { sanisResponse } = setupSanisResponse(); - sanisResponse.personenkontexte[0].gruppen![0]!.gruppe.typ = SanisGroupType.COURSE; + sanisResponse.personenkontexte[0].gruppen![0]!.gruppe.typ = SchulconnexGroupType.COURSE; return { sanisResponse, @@ -201,7 +201,9 @@ describe('SanisResponseMapper', () => { describe('when the group role mapping for the user is missing', () => { const setup = () => { const { sanisResponse } = setupSanisResponse(); - sanisResponse.personenkontexte[0].gruppen![0]!.gruppenzugehoerigkeit.rollen = [SanisGroupRole.SCHOOL_SUPPORT]; + sanisResponse.personenkontexte[0].gruppen![0]!.gruppenzugehoerigkeit.rollen = [ + SchulconnexGroupRole.SCHOOL_SUPPORT, + ]; return { sanisResponse, @@ -287,7 +289,7 @@ describe('SanisResponseMapper', () => { sanisResponse.personenkontexte[0].gruppen![0]!.sonstige_gruppenzugehoerige = [ { ktid: 'ktid', - rollen: [SanisGroupRole.SCHOOL_SUPPORT], + rollen: [SchulconnexGroupRole.SCHOOL_SUPPORT], }, ]; diff --git a/apps/server/src/modules/user-import/controller/api-test/import-user-populate.api.spec.ts b/apps/server/src/modules/user-import/controller/api-test/import-user-populate.api.spec.ts index b32653f4eb5..c5e0f1dbc9e 100644 --- a/apps/server/src/modules/user-import/controller/api-test/import-user-populate.api.spec.ts +++ b/apps/server/src/modules/user-import/controller/api-test/import-user-populate.api.spec.ts @@ -1,4 +1,4 @@ -import { SanisResponse, schulconnexResponseFactory } from '@infra/schulconnex-client'; +import { SchulconnexResponse, schulconnexResponseFactory } from '@infra/schulconnex-client'; import { EntityManager, ObjectId } from '@mikro-orm/mongodb'; import { OauthTokenResponse } from '@modules/oauth/service/dto'; import { ServerTestModule } from '@modules/server/server.module'; @@ -6,7 +6,7 @@ import { HttpStatus, INestApplication } from '@nestjs/common'; import { Test, TestingModule } from '@nestjs/testing'; import { Permission, RoleName } from '@shared/domain/interface'; import { SchoolFeature } from '@shared/domain/types'; -import { TestApiClient, roleFactory, schoolEntityFactory, systemEntityFactory, userFactory } from '@shared/testing'; +import { roleFactory, schoolEntityFactory, systemEntityFactory, TestApiClient, userFactory } from '@shared/testing'; import { accountFactory } from '@src/modules/account/testing'; import axios from 'axios'; import MockAdapter from 'axios-mock-adapter'; @@ -152,7 +152,7 @@ describe('ImportUser Controller Populate (API)', () => { access_token: 'accessToken', }); - const schulconnexResponse: SanisResponse = schulconnexResponseFactory.build(); + const schulconnexResponse: SchulconnexResponse = schulconnexResponseFactory.build(); axiosMock.onGet(/(.*)\/personen-info/).reply(HttpStatus.OK, [schulconnexResponse]); return { loggedInClient, account, school }; diff --git a/apps/server/src/modules/user-import/mapper/schulconnex-import-user.mapper.ts b/apps/server/src/modules/user-import/mapper/schulconnex-import-user.mapper.ts index 4a4b1095172..a17b555bc3a 100644 --- a/apps/server/src/modules/user-import/mapper/schulconnex-import-user.mapper.ts +++ b/apps/server/src/modules/user-import/mapper/schulconnex-import-user.mapper.ts @@ -1,18 +1,18 @@ -import { SanisGroupType, SanisGruppenResponse, SanisResponse } from '@infra/schulconnex-client'; -import { SanisResponseMapper } from '@modules/provisioning'; +import { SchulconnexGroupType, SchulconnexGruppenResponse, SchulconnexResponse } from '@infra/schulconnex-client'; +import { SchulconnexResponseMapper } from '@modules/provisioning'; import { ImportUser, SchoolEntity, SystemEntity } from '@shared/domain/entity'; import { RoleName } from '@shared/domain/interface'; export class SchulconnexImportUserMapper { public static mapDataToUserImportEntities( - response: SanisResponse[], + response: SchulconnexResponse[], system: SystemEntity, school: SchoolEntity ): ImportUser[] { - const importUsers: ImportUser[] = response.map((externalUser: SanisResponse): ImportUser => { - const role: RoleName = SanisResponseMapper.mapSanisRoleToRoleName(externalUser); - const groups: SanisGruppenResponse[] | undefined = externalUser.personenkontexte[0]?.gruppen?.filter( - (group) => group.gruppe.typ === SanisGroupType.CLASS + const importUsers: ImportUser[] = response.map((externalUser: SchulconnexResponse): ImportUser => { + const role: RoleName = SchulconnexResponseMapper.mapSanisRoleToRoleName(externalUser); + const groups: SchulconnexGruppenResponse[] | undefined = externalUser.personenkontexte[0]?.gruppen?.filter( + (group) => group.gruppe.typ === SchulconnexGroupType.CLASS ); const importUser: ImportUser = new ImportUser({ @@ -24,7 +24,7 @@ export class SchulconnexImportUserMapper { lastName: externalUser.person.name.familienname, roleNames: ImportUser.isImportUserRole(role) ? [role] : [], email: `${externalUser.person.name.vorname}.${externalUser.person.name.familienname}.${externalUser.pid}@schul-cloud.org`, - classNames: groups ? SanisResponseMapper.mapToGroupNameList(groups) : [], + classNames: groups ? SchulconnexResponseMapper.mapToGroupNameList(groups) : [], }); return importUser; diff --git a/apps/server/src/modules/user-import/service/schulconnex-fetch-import-users.service.spec.ts b/apps/server/src/modules/user-import/service/schulconnex-fetch-import-users.service.spec.ts index f1d2df711f1..839783e63c8 100644 --- a/apps/server/src/modules/user-import/service/schulconnex-fetch-import-users.service.spec.ts +++ b/apps/server/src/modules/user-import/service/schulconnex-fetch-import-users.service.spec.ts @@ -1,5 +1,5 @@ import { createMock, DeepMocked } from '@golevelup/ts-jest'; -import { SanisResponse, schulconnexResponseFactory, SchulconnexRestClient } from '@infra/schulconnex-client'; +import { SchulconnexResponse, schulconnexResponseFactory, SchulconnexRestClient } from '@infra/schulconnex-client'; import { UserService } from '@modules/user'; import { Test, TestingModule } from '@nestjs/testing'; import { UserDO } from '@shared/domain/domainobject'; @@ -52,7 +52,11 @@ describe(SchulconnexFetchImportUsersService.name, () => { jest.resetAllMocks(); }); - const createImportUser = (externalUserData: SanisResponse, school: SchoolEntity, system: SystemEntity): ImportUser => + const createImportUser = ( + externalUserData: SchulconnexResponse, + school: SchoolEntity, + system: SystemEntity + ): ImportUser => importUserFactory.build({ system, school, @@ -68,7 +72,7 @@ describe(SchulconnexFetchImportUsersService.name, () => { describe('getData', () => { describe('when fetching the data', () => { const setup = () => { - const externalUserData: SanisResponse = schulconnexResponseFactory.build(); + const externalUserData: SchulconnexResponse = schulconnexResponseFactory.build(); const system: SystemEntity = systemEntityFactory.buildWithId(); const school: SchoolEntity = schoolEntityFactory.buildWithId({ systems: [system], @@ -132,7 +136,7 @@ describe(SchulconnexFetchImportUsersService.name, () => { describe('filterAlreadyMigratedUser', () => { describe('when the user was not migrated yet', () => { const setup = () => { - const externalUserData: SanisResponse = schulconnexResponseFactory.build(); + const externalUserData: SchulconnexResponse = schulconnexResponseFactory.build(); const system: SystemEntity = systemEntityFactory.buildWithId(); const school: SchoolEntity = schoolEntityFactory.buildWithId({ systems: [system], @@ -160,7 +164,7 @@ describe(SchulconnexFetchImportUsersService.name, () => { describe('when the user already was migrated', () => { const setup = () => { - const externalUserData: SanisResponse = schulconnexResponseFactory.build(); + const externalUserData: SchulconnexResponse = schulconnexResponseFactory.build(); const system: SystemEntity = systemEntityFactory.buildWithId(); const school: SchoolEntity = schoolEntityFactory.buildWithId({ systems: [system], diff --git a/apps/server/src/modules/user-import/service/schulconnex-fetch-import-users.service.ts b/apps/server/src/modules/user-import/service/schulconnex-fetch-import-users.service.ts index 1c2b2f2e184..c5a3f7815eb 100644 --- a/apps/server/src/modules/user-import/service/schulconnex-fetch-import-users.service.ts +++ b/apps/server/src/modules/user-import/service/schulconnex-fetch-import-users.service.ts @@ -1,4 +1,4 @@ -import { SanisResponse, SchulconnexRestClient } from '@infra/schulconnex-client'; +import { SchulconnexResponse, SchulconnexRestClient } from '@infra/schulconnex-client'; import { UserService } from '@modules/user'; import { Injectable } from '@nestjs/common'; import { UserDO } from '@shared/domain/domainobject'; @@ -20,7 +20,7 @@ export class SchulconnexFetchImportUsersService { throw new UserImportSchoolExternalIdMissingLoggableException(school.id); } - const response: SanisResponse[] = await this.schulconnexRestClient.getPersonenInfo({ + const response: SchulconnexResponse[] = await this.schulconnexRestClient.getPersonenInfo({ vollstaendig: ['personen', 'personenkontexte', 'organisationen', 'gruppen'], 'organisation.id': externalSchoolId, }); diff --git a/apps/server/src/modules/user-login-migration/controller/api-test/user-login-migration.api.spec.ts b/apps/server/src/modules/user-login-migration/controller/api-test/user-login-migration.api.spec.ts index c72c462294b..2d833de69df 100644 --- a/apps/server/src/modules/user-login-migration/controller/api-test/user-login-migration.api.spec.ts +++ b/apps/server/src/modules/user-login-migration/controller/api-test/user-login-migration.api.spec.ts @@ -1,5 +1,5 @@ import { Configuration } from '@hpi-schul-cloud/commons/lib'; -import { SanisResponse, SanisRole } from '@infra/schulconnex-client'; +import { SchulconnexResponse, SchulconnexRole } from '@infra/schulconnex-client'; import { EntityManager, ObjectId } from '@mikro-orm/mongodb'; import { OauthTokenResponse } from '@modules/oauth/service/dto'; import { ServerTestModule } from '@modules/server'; @@ -439,7 +439,7 @@ describe('UserLoginMigrationController (API)', () => { access_token: 'accessToken', }) .onGet(targetSystem.provisioningUrl) - .replyOnce(200, { + .replyOnce(200, { pid: targetUserId, person: { name: { @@ -450,7 +450,7 @@ describe('UserLoginMigrationController (API)', () => { personenkontexte: [ { id: new UUID('aef1f4fd-c323-466e-962b-a84354c0e713').toString(), - rolle: SanisRole.LEHR, + rolle: SchulconnexRole.LEHR, organisation: { id: new UUID('aef1f4fd-c323-466e-962b-a84354c0e713').toString(), kennung: officialSchoolNumber,