@flusys/nestjs-iam 6.0.1 → 6.1.0

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.
Files changed (60) hide show
  1. package/cjs/controllers/action.controller.js +17 -9
  2. package/cjs/controllers/action.controller.spec.js +79 -0
  3. package/cjs/controllers/company-action-permission.controller.spec.js +65 -0
  4. package/cjs/controllers/my-permission.controller.spec.js +56 -0
  5. package/cjs/controllers/role-permission.controller.spec.js +140 -0
  6. package/cjs/controllers/role.controller.spec.js +86 -0
  7. package/cjs/controllers/user-action-permission.controller.js +0 -3
  8. package/cjs/controllers/user-action-permission.controller.spec.js +68 -0
  9. package/cjs/docs/iam-swagger.config.js +6 -0
  10. package/cjs/docs/iam-swagger.config.spec.js +99 -0
  11. package/cjs/dtos/action.dto.js +17 -0
  12. package/cjs/entities/index.spec.js +56 -0
  13. package/cjs/helpers/company-access.helper.spec.js +68 -0
  14. package/cjs/helpers/permission-mode.helper.spec.js +54 -0
  15. package/cjs/modules/iam.module.js +3 -1
  16. package/cjs/modules/iam.module.spec.js +293 -0
  17. package/cjs/services/action.service.js +90 -7
  18. package/cjs/services/action.service.spec.js +314 -0
  19. package/cjs/services/iam-config.service.spec.js +110 -0
  20. package/cjs/services/iam-datasource.service.spec.js +117 -0
  21. package/cjs/services/permission-cache.service.js +113 -110
  22. package/cjs/services/permission-cache.service.spec.js +252 -0
  23. package/cjs/services/permission.service.js +213 -92
  24. package/cjs/services/permission.service.spec.js +967 -0
  25. package/cjs/services/role.service.js +47 -3
  26. package/cjs/services/role.service.spec.js +312 -0
  27. package/controllers/action.controller.d.ts +5 -3
  28. package/dtos/action.dto.d.ts +3 -0
  29. package/entities/index.d.ts +2 -2
  30. package/fesm/controllers/action.controller.js +18 -10
  31. package/fesm/controllers/action.controller.spec.js +75 -0
  32. package/fesm/controllers/company-action-permission.controller.spec.js +61 -0
  33. package/fesm/controllers/my-permission.controller.spec.js +52 -0
  34. package/fesm/controllers/role-permission.controller.spec.js +136 -0
  35. package/fesm/controllers/role.controller.spec.js +82 -0
  36. package/fesm/controllers/user-action-permission.controller.js +0 -3
  37. package/fesm/controllers/user-action-permission.controller.spec.js +64 -0
  38. package/fesm/docs/iam-swagger.config.js +6 -0
  39. package/fesm/docs/iam-swagger.config.spec.js +95 -0
  40. package/fesm/dtos/action.dto.js +14 -0
  41. package/fesm/entities/index.spec.js +52 -0
  42. package/fesm/helpers/company-access.helper.spec.js +64 -0
  43. package/fesm/helpers/permission-mode.helper.spec.js +50 -0
  44. package/fesm/modules/iam.module.js +4 -2
  45. package/fesm/modules/iam.module.spec.js +289 -0
  46. package/fesm/services/action.service.js +90 -7
  47. package/fesm/services/action.service.spec.js +310 -0
  48. package/fesm/services/iam-config.service.spec.js +106 -0
  49. package/fesm/services/iam-datasource.service.spec.js +113 -0
  50. package/fesm/services/permission-cache.service.js +101 -108
  51. package/fesm/services/permission-cache.service.spec.js +248 -0
  52. package/fesm/services/permission.service.js +213 -92
  53. package/fesm/services/permission.service.spec.js +963 -0
  54. package/fesm/services/role.service.js +48 -4
  55. package/fesm/services/role.service.spec.js +308 -0
  56. package/package.json +3 -3
  57. package/services/action.service.d.ts +7 -3
  58. package/services/permission-cache.service.d.ts +13 -19
  59. package/services/permission.service.d.ts +6 -3
  60. package/services/role.service.d.ts +7 -3
@@ -8,13 +8,14 @@ Object.defineProperty(exports, "ActionController", {
8
8
  return ActionController;
9
9
  }
10
10
  });
11
- const _guards = require("@flusys/nestjs-shared/guards");
12
11
  const _nestjsshared = require("@flusys/nestjs-shared");
13
- const _config = require("../config");
12
+ const _guards = require("@flusys/nestjs-shared/guards");
14
13
  const _common = require("@nestjs/common");
15
14
  const _swagger = require("@nestjs/swagger");
15
+ const _config = require("../config");
16
16
  const _actiondto = require("../dtos/action.dto");
17
17
  const _actionservice = require("../services/action.service");
18
+ const _iamconfigservice = require("../services/iam-config.service");
18
19
  function _define_property(obj, key, value) {
19
20
  if (key in obj) {
20
21
  Object.defineProperty(obj, key, {
@@ -89,8 +90,8 @@ let ActionController = class ActionController extends (0, _nestjsshared.createAp
89
90
  }
90
91
  }
91
92
  }) {
92
- async getActionsForPermission(user) {
93
- const actions = await this.actionService.getActionsForPermission(user);
93
+ async getActionsForPermission(dto, user) {
94
+ const actions = await this.actionService.getActionsForPermission(user, dto?.companyId);
94
95
  return {
95
96
  success: true,
96
97
  message: 'Actions retrieved successfully',
@@ -107,8 +108,8 @@ let ActionController = class ActionController extends (0, _nestjsshared.createAp
107
108
  data: tree
108
109
  };
109
110
  }
110
- constructor(actionService){
111
- super(actionService), _define_property(this, "actionService", void 0), this.actionService = actionService;
111
+ constructor(actionService, iamConfigService){
112
+ super(actionService), _define_property(this, "actionService", void 0), _define_property(this, "iamConfigService", void 0), this.actionService = actionService, this.iamConfigService = iamConfigService;
112
113
  }
113
114
  };
114
115
  _ts_decorate([
@@ -117,15 +118,20 @@ _ts_decorate([
117
118
  (0, _swagger.ApiBearerAuth)(),
118
119
  (0, _swagger.ApiOperation)({
119
120
  summary: 'Get actions for permission assignment',
120
- description: 'Returns actions available for permission assignment. If company feature enabled, filtered by company whitelist.'
121
+ description: "Returns actions available for permission assignment, filtered by company whitelist when company feature is enabled. Optional companyId scopes the whitelist to a specific company (must match the caller's own company); defaults to the caller's session company when omitted."
121
122
  }),
122
123
  (0, _swagger.ApiResponse)({
123
124
  status: 200,
124
125
  type: _nestjsshared.SingleResponseDto
125
126
  }),
126
- _ts_param(0, (0, _nestjsshared.CurrentUser)()),
127
+ (0, _swagger.ApiBody)({
128
+ type: _actiondto.ActionTreeForPermissionDto
129
+ }),
130
+ _ts_param(0, (0, _common.Body)()),
131
+ _ts_param(1, (0, _nestjsshared.CurrentUser)()),
127
132
  _ts_metadata("design:type", Function),
128
133
  _ts_metadata("design:paramtypes", [
134
+ typeof _actiondto.ActionTreeForPermissionDto === "undefined" ? Object : _actiondto.ActionTreeForPermissionDto,
129
135
  typeof _nestjsshared.ILoggedUserInfo === "undefined" ? Object : _nestjsshared.ILoggedUserInfo
130
136
  ]),
131
137
  _ts_metadata("design:returntype", Promise)
@@ -159,8 +165,10 @@ ActionController = _ts_decorate([
159
165
  (0, _swagger.ApiTags)('IAM - Actions'),
160
166
  (0, _common.Controller)('iam/actions'),
161
167
  _ts_param(0, (0, _common.Inject)(_actionservice.ActionService)),
168
+ _ts_param(1, (0, _common.Inject)(_iamconfigservice.IAMConfigService)),
162
169
  _ts_metadata("design:type", Function),
163
170
  _ts_metadata("design:paramtypes", [
164
- typeof _actionservice.ActionService === "undefined" ? Object : _actionservice.ActionService
171
+ typeof _actionservice.ActionService === "undefined" ? Object : _actionservice.ActionService,
172
+ typeof _iamconfigservice.IAMConfigService === "undefined" ? Object : _iamconfigservice.IAMConfigService
165
173
  ])
166
174
  ], ActionController);
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
6
+ const _actioncontroller = require("./action.controller");
7
+ describe('ActionController', ()=>{
8
+ let controller;
9
+ let mockActionService;
10
+ let mockIamConfigService;
11
+ beforeEach(()=>{
12
+ mockActionService = {
13
+ insert: jest.fn(),
14
+ findById: jest.fn(),
15
+ getAll: jest.fn(),
16
+ update: jest.fn(),
17
+ delete: jest.fn(),
18
+ getActionsForPermission: jest.fn(),
19
+ getActionTree: jest.fn()
20
+ };
21
+ mockIamConfigService = {};
22
+ controller = new _actioncontroller.ActionController(mockActionService, mockIamConfigService);
23
+ });
24
+ it('wires the injected service onto the generated controller base', ()=>{
25
+ expect(controller.actionService).toBe(mockActionService);
26
+ expect(controller.service).toBe(mockActionService);
27
+ });
28
+ describe('getActionsForPermission', ()=>{
29
+ it('returns actions scoped to the caller session company when no companyId is given', async ()=>{
30
+ const user = (0, _loggedusermock.buildMockUser)();
31
+ mockActionService.getActionsForPermission.mockResolvedValue([
32
+ {
33
+ id: 'action-1',
34
+ code: 'user.create'
35
+ }
36
+ ]);
37
+ const result = await controller.getActionsForPermission({}, user);
38
+ expect(mockActionService.getActionsForPermission).toHaveBeenCalledWith(user, undefined);
39
+ expect(result.success).toBe(true);
40
+ expect(result.data).toEqual([
41
+ {
42
+ id: 'action-1',
43
+ code: 'user.create'
44
+ }
45
+ ]);
46
+ });
47
+ it('forwards an explicit companyId override', async ()=>{
48
+ const user = (0, _loggedusermock.buildMockUser)();
49
+ mockActionService.getActionsForPermission.mockResolvedValue([]);
50
+ await controller.getActionsForPermission({
51
+ companyId: 'company-2'
52
+ }, user);
53
+ expect(mockActionService.getActionsForPermission).toHaveBeenCalledWith(user, 'company-2');
54
+ });
55
+ });
56
+ describe('getActionTree', ()=>{
57
+ it('returns the hierarchical action tree with query filters applied', async ()=>{
58
+ const user = (0, _loggedusermock.buildMockUser)();
59
+ mockActionService.getActionTree.mockResolvedValue([
60
+ {
61
+ id: 'action-1',
62
+ children: []
63
+ }
64
+ ]);
65
+ const result = await controller.getActionTree({
66
+ search: 'user',
67
+ isActive: true,
68
+ withDeleted: false
69
+ }, user);
70
+ expect(mockActionService.getActionTree).toHaveBeenCalledWith(user, 'user', true, false);
71
+ expect(result.data).toEqual([
72
+ {
73
+ id: 'action-1',
74
+ children: []
75
+ }
76
+ ]);
77
+ });
78
+ });
79
+ });
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _companyactionpermissioncontroller = require("./company-action-permission.controller");
6
+ describe('CompanyActionPermissionController', ()=>{
7
+ let controller;
8
+ let mockPermissionService;
9
+ beforeEach(()=>{
10
+ mockPermissionService = {
11
+ assignCompanyActions: jest.fn(),
12
+ getCompanyActions: jest.fn()
13
+ };
14
+ controller = new _companyactionpermissioncontroller.CompanyActionPermissionController(mockPermissionService);
15
+ });
16
+ describe('assignCompanyActions', ()=>{
17
+ it('whitelists actions for a company', async ()=>{
18
+ mockPermissionService.assignCompanyActions.mockResolvedValue({
19
+ added: 3,
20
+ removed: 0,
21
+ total: 3
22
+ });
23
+ const result = await controller.assignCompanyActions({
24
+ companyId: 'company-1',
25
+ actionIds: [
26
+ 'action-1',
27
+ 'action-2',
28
+ 'action-3'
29
+ ]
30
+ });
31
+ expect(mockPermissionService.assignCompanyActions).toHaveBeenCalledWith({
32
+ companyId: 'company-1',
33
+ actionIds: [
34
+ 'action-1',
35
+ 'action-2',
36
+ 'action-3'
37
+ ]
38
+ });
39
+ expect(result.success).toBe(true);
40
+ expect(result.data).toEqual({
41
+ added: 3,
42
+ removed: 0,
43
+ total: 3
44
+ });
45
+ });
46
+ });
47
+ describe('getCompanyActions', ()=>{
48
+ it('returns the whitelisted actions for a company', async ()=>{
49
+ mockPermissionService.getCompanyActions.mockResolvedValue([
50
+ {
51
+ actionId: 'action-1'
52
+ }
53
+ ]);
54
+ const result = await controller.getCompanyActions({
55
+ companyId: 'company-1'
56
+ });
57
+ expect(mockPermissionService.getCompanyActions).toHaveBeenCalledWith('company-1');
58
+ expect(result.data).toEqual([
59
+ {
60
+ actionId: 'action-1'
61
+ }
62
+ ]);
63
+ });
64
+ });
65
+ });
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
6
+ const _mypermissioncontroller = require("./my-permission.controller");
7
+ describe('MyPermissionController', ()=>{
8
+ let controller;
9
+ let mockPermissionService;
10
+ beforeEach(()=>{
11
+ mockPermissionService = {
12
+ getMyPermissions: jest.fn()
13
+ };
14
+ controller = new _mypermissioncontroller.MyPermissionController(mockPermissionService);
15
+ });
16
+ describe('getMyPermissions', ()=>{
17
+ it('resolves permissions for the current user, branch, and company', async ()=>{
18
+ const user = (0, _loggedusermock.buildMockUser)({
19
+ id: 'user-1',
20
+ companyId: 'company-1',
21
+ branchId: 'branch-1'
22
+ });
23
+ const permissions = {
24
+ menus: [],
25
+ actions: [
26
+ 'user.create'
27
+ ]
28
+ };
29
+ mockPermissionService.getMyPermissions.mockResolvedValue(permissions);
30
+ const result = await controller.getMyPermissions({
31
+ parentCodes: [
32
+ 'user'
33
+ ]
34
+ }, user);
35
+ expect(mockPermissionService.getMyPermissions).toHaveBeenCalledWith('user-1', 'branch-1', 'company-1', [
36
+ 'user'
37
+ ]);
38
+ expect(result).toEqual({
39
+ success: true,
40
+ message: 'Permissions loaded successfully',
41
+ messageKey: expect.any(String),
42
+ data: permissions
43
+ });
44
+ });
45
+ it('passes null for missing branch and company context', async ()=>{
46
+ const user = (0, _loggedusermock.buildMockUser)({
47
+ id: 'user-1',
48
+ companyId: undefined,
49
+ branchId: undefined
50
+ });
51
+ mockPermissionService.getMyPermissions.mockResolvedValue({});
52
+ await controller.getMyPermissions({}, user);
53
+ expect(mockPermissionService.getMyPermissions).toHaveBeenCalledWith('user-1', null, null, undefined);
54
+ });
55
+ });
56
+ });
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _common = require("@nestjs/common");
6
+ const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
7
+ const _rolepermissioncontroller = require("./role-permission.controller");
8
+ describe('RolePermissionController', ()=>{
9
+ let controller;
10
+ let mockPermissionService;
11
+ let mockConfig;
12
+ beforeEach(()=>{
13
+ mockPermissionService = {
14
+ assignRoleActions: jest.fn(),
15
+ getRoleActions: jest.fn(),
16
+ assignUserRoles: jest.fn(),
17
+ getUserRoles: jest.fn()
18
+ };
19
+ mockConfig = {
20
+ isCompanyFeatureEnabled: jest.fn().mockReturnValue(false)
21
+ };
22
+ controller = new _rolepermissioncontroller.RolePermissionController(mockPermissionService, mockConfig);
23
+ });
24
+ describe('assignRoleActions', ()=>{
25
+ it('assigns actions to a role and returns the operation summary', async ()=>{
26
+ mockPermissionService.assignRoleActions.mockResolvedValue({
27
+ added: 2,
28
+ removed: 1,
29
+ total: 3
30
+ });
31
+ const result = await controller.assignRoleActions({
32
+ roleId: 'role-1',
33
+ actionIds: [
34
+ 'action-1',
35
+ 'action-2'
36
+ ]
37
+ });
38
+ expect(mockPermissionService.assignRoleActions).toHaveBeenCalledWith({
39
+ roleId: 'role-1',
40
+ actionIds: [
41
+ 'action-1',
42
+ 'action-2'
43
+ ]
44
+ });
45
+ expect(result.success).toBe(true);
46
+ expect(result.data).toEqual({
47
+ added: 2,
48
+ removed: 1,
49
+ total: 3
50
+ });
51
+ });
52
+ });
53
+ describe('getRoleActions', ()=>{
54
+ it('returns actions assigned to the role', async ()=>{
55
+ mockPermissionService.getRoleActions.mockResolvedValue([
56
+ {
57
+ actionId: 'action-1'
58
+ }
59
+ ]);
60
+ const result = await controller.getRoleActions({
61
+ roleId: 'role-1'
62
+ });
63
+ expect(mockPermissionService.getRoleActions).toHaveBeenCalledWith('role-1');
64
+ expect(result.data).toEqual([
65
+ {
66
+ actionId: 'action-1'
67
+ }
68
+ ]);
69
+ });
70
+ });
71
+ describe('assignUserRoles', ()=>{
72
+ it('assigns roles to a user when the caller has access to the target company', async ()=>{
73
+ mockConfig.isCompanyFeatureEnabled.mockReturnValue(true);
74
+ const user = (0, _loggedusermock.buildMockUser)({
75
+ companyId: 'company-1'
76
+ });
77
+ mockPermissionService.assignUserRoles.mockResolvedValue({
78
+ added: 1,
79
+ removed: 0,
80
+ total: 1
81
+ });
82
+ const result = await controller.assignUserRoles({
83
+ userId: 'user-2',
84
+ roleIds: [
85
+ 'role-1'
86
+ ],
87
+ companyId: 'company-1'
88
+ }, user);
89
+ expect(mockPermissionService.assignUserRoles).toHaveBeenCalledWith({
90
+ userId: 'user-2',
91
+ roleIds: [
92
+ 'role-1'
93
+ ],
94
+ companyId: 'company-1'
95
+ });
96
+ expect(result.data).toEqual({
97
+ added: 1,
98
+ removed: 0,
99
+ total: 1
100
+ });
101
+ });
102
+ it('rejects assignment when the caller has no access to the target company', async ()=>{
103
+ mockConfig.isCompanyFeatureEnabled.mockReturnValue(true);
104
+ const user = (0, _loggedusermock.buildMockUser)({
105
+ companyId: 'company-1'
106
+ });
107
+ await expect(controller.assignUserRoles({
108
+ userId: 'user-2',
109
+ roleIds: [
110
+ 'role-1'
111
+ ],
112
+ companyId: 'company-2'
113
+ }, user)).rejects.toThrow(_common.ForbiddenException);
114
+ expect(mockPermissionService.assignUserRoles).not.toHaveBeenCalled();
115
+ });
116
+ });
117
+ describe('getUserRoles', ()=>{
118
+ it('returns roles assigned to the user scoped by branch and company', async ()=>{
119
+ const user = (0, _loggedusermock.buildMockUser)({
120
+ companyId: 'company-1'
121
+ });
122
+ mockPermissionService.getUserRoles.mockResolvedValue([
123
+ {
124
+ roleId: 'role-1'
125
+ }
126
+ ]);
127
+ const result = await controller.getUserRoles({
128
+ userId: 'user-2',
129
+ branchId: 'branch-1',
130
+ companyId: 'company-1'
131
+ }, user);
132
+ expect(mockPermissionService.getUserRoles).toHaveBeenCalledWith('user-2', 'branch-1', 'company-1');
133
+ expect(result.data).toEqual([
134
+ {
135
+ roleId: 'role-1'
136
+ }
137
+ ]);
138
+ });
139
+ });
140
+ });
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
6
+ const _rolecontroller = require("./role.controller");
7
+ function buildRole(overrides = {}) {
8
+ return {
9
+ id: 'role-1',
10
+ name: 'Admin',
11
+ description: null,
12
+ isActive: true,
13
+ readOnly: false,
14
+ createdAt: new Date(),
15
+ updatedAt: new Date(),
16
+ ...overrides
17
+ };
18
+ }
19
+ describe('RoleController', ()=>{
20
+ let controller;
21
+ let mockRoleService;
22
+ beforeEach(()=>{
23
+ mockRoleService = {
24
+ insert: jest.fn(),
25
+ findById: jest.fn(),
26
+ getAll: jest.fn(),
27
+ update: jest.fn(),
28
+ delete: jest.fn()
29
+ };
30
+ controller = new _rolecontroller.RoleController(mockRoleService);
31
+ });
32
+ it('wires the injected service onto the generated controller base', ()=>{
33
+ expect(controller.roleService).toBe(mockRoleService);
34
+ expect(controller.service).toBe(mockRoleService);
35
+ });
36
+ describe('insert', ()=>{
37
+ it('creates a role and returns the mapped response', async ()=>{
38
+ const user = (0, _loggedusermock.buildMockUser)();
39
+ mockRoleService.insert.mockResolvedValue(buildRole());
40
+ const result = await controller.insert({
41
+ name: 'Admin'
42
+ }, user);
43
+ expect(mockRoleService.insert).toHaveBeenCalledWith({
44
+ name: 'Admin'
45
+ }, user);
46
+ expect(result.success).toBe(true);
47
+ expect(result.data).toEqual(expect.objectContaining({
48
+ id: 'role-1',
49
+ name: 'Admin'
50
+ }));
51
+ });
52
+ });
53
+ describe('getAll', ()=>{
54
+ it('paginates roles and maps the response list', async ()=>{
55
+ mockRoleService.getAll.mockResolvedValue({
56
+ data: [
57
+ buildRole()
58
+ ],
59
+ total: 1
60
+ });
61
+ const result = await controller.getAll({}, (0, _loggedusermock.buildMockUser)(), '');
62
+ expect(mockRoleService.getAll).toHaveBeenCalledWith('', {}, (0, _loggedusermock.buildMockUser)());
63
+ expect(result.data).toHaveLength(1);
64
+ });
65
+ });
66
+ describe('delete', ()=>{
67
+ it('delegates soft-delete to the service', async ()=>{
68
+ mockRoleService.delete.mockResolvedValue({
69
+ count: 1
70
+ });
71
+ const result = await controller.delete({
72
+ id: [
73
+ 'role-1'
74
+ ],
75
+ type: 'delete'
76
+ }, (0, _loggedusermock.buildMockUser)());
77
+ expect(mockRoleService.delete).toHaveBeenCalledWith({
78
+ id: [
79
+ 'role-1'
80
+ ],
81
+ type: 'delete'
82
+ }, (0, _loggedusermock.buildMockUser)());
83
+ expect(result.success).toBe(true);
84
+ });
85
+ });
86
+ });
@@ -13,7 +13,6 @@ const _common = require("@nestjs/common");
13
13
  const _swagger = require("@nestjs/swagger");
14
14
  const _config = require("../config");
15
15
  const _permissiondto = require("../dtos/permission.dto");
16
- const _helpers = require("../helpers");
17
16
  const _iamconfigservice = require("../services/iam-config.service");
18
17
  const _permissionservice = require("../services/permission.service");
19
18
  function _define_property(obj, key, value) {
@@ -45,7 +44,6 @@ function _ts_param(paramIndex, decorator) {
45
44
  }
46
45
  let UserActionPermissionController = class UserActionPermissionController {
47
46
  async assignUserActions(dto, user) {
48
- (0, _helpers.validateCompanyAccess)(this.config, dto.companyId, user);
49
47
  const result = await this.permissionService.assignUserActions(dto);
50
48
  return {
51
49
  success: true,
@@ -60,7 +58,6 @@ let UserActionPermissionController = class UserActionPermissionController {
60
58
  };
61
59
  }
62
60
  async getUserActions(dto, user) {
63
- (0, _helpers.validateCompanyAccess)(this.config, dto.companyId, user);
64
61
  const actions = await this.permissionService.getUserActions(dto.userId, dto.branchId, dto.companyId);
65
62
  return {
66
63
  success: true,
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", {
3
+ value: true
4
+ });
5
+ const _loggedusermock = require("@test-utils/mocks/logged-user.mock");
6
+ const _useractionpermissioncontroller = require("./user-action-permission.controller");
7
+ describe('UserActionPermissionController', ()=>{
8
+ let controller;
9
+ let mockPermissionService;
10
+ let mockConfig;
11
+ beforeEach(()=>{
12
+ mockPermissionService = {
13
+ assignUserActions: jest.fn(),
14
+ getUserActions: jest.fn()
15
+ };
16
+ mockConfig = {};
17
+ controller = new _useractionpermissioncontroller.UserActionPermissionController(mockPermissionService, mockConfig);
18
+ });
19
+ describe('assignUserActions', ()=>{
20
+ it('assigns direct action permissions to a user', async ()=>{
21
+ const user = (0, _loggedusermock.buildMockUser)();
22
+ mockPermissionService.assignUserActions.mockResolvedValue({
23
+ added: 1,
24
+ removed: 0,
25
+ total: 1
26
+ });
27
+ const result = await controller.assignUserActions({
28
+ userId: 'user-2',
29
+ actionIds: [
30
+ 'action-1'
31
+ ]
32
+ }, user);
33
+ expect(mockPermissionService.assignUserActions).toHaveBeenCalledWith({
34
+ userId: 'user-2',
35
+ actionIds: [
36
+ 'action-1'
37
+ ]
38
+ });
39
+ expect(result.success).toBe(true);
40
+ expect(result.data).toEqual({
41
+ added: 1,
42
+ removed: 0,
43
+ total: 1
44
+ });
45
+ });
46
+ });
47
+ describe('getUserActions', ()=>{
48
+ it('returns direct action permissions for a user scoped by branch/company', async ()=>{
49
+ const user = (0, _loggedusermock.buildMockUser)();
50
+ mockPermissionService.getUserActions.mockResolvedValue([
51
+ {
52
+ actionId: 'action-1'
53
+ }
54
+ ]);
55
+ const result = await controller.getUserActions({
56
+ userId: 'user-2',
57
+ branchId: 'branch-1',
58
+ companyId: 'company-1'
59
+ }, user);
60
+ expect(mockPermissionService.getUserActions).toHaveBeenCalledWith('user-2', 'branch-1', 'company-1');
61
+ expect(result.data).toEqual([
62
+ {
63
+ actionId: 'action-1'
64
+ }
65
+ ]);
66
+ });
67
+ });
68
+ });
@@ -49,6 +49,12 @@ function iamSwaggerConfig(enableCompanyFeature = false, permissionMode = _permis
49
49
  'branchId'
50
50
  ]
51
51
  },
52
+ {
53
+ schemaName: 'ActionTreeForPermissionDto',
54
+ properties: [
55
+ 'companyId'
56
+ ]
57
+ },
52
58
  // Response DTOs with branchId
53
59
  {
54
60
  schemaName: 'UserActionResponseDto',