@drax/crud-back 0.26.0 → 0.28.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.
@@ -9,10 +9,19 @@ class AbstractFastifyController extends CommonController {
9
9
  this.tenantField = 'tenant';
10
10
  this.userField = 'user';
11
11
  this.tenantFilter = false;
12
- this.userFilter = false;
13
12
  this.tenantSetter = false;
14
- this.userSetter = false;
15
13
  this.tenantAssert = false;
14
+ /**
15
+ * userFilter is used to filter items by user field like createdBy with auth user. Used by find, search, paginate
16
+ */
17
+ this.userFilter = false;
18
+ /**
19
+ * userSetter is used to set user like createdBy with auth user. Used by create
20
+ */
21
+ this.userSetter = false;
22
+ /**
23
+ * userSetter is used to verify item user like createdBy with auth user. Used by update, delete, findById
24
+ */
16
25
  this.userAssert = false;
17
26
  this.defaultLimit = 1000;
18
27
  this.maximumLimit = 10000;
@@ -42,13 +51,22 @@ class AbstractFastifyController extends CommonController {
42
51
  }
43
52
  }
44
53
  applyUserAndTenantFilters(filters, rbac) {
45
- if (this.tenantFilter && rbac.tenantId) {
46
- filters.push({ field: this.tenantField, operator: 'eq', value: rbac.tenantId });
54
+ this.applyTenantFilter(filters, rbac);
55
+ this.applyUserFilter(filters, rbac);
56
+ }
57
+ applyUserFilter(filters, rbac) {
58
+ if (rbac.hasSomePermission([this.permission.All, this.permission.ViewAll])) {
59
+ return;
47
60
  }
48
61
  if (this.userFilter && rbac.userId) {
49
62
  filters.push({ field: this.userField, operator: 'eq', value: rbac.userId });
50
63
  }
51
64
  }
65
+ applyTenantFilter(filters, rbac) {
66
+ if (this.tenantFilter && rbac.tenantId) {
67
+ filters.push({ field: this.tenantField, operator: 'eq', value: rbac.tenantId });
68
+ }
69
+ }
52
70
  assertTenant(item, rbac) {
53
71
  if (this.tenantAssert) {
54
72
  const itemTenantId = item[this.tenantField]?._id ? item[this.tenantField]._id.toString() : null;
@@ -94,10 +112,17 @@ class AbstractFastifyController extends CommonController {
94
112
  }
95
113
  const id = request.params.id;
96
114
  const payload = request.body;
115
+ if (!request.rbac.hasSomePermission([this.permission.All, this.permission.UpdateAll])) {
116
+ let preItem = await this.service.findById(id);
117
+ if (!preItem) {
118
+ reply.statusCode = 404;
119
+ reply.send({ error: 'NOT_FOUND' });
120
+ }
121
+ this.assertUser(preItem, request.rbac);
122
+ }
123
+ //Definido el tenant/user en el create no debe modificarse en un update
97
124
  delete payload[this.tenantField];
98
125
  delete payload[this.userField];
99
- //Una vez que un registro se crea con un tenant, no deberia actualizarse nunca mas
100
- //this.applyUserAndTenantSetters(payload, request.rbac)
101
126
  let item = await this.service.update(id, payload);
102
127
  if (!item) {
103
128
  throw new NotFoundError();
@@ -117,10 +142,17 @@ class AbstractFastifyController extends CommonController {
117
142
  }
118
143
  const id = request.params.id;
119
144
  const payload = request.body;
145
+ if (!request.rbac.hasSomePermission([this.permission.All, this.permission.UpdateAll])) {
146
+ let preItem = await this.service.findById(id);
147
+ if (!preItem) {
148
+ reply.statusCode = 404;
149
+ reply.send({ error: 'NOT_FOUND' });
150
+ }
151
+ this.assertUser(preItem, request.rbac);
152
+ }
153
+ //Definido el tenant/user en el create no debe modificarse en un update
120
154
  delete payload[this.tenantField];
121
155
  delete payload[this.userField];
122
- //Una vez que un registro se crea con un tenant, no deberia actualizarse nunca mas
123
- //this.applyUserAndTenantSetters(payload, request.rbac)
124
156
  let item = await this.service.updatePartial(id, payload);
125
157
  if (!item) {
126
158
  throw new NotFoundError();
@@ -144,7 +176,10 @@ class AbstractFastifyController extends CommonController {
144
176
  reply.statusCode = 404;
145
177
  reply.send({ error: 'NOT_FOUND' });
146
178
  }
147
- this.assertUserAndTenant(item, request.rbac);
179
+ if (!request.rbac.hasSomePermission([this.permission.All, this.permission.DeleteAll])) {
180
+ this.assertUser(item, request.rbac);
181
+ }
182
+ this.assertTenant(item, request.rbac);
148
183
  await this.service.delete(id);
149
184
  reply.send({
150
185
  id: id,
@@ -169,7 +204,10 @@ class AbstractFastifyController extends CommonController {
169
204
  if (!item) {
170
205
  throw new NotFoundError();
171
206
  }
172
- this.assertUserAndTenant(item, request.rbac);
207
+ if (!request.rbac.hasSomePermission([this.permission.All, this.permission.ViewAll])) {
208
+ this.assertUser(item, request.rbac);
209
+ }
210
+ this.assertTenant(item, request.rbac);
173
211
  return item;
174
212
  }
175
213
  catch (e) {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.26.0",
6
+ "version": "0.28.0",
7
7
  "description": "Crud utils across modules",
8
8
  "main": "dist/index.js",
9
9
  "types": "types/index.d.ts",
@@ -22,10 +22,10 @@
22
22
  "author": "Cristian Incarnato & Drax Team",
23
23
  "license": "ISC",
24
24
  "dependencies": {
25
- "@drax/common-back": "^0.26.0",
26
- "@drax/common-share": "^0.26.0",
27
- "@drax/identity-share": "^0.26.0",
28
- "@drax/media-back": "^0.26.0",
25
+ "@drax/common-back": "^0.28.0",
26
+ "@drax/common-share": "^0.28.0",
27
+ "@drax/identity-share": "^0.28.0",
28
+ "@drax/media-back": "^0.28.0",
29
29
  "@graphql-tools/load-files": "^7.0.0",
30
30
  "@graphql-tools/merge": "^9.0.4",
31
31
  "mongoose": "^8.6.3",
@@ -45,5 +45,5 @@
45
45
  "tsc-alias": "^1.8.10",
46
46
  "typescript": "^5.6.2"
47
47
  },
48
- "gitHead": "e4b5e941f7d847b340cd290d650100caf1bebf0b"
48
+ "gitHead": "062c6d15dbbf8b6e337869549ab0bdbc27200a9e"
49
49
  }
@@ -53,12 +53,22 @@ class AbstractFastifyController<T, C, U> extends CommonController {
53
53
  protected userField: string = 'user'
54
54
 
55
55
  protected tenantFilter: boolean = false
56
+ protected tenantSetter: boolean = false
57
+ protected tenantAssert: boolean = false
58
+
59
+ /**
60
+ * userFilter is used to filter items by user field like createdBy with auth user. Used by find, search, paginate
61
+ */
56
62
  protected userFilter: boolean = false
57
63
 
58
- protected tenantSetter: boolean = false
64
+ /**
65
+ * userSetter is used to set user like createdBy with auth user. Used by create
66
+ */
59
67
  protected userSetter: boolean = false
60
68
 
61
- protected tenantAssert: boolean = false
69
+ /**
70
+ * userSetter is used to verify item user like createdBy with auth user. Used by update, delete, findById
71
+ */
62
72
  protected userAssert: boolean = false
63
73
 
64
74
  protected defaultLimit: number = 1000
@@ -89,19 +99,32 @@ class AbstractFastifyController<T, C, U> extends CommonController {
89
99
  })
90
100
  return filters
91
101
  } catch (e) {
92
- console.error("parseFilters error",e)
102
+ console.error("parseFilters error", e)
93
103
  throw e
94
104
  }
95
105
  }
96
106
 
97
107
  protected applyUserAndTenantFilters(filters: IDraxFieldFilter[], rbac: IRbac) {
98
- if (this.tenantFilter && rbac.tenantId) {
99
- filters.push({field: this.tenantField, operator: 'eq', value: rbac.tenantId})
108
+ this.applyTenantFilter(filters, rbac)
109
+ this.applyUserFilter(filters, rbac)
110
+ }
111
+
112
+ protected applyUserFilter(filters: IDraxFieldFilter[], rbac: IRbac) {
113
+
114
+ if(rbac.hasSomePermission([this.permission.All, this.permission.ViewAll])) {
115
+ return
100
116
  }
101
117
 
102
- if (this.userFilter && rbac.userId) {
118
+ if(this.userFilter && rbac.userId) {
103
119
  filters.push({field: this.userField, operator: 'eq', value: rbac.userId})
104
120
  }
121
+
122
+ }
123
+
124
+ protected applyTenantFilter(filters: IDraxFieldFilter[], rbac: IRbac) {
125
+ if (this.tenantFilter && rbac.tenantId) {
126
+ filters.push({field: this.tenantField, operator: 'eq', value: rbac.tenantId})
127
+ }
105
128
  }
106
129
 
107
130
  protected assertTenant(item: T, rbac: IRbac) {
@@ -112,6 +135,7 @@ class AbstractFastifyController<T, C, U> extends CommonController {
112
135
  }
113
136
 
114
137
  protected assertUser(item: T, rbac: IRbac) {
138
+
115
139
  if (this.userAssert) {
116
140
  const itemUserId = item[this.userField]?._id ? item[this.userField]._id.toString() : null
117
141
  rbac.assertUserId(itemUserId)
@@ -155,10 +179,23 @@ class AbstractFastifyController<T, C, U> extends CommonController {
155
179
  }
156
180
  const id = request.params.id
157
181
  const payload = request.body
182
+
183
+ if (!request.rbac.hasSomePermission([this.permission.All, this.permission.UpdateAll])) {
184
+
185
+ let preItem = await this.service.findById(id)
186
+
187
+ if (!preItem) {
188
+ reply.statusCode = 404
189
+ reply.send({error: 'NOT_FOUND'})
190
+ }
191
+
192
+ this.assertUser(preItem, request.rbac)
193
+ }
194
+
195
+ //Definido el tenant/user en el create no debe modificarse en un update
158
196
  delete payload[this.tenantField]
159
197
  delete payload[this.userField]
160
- //Una vez que un registro se crea con un tenant, no deberia actualizarse nunca mas
161
- //this.applyUserAndTenantSetters(payload, request.rbac)
198
+
162
199
  let item = await this.service.update(id, payload as U)
163
200
 
164
201
  if (!item) {
@@ -180,10 +217,23 @@ class AbstractFastifyController<T, C, U> extends CommonController {
180
217
  }
181
218
  const id = request.params.id
182
219
  const payload = request.body
220
+
221
+ if (!request.rbac.hasSomePermission([this.permission.All, this.permission.UpdateAll])) {
222
+
223
+ let preItem = await this.service.findById(id)
224
+
225
+ if (!preItem) {
226
+ reply.statusCode = 404
227
+ reply.send({error: 'NOT_FOUND'})
228
+ }
229
+
230
+ this.assertUser(preItem, request.rbac)
231
+ }
232
+
233
+ //Definido el tenant/user en el create no debe modificarse en un update
183
234
  delete payload[this.tenantField]
184
235
  delete payload[this.userField]
185
- //Una vez que un registro se crea con un tenant, no deberia actualizarse nunca mas
186
- //this.applyUserAndTenantSetters(payload, request.rbac)
236
+
187
237
  let item = await this.service.updatePartial(id, payload as U)
188
238
  if (!item) {
189
239
  throw new NotFoundError()
@@ -201,6 +251,7 @@ class AbstractFastifyController<T, C, U> extends CommonController {
201
251
  reply.statusCode = 400
202
252
  reply.send({error: 'BAD REQUEST'})
203
253
  }
254
+
204
255
  const id = request.params.id
205
256
 
206
257
  let item = await this.service.findById(id)
@@ -210,7 +261,12 @@ class AbstractFastifyController<T, C, U> extends CommonController {
210
261
  reply.send({error: 'NOT_FOUND'})
211
262
  }
212
263
 
213
- this.assertUserAndTenant(item, request.rbac)
264
+ if (!request.rbac.hasSomePermission([this.permission.All, this.permission.DeleteAll])) {
265
+ this.assertUser(item, request.rbac)
266
+ }
267
+
268
+ this.assertTenant(item, request.rbac)
269
+
214
270
 
215
271
  await this.service.delete(id)
216
272
  reply.send({
@@ -240,7 +296,11 @@ class AbstractFastifyController<T, C, U> extends CommonController {
240
296
  throw new NotFoundError()
241
297
  }
242
298
 
243
- this.assertUserAndTenant(item, request.rbac)
299
+ if (!request.rbac.hasSomePermission([this.permission.All, this.permission.ViewAll])) {
300
+ this.assertUser(item, request.rbac)
301
+ }
302
+
303
+ this.assertTenant(item, request.rbac)
244
304
 
245
305
  return item
246
306
  } catch (e) {
@@ -281,6 +341,7 @@ class AbstractFastifyController<T, C, U> extends CommonController {
281
341
  const search = request.query.search ??= undefined
282
342
  const filters = this.parseFilters(request.query.filters)
283
343
 
344
+
284
345
  this.applyUserAndTenantFilters(filters, request.rbac);
285
346
 
286
347
  let items = await this.service.find({search, filters, order, orderBy, limit})
@@ -353,7 +414,6 @@ class AbstractFastifyController<T, C, U> extends CommonController {
353
414
  }
354
415
 
355
416
 
356
-
357
417
  async search(request: CustomRequest, reply: FastifyReply) {
358
418
  try {
359
419
  request.rbac.assertPermission(this.permission.View)