Skip to content

Commit 60b657b

Browse files
authored
Merge pull request #117 from netgrif/release/6.2.2
Release 6.2.2
2 parents a2347a7 + 563d55e commit 60b657b

File tree

26 files changed

+492
-57
lines changed

26 files changed

+492
-57
lines changed

CHANGELOG.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,21 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres
66
to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
Full Changelog: [https://github.com/netgrif/components/commits/v6.2.1](https://github.com/netgrif/components/commits/v6.2.1)
8+
Full Changelog: [https://github.com/netgrif/components/commits/v6.2.2](https://github.com/netgrif/components/commits/v6.2.2)
9+
10+
## [6.2.2](https://github.com/netgrif/components/releases/tag/v6.2.2) (2022-09-28)
11+
12+
### Fixed
13+
14+
- [NAE-1693] TaskController deleteFile endpoint lacks data about tasks
15+
- [NAE-1712] Advanced search in case of date operators is blinking (very quickly opening and closing)
16+
- [NAE-1713] Advanced search searching based on case data does not work
17+
- [NAE-1715] Currency component not working properly
18+
- [NAE-1716] Autocomplete component not working properly on enumration_map field
19+
- [NAE-1717] Banned roles not hiding menu entries
20+
- [NAE-1721] Create case event bad handling on frontend
21+
- [NAE-1724] Incorrect german translation
22+
923

1024
## [6.2.1](https://github.com/netgrif/components/releases/tag/v6.2.1) (2022-09-15)
1125

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@netgrif/components-project",
3-
"version": "6.2.1",
3+
"version": "6.2.2-rc.1",
44
"description": "Netgrif Application Engine Frontend project. Project includes angular libraries as base for NAE applications.",
55
"homepage": "https://components.netgrif.com",
66
"license": "SEE LICENSE IN LICENSE",

projects/netgrif-components-core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@netgrif/components-core",
3-
"version": "6.2.1",
3+
"version": "6.2.2-rc.1",
44
"description": "Netgrif Application engine frontend core Angular library",
55
"homepage": "https://components.netgrif.com",
66
"license": "SEE LICENSE IN LICENSE",

projects/netgrif-components-core/src/assets/i18n/de.json

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,15 @@
8787
"errThird": "Sie müssen eine Farbe auswählen.",
8888
"noNets": "Es gibt keine erlaubte Netze",
8989
"createCase": "Neuen Fall würde erfolgreich erzeugt",
90-
"defaultCaseName": "mit einem Standardfallnamen"
90+
"defaultCaseName": "mit einem Standardfallnamen",
91+
"createCaseError": "Neuer Fall wurde erstellt, aber beim Ausführen von Aktionen ist ein Fehler aufgetreten"
9192
},
9293
"user": {
93-
"assign": "Benützer zuweisen",
94-
"choose": "Benützer auswählen",
95-
"noUser": "Es gibt keine Benützer",
96-
"err": "Beim laden der Benützer ist eine Fehler aufgetreten",
97-
"showcase": "Benützeransichtmodus ist nicht ausgewählt!"
94+
"assign": "Benutzer zuweisen",
95+
"choose": "Benutzer auswählen",
96+
"noUser": "Es gibt keine Benutzer",
97+
"err": "Beim laden der Benutzer ist eine Fehler aufgetreten",
98+
"showcase": "Die Benutzeransicht ist nicht gesetzt!"
9899
},
99100
"ldapGroup": {
100101
"choose": "LDAP-Gruppe suchen",
@@ -288,8 +289,8 @@
288289
"enterEmail": "Ihre E-Mail Adresse eingeben"
289290
},
290291
"login": {
291-
"length": "Das Benützername muss mindestens 4 Zeichen enthalten",
292-
"login": "Benützername",
292+
"length": "Das Benutzername muss mindestens 4 Zeichen enthalten",
293+
"login": "Benutzername",
293294
"wrongCredentials": "Falsche Anmeldeinformationen!",
294295
"loginButton": "Anmelden",
295296
"reset": "Kennwort wiederherstellen",

projects/netgrif-components-core/src/assets/i18n/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@
8787
"errThird": "Color is required.",
8888
"noNets": "No allowed Nets",
8989
"createCase": "Successful create new case",
90-
"defaultCaseName": "with default case name"
90+
"defaultCaseName": "with default case name",
91+
"createCaseError": "A new case was created, but an error occurred while executing actions"
9192
},
9293
"user": {
9394
"assign": "User Assign",

projects/netgrif-components-core/src/assets/i18n/sk.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@
8787
"errThird": "Farba je povinné pole.",
8888
"noNets": "Žiadne povolené siete",
8989
"createCase": "Úspešne vytvorený nový prípad",
90-
"defaultCaseName": "s prednastaveným názvom prípadu"
90+
"defaultCaseName": "s prednastaveným názvom prípadu",
91+
"createCaseError": "Nový prípad vytvorený, nastala však chyba pri vykonávaní akcií"
9192
},
9293
"user": {
9394
"assign": "Priradiť používateľa",

projects/netgrif-components-core/src/commons/schema.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ export interface Access {
245245
* For `string` values the format is: <net import id>.<role name>
246246
*/
247247
role?: Array<string> | string | RoleAccess | Array<RoleAccess>;
248+
bannedRole?: Array<string> | string | RoleAccess | Array<RoleAccess>;
248249
group?: Array<string> | string;
249250
authority?: Array<string> | string;
250251

projects/netgrif-components-core/src/lib/authorization/permission/access.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export class AccessService {
5656
* @returns whether the user passes the role guard condition for accessing the specified view
5757
*/
5858
public passesRoleGuard(view: View, url: string): boolean {
59-
return !view.access.hasOwnProperty('role') || this._roleGuard.canAccessView(view, url);
59+
return (!view.access.hasOwnProperty('role') && !view.access.hasOwnProperty('bannedRole')) || this._roleGuard.canAccessView(view, url);
6060
}
6161

6262
/**
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import {TestBed} from '@angular/core/testing';
2+
3+
import {MaterialModule} from "../../material/material.module";
4+
import {CommonModule} from "@angular/common";
5+
import {FlexModule} from "@angular/flex-layout";
6+
import {BrowserAnimationsModule, NoopAnimationsModule} from "@angular/platform-browser/animations";
7+
import {TranslateLibModule} from "../../translate/translate-lib.module";
8+
import {HttpClientTestingModule} from "@angular/common/http/testing";
9+
import {UserService} from "../../user/services/user.service";
10+
import {MockUserService} from "../../utility/tests/mocks/mock-user.service";
11+
import { Injectable, NO_ERRORS_SCHEMA } from '@angular/core';
12+
import {ConfigurationService} from "../../configuration/configuration.service";
13+
import {TestConfigurationService} from "../../utility/tests/test-config";
14+
import {AuthenticationModule} from "../../authentication/authentication.module";
15+
import {RouterTestingModule} from "@angular/router/testing";
16+
import { RoleGuardService } from './role-guard.service';
17+
import { Access, View } from '../../../commons/schema';
18+
import { User } from '../../user/models/user';
19+
20+
describe('RoleGuardService', () => {
21+
let service: RoleGuardService;
22+
23+
beforeEach(() => {
24+
TestBed.configureTestingModule({
25+
imports: [
26+
MaterialModule,
27+
CommonModule,
28+
FlexModule,
29+
NoopAnimationsModule,
30+
BrowserAnimationsModule,
31+
TranslateLibModule,
32+
HttpClientTestingModule,
33+
AuthenticationModule,
34+
RouterTestingModule.withRoutes([]),
35+
],
36+
providers: [
37+
RoleGuardService,
38+
{provide: ConfigurationService, useClass: TestConfigurationService},
39+
{provide: UserService, useClass: CustomMockUserService},
40+
],
41+
declarations: [],
42+
schemas: [NO_ERRORS_SCHEMA]
43+
});
44+
service = TestBed.inject(RoleGuardService);
45+
});
46+
47+
it('should be created', () => {
48+
expect(service).toBeTruthy();
49+
});
50+
51+
it('should access view with role only', () => {
52+
const view = {access: {role: ['test.role_user']} as Access} as View
53+
expect(service.canAccessView(view, 'test')).toBeTrue();
54+
});
55+
56+
it('should not access view', () => {
57+
const view = {access: {role: [], bannedRole: []} as Access} as View
58+
expect(service.canAccessView(view, 'test')).toBeFalse();
59+
});
60+
61+
it('should not access view with banned role only', () => {
62+
const view = {access: {bannedRole: ['test.banned_role']} as Access} as View
63+
expect(service.canAccessView(view, 'test')).toBeFalse();
64+
});
65+
66+
it('should not access view with role and banned role', () => {
67+
const view = {access: {role: ['test.role_user'], bannedRole: ['test.banned_role']} as Access} as View
68+
expect(service.canAccessView(view, 'test')).toBeFalse();
69+
});
70+
});
71+
72+
@Injectable()
73+
class CustomMockUserService extends MockUserService {
74+
constructor() {
75+
super();
76+
this._user = new User('123', 'test@netgrif.com', 'Test', 'User', ['ROLE_USER'], [{
77+
stringId: 'role_user',
78+
name: 'role_user',
79+
description: '',
80+
importId: 'role_user',
81+
netImportId: 'test',
82+
netVersion: '1.0.0',
83+
netStringId: 'test',
84+
},{
85+
stringId: 'banned_role',
86+
name: 'banned_role',
87+
description: '',
88+
importId: 'banned_role',
89+
netImportId: 'test',
90+
netVersion: '1.0.0',
91+
netStringId: 'test',
92+
} ]);
93+
}
94+
}

projects/netgrif-components-core/src/lib/authorization/role/role-guard.service.ts

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,29 +37,51 @@ export class RoleGuardService implements CanActivate {
3737
}
3838

3939
public canAccessView(view: View, url: string): boolean {
40-
if (typeof view.access !== 'string' && view.access.hasOwnProperty('role')) {
41-
const allowedRoles = this.parseRoleConstraints(view.access.role, url);
42-
43-
return allowedRoles.some(constraint => {
44-
if (constraint.roleIdentifier) {
45-
return this._userService.hasRoleByIdentifier(constraint.roleIdentifier, constraint.processIdentifier);
46-
} else {
47-
return this._userService.hasRoleByName(constraint.roleName, constraint.processIdentifier);
40+
if (typeof view.access !== 'string' && (view.access.hasOwnProperty('role') || view.access.hasOwnProperty('bannedRole'))) {
41+
42+
if (view.access.hasOwnProperty('role') && view.access.hasOwnProperty('bannedRole')) {
43+
const bannedRoles = this.parseRoleConstraints(view.access.bannedRole, url);
44+
const allowedRoles = this.parseRoleConstraints(view.access.role, url);
45+
46+
if (bannedRoles.some(role => this.decideAccessByRole(role))) {
47+
return false;
48+
}
49+
50+
if (allowedRoles.length === 0) {
51+
this._log.warn(`View at '${url}' defines role access constraint with an empty array!`
52+
+ ` No users will be allowed to enter this view!`);
4853
}
49-
});
54+
return allowedRoles.some(role => this.decideAccessByRole(role)); // user was not denied access by a banned role, they need at least one allowed role
55+
}
56+
57+
if (view.access.hasOwnProperty('bannedRole')) {
58+
const bannedRoles = this.parseRoleConstraints(view.access.bannedRole, url);
59+
return !bannedRoles.some(constraint => {
60+
return this.decideAccessByRole(constraint);
61+
});
62+
}
63+
64+
if (view.access.hasOwnProperty('role')) {
65+
const allowedRoles = this.parseRoleConstraints(view.access.role, url);
66+
if (allowedRoles.length === 0) {
67+
this._log.warn(`View at '${url}' defines role access constraint with an empty array!`
68+
+ ` No users will be allowed to enter this view!`);
69+
}
70+
return allowedRoles.some(constraint => {
71+
return this.decideAccessByRole(constraint);
72+
});
73+
}
5074
}
5175
throw new Error('Role guard is declared for a view with no role guard configuration!'
5276
+ ` Add role guard configuration for view at ${url}, or remove the guard.`);
5377
}
5478

55-
protected parseRoleConstraints(roleConstrains: Access['role'], viewUrl: string): Array<RoleConstraint> {
79+
protected parseRoleConstraints(roleConstrains: Access['role'] | Access['bannedRole'], viewUrl: string): Array<RoleConstraint> {
5680
if (typeof roleConstrains === 'string') {
5781
return this.parseStringRoleConstraints(roleConstrains);
5882
}
5983
if (Array.isArray(roleConstrains)) {
6084
if (roleConstrains.length === 0) {
61-
this._log.warn(`View at '${viewUrl}' defines role access constraint with an empty array!`
62-
+ ` No users will be allowed to enter this view!`);
6385
return [];
6486
}
6587
if (typeof roleConstrains[0] === 'string') {
@@ -102,4 +124,12 @@ export class RoleGuardService implements CanActivate {
102124
});
103125
}
104126

127+
private decideAccessByRole(constraint: RoleConstraint): boolean {
128+
if (constraint.roleIdentifier) {
129+
return this._userService.hasRoleByIdentifier(constraint.roleIdentifier, constraint.processIdentifier);
130+
} else {
131+
return this._userService.hasRoleByName(constraint.roleName, constraint.processIdentifier);
132+
}
133+
}
134+
105135
}

0 commit comments

Comments
 (0)