@escapenavigator/utils 2.2.0 → 2.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,6 +9,12 @@ export declare const createFullEmployeeAccess: () => EmployeeAccess;
9
9
  * granular editor yet. No existing role is migrated or silently restricted.
10
10
  */
11
11
  export declare const deriveLegacyEmployeeAccess: (role?: LegacyEmployeeAccessRole | null) => EmployeeAccess;
12
+ /**
13
+ * Form values must always have every section. A stored object with no sections
14
+ * (legacy null, or a nested DTO stripped by serialization) keeps the fallback.
15
+ * A partial object keeps what was saved and denies only the missing sections.
16
+ */
17
+ export declare const completeEmployeeAccess: (access: Partial<EmployeeAccess> | null | undefined, fallback: EmployeeAccess) => EmployeeAccess;
12
18
  export declare const resolveEmployeeAccess: (role?: LegacyEmployeeAccessRole | null) => EmployeeAccess;
13
19
  export declare const hasEmployeeAccess: (role: LegacyEmployeeAccessRole | null | undefined, section: EmployeeAccessSection, action: EmployeeAccessAction) => boolean;
14
20
  export declare const getEmployeeAccessScope: (role: LegacyEmployeeAccessRole | null | undefined, section: "shifts" | "bonuses" | "fines" | "payroll") => EmployeeAccessScope;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.canAssignEmployeeRoles = exports.canManageEmployeeAccess = exports.getEmployeeAccessScope = exports.hasEmployeeAccess = exports.resolveEmployeeAccess = exports.deriveLegacyEmployeeAccess = exports.createFullEmployeeAccess = void 0;
3
+ exports.canAssignEmployeeRoles = exports.canManageEmployeeAccess = exports.getEmployeeAccessScope = exports.hasEmployeeAccess = exports.resolveEmployeeAccess = exports.completeEmployeeAccess = exports.deriveLegacyEmployeeAccess = exports.createFullEmployeeAccess = void 0;
4
4
  const employee_access_1 = require("@escapenavigator/types/dist/role/employee-access");
5
5
  const crud = (view, create = view, edit = create, remove = edit) => ({
6
6
  view,
@@ -42,9 +42,7 @@ const deriveLegacyEmployeeAccess = (role) => {
42
42
  ...crud(usersBase, manageAccess, editOthers, manageAccess && editOthers),
43
43
  manageAccess,
44
44
  },
45
- shifts: scoped(crud(usersBase || ownShifts, manageShifts || ownShifts, manageShifts || ownShifts), usersBase || manageShifts
46
- ? employee_access_1.EmployeeAccessScope.ALL
47
- : employee_access_1.EmployeeAccessScope.SELF),
45
+ shifts: scoped(crud(usersBase || ownShifts, manageShifts || ownShifts, manageShifts || ownShifts), usersBase || manageShifts ? employee_access_1.EmployeeAccessScope.ALL : employee_access_1.EmployeeAccessScope.SELF),
48
46
  bonuses: scoped(crud(manageAdjustments), employee_access_1.EmployeeAccessScope.ALL),
49
47
  fines: scoped(crud(manageAdjustments), employee_access_1.EmployeeAccessScope.ALL),
50
48
  roles: crud(false),
@@ -54,6 +52,39 @@ const deriveLegacyEmployeeAccess = (role) => {
54
52
  };
55
53
  };
56
54
  exports.deriveLegacyEmployeeAccess = deriveLegacyEmployeeAccess;
55
+ const deniedCrud = () => crud(false);
56
+ const deniedScoped = () => scoped(deniedCrud(), employee_access_1.EmployeeAccessScope.SELF);
57
+ const EMPLOYEE_ACCESS_SECTIONS = [
58
+ 'employees',
59
+ 'shifts',
60
+ 'bonuses',
61
+ 'fines',
62
+ 'roles',
63
+ 'positions',
64
+ 'reports',
65
+ 'payroll',
66
+ ];
67
+ /**
68
+ * Form values must always have every section. A stored object with no sections
69
+ * (legacy null, or a nested DTO stripped by serialization) keeps the fallback.
70
+ * A partial object keeps what was saved and denies only the missing sections.
71
+ */
72
+ const completeEmployeeAccess = (access, fallback) => {
73
+ const hasSection = !!access && EMPLOYEE_ACCESS_SECTIONS.some((section) => access[section] != null);
74
+ if (!hasSection)
75
+ return fallback;
76
+ return {
77
+ employees: access.employees ?? { ...deniedCrud(), manageAccess: false },
78
+ shifts: access.shifts ?? deniedScoped(),
79
+ bonuses: access.bonuses ?? deniedScoped(),
80
+ fines: access.fines ?? deniedScoped(),
81
+ roles: access.roles ?? deniedCrud(),
82
+ positions: access.positions ?? deniedCrud(),
83
+ reports: access.reports ?? deniedCrud(),
84
+ payroll: access.payroll ?? deniedScoped(),
85
+ };
86
+ };
87
+ exports.completeEmployeeAccess = completeEmployeeAccess;
57
88
  const resolveEmployeeAccess = (role) => role?.totalAccess
58
89
  ? (0, exports.createFullEmployeeAccess)()
59
90
  : role?.employeeAccess || (0, exports.deriveLegacyEmployeeAccess)(role);
@@ -53,4 +53,24 @@ describe('employee access permissions', () => {
53
53
  expect(permissions.payroll.scope).toBe(employee_access_1.EmployeeAccessScope.ALL);
54
54
  expect(permissions.reports.create).toBe(false);
55
55
  });
56
+ it('keeps a legacy fallback when stored access has no sections', () => {
57
+ const fallback = (0, employee_access_permissions_1.deriveLegacyEmployeeAccess)(role({ canEditUsersAccessAndTime: true }));
58
+ expect((0, employee_access_permissions_1.completeEmployeeAccess)(null, fallback)).toBe(fallback);
59
+ expect((0, employee_access_permissions_1.completeEmployeeAccess)({}, fallback).employees.view).toBe(true);
60
+ });
61
+ it('fills only the sections missing from a partial access object', () => {
62
+ const fallback = (0, employee_access_permissions_1.deriveLegacyEmployeeAccess)(role({ canEditUsersAccessAndTime: true }));
63
+ const access = (0, employee_access_permissions_1.completeEmployeeAccess)({
64
+ employees: {
65
+ view: true,
66
+ create: false,
67
+ edit: false,
68
+ delete: false,
69
+ manageAccess: false,
70
+ },
71
+ }, fallback);
72
+ expect(access.employees.create).toBe(false);
73
+ expect(access.payroll.view).toBe(false);
74
+ expect(access.payroll.scope).toBe(employee_access_1.EmployeeAccessScope.SELF);
75
+ });
56
76
  });
@@ -0,0 +1 @@
1
+ import 'reflect-metadata';
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ require("reflect-metadata");
4
+ const create_role_dto_1 = require("@escapenavigator/types/dist/role/create-role.dto");
5
+ const employee_access_1 = require("@escapenavigator/types/dist/role/employee-access");
6
+ const serialize_record_1 = require("./serialize-record");
7
+ describe('CreateRoleDto employeeAccess', () => {
8
+ it('сохраняет вложенные права при сборке формы роли', () => {
9
+ const dto = (0, serialize_record_1.serializeRecord)(create_role_dto_1.CreateRoleDto, {
10
+ title: 'Администратор',
11
+ totalAccess: false,
12
+ employeeAccess: {
13
+ employees: {
14
+ view: true,
15
+ create: false,
16
+ edit: true,
17
+ delete: false,
18
+ manageAccess: true,
19
+ },
20
+ shifts: {
21
+ view: true,
22
+ create: false,
23
+ edit: false,
24
+ delete: false,
25
+ scope: employee_access_1.EmployeeAccessScope.ALL,
26
+ },
27
+ bonuses: {
28
+ view: false,
29
+ create: false,
30
+ edit: false,
31
+ delete: false,
32
+ scope: employee_access_1.EmployeeAccessScope.SELF,
33
+ },
34
+ fines: {
35
+ view: false,
36
+ create: false,
37
+ edit: false,
38
+ delete: false,
39
+ scope: employee_access_1.EmployeeAccessScope.SELF,
40
+ },
41
+ roles: { view: true, create: false, edit: false, delete: false },
42
+ positions: { view: true, create: true, edit: false, delete: false },
43
+ reports: { view: true, create: false, edit: false, delete: false },
44
+ payroll: {
45
+ view: true,
46
+ create: false,
47
+ edit: false,
48
+ delete: false,
49
+ scope: employee_access_1.EmployeeAccessScope.ASSIGNED_LOCATIONS,
50
+ },
51
+ },
52
+ });
53
+ expect(dto.employeeAccess?.employees.view).toBe(true);
54
+ expect(dto.employeeAccess?.employees.manageAccess).toBe(true);
55
+ expect(dto.employeeAccess?.shifts.scope).toBe(employee_access_1.EmployeeAccessScope.ALL);
56
+ expect(dto.employeeAccess?.payroll.view).toBe(true);
57
+ expect(dto.employeeAccess?.roles.view).toBe(true);
58
+ });
59
+ });
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const user_session_permissions_1 = require("./user-session-permissions");
4
3
  const employee_access_permissions_1 = require("./employee-access-permissions");
4
+ const user_session_permissions_1 = require("./user-session-permissions");
5
5
  const openSession = {
6
6
  hold: false,
7
7
  userId: null,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@escapenavigator/utils",
3
- "version": "2.2.0",
3
+ "version": "2.2.2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -14,7 +14,7 @@
14
14
  "test": "jest"
15
15
  },
16
16
  "dependencies": {
17
- "@escapenavigator/types": "^2.2.0",
17
+ "@escapenavigator/types": "^2.2.2",
18
18
  "axios": "^0.21.4",
19
19
  "class-transformer": "^0.5.1",
20
20
  "class-validator": "^0.13.2",
@@ -29,5 +29,5 @@
29
29
  "ts-jest": "^29.1.1",
30
30
  "typescript": "^5.6"
31
31
  },
32
- "gitHead": "63060e4187f812e4c4e86d4211cfcc1b2e117a76"
32
+ "gitHead": "18385cda4cb9e0a5a0a1490c9d3374b76f047b9f"
33
33
  }