Skip to content

Commit

Permalink
Merge branch 'main' into SPSH-708
Browse files Browse the repository at this point in the history
  • Loading branch information
phaelcg committed Jul 2, 2024
2 parents cbeb83b + a36d16c commit ce9816c
Show file tree
Hide file tree
Showing 14 changed files with 158 additions and 43 deletions.
6 changes: 3 additions & 3 deletions charts/dbildungs-iam-server/seeding/dev/01_organisation.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
"entities": [
{
"id": 0,
"name": "Wurzel Land Schleswig Holstein",
"name": "Land Schleswig-Holstein",
"kuerzel": "Root",
"typ": "ROOT",
"administriertVon": null,
"zugehoerigZu": null
},
{
"id": 1,
"name": "Öffentliche Schulen Land Schleswig Holstein",
"name": "Öffentliche Schulen Land Schleswig-Holstein",
"kuerzel": "Öffentl. Schulen",
"typ": "LAND",
"administriertVon": 0,
"zugehoerigZu": 0
},
{
"id": 2,
"name": "Ersatzschulen Land Schleswig Holstein",
"name": "Ersatzschulen Land Schleswig-Holstein",
"kuerzel": "Ersatzschulen",
"typ": "LAND",
"administriertVon": 0,
Expand Down
6 changes: 3 additions & 3 deletions seeding/dev/01/01_organisation.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@
"entities": [
{
"id": 0,
"name": "Wurzel Land Schleswig Holstein",
"name": "Land Schleswig-Holstein",
"kuerzel": "Root",
"typ": "ROOT",
"administriertVon": null,
"zugehoerigZu": null
},
{
"id": 1,
"name": "Öffentliche Schulen Land Schleswig Holstein",
"name": "Öffentliche Schulen Land Schleswig-Holstein",
"kuerzel": "Öffentl. Schulen",
"typ": "LAND",
"administriertVon": 0,
"zugehoerigZu": 0
},
{
"id": 2,
"name": "Ersatzschulen Land Schleswig Holstein",
"name": "Ersatzschulen Land Schleswig-Holstein",
"kuerzel": "Ersatzschulen",
"typ": "LAND",
"administriertVon": 0,
Expand Down
9 changes: 9 additions & 0 deletions seeding/dev/01/04_rolle.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,15 @@
"MIGRATION_DURCHFUEHREN"
],
"serviceProviderIds": []
},
{
"id": 6,
"administeredBySchulstrukturknoten": 0,
"name": "Schulbegleitung",
"rollenart": "LERN",
"merkmale": [],
"systemrechte": [],
"serviceProviderIds": []
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
"entities": [
{
"id": 0,
"name": "Wurzel Land Schleswig Holstein",
"name": "Land Schleswig-Holstein",
"kuerzel": "Root",
"typ": "ROOT",
"administriertVon": null,
"zugehoerigZu": null
}
]
}


Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,18 @@ export class KeycloakUserService {
}
let algorithm: string;
let hashIterations: number | undefined;
let passwordValue: string;
if (hashedPassword.startsWith('{BCRYPT}')) {
algorithm = 'bcrypt';
const parts: string[] = hashedPassword.split('$');
const parts: string[] = hashedPassword.split('$'); //Only Everything After and including the First $
if (parts.length < 4 || !parts[2]) {
return {
ok: false,
error: new KeycloakClientError('Invalid bcrypt hash format'),
};
}
hashIterations = parseInt(parts[2]);
passwordValue = hashedPassword.substring(hashedPassword.indexOf('$'));
} else if (hashedPassword.startsWith('{crypt}')) {
algorithm = 'crypt';
const parts: string[] = hashedPassword.split('$');
Expand All @@ -107,6 +109,7 @@ export class KeycloakUserService {
};
}
hashIterations = undefined;
passwordValue = hashedPassword.substring(hashedPassword.indexOf('$'));
} else {
return {
ok: false,
Expand Down Expand Up @@ -144,7 +147,7 @@ export class KeycloakUserService {
algorithm: algorithm,
}),
secretData: JSON.stringify({
value: hashedPassword,
value: passwordValue,
}),
type: 'password',
},
Expand Down
4 changes: 2 additions & 2 deletions src/modules/organisation/api/organisation.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ describe('OrganisationController', () => {
faker.string.uuid(),
faker.string.uuid(),
faker.string.numeric(),
'Öffentliche Schulen Land Schleswig Holstein',
'Öffentliche Schulen Land Schleswig-Holstein',
faker.lorem.word(),
faker.string.uuid(),
OrganisationsTyp.ROOT,
Expand All @@ -349,7 +349,7 @@ describe('OrganisationController', () => {
faker.string.uuid(),
faker.string.uuid(),
faker.string.numeric(),
'Ersatzschulen Land Schleswig Holstein',
'Ersatzschulen Land Schleswig-Holstein',
faker.lorem.word(),
faker.string.uuid(),
OrganisationsTyp.SCHULE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ describe('OrganisationRepository', () => {
ROOT_ORGANISATION_ID,
faker.string.uuid(),
faker.string.numeric(),
'Öffentliche Schulen Land Schleswig Holstein',
'Öffentliche Schulen Land Schleswig-Holstein',
faker.lorem.word(),
faker.string.uuid(),
OrganisationsTyp.ROOT,
Expand All @@ -443,7 +443,7 @@ describe('OrganisationRepository', () => {
ROOT_ORGANISATION_ID,
faker.string.uuid(),
faker.string.numeric(),
'Ersatzschulen Land Schleswig Holstein',
'Ersatzschulen Land Schleswig-Holstein',
faker.lorem.word(),
faker.string.uuid(),
OrganisationsTyp.SCHULE,
Expand Down
12 changes: 1 addition & 11 deletions src/modules/person/person-api.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ import { PersonModule } from './person.module.js';
import { PersonFrontendController } from './api/person.frontend.controller.js';
import { PersonenkontextUc } from '../personenkontext/api/personenkontext.uc.js';
import { PersonenKontextModule } from '../personenkontext/personenkontext.module.js';
import { UsernameGeneratorService } from './domain/username-generator.service.js';
import { PersonRepository } from './persistence/person.repository.js';
import { RolleModule } from '../rolle/rolle.module.js';
import { OrganisationModule } from '../organisation/organisation.module.js';
import { KeycloakAdministrationModule } from '../keycloak-administration/keycloak-administration.module.js';
import { DBiamPersonenuebersichtController } from './api/personenuebersicht/dbiam-personenuebersicht.controller.js';
import { DBiamPersonenkontextRepo } from '../personenkontext/persistence/dbiam-personenkontext.repo.js';
import { PersonInfoController } from './api/person-info.controller.js';
import { PersonApiMapper } from './mapper/person-api.mapper.js';
import { DBiamPersonController } from './api/dbiam-person.controller.js';
Expand All @@ -29,14 +26,7 @@ import { EventModule } from '../../core/eventbus/event.module.js';
LoggerModule.register(PersonApiModule.name),
EventModule,
],
providers: [
PersonApiMapperProfile,
PersonenkontextUc,
UsernameGeneratorService,
PersonRepository,
DBiamPersonenkontextRepo,
PersonApiMapper,
],
providers: [PersonApiMapperProfile, PersonenkontextUc, PersonApiMapper],
controllers: [
PersonController,
PersonFrontendController,
Expand Down
18 changes: 14 additions & 4 deletions src/modules/rolle/api/rolle.controller.integration-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@ import { OrganisationRepository } from '../../organisation/persistence/organisat
import { PagedResponse } from '../../../shared/paging/index.js';
import { ServiceProviderIdNameResponse } from './serviceprovider-id-name.response.js';
import { createMock, DeepMocked } from '@golevelup/ts-jest';
import { PersonPermissionsRepo } from '../../authentication/domain/person-permission.repo.js';
//import {PersonPermissions} from "../../authentication/domain/person-permissions.js";
import { Observable } from 'rxjs';
import { Request } from 'express';
import { PersonPermissionsRepo } from '../../authentication/domain/person-permission.repo.js';
import { PassportUser } from '../../authentication/types/user.js';
import { Request } from 'express';

describe('Rolle API', () => {
let app: INestApplication;
Expand Down Expand Up @@ -87,7 +86,6 @@ describe('Rolle API', () => {
rolleRepo = module.get(RolleRepo);
serviceProviderRepo = module.get(ServiceProviderRepo);
personpermissionsRepoMock = module.get(PersonPermissionsRepo);

await DatabaseTestModule.setupDatabase(module.get(MikroORM));
app = module.createNestApplication();
await app.init();
Expand Down Expand Up @@ -238,6 +236,18 @@ describe('Rolle API', () => {
expect(pagedResponse.items).toHaveLength(3);
});

it('should return no rollen', async () => {
const response: Response = await request(app.getHttpServer() as App)
.get('/rolle')
.send();

expect(response.status).toBe(200);
expect(response.body).toBeInstanceOf(Object);
const pagedResponse: PagedResponse<RolleWithServiceProvidersResponse> =
response.body as PagedResponse<RolleWithServiceProvidersResponse>;
expect(pagedResponse.items).toHaveLength(0);
});

it('should return rollen with the given queried name', async () => {
const testRolle: { name: string } = await rolleRepo.save(DoFactory.createRolle(false));

Expand Down
6 changes: 5 additions & 1 deletion src/modules/rolle/api/rolle.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { FindRolleByIdParams } from './find-rolle-by-id.params.js';
import { OrganisationService } from '../../organisation/domain/organisation.service.js';
import { OrganisationRepository } from '../../organisation/persistence/organisation.repository.js';
import { RolleNameQueryParams } from './rolle-name-query.param.js';
import { PersonPermissions } from '../../authentication/domain/person-permissions.js';

describe('Rolle API with mocked ServiceProviderRepo', () => {
let rolleRepoMock: DeepMocked<RolleRepo>;
Expand Down Expand Up @@ -84,11 +85,14 @@ describe('Rolle API with mocked ServiceProviderRepo', () => {
const params: RolleNameQueryParams = {
searchStr: faker.string.alpha(),
};
const permissions: DeepMocked<PersonPermissions> = createMock<PersonPermissions>();
permissions.getOrgIdsWithSystemrecht.mockResolvedValueOnce([]);

//mock getRollenByName
rolleRepoMock.findByName.mockResolvedValueOnce(undefined);
//mock call to get sp (direct in controller-method)
serviceProviderRepoMock.findById.mockResolvedValueOnce(undefined);
await expect(rolleController.findRollen(params)).resolves.not.toThrow(Error);
await expect(rolleController.findRollen(params, permissions)).resolves.not.toThrow(Error);
});
});
});
Expand Down
19 changes: 9 additions & 10 deletions src/modules/rolle/api/rolle.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,16 @@ export class RolleController {
@ApiInternalServerErrorResponse({ description: 'Internal server error while getting all rollen.' })
public async findRollen(
@Query() queryParams: RolleNameQueryParams,
@Permissions() permissions: PersonPermissions,
): Promise<PagedResponse<RolleWithServiceProvidersResponse>> {
let rollen: Option<Rolle<true>[]>;

if (queryParams.searchStr) {
rollen = await this.rolleRepo.findByName(queryParams.searchStr, queryParams.limit, queryParams.offset);
} else {
rollen = await this.rolleRepo.find(queryParams.limit, queryParams.offset);
}

const serviceProviders: ServiceProvider<true>[] = await this.serviceProviderRepo.find();
const rollen: Option<Rolle<true>[]> = await this.rolleRepo.findRollenAuthorized(
permissions,
queryParams.searchStr,
queryParams.limit,
queryParams.offset,
);

if (!rollen) {
if (!rollen || rollen.length === 0) {
const pagedRolleWithServiceProvidersResponse: Paged<RolleWithServiceProvidersResponse> = {
total: 0,
offset: 0,
Expand All @@ -97,6 +95,7 @@ export class RolleController {
};
return new PagedResponse(pagedRolleWithServiceProvidersResponse);
}
const serviceProviders: ServiceProvider<true>[] = await this.serviceProviderRepo.find();

const rollenWithServiceProvidersResponses: RolleWithServiceProvidersResponse[] = rollen.map(
(r: Rolle<true>) => {
Expand Down
67 changes: 67 additions & 0 deletions src/modules/rolle/repo/rolle.repo.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,74 @@ describe('RolleRepo', () => {
expect(rolle).toBeNull();
});
});
describe('findRollenAuthorized', () => {
it('should return no rollen because there are none', async () => {
const organisationId: OrganisationID = faker.string.uuid();

const permissions: DeepMocked<PersonPermissions> = createMock<PersonPermissions>();
permissions.getOrgIdsWithSystemrecht.mockResolvedValueOnce([organisationId]);

const rolleResult: Option<Rolle<true>[]> = await sut.findRollenAuthorized(permissions, undefined, 10, 0);

expect(rolleResult?.length).toBe(0);
});

it('should return the rollen when permissions are sufficient', async () => {
const organisationId: OrganisationID = faker.string.uuid();
await sut.save(DoFactory.createRolle(false, { administeredBySchulstrukturknoten: organisationId }));

const permissions: DeepMocked<PersonPermissions> = createMock<PersonPermissions>();
permissions.getOrgIdsWithSystemrecht.mockResolvedValueOnce([organisationId]);

const rolleResult: Option<Rolle<true>[]> = await sut.findRollenAuthorized(permissions, undefined, 10, 0);

expect(rolleResult?.length).toBe(1);
});

it('should return empty array when permissions are insufficient', async () => {
const organisationId: OrganisationID = faker.string.uuid();
await sut.save(DoFactory.createRolle(false, { administeredBySchulstrukturknoten: organisationId }));

const permissions: DeepMocked<PersonPermissions> = createMock<PersonPermissions>();
permissions.getOrgIdsWithSystemrecht.mockResolvedValueOnce([]);

const rolleResult: Option<Rolle<true>[]> = await sut.findRollenAuthorized(permissions, undefined, 10, 0);

expect(rolleResult?.length).toBe(0);
});

it('should filter rollen based on search string and permissions', async () => {
const organisationId: OrganisationID = faker.string.uuid();
await sut.save(
DoFactory.createRolle(false, { administeredBySchulstrukturknoten: organisationId, name: 'Test' }),
);
await sut.save(
DoFactory.createRolle(false, {
administeredBySchulstrukturknoten: organisationId,
name: 'AnotherName',
}),
);

const permissions: DeepMocked<PersonPermissions> = createMock<PersonPermissions>();
permissions.getOrgIdsWithSystemrecht.mockResolvedValueOnce([organisationId]);

const rolleResult: Option<Rolle<true>[]> = await sut.findRollenAuthorized(permissions, 'Test', 10, 0);

expect(rolleResult?.length).toBe(1);
});

it('should return all rollen when no search string is provided and permissions are sufficient', async () => {
const organisationId: OrganisationID = faker.string.uuid();
await sut.save(DoFactory.createRolle(false, { administeredBySchulstrukturknoten: organisationId }));

const permissions: DeepMocked<PersonPermissions> = createMock<PersonPermissions>();
permissions.getOrgIdsWithSystemrecht.mockResolvedValueOnce([organisationId]);

const rolleResult: Option<Rolle<true>[]> = await sut.findRollenAuthorized(permissions, undefined, 10, 0);

expect(rolleResult?.length).toBe(1);
});
});
describe('findByIdAuthorized', () => {
it('should return the rolle', async () => {
const organisationId: OrganisationID = faker.string.uuid();
Expand Down
Loading

0 comments on commit ce9816c

Please sign in to comment.