Skip to content

Commit

Permalink
SPSH-1544: UEM Inbetriebnahme-Passwort erzeugen (#820)
Browse files Browse the repository at this point in the history
* rm PersonRepository-ref in LdapClientSvc, adjust Email-events to contain referrer, add resetUEMPasswordByPersonId in PersonController, add PersonReferrer-type

* fix existing test cases

* add test cases after adjusting LDAPClientSvc

* remove dead imports and comments

* add RollenArt to DBiamPersonenzuordnungResponse

* remove StepUp-Guard for Reset-UEM-password

* allow Lehrer to use UEM-password-reset for themselves

* undo StepUpGuard-disabling for creating person with kontexte via POST

* adjust i18 for Person-UEM-Password, adjust test cases

---------

Co-authored-by: Youssef Bouchara <[email protected]>
  • Loading branch information
DPDS93CT and YoussefBouch authored Dec 12, 2024
1 parent 2ef7a25 commit 8f74727
Show file tree
Hide file tree
Showing 22 changed files with 680 additions and 69 deletions.
150 changes: 129 additions & 21 deletions src/core/ldap/domain/ldap-client.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import { LdapEmailDomainError } from '../error/ldap-email-domain.error.js';
import { LdapEmailAddressError } from '../error/ldap-email-address.error.js';
import { LdapCreateLehrerError } from '../error/ldap-create-lehrer.error.js';
import { LdapModifyEmailError } from '../error/ldap-modify-email.error.js';
import { PersonRepository } from '../../../modules/person/persistence/person.repository.js';
import { LdapInstanceConfig } from '../ldap-instance-config.js';
import { LdapModifyUserPasswordError } from '../error/ldap-modify-user-password.error.js';

describe('LDAP Client Service', () => {
let app: INestApplication;
Expand All @@ -40,7 +40,6 @@ describe('LDAP Client Service', () => {
let loggerMock: DeepMocked<ClassLogger>;
let eventServiceMock: DeepMocked<EventService>;
let clientMock: DeepMocked<Client>;
let personRepoMock: DeepMocked<PersonRepository>;
let instanceConfig: LdapInstanceConfig;

let person: Person<true>;
Expand Down Expand Up @@ -69,8 +68,6 @@ describe('LDAP Client Service', () => {
.useValue(createMock<ClassLogger>())
.overrideProvider(EventService)
.useValue(createMock<EventService>())
.overrideProvider(PersonRepository)
.useValue(createMock<PersonRepository>())
.compile();

orm = module.get(MikroORM);
Expand All @@ -80,7 +77,6 @@ describe('LDAP Client Service', () => {
loggerMock = module.get(ClassLogger);
eventServiceMock = module.get(EventService);
clientMock = createMock<Client>();
personRepoMock = module.get(PersonRepository);
instanceConfig = module.get(LdapInstanceConfig);

person = Person.construct(
Expand Down Expand Up @@ -459,7 +455,6 @@ describe('LDAP Client Service', () => {
clientMock.del.mockResolvedValueOnce();
return clientMock;
});
personRepoMock.findById.mockResolvedValueOnce(person);

const result: Result<PersonID> = await ldapClientService.deleteLehrerByReferrer(person.referrer!);

Expand Down Expand Up @@ -613,13 +608,13 @@ describe('LDAP Client Service', () => {

describe('when bind returns error', () => {
it('should return falsy result', async () => {
personRepoMock.findById.mockResolvedValueOnce(person);
ldapClientMock.getClient.mockImplementation(() => {
clientMock.bind.mockRejectedValueOnce(new Error());
return clientMock;
});
const result: Result<PersonID> = await ldapClientService.changeEmailAddressByPersonId(
faker.string.uuid(),
faker.internet.userName(),
fakeSchuleSHAddress,
);

Expand All @@ -629,9 +624,9 @@ describe('LDAP Client Service', () => {

describe('when person can not be found in DB', () => {
it('should return falsy result', async () => {
personRepoMock.findById.mockResolvedValueOnce(undefined);
const result: Result<PersonID> = await ldapClientService.changeEmailAddressByPersonId(
faker.string.uuid(),
faker.internet.userName(),
fakeSchuleSHAddress,
);

Expand All @@ -641,10 +636,9 @@ describe('LDAP Client Service', () => {

describe('when called with invalid emailDomain', () => {
it('should return LdapEmailDomainError', async () => {
personRepoMock.findById.mockResolvedValueOnce(person);

const result: Result<PersonID> = await ldapClientService.changeEmailAddressByPersonId(
faker.string.uuid(),
faker.internet.userName(),
'[email protected]',
);

Expand All @@ -656,10 +650,9 @@ describe('LDAP Client Service', () => {

describe('when called with newEmailAddress that is not splittable', () => {
it('should return LdapEmailAddressError', async () => {
personRepoMock.findById.mockResolvedValueOnce(person);

const result: Result<PersonID> = await ldapClientService.changeEmailAddressByPersonId(
faker.string.uuid(),
faker.internet.userName(),
'user-at-wrong-email-domain.de',
);

Expand All @@ -671,7 +664,6 @@ describe('LDAP Client Service', () => {

describe('when person cannot be found by personID', () => {
it('should return LdapSearchError', async () => {
personRepoMock.findById.mockResolvedValueOnce(person);
ldapClientMock.getClient.mockImplementation(() => {
clientMock.bind.mockResolvedValueOnce();
clientMock.search.mockResolvedValueOnce(
Expand All @@ -684,6 +676,7 @@ describe('LDAP Client Service', () => {

const result: Result<PersonID> = await ldapClientService.changeEmailAddressByPersonId(
faker.string.uuid(),
faker.internet.userName(),
fakeSchuleSHAddress,
);

Expand All @@ -702,8 +695,6 @@ describe('LDAP Client Service', () => {
const currentEmailAddress: string = '[email protected]';

it('should set mailAlternativeAddress as current mailPrimaryAddress and throw LdapPersonEntryChangedEvent', async () => {
personRepoMock.findById.mockResolvedValueOnce(person);

ldapClientMock.getClient.mockImplementation(() => {
clientMock.bind.mockResolvedValueOnce();
clientMock.search.mockResolvedValueOnce(
Expand All @@ -723,6 +714,7 @@ describe('LDAP Client Service', () => {

const result: Result<PersonID> = await ldapClientService.changeEmailAddressByPersonId(
fakePersonID,
faker.internet.userName(),
newEmailAddress,
);

Expand Down Expand Up @@ -750,8 +742,6 @@ describe('LDAP Client Service', () => {

describe('and already has a mailPrimaryAddress', () => {
it('should set mailAlternativeAddress as current mailPrimaryAddress and throw LdapPersonEntryChangedEvent', async () => {
personRepoMock.findById.mockResolvedValueOnce(person);

ldapClientMock.getClient.mockImplementation(() => {
clientMock.bind.mockResolvedValueOnce();
clientMock.search.mockResolvedValueOnce(
Expand All @@ -771,6 +761,7 @@ describe('LDAP Client Service', () => {

const result: Result<PersonID> = await ldapClientService.changeEmailAddressByPersonId(
fakePersonID,
faker.internet.userName(),
newEmailAddress,
);

Expand Down Expand Up @@ -798,8 +789,6 @@ describe('LDAP Client Service', () => {

describe('and already has a mailPrimaryAddress', () => {
it('should set mailAlternativeAddress as current mailPrimaryAddress and throw LdapPersonEntryChangedEvent', async () => {
personRepoMock.findById.mockResolvedValueOnce(person);

ldapClientMock.getClient.mockImplementation(() => {
clientMock.bind.mockResolvedValueOnce();
clientMock.search.mockResolvedValueOnce(
Expand All @@ -819,6 +808,7 @@ describe('LDAP Client Service', () => {

const result: Result<PersonID> = await ldapClientService.changeEmailAddressByPersonId(
fakePersonID,
faker.internet.userName(),
newEmailAddress,
);

Expand All @@ -839,8 +829,6 @@ describe('LDAP Client Service', () => {

describe('but does NOT have a mailPrimaryAddress', () => {
it('should set mailAlternativeAddress to same value as mailPrimaryAddress and throw LdapPersonEntryChangedEvent', async () => {
personRepoMock.findById.mockResolvedValueOnce(person);

ldapClientMock.getClient.mockImplementation(() => {
clientMock.bind.mockResolvedValueOnce();
clientMock.search.mockResolvedValueOnce(
Expand All @@ -860,6 +848,7 @@ describe('LDAP Client Service', () => {

const result: Result<PersonID> = await ldapClientService.changeEmailAddressByPersonId(
fakePersonID,
faker.internet.userName(),
newEmailAddress,
);

Expand All @@ -878,4 +867,123 @@ describe('LDAP Client Service', () => {
});
});
});

describe('changeUserPasswordByPersonId', () => {
describe('when bind returns error', () => {
it('should return falsy result', async () => {
ldapClientMock.getClient.mockImplementation(() => {
clientMock.bind.mockRejectedValueOnce(new Error());
return clientMock;
});
const result: Result<PersonID> = await ldapClientService.changeUserPasswordByPersonId(
faker.string.uuid(),
faker.internet.userName(),
);

expect(result.ok).toBeFalsy();
});
});

describe('when person cannot be found by personID', () => {
it('should return LdapSearchError', async () => {
ldapClientMock.getClient.mockImplementation(() => {
clientMock.bind.mockResolvedValueOnce();
clientMock.search.mockResolvedValueOnce(
createMock<SearchResult>({
searchEntries: [],
}),
);
return clientMock;
});

const result: Result<PersonID> = await ldapClientService.changeUserPasswordByPersonId(
faker.string.uuid(),
faker.internet.userName(),
);

expect(result.ok).toBeFalsy();
expect(result).toEqual({
ok: false,
error: new LdapSearchError(LdapEntityType.LEHRER),
});
});
});

describe('when person can be found but modification fails', () => {
const fakePersonID: string = faker.string.uuid();
const fakeDN: string = faker.string.alpha();

it('should NOT publish event and throw LdapPersonEntryChangedEvent', async () => {
ldapClientMock.getClient.mockImplementation(() => {
clientMock.bind.mockResolvedValueOnce();
clientMock.search.mockResolvedValueOnce(
createMock<SearchResult>({
searchEntries: [
createMock<Entry>({
dn: fakeDN,
}),
],
}),
);
clientMock.modify.mockRejectedValueOnce(new Error());

return clientMock;
});

const result: Result<PersonID> = await ldapClientService.changeUserPasswordByPersonId(
fakePersonID,
faker.internet.userName(),
);

if (result.ok) throw Error();
expect(result.error).toStrictEqual(new LdapModifyUserPasswordError());
expect(loggerMock.error).toHaveBeenLastCalledWith(
`LDAP: Modifying userPassword (UEM) FAILED, errMsg:{}`,
);
expect(eventServiceMock.publish).toHaveBeenCalledTimes(0);
});
});

describe('when person can be found and userPassword can be modified', () => {
let fakePersonID: string;
let fakeDN: string;

beforeEach(() => {
fakePersonID = faker.string.uuid();
fakeDN = faker.string.alpha();
});

describe('when', () => {
it('should publish event and return new (UEM) userPassword', async () => {
ldapClientMock.getClient.mockImplementation(() => {
clientMock.bind.mockResolvedValueOnce();
clientMock.search.mockResolvedValueOnce(
createMock<SearchResult>({
searchEntries: [
createMock<Entry>({
dn: fakeDN,
}),
],
}),
);
clientMock.modify.mockResolvedValueOnce(undefined);

return clientMock;
});

const result: Result<PersonID> = await ldapClientService.changeUserPasswordByPersonId(
fakePersonID,
faker.internet.userName(),
);

if (!result.ok) throw Error();
expect(result.value).toHaveLength(8);
expect(loggerMock.info).toHaveBeenLastCalledWith(
`LDAP: Successfully modified userPassword (UEM) for personId:${fakePersonID}`,
);
expect(eventServiceMock.publish).toHaveBeenCalledTimes(1);
});
});
});
});
});
Loading

0 comments on commit 8f74727

Please sign in to comment.