Skip to content
Snippets Groups Projects
Verified Commit bf532f50 authored by Sebastian Bergandy's avatar Sebastian Bergandy :keyboard:
Browse files

OZG-7838 map admin roles in repository

Based on CR comment.
parent eb9d3a83
No related branches found
No related tags found
1 merge request!95OZG-7383 add realm-management roles for admin
......@@ -3,9 +3,9 @@ export const KeycloakDefaults = {
realmManagement: {
clientName: 'realm-management',
roles: {
managerUsers: {
roleName: 'manage-users',
},
managerUsers: { roleName: 'manage-users' },
queryGroups: { roleName: 'query-groups' },
viewClients: { roleName: 'view-clients' },
},
},
},
......
......@@ -21,12 +21,13 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
import { RoleMappings, User } from '@admin-client/user-shared';
import { AdminRoles, RoleMappings, User } from '@admin-client/user-shared';
import { UserRepository } from '@admin/keycloak-shared';
import { StateResource } from '@alfa-client/tech-shared';
import { Mock, mock } from '@alfa-client/test-utils';
import { fakeAsync, TestBed, tick } from '@angular/core/testing';
import { faker } from '@faker-js/faker';
import { expect } from '@jest/globals';
import KcAdminClient from '@keycloak/keycloak-admin-client';
import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation';
import MappingsRepresentation from '@keycloak/keycloak-admin-client/lib/defs/mappingsRepresentation';
......@@ -274,20 +275,6 @@ describe('UserRepository', () => {
expect(repository._updateUserRolesForClient).toHaveBeenCalledWith(user.id, [UserFormService.POSTSTELLE], clientId);
});
it('should update user roles for realm-management client', async () => {
await repository._updateUserRoles(user.id, {
realmManagement: [KeycloakDefaults.clients.realmManagement.roles.managerUsers.roleName],
admin: [],
alfa: [],
});
expect(repository._updateUserRolesForClient).toHaveBeenCalledWith(
user.id,
[KeycloakDefaults.clients.realmManagement.roles.managerUsers.roleName],
clientId,
);
});
});
describe('updateUserRolesForClient', () => {
......@@ -546,6 +533,50 @@ describe('UserRepository', () => {
});
});
describe('update user roles for admin', () => {
const clientId: string = faker.string.uuid();
beforeEach(() => {
repository._updateUserRolesForClient = jest.fn();
repository._getClientId = jest.fn().mockReturnValue(new Promise((resolve) => resolve(clientId)));
});
it('should get client id', async () => {
await repository._updateUserRolesForAdmin(user.id, {
admin: [AdminRoles.ADMIN],
alfa: [],
});
expect(repository._getClientId).toHaveBeenCalledWith(KeycloakDefaults.clients.realmManagement.clientName);
});
it('should update user roles', async () => {
await repository._updateUserRolesForAdmin(user.id, {
admin: [AdminRoles.ADMIN],
alfa: [],
});
expect(repository._updateUserRolesForClient).toHaveBeenCalledWith(
user.id,
[
KeycloakDefaults.clients.realmManagement.roles.managerUsers.roleName,
KeycloakDefaults.clients.realmManagement.roles.queryGroups.roleName,
KeycloakDefaults.clients.realmManagement.roles.viewClients.roleName,
],
clientId,
);
});
it('should NOT update user roles for no ADMIN_ADMIN role', async () => {
await repository._updateUserRolesForAdmin(user.id, {
admin: [faker.word.noun()],
alfa: [],
});
expect(repository._updateUserRolesForClient).not.toHaveBeenCalled();
});
});
describe('sendActivationMail', () => {
it('should call kcAdminClient users executeActionsEmail', () => {
const userId: string = faker.string.uuid();
......
......@@ -21,7 +21,7 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
import { ClientMapping, ClientRoles, RoleMappings, User } from '@admin-client/user-shared';
import { AdminRoles, ClientMapping, ClientRoles, RoleMappings, User } from '@admin-client/user-shared';
import { createStateResource, StateResource } from '@alfa-client/tech-shared';
import { inject, Injectable } from '@angular/core';
import KcAdminClient from '@keycloak/keycloak-admin-client';
......@@ -105,11 +105,7 @@ export class UserRepository {
async _updateUserRoles(userId: string, clientRoles: ClientRoles): Promise<void> {
await this._updateUserRolesForClient(userId, clientRoles.admin, await this._getClientId(UserRepository.ADMIN_CLIENT_NAME));
await this._updateUserRolesForClient(userId, clientRoles.alfa, await this._getClientId(UserRepository.ALFA_CLIENT_NAME));
await this._updateUserRolesForClient(
userId,
clientRoles.realmManagement,
await this._getClientId(KeycloakDefaults.clients.realmManagement.clientName),
);
await this._updateUserRolesForAdmin(userId, clientRoles);
}
async _updateUserRolesForClient(userId: string, clientRoles: string[], clientId: string): Promise<void> {
......@@ -183,6 +179,20 @@ export class UserRepository {
});
}
async _updateUserRolesForAdmin(userId: string, clientRoles: ClientRoles): Promise<void> {
if (clientRoles.admin.includes(AdminRoles.ADMIN)) {
await this._updateUserRolesForClient(
userId,
[
KeycloakDefaults.clients.realmManagement.roles.managerUsers.roleName,
KeycloakDefaults.clients.realmManagement.roles.queryGroups.roleName,
KeycloakDefaults.clients.realmManagement.roles.viewClients.roleName,
],
await this._getClientId(KeycloakDefaults.clients.realmManagement.clientName),
);
}
}
_sendActivationMail(userId: string): void {
this.kcAdminClient.users.executeActionsEmail({
id: userId,
......
......@@ -33,13 +33,11 @@ export interface User {
groups: string[];
groupIds?: string[];
clientRoles: ClientRoles;
realmManagement?: string[];
}
export interface ClientRoles {
alfa: string[];
admin: string[];
realmManagement?: string[];
}
export interface ClientMapping {
......@@ -50,3 +48,7 @@ export interface RoleMappings {
newClientRoleMappings: RoleMappingPayload[];
oldClientRoleMappings: RoleMappingPayload[];
}
export enum AdminRoles {
ADMIN = 'ADMIN_ADMIN',
}
......@@ -39,7 +39,6 @@ import { createUser } from 'libs/admin/user-shared/test/user';
import { Observable, of, throwError } from 'rxjs';
import { createUrlSegment } from '../../../../../navigation-shared/test/navigation-test-factory';
import { singleCold, singleColdCompleted, singleHot } from '../../../../../tech-shared/test/marbles';
import { KeycloakDefaults } from '../../../../keycloak-shared/src/lib/keycloak.model';
import { createAdminOrganisationsEinheit } from '../../../../organisations-einheit-shared/src/test/organisations-einheit';
import { UserFormService } from './user.formservice';
import SpyInstance = jest.SpyInstance;
......@@ -504,90 +503,4 @@ describe('UserFormService', () => {
expect(userName).toBe('userNameDummy');
});
});
describe('map administration role to realm-management role', () => {
it('should map ADMIN role', () => {
expect(formService._mapAdministrationRoleToManagementRealmRole(UserFormService.ADMIN)).toEqual(
KeycloakDefaults.clients.realmManagement.roles.managerUsers.roleName,
);
});
it('should throw error', () => {
expect(() => formService._mapAdministrationRoleToManagementRealmRole(UserFormService.USER)).toThrow();
});
});
describe('can map administration role to realm-management role', () => {
it('should return true for ADMIN', () => {
expect(formService._canMapAdministrationRoleToManagementRealmRole(UserFormService.ADMIN)).toBe(true);
});
it('should return false', () => {
expect(formService._canMapAdministrationRoleToManagementRealmRole(UserFormService.USER)).toBe(false);
});
});
describe('map administration group roles to realm-management roles', () => {
beforeEach(() => {
formService._canMapAdministrationRoleToManagementRealmRole = jest.fn();
formService._mapAdministrationRoleToManagementRealmRole = jest.fn();
});
it('should check if can map', () => {
formService._mapAdministrationRolesToManagementRealmRoles([UserFormService.ADMIN]);
expect(formService._canMapAdministrationRoleToManagementRealmRole).toHaveBeenCalledWith(UserFormService.ADMIN);
});
it('should map', () => {
formService._canMapAdministrationRoleToManagementRealmRole = jest.fn().mockReturnValue(true);
formService._mapAdministrationRolesToManagementRealmRoles([UserFormService.ADMIN]);
expect(formService._mapAdministrationRoleToManagementRealmRole).toHaveBeenCalledWith(UserFormService.ADMIN);
});
it('should NOT map', () => {
formService._canMapAdministrationRoleToManagementRealmRole = jest.fn().mockReturnValue(false);
formService._mapAdministrationRolesToManagementRealmRoles([UserFormService.ADMIN]);
expect(formService._mapAdministrationRoleToManagementRealmRole).not.toHaveBeenCalled();
});
it('should return mapping result', () => {
const mappingResult: string = faker.word.noun();
formService._canMapAdministrationRoleToManagementRealmRole = jest.fn().mockReturnValue(true);
formService._mapAdministrationRoleToManagementRealmRole = jest.fn().mockReturnValue(mappingResult);
const realmManagementRoles: string[] = formService._mapAdministrationRolesToManagementRealmRoles([UserFormService.ADMIN]);
expect(realmManagementRoles).toEqual([mappingResult]);
});
});
describe('create user', () => {
beforeEach(() => {
formService._getRoles = jest.fn();
formService._getFormValue = jest.fn();
formService._mapAdministrationRolesToManagementRealmRoles = jest.fn();
formService._getActiveOrganisationsEinheiten = jest.fn();
});
it('should map administration roles to realm-management roles', () => {
formService._getRoles = jest.fn().mockReturnValue([UserFormService.ADMIN]);
formService._createUser();
expect(formService._mapAdministrationRolesToManagementRealmRoles).toHaveBeenCalledWith([UserFormService.ADMIN]);
});
it('should set realmManagement clientRoles', () => {
formService._mapAdministrationRolesToManagementRealmRoles = jest.fn().mockReturnValue([UserFormService.ADMIN]);
const user: User = formService._createUser();
expect(user.clientRoles.realmManagement).toEqual([UserFormService.ADMIN]);
});
});
});
......@@ -23,7 +23,7 @@
*/
import { AdminOrganisationsEinheit, AdminOrganisationsEinheitService } from '@admin-client/organisations-einheit-shared';
import { ROUTES } from '@admin-client/shared';
import { User, UserService } from '@admin-client/user-shared';
import { AdminRoles, User, UserService } from '@admin-client/user-shared';
import { KeycloakFormService, PatchConfig } from '@admin/keycloak-shared';
import { NavigationService } from '@alfa-client/navigation-shared';
import { createEmptyStateResource, EMPTY_STRING, isLoaded, mapToResource, StateResource } from '@alfa-client/tech-shared';
......@@ -32,7 +32,6 @@ import { Injectable, OnDestroy } from '@angular/core';
import { AbstractControl, FormControl, UntypedFormBuilder, UntypedFormGroup, ValidationErrors, ValidatorFn, Validators, } from '@angular/forms';
import { UrlSegment } from '@angular/router';
import { catchError, filter, Observable, of, Subscription, tap } from 'rxjs';
import { KeycloakDefaults } from '../../../../keycloak-shared/src/lib/keycloak.model';
@Injectable()
export class UserFormService extends KeycloakFormService<User> implements OnDestroy {
......@@ -44,7 +43,7 @@ export class UserFormService extends KeycloakFormService<User> implements OnDest
public static readonly CLIENT_ROLES: string = 'clientRoles';
public static readonly GROUPS: string = 'groups';
public static readonly ADMINISTRATION_GROUP: string = 'admin';
public static readonly ADMIN: string = 'ADMIN_ADMIN';
public static readonly ADMIN: string = AdminRoles.ADMIN;
public static readonly DATENBEAUFTRAGUNG: string = 'DATENBEAUFTRAGUNG';
public static readonly ALFA_GROUP: string = 'alfa';
public static readonly LOESCHEN: string = 'VERWALTUNG_LOESCHEN';
......@@ -234,7 +233,6 @@ export class UserFormService extends KeycloakFormService<User> implements OnDest
clientRoles: {
alfa: this._getRoles(UserFormService.ALFA_GROUP),
admin: administrationRoles,
realmManagement: this._mapAdministrationRolesToManagementRealmRoles(administrationRoles),
},
groups: this._getActiveOrganisationsEinheiten(),
};
......@@ -244,30 +242,6 @@ export class UserFormService extends KeycloakFormService<User> implements OnDest
return this.getActive(this.getRoleGroup(roleGroup));
}
_mapAdministrationRolesToManagementRealmRoles(administrationRoles: string[]): string[] {
return administrationRoles
.filter((role: string) => this._canMapAdministrationRoleToManagementRealmRole(role))
.map((role: string) => this._mapAdministrationRoleToManagementRealmRole(role));
}
_canMapAdministrationRoleToManagementRealmRole(administrationRole: string): boolean {
switch (administrationRole) {
case UserFormService.ADMIN:
return true;
default:
return false;
}
}
_mapAdministrationRoleToManagementRealmRole(administrationRole: string): string {
switch (administrationRole) {
case UserFormService.ADMIN:
return KeycloakDefaults.clients.realmManagement.roles.managerUsers.roleName;
default:
throw new Error(`Cannot map administration role ${administrationRole}. Check before if map is possible.`);
}
}
_getActiveOrganisationsEinheiten(): string[] {
return this.getActive(this.getOrganisationsEinheitenGroup());
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment