@flowerforce/flowerbase 1.7.6-beta.5 → 1.7.6-beta.7

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.
@@ -1 +1 @@
1
- {"version":3,"file":"fieldPermissions.d.ts","sourceRoot":"","sources":["../../../../src/utils/roles/machines/fieldPermissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAElC,OAAO,EAGL,IAAI,EACL,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AA4C5C,eAAO,MAAM,0BAA0B,GAAI,OAAO,IAAI,YACN,CAAA;AAEhD,eAAO,MAAM,gCAAgC,GAC3C,SAAS,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC,EACzD,MAAM,MAAM,GAAG,OAAO,EACtB,UAAU;IACR,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,KACA,OAAO,CAAC,QAAQ,CAyBlB,CAAA"}
1
+ {"version":3,"file":"fieldPermissions.d.ts","sourceRoot":"","sources":["../../../../src/utils/roles/machines/fieldPermissions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAElC,OAAO,EAGL,IAAI,EACL,MAAM,cAAc,CAAA;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AA0C5C,eAAO,MAAM,0BAA0B,GAAI,OAAO,IAAI,YACN,CAAA;AAEhD,eAAO,MAAM,gCAAgC,GAC3C,SAAS,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,CAAC,EACzD,MAAM,MAAM,GAAG,OAAO,EACtB,UAAU;IACR,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,KACA,OAAO,CAAC,QAAQ,CAkClB,CAAA"}
@@ -26,12 +26,9 @@ const getAdditionalFieldPermission = (additionalFields, fieldName) => {
26
26
  return undefined;
27
27
  };
28
28
  const canReadField = (context, permission) => __awaiter(void 0, void 0, void 0, function* () {
29
- if (!permission)
30
- return false;
31
- const read = yield (0, helpers_1.evaluateExpression)(context.params, permission.read, context.user);
32
- if (read)
33
- return true;
34
- return yield (0, helpers_1.evaluateExpression)(context.params, permission.write, context.user);
29
+ if (!permission || typeof permission.read === 'undefined')
30
+ return undefined;
31
+ return yield (0, helpers_1.evaluateExpression)(context.params, permission.read, context.user);
35
32
  });
36
33
  const canWriteField = (context, permission) => __awaiter(void 0, void 0, void 0, function* () {
37
34
  if (!permission)
@@ -49,14 +46,23 @@ const filterDocumentByFieldPermissions = (context, mode, options) => __awaiter(v
49
46
  const fields = (_b = context.role.fields) !== null && _b !== void 0 ? _b : {};
50
47
  const additionalFields = context.role.additional_fields;
51
48
  for (const [key, value] of Object.entries(source)) {
49
+ if (mode === 'read' && key === '_id') {
50
+ document[key] = value;
51
+ continue;
52
+ }
52
53
  const fieldPermission = fields[key];
53
54
  const permission = fieldPermission !== null && fieldPermission !== void 0 ? fieldPermission : getAdditionalFieldPermission(additionalFields, key);
54
55
  let allowed = (options === null || options === void 0 ? void 0 : options.defaultAllow) === true;
55
56
  if (permission) {
56
- allowed =
57
- mode === 'read'
58
- ? yield canReadField(context, permission)
59
- : yield canWriteField(context, permission);
57
+ if (mode === 'read') {
58
+ const readAllowed = yield canReadField(context, permission);
59
+ if (typeof readAllowed !== 'undefined') {
60
+ allowed = readAllowed;
61
+ }
62
+ }
63
+ else {
64
+ allowed = yield canWriteField(context, permission);
65
+ }
60
66
  }
61
67
  if (allowed) {
62
68
  document[key] = value;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flowerbase",
3
- "version": "1.7.6-beta.5",
3
+ "version": "1.7.6-beta.7",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -32,8 +32,8 @@ describe('checkIsValidFieldNameFn', () => {
32
32
 
33
33
  const result = await checkIsValidFieldNameFn(context)
34
34
  expect(result).toEqual({
35
- name: 'Alice',
36
- email: 'alice@example.com'
35
+ _id: mockId,
36
+ name: 'Alice'
37
37
  })
38
38
  })
39
39
 
@@ -56,8 +56,58 @@ describe('checkIsValidFieldNameFn', () => {
56
56
 
57
57
  const result = await checkIsValidFieldNameFn(context)
58
58
  expect(result).toEqual({
59
- phone: '123456789',
60
- address: 'Unknown'
59
+ _id: mockId,
60
+ phone: '123456789'
61
+ })
62
+ })
63
+
64
+ it('keeps fields readable when top-level read is true and the field only defines write rules', async () => {
65
+ const mockedRole = {
66
+ name: 'test',
67
+ apply_when: { '%%true': true },
68
+ read: true,
69
+ fields: {
70
+ avatar: { write: false },
71
+ name: { write: true }
72
+ }
73
+ } as Role
74
+ const context = {
75
+ user: mockUser,
76
+ role: mockedRole,
77
+ params: {
78
+ type: 'read',
79
+ cursor: { _id: mockId, avatar: 'avatar.png', name: 'Alice' }
80
+ }
81
+ } as MachineContext
82
+
83
+ const result = await checkIsValidFieldNameFn(context)
84
+ expect(result).toEqual({
85
+ _id: mockId,
86
+ avatar: 'avatar.png',
87
+ name: 'Alice'
88
+ })
89
+ })
90
+
91
+ it('always keeps _id in read results even when no field read rule is defined', async () => {
92
+ const mockedRole = {
93
+ name: 'test',
94
+ apply_when: { '%%true': true },
95
+ fields: {
96
+ name: { read: true }
97
+ }
98
+ } as Role
99
+ const context = {
100
+ user: mockUser,
101
+ role: mockedRole,
102
+ params: {
103
+ type: 'read',
104
+ cursor: { _id: mockId, email: 'alice@example.com' }
105
+ }
106
+ } as MachineContext
107
+
108
+ const result = await checkIsValidFieldNameFn(context)
109
+ expect(result).toEqual({
110
+ _id: mockId
61
111
  })
62
112
  })
63
113
 
@@ -122,6 +172,8 @@ describe('checkIsValidFieldNameFn', () => {
122
172
  } as MachineContext
123
173
 
124
174
  const result = await checkIsValidFieldNameFn(context)
125
- expect(result).toEqual({})
175
+ expect(result).toEqual({
176
+ _id: mockId
177
+ })
126
178
  })
127
179
  })
@@ -35,10 +35,8 @@ const canReadField = async (
35
35
  context: Pick<MachineContext, 'params' | 'user'>,
36
36
  permission?: FieldPermissionExpression
37
37
  ) => {
38
- if (!permission) return false
39
- const read = await evaluateExpression(context.params, permission.read, context.user)
40
- if (read) return true
41
- return await evaluateExpression(context.params, permission.write, context.user)
38
+ if (!permission || typeof permission.read === 'undefined') return undefined
39
+ return await evaluateExpression(context.params, permission.read, context.user)
42
40
  }
43
41
 
44
42
  const canWriteField = async (
@@ -67,14 +65,23 @@ export const filterDocumentByFieldPermissions = async (
67
65
  const additionalFields = context.role.additional_fields
68
66
 
69
67
  for (const [key, value] of Object.entries(source)) {
68
+ if (mode === 'read' && key === '_id') {
69
+ document[key] = value
70
+ continue
71
+ }
72
+
70
73
  const fieldPermission = fields[key]
71
74
  const permission = fieldPermission ?? getAdditionalFieldPermission(additionalFields, key)
72
75
  let allowed = options?.defaultAllow === true
73
76
  if (permission) {
74
- allowed =
75
- mode === 'read'
76
- ? await canReadField(context, permission)
77
- : await canWriteField(context, permission)
77
+ if (mode === 'read') {
78
+ const readAllowed = await canReadField(context, permission)
79
+ if (typeof readAllowed !== 'undefined') {
80
+ allowed = readAllowed
81
+ }
82
+ } else {
83
+ allowed = await canWriteField(context, permission)
84
+ }
78
85
  }
79
86
 
80
87
  if (allowed) {