Skip to content

Commit 12b5d78

Browse files
authored
feat: Add default ACL (#8701)
1 parent b9917dd commit 12b5d78

10 files changed

+245
-5
lines changed

spec/MongoSchemaCollectionAdapter.spec.js

+12
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ describe('MongoSchemaCollection', () => {
1818
},
1919
_metadata: {
2020
class_permissions: {
21+
ACL: {
22+
'*': {
23+
read: true,
24+
write: true,
25+
},
26+
},
2127
get: { '*': true },
2228
find: { '*': true },
2329
count: { '*': true },
@@ -69,6 +75,12 @@ describe('MongoSchemaCollection', () => {
6975
objectId: { type: 'String' },
7076
},
7177
classLevelPermissions: {
78+
ACL: {
79+
'*': {
80+
read: true,
81+
write: true,
82+
},
83+
},
7284
find: { '*': true },
7385
get: { '*': true },
7486
count: { '*': true },

spec/ParseACL.spec.js

+28
Original file line numberDiff line numberDiff line change
@@ -923,4 +923,32 @@ describe('Parse.ACL', () => {
923923

924924
rest.create(config, auth.nobody(config), '_User', anonUser);
925925
});
926+
927+
it('support defaultACL in schema', async () => {
928+
await new Parse.Object('TestObject').save();
929+
const schema = await Parse.Server.database.loadSchema();
930+
await schema.updateClass(
931+
'TestObject',
932+
{},
933+
{
934+
create: {
935+
'*': true,
936+
},
937+
ACL: {
938+
'*': { read: true },
939+
currentUser: { read: true, write: true },
940+
},
941+
}
942+
);
943+
const acls = new Parse.ACL();
944+
acls.setPublicReadAccess(true);
945+
const user = await Parse.User.signUp('testuser', 'p@ssword');
946+
const obj = new Parse.Object('TestObject');
947+
await obj.save(null, { sessionToken: user.getSessionToken() });
948+
expect(obj.getACL()).toBeDefined();
949+
const acl = obj.getACL().toJSON();
950+
expect(acl['*']).toEqual({ read: true });
951+
expect(acl[user.id].write).toBeTrue();
952+
expect(acl[user.id].read).toBeTrue();
953+
});
926954
});

spec/Schema.spec.js

+60
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,12 @@ describe('SchemaController', () => {
309309
foo: { type: 'String' },
310310
},
311311
classLevelPermissions: {
312+
ACL: {
313+
'*': {
314+
read: true,
315+
write: true,
316+
},
317+
},
312318
find: { '*': true },
313319
get: { '*': true },
314320
count: { '*': true },
@@ -329,6 +335,12 @@ describe('SchemaController', () => {
329335

330336
it('can update classes without needing an object', done => {
331337
const levelPermissions = {
338+
ACL: {
339+
'*': {
340+
read: true,
341+
write: true,
342+
},
343+
},
332344
find: { '*': true },
333345
get: { '*': true },
334346
count: { '*': true },
@@ -489,6 +501,12 @@ describe('SchemaController', () => {
489501
foo: { type: 'String' },
490502
},
491503
classLevelPermissions: {
504+
ACL: {
505+
'*': {
506+
read: true,
507+
write: true,
508+
},
509+
},
492510
find: { '*': true },
493511
get: { '*': true },
494512
count: { '*': true },
@@ -694,6 +712,12 @@ describe('SchemaController', () => {
694712

695713
it('refuses to add CLP with incorrect find', done => {
696714
const levelPermissions = {
715+
ACL: {
716+
'*': {
717+
read: true,
718+
write: true,
719+
},
720+
},
697721
find: { '*': false },
698722
get: { '*': true },
699723
create: { '*': true },
@@ -717,6 +741,12 @@ describe('SchemaController', () => {
717741

718742
it('refuses to add CLP when incorrectly sending a string to protectedFields object value instead of an array', done => {
719743
const levelPermissions = {
744+
ACL: {
745+
'*': {
746+
read: true,
747+
write: true,
748+
},
749+
},
720750
find: { '*': true },
721751
get: { '*': true },
722752
create: { '*': true },
@@ -785,6 +815,12 @@ describe('SchemaController', () => {
785815
aPolygon: { type: 'Polygon' },
786816
},
787817
classLevelPermissions: {
818+
ACL: {
819+
'*': {
820+
read: true,
821+
write: true,
822+
},
823+
},
788824
find: { '*': true },
789825
get: { '*': true },
790826
count: { '*': true },
@@ -832,6 +868,12 @@ describe('SchemaController', () => {
832868
parseVersion: { type: 'String' },
833869
},
834870
classLevelPermissions: {
871+
ACL: {
872+
'*': {
873+
read: true,
874+
write: true,
875+
},
876+
},
835877
find: { '*': true },
836878
get: { '*': true },
837879
count: { '*': true },
@@ -866,6 +908,12 @@ describe('SchemaController', () => {
866908
roles: { type: 'Relation', targetClass: '_Role' },
867909
},
868910
classLevelPermissions: {
911+
ACL: {
912+
'*': {
913+
read: true,
914+
write: true,
915+
},
916+
},
869917
find: { '*': true },
870918
get: { '*': true },
871919
count: { '*': true },
@@ -900,6 +948,12 @@ describe('SchemaController', () => {
900948
ACL: { type: 'ACL' },
901949
},
902950
classLevelPermissions: {
951+
ACL: {
952+
'*': {
953+
read: true,
954+
write: true,
955+
},
956+
},
903957
find: { '*': true },
904958
get: { '*': true },
905959
count: { '*': true },
@@ -1070,6 +1124,12 @@ describe('SchemaController', () => {
10701124
relationField: { type: 'Relation', targetClass: '_User' },
10711125
},
10721126
classLevelPermissions: {
1127+
ACL: {
1128+
'*': {
1129+
read: true,
1130+
write: true,
1131+
},
1132+
},
10731133
find: { '*': true },
10741134
get: { '*': true },
10751135
count: { '*': true },

spec/SchemaPerformance.spec.js

+6
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ describe('Schema Performance', function () {
167167
await schema.reloadData();
168168

169169
const levelPermissions = {
170+
ACL: {
171+
'*': {
172+
read: true,
173+
write: true,
174+
},
175+
},
170176
find: { '*': true },
171177
get: { '*': true },
172178
create: { '*': true },

spec/schemas.spec.js

+78-2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ const hasAllPODobject = () => {
2626
};
2727

2828
const defaultClassLevelPermissions = {
29+
ACL: {
30+
'*': {
31+
read: true,
32+
write: true,
33+
},
34+
},
2935
find: {
3036
'*': true,
3137
},
@@ -2058,12 +2064,70 @@ describe('schemas', () => {
20582064
},
20592065
}).then(fail, response => {
20602066
expect(response.data.error).toEqual(
2061-
"'1' is not a valid value for class level permissions find:*:1"
2067+
"'1' is not a valid value for class level permissions acl find:*"
20622068
);
20632069
done();
20642070
});
20652071
});
20662072

2073+
it('should validate defaultAcl with class level permissions when request is not an object', async () => {
2074+
const response = await request({
2075+
method: 'POST',
2076+
url: 'http://localhost:8378/1/schemas/AClass',
2077+
headers: masterKeyHeaders,
2078+
json: true,
2079+
body: {
2080+
classLevelPermissions: {
2081+
ACL: {
2082+
'*': true,
2083+
},
2084+
},
2085+
},
2086+
}).catch(error => error.data);
2087+
2088+
expect(response.error).toEqual(`'true' is not a valid value for class level permissions acl`);
2089+
});
2090+
2091+
it('should validate defaultAcl with class level permissions when request is an object and invalid key', async () => {
2092+
const response = await request({
2093+
method: 'POST',
2094+
url: 'http://localhost:8378/1/schemas/AClass',
2095+
headers: masterKeyHeaders,
2096+
json: true,
2097+
body: {
2098+
classLevelPermissions: {
2099+
ACL: {
2100+
'*': {
2101+
foo: true,
2102+
},
2103+
},
2104+
},
2105+
},
2106+
}).catch(error => error.data);
2107+
2108+
expect(response.error).toEqual(`'foo' is not a valid key for class level permissions acl`);
2109+
});
2110+
2111+
it('should validate defaultAcl with class level permissions when request is an object and invalid value', async () => {
2112+
const response = await request({
2113+
method: 'POST',
2114+
url: 'http://localhost:8378/1/schemas/AClass',
2115+
headers: masterKeyHeaders,
2116+
json: true,
2117+
body: {
2118+
classLevelPermissions: {
2119+
ACL: {
2120+
'*': {
2121+
read: 1,
2122+
},
2123+
},
2124+
},
2125+
},
2126+
}).catch(error => error.data);
2127+
2128+
expect(response.error).toEqual(`'1' is not a valid value for class level permissions acl`);
2129+
});
2130+
20672131
it('should throw if permission is empty string', done => {
20682132
request({
20692133
method: 'POST',
@@ -2079,7 +2143,7 @@ describe('schemas', () => {
20792143
},
20802144
}).then(fail, response => {
20812145
expect(response.data.error).toEqual(
2082-
"'' is not a valid value for class level permissions find:*:"
2146+
`'' is not a valid value for class level permissions acl find:*`
20832147
);
20842148
done();
20852149
});
@@ -2690,6 +2754,12 @@ describe('schemas', () => {
26902754
setPermissionsOnClass(
26912755
'_Role',
26922756
{
2757+
ACL: {
2758+
'*': {
2759+
read: true,
2760+
write: true,
2761+
},
2762+
},
26932763
get: { '*': true },
26942764
find: { '*': true },
26952765
count: { '*': true },
@@ -2710,6 +2780,12 @@ describe('schemas', () => {
27102780
})
27112781
.then(res => {
27122782
expect(res.data.classLevelPermissions).toEqual({
2783+
ACL: {
2784+
'*': {
2785+
read: true,
2786+
write: true,
2787+
},
2788+
},
27132789
get: { '*': true },
27142790
find: { '*': true },
27152791
count: { '*': true },

src/Adapters/Storage/Mongo/MongoSchemaCollection.js

+6
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,12 @@ const emptyCLPS = Object.freeze({
7676
});
7777

7878
const defaultCLPS = Object.freeze({
79+
ACL: {
80+
'*': {
81+
read: true,
82+
write: true,
83+
},
84+
},
7985
find: { '*': true },
8086
count: { '*': true },
8187
get: { '*': true },

src/Adapters/Storage/Postgres/PostgresStorageAdapter.js

+6
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ const emptyCLPS = Object.freeze({
127127
});
128128

129129
const defaultCLPS = Object.freeze({
130+
ACL: {
131+
'*': {
132+
read: true,
133+
write: true,
134+
},
135+
},
130136
find: { '*': true },
131137
get: { '*': true },
132138
count: { '*': true },

src/Controllers/SchemaController.js

+25-3
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ function validateProtectedFieldsKey(key, userIdRegExp) {
255255
}
256256

257257
const CLPValidKeys = Object.freeze([
258+
'ACL',
258259
'find',
259260
'count',
260261
'get',
@@ -364,13 +365,34 @@ function validateCLP(perms: ClassLevelPermissions, fields: SchemaFields, userIdR
364365
continue;
365366
}
366367

367-
// or [entity]: boolean
368368
const permit = operation[entity];
369369

370-
if (permit !== true) {
370+
if (operationKey === 'ACL') {
371+
if (Object.prototype.toString.call(permit) !== '[object Object]') {
372+
throw new Parse.Error(
373+
Parse.Error.INVALID_JSON,
374+
`'${permit}' is not a valid value for class level permissions acl`
375+
);
376+
}
377+
const invalidKeys = Object.keys(permit).filter(key => !['read', 'write'].includes(key));
378+
const invalidValues = Object.values(permit).filter(key => typeof key !== 'boolean');
379+
if (invalidKeys.length) {
380+
throw new Parse.Error(
381+
Parse.Error.INVALID_JSON,
382+
`'${invalidKeys.join(',')}' is not a valid key for class level permissions acl`
383+
);
384+
}
385+
386+
if (invalidValues.length) {
387+
throw new Parse.Error(
388+
Parse.Error.INVALID_JSON,
389+
`'${invalidValues.join(',')}' is not a valid value for class level permissions acl`
390+
);
391+
}
392+
} else if (permit !== true) {
371393
throw new Parse.Error(
372394
Parse.Error.INVALID_JSON,
373-
`'${permit}' is not a valid value for class level permissions ${operationKey}:${entity}:${permit}`
395+
`'${permit}' is not a valid value for class level permissions acl ${operationKey}:${entity}`
374396
);
375397
}
376398
}

0 commit comments

Comments
 (0)