@flusys/nestjs-form-builder 7.1.0 → 8.0.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 (118) hide show
  1. package/config/index.d.ts +3 -3
  2. package/controllers/form-result.controller.d.ts +3 -3
  3. package/controllers/form.controller.d.ts +3 -3
  4. package/controllers/index.d.ts +2 -2
  5. package/docs/form-builder-swagger.config.d.ts +2 -2
  6. package/docs/index.d.ts +1 -1
  7. package/dtos/form.dto.d.ts +1 -1
  8. package/dtos/index.d.ts +2 -2
  9. package/entities/form-with-company.entity.d.ts +1 -1
  10. package/entities/form.entity.d.ts +1 -1
  11. package/entities/index.d.ts +7 -7
  12. package/enums/index.d.ts +1 -1
  13. package/fesm/262.js +1841 -0
  14. package/fesm/98.js +807 -0
  15. package/fesm/config/index.js +98 -3
  16. package/fesm/controllers/index.js +14 -2
  17. package/fesm/docs/index.js +171 -1
  18. package/fesm/dtos/index.js +571 -2
  19. package/fesm/entities/index.js +342 -10
  20. package/fesm/enums/index.js +38 -1
  21. package/fesm/index.js +482 -10
  22. package/fesm/interfaces/index.js +17 -3
  23. package/fesm/modules/index.js +178 -1
  24. package/fesm/runtime.js +85 -0
  25. package/fesm/services/index.js +35 -4
  26. package/index.d.ts +10 -10
  27. package/interfaces/form-builder-module.interface.d.ts +3 -3
  28. package/interfaces/form-result.interface.d.ts +1 -1
  29. package/interfaces/form.interface.d.ts +2 -2
  30. package/interfaces/index.d.ts +3 -3
  31. package/modules/form-builder.module.d.ts +2 -2
  32. package/modules/index.d.ts +1 -1
  33. package/package.json +26 -36
  34. package/services/form-builder-config.service.d.ts +4 -4
  35. package/services/form-builder-datasource.provider.d.ts +3 -3
  36. package/services/form-result.service.d.ts +6 -6
  37. package/services/form.service.d.ts +7 -7
  38. package/services/index.d.ts +4 -4
  39. package/utils/index.d.ts +2 -2
  40. package/utils/permission.utils.d.ts +1 -1
  41. package/cjs/config/event-actions.js +0 -33
  42. package/cjs/config/form-builder.constants.js +0 -13
  43. package/cjs/config/index.js +0 -20
  44. package/cjs/config/message-keys.js +0 -38
  45. package/cjs/controllers/form-result.controller.js +0 -281
  46. package/cjs/controllers/form-result.controller.spec.js +0 -257
  47. package/cjs/controllers/form.controller.js +0 -231
  48. package/cjs/controllers/form.controller.spec.js +0 -212
  49. package/cjs/controllers/index.js +0 -19
  50. package/cjs/docs/form-builder-swagger.config.js +0 -150
  51. package/cjs/docs/form-builder-swagger.config.spec.js +0 -75
  52. package/cjs/docs/index.js +0 -11
  53. package/cjs/dtos/form-result.dto.js +0 -248
  54. package/cjs/dtos/form.dto.js +0 -270
  55. package/cjs/dtos/index.js +0 -19
  56. package/cjs/entities/form-result.entity.js +0 -100
  57. package/cjs/entities/form-with-company.entity.js +0 -65
  58. package/cjs/entities/form.entity.js +0 -127
  59. package/cjs/entities/index.js +0 -52
  60. package/cjs/entities/index.spec.js +0 -18
  61. package/cjs/enums/form-access-type.enum.js +0 -19
  62. package/cjs/enums/index.js +0 -18
  63. package/cjs/index.js +0 -28
  64. package/cjs/interfaces/form-builder-module.interface.js +0 -4
  65. package/cjs/interfaces/form-result.interface.js +0 -4
  66. package/cjs/interfaces/form.interface.js +0 -4
  67. package/cjs/interfaces/index.js +0 -20
  68. package/cjs/modules/form-builder.module.js +0 -136
  69. package/cjs/modules/form-builder.module.spec.js +0 -133
  70. package/cjs/modules/index.js +0 -18
  71. package/cjs/services/form-builder-config.service.js +0 -69
  72. package/cjs/services/form-builder-config.service.spec.js +0 -121
  73. package/cjs/services/form-builder-datasource.provider.js +0 -125
  74. package/cjs/services/form-builder-datasource.provider.spec.js +0 -147
  75. package/cjs/services/form-result.service.js +0 -366
  76. package/cjs/services/form-result.service.spec.js +0 -823
  77. package/cjs/services/form.service.js +0 -341
  78. package/cjs/services/form.service.spec.js +0 -746
  79. package/cjs/services/index.js +0 -21
  80. package/cjs/utils/computed-field.utils.js +0 -199
  81. package/cjs/utils/computed-field.utils.spec.js +0 -1205
  82. package/cjs/utils/index.js +0 -19
  83. package/cjs/utils/permission.utils.js +0 -44
  84. package/cjs/utils/permission.utils.spec.js +0 -118
  85. package/fesm/config/event-actions.js +0 -12
  86. package/fesm/config/form-builder.constants.js +0 -3
  87. package/fesm/config/message-keys.js +0 -20
  88. package/fesm/controllers/form-result.controller.js +0 -271
  89. package/fesm/controllers/form-result.controller.spec.js +0 -253
  90. package/fesm/controllers/form.controller.js +0 -221
  91. package/fesm/controllers/form.controller.spec.js +0 -208
  92. package/fesm/docs/form-builder-swagger.config.js +0 -146
  93. package/fesm/docs/form-builder-swagger.config.spec.js +0 -71
  94. package/fesm/dtos/form-result.dto.js +0 -215
  95. package/fesm/dtos/form.dto.js +0 -243
  96. package/fesm/entities/form-result.entity.js +0 -90
  97. package/fesm/entities/form-with-company.entity.js +0 -55
  98. package/fesm/entities/form.entity.js +0 -117
  99. package/fesm/entities/index.spec.js +0 -14
  100. package/fesm/enums/form-access-type.enum.js +0 -9
  101. package/fesm/interfaces/form-builder-module.interface.js +0 -3
  102. package/fesm/interfaces/form-result.interface.js +0 -6
  103. package/fesm/interfaces/form.interface.js +0 -3
  104. package/fesm/modules/form-builder.module.js +0 -126
  105. package/fesm/modules/form-builder.module.spec.js +0 -129
  106. package/fesm/services/form-builder-config.service.js +0 -59
  107. package/fesm/services/form-builder-config.service.spec.js +0 -117
  108. package/fesm/services/form-builder-datasource.provider.js +0 -74
  109. package/fesm/services/form-builder-datasource.provider.spec.js +0 -143
  110. package/fesm/services/form-result.service.js +0 -356
  111. package/fesm/services/form-result.service.spec.js +0 -778
  112. package/fesm/services/form.service.js +0 -331
  113. package/fesm/services/form.service.spec.js +0 -701
  114. package/fesm/utils/computed-field.utils.js +0 -195
  115. package/fesm/utils/computed-field.utils.spec.js +0 -1201
  116. package/fesm/utils/index.js +0 -2
  117. package/fesm/utils/permission.utils.js +0 -42
  118. package/fesm/utils/permission.utils.spec.js +0 -114
@@ -1,2 +0,0 @@
1
- export * from './permission.utils';
2
- export * from './computed-field.utils';
@@ -1,42 +0,0 @@
1
- import { FORM_MESSAGES } from '../config';
2
- import { ForbiddenException } from '@nestjs/common';
3
- const CACHE_PREFIX = 'permissions';
4
- /**
5
- * Build permission cache key for a user
6
- * Uses same cache key format as PermissionGuard in nestjs-shared
7
- */ function buildPermissionCacheKey(user, enableCompanyFeature) {
8
- if (enableCompanyFeature && user.companyId) {
9
- return `${CACHE_PREFIX}:company:${user.companyId}:branch:${user.branchId || 'null'}:user:${user.id}`;
10
- }
11
- return `${CACHE_PREFIX}:user:${user.id}`;
12
- }
13
- /**
14
- * Get user permissions from cache
15
- * Fail-closed: if cache fails, deny access rather than allowing potentially unauthorized access
16
- */ async function getUserPermissionsFromCache(user, cacheManager, enableCompanyFeature) {
17
- const cacheKey = buildPermissionCacheKey(user, enableCompanyFeature);
18
- try {
19
- const permissions = await cacheManager.get(cacheKey);
20
- return permissions ?? [];
21
- } catch {
22
- throw new ForbiddenException({
23
- message: 'Unable to verify permissions. Please try again.',
24
- messageKey: FORM_MESSAGES.PERMISSION_CHECK_FAILED
25
- });
26
- }
27
- }
28
- /**
29
- * Validate user has at least one of the required permissions
30
- *
31
- * @param user - The logged-in user
32
- * @param requiredPermissions - Array of required permission strings (user needs at least one)
33
- * @param cacheManager - Cache manager instance
34
- * @param enableCompanyFeature - Whether company feature is enabled
35
- * @returns true if user has permission, false otherwise
36
- */ export async function validateUserPermissions(user, requiredPermissions, cacheManager, enableCompanyFeature) {
37
- if (!requiredPermissions.length) {
38
- return true;
39
- }
40
- const userPermissions = await getUserPermissionsFromCache(user, cacheManager, enableCompanyFeature);
41
- return requiredPermissions.some((perm)=>userPermissions.includes(perm));
42
- }
@@ -1,114 +0,0 @@
1
- import { ForbiddenException } from '@nestjs/common';
2
- import { buildMockUser } from '@test-utils/mocks/logged-user.mock';
3
- import { validateUserPermissions } from './permission.utils';
4
- function buildMockCache() {
5
- return {
6
- get: jest.fn(),
7
- set: jest.fn(),
8
- del: jest.fn()
9
- };
10
- }
11
- describe('validateUserPermissions', ()=>{
12
- it('returns true immediately without touching the cache when no permissions are required', async ()=>{
13
- const cache = buildMockCache();
14
- const result = await validateUserPermissions(buildMockUser(), [], cache, false);
15
- expect(result).toBe(true);
16
- expect(cache.get).not.toHaveBeenCalled();
17
- });
18
- it('returns true when the user has at least one of the required permissions', async ()=>{
19
- const cache = buildMockCache();
20
- cache.get.mockResolvedValue([
21
- 'hr.survey.submit',
22
- 'other.permission'
23
- ]);
24
- const result = await validateUserPermissions(buildMockUser(), [
25
- 'hr.survey.submit',
26
- 'employee.feedback.submit'
27
- ], cache, false);
28
- expect(result).toBe(true);
29
- });
30
- it('returns false when the user has none of the required permissions', async ()=>{
31
- const cache = buildMockCache();
32
- cache.get.mockResolvedValue([
33
- 'some.other.permission'
34
- ]);
35
- const result = await validateUserPermissions(buildMockUser(), [
36
- 'hr.survey.submit'
37
- ], cache, false);
38
- expect(result).toBe(false);
39
- });
40
- it('treats a missing cache entry as no permissions (returns false)', async ()=>{
41
- const cache = buildMockCache();
42
- cache.get.mockResolvedValue(undefined);
43
- const result = await validateUserPermissions(buildMockUser(), [
44
- 'hr.survey.submit'
45
- ], cache, false);
46
- expect(result).toBe(false);
47
- });
48
- it('fails closed with a ForbiddenException when the cache lookup throws', async ()=>{
49
- const cache = buildMockCache();
50
- cache.get.mockRejectedValue(new Error('redis down'));
51
- await expect(validateUserPermissions(buildMockUser(), [
52
- 'hr.survey.submit'
53
- ], cache, false)).rejects.toMatchObject({
54
- response: expect.objectContaining({
55
- messageKey: 'form.permission.check.failed'
56
- })
57
- });
58
- await expect(validateUserPermissions(buildMockUser(), [
59
- 'hr.survey.submit'
60
- ], cache, false)).rejects.toBeInstanceOf(ForbiddenException);
61
- });
62
- describe('cache key construction', ()=>{
63
- it('uses a company/branch/user scoped key when the company feature is enabled and both are present', async ()=>{
64
- const cache = buildMockCache();
65
- cache.get.mockResolvedValue([]);
66
- const user = buildMockUser({
67
- companyId: 'company-1',
68
- branchId: 'branch-1',
69
- id: 'user-1'
70
- });
71
- await validateUserPermissions(user, [
72
- 'perm.read'
73
- ], cache, true);
74
- expect(cache.get).toHaveBeenCalledWith('permissions:company:company-1:branch:branch-1:user:user-1');
75
- });
76
- it('uses "null" as the branch placeholder when branchId is missing under the company feature', async ()=>{
77
- const cache = buildMockCache();
78
- cache.get.mockResolvedValue([]);
79
- const user = buildMockUser({
80
- companyId: 'company-1',
81
- branchId: undefined,
82
- id: 'user-1'
83
- });
84
- await validateUserPermissions(user, [
85
- 'perm.read'
86
- ], cache, true);
87
- expect(cache.get).toHaveBeenCalledWith('permissions:company:company-1:branch:null:user:user-1');
88
- });
89
- it('falls back to a plain user-scoped key when the company feature is enabled but companyId is missing', async ()=>{
90
- const cache = buildMockCache();
91
- cache.get.mockResolvedValue([]);
92
- const user = buildMockUser({
93
- companyId: undefined,
94
- id: 'user-1'
95
- });
96
- await validateUserPermissions(user, [
97
- 'perm.read'
98
- ], cache, true);
99
- expect(cache.get).toHaveBeenCalledWith('permissions:user:user-1');
100
- });
101
- it('uses a plain user-scoped key when the company feature is disabled', async ()=>{
102
- const cache = buildMockCache();
103
- cache.get.mockResolvedValue([]);
104
- const user = buildMockUser({
105
- companyId: 'company-1',
106
- id: 'user-1'
107
- });
108
- await validateUserPermissions(user, [
109
- 'perm.read'
110
- ], cache, false);
111
- expect(cache.get).toHaveBeenCalledWith('permissions:user:user-1');
112
- });
113
- });
114
- });