@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;
|
|
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
|
|
31
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
@@ -32,8 +32,8 @@ describe('checkIsValidFieldNameFn', () => {
|
|
|
32
32
|
|
|
33
33
|
const result = await checkIsValidFieldNameFn(context)
|
|
34
34
|
expect(result).toEqual({
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
60
|
-
|
|
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
|
|
39
|
-
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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) {
|