Skip to content

Commit fe3851e

Browse files
committed
Fixes for Pointer Permissions
- Fix bug that would leave public CLP when setting a new set of permissions - Sets empty permissions if missing to match parse.com API - Updates tests to reflect changes
1 parent ac705a8 commit fe3851e

File tree

6 files changed

+60
-41
lines changed

6 files changed

+60
-41
lines changed

spec/PointerPermissions.spec.js

+9-9
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ describe('Pointer Permissions', () => {
282282
it('tests CLP / Pointer Perms / ACL write (PP Locked)', (done) => {
283283
/*
284284
tests:
285-
CLP: update open ({"*": true})
285+
CLP: update closed ({})
286286
PointerPerm: "owner"
287287
ACL: logged in user has access
288288
@@ -300,7 +300,7 @@ describe('Pointer Permissions', () => {
300300
password: 'password'
301301
});
302302
let obj = new Parse.Object('AnObject');
303-
Parse.Object.saveAll([user, user2]).then(() => {
303+
Parse.Object.saveAll([user, user2]).then(() => {
304304
let ACL = new Parse.ACL();
305305
ACL.setReadAccess(user, true);
306306
ACL.setWriteAccess(user, true);
@@ -310,7 +310,7 @@ describe('Pointer Permissions', () => {
310310
}).then(() => {
311311
return config.database.loadSchema().then((schema) => {
312312
// Lock the update, and let only owner write
313-
return schema.updateClass('AnObject', {}, {update: {"*": true}, writeUserFields: ['owner']});
313+
return schema.updateClass('AnObject', {}, {update: {}, writeUserFields: ['owner']});
314314
});
315315
}).then(() => {
316316
return Parse.User.logIn('user1', 'password');
@@ -329,7 +329,7 @@ describe('Pointer Permissions', () => {
329329
it('tests CLP / Pointer Perms / ACL write (ACL Locked)', (done) => {
330330
/*
331331
tests:
332-
CLP: update open ({"*": true})
332+
CLP: update closed ({})
333333
PointerPerm: "owner"
334334
ACL: logged in user has access
335335
*/
@@ -355,7 +355,7 @@ describe('Pointer Permissions', () => {
355355
}).then(() => {
356356
return config.database.loadSchema().then((schema) => {
357357
// Lock the update, and let only owner write
358-
return schema.updateClass('AnObject', {}, {update: {"*": true}, writeUserFields: ['owner']});
358+
return schema.updateClass('AnObject', {}, {update: {}, writeUserFields: ['owner']});
359359
});
360360
}).then(() => {
361361
return Parse.User.logIn('user2', 'password');
@@ -374,7 +374,7 @@ describe('Pointer Permissions', () => {
374374
it('tests CLP / Pointer Perms / ACL write (ACL/PP OK)', (done) => {
375375
/*
376376
tests:
377-
CLP: update open ({"*": true})
377+
CLP: update closed ({})
378378
PointerPerm: "owner"
379379
ACL: logged in user has access
380380
*/
@@ -400,7 +400,7 @@ describe('Pointer Permissions', () => {
400400
}).then(() => {
401401
return config.database.loadSchema().then((schema) => {
402402
// Lock the update, and let only owner write
403-
return schema.updateClass('AnObject', {}, {update: {"*": true}, writeUserFields: ['owner']});
403+
return schema.updateClass('AnObject', {}, {update: {}, writeUserFields: ['owner']});
404404
});
405405
}).then(() => {
406406
return Parse.User.logIn('user2', 'password');
@@ -419,7 +419,7 @@ describe('Pointer Permissions', () => {
419419
it('tests CLP / Pointer Perms / ACL read (PP locked)', (done) => {
420420
/*
421421
tests:
422-
CLP: find/get open ({"*": true})
422+
CLP: find/get open ({})
423423
PointerPerm: "owner" : read
424424
ACL: logged in user has access
425425
@@ -447,7 +447,7 @@ describe('Pointer Permissions', () => {
447447
}).then(() => {
448448
return config.database.loadSchema().then((schema) => {
449449
// Lock the update, and let only owner write
450-
return schema.updateClass('AnObject', {}, {find: {"*": true}, get: {"*": true}, readUserFields: ['owner']});
450+
return schema.updateClass('AnObject', {}, {find: {}, get: {}, readUserFields: ['owner']});
451451
});
452452
}).then(() => {
453453
return Parse.User.logIn('user1', 'password');

spec/Schema.spec.js

+2
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ describe('SchemaController', () => {
132132
var get = {};
133133
get[user.id] = true;
134134
return schema.setPermissions('Stuff', {
135+
'create': {'*': true},
135136
'find': find,
136137
'get': get
137138
});
@@ -152,6 +153,7 @@ describe('SchemaController', () => {
152153
done();
153154
}, (e) => {
154155
fail('Class permissions should have allowed this get query');
156+
done();
155157
});
156158
});
157159
});

spec/schemas.spec.js

+14-18
Original file line numberDiff line numberDiff line change
@@ -963,18 +963,10 @@ describe('schemas', () => {
963963
create: {
964964
'role:admin': true
965965
},
966-
get: {
967-
'*': true
968-
},
969-
update: {
970-
'*': true
971-
},
972-
addField: {
973-
'*': true
974-
},
975-
delete: {
976-
'*': true
977-
}
966+
get: {},
967+
update: {},
968+
delete: {},
969+
addField: {}
978970
});
979971
done();
980972
});
@@ -1018,6 +1010,9 @@ describe('schemas', () => {
10181010
json: true,
10191011
body: {
10201012
classLevelPermissions: {
1013+
create: {
1014+
'*': true
1015+
},
10211016
find: {
10221017
'*': true
10231018
},
@@ -1040,14 +1035,14 @@ describe('schemas', () => {
10401035
})
10411036
});
10421037

1043-
it('should not be able to add a field', done => {
1038+
it('should be able to add a field', done => {
10441039
request.post({
10451040
url: 'http://localhost:8378/1/schemas/AClass',
10461041
headers: masterKeyHeaders,
10471042
json: true,
10481043
body: {
10491044
classLevelPermissions: {
1050-
find: {
1045+
create: {
10511046
'*': true
10521047
},
10531048
addField: {
@@ -1243,7 +1238,7 @@ describe('schemas', () => {
12431238
}).then(() => {
12441239
return Parse.User.logIn('user', 'user').then(() => {
12451240
let obj = new Parse.Object('AClass');
1246-
return obj.save();
1241+
return obj.save(null, {useMasterKey: true});
12471242
})
12481243
}).then(() => {
12491244
let query = new Parse.Query('AClass');
@@ -1292,7 +1287,7 @@ describe('schemas', () => {
12921287
}).then(() => {
12931288
return Parse.User.logIn('user', 'user').then(() => {
12941289
let obj = new Parse.Object('AClass');
1295-
return obj.save();
1290+
return obj.save(null, {useMasterKey: true});
12961291
})
12971292
}).then(() => {
12981293
let query = new Parse.Query('AClass');
@@ -1357,7 +1352,7 @@ describe('schemas', () => {
13571352
}).then(() => {
13581353
return Parse.User.logIn('user', 'user').then(() => {
13591354
let obj = new Parse.Object('AClass');
1360-
return obj.save();
1355+
return obj.save(null, {useMasterKey: true});
13611356
})
13621357
}).then(() => {
13631358
let query = new Parse.Query('AClass');
@@ -1415,7 +1410,7 @@ describe('schemas', () => {
14151410
}).then(() => {
14161411
return Parse.User.logIn('user', 'user').then(() => {
14171412
let obj = new Parse.Object('AClass');
1418-
return obj.save();
1413+
return obj.save(null, {useMasterKey: true});
14191414
})
14201415
}).then(() => {
14211416
let query = new Parse.Query('AClass');
@@ -1544,6 +1539,7 @@ describe('schemas', () => {
15441539

15451540
it('can login when addFields is false (issue #1355)', (done) => {
15461541
setPermissionsOnClass('_User', {
1542+
'create': {'*': true},
15471543
'addField': {}
15481544
}).then(() => {
15491545
return Parse.User.signUp('foo', 'bar');

src/Adapters/Storage/Mongo/MongoSchemaCollection.js

+12-3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,15 @@ function mongoSchemaFieldsToParseSchemaFields(schema) {
4343
return response;
4444
}
4545

46+
const emptyCLPS = Object.freeze({
47+
find: {},
48+
get: {},
49+
create: {},
50+
update: {},
51+
delete: {},
52+
addField: {},
53+
});
54+
4655
const defaultCLPS = Object.freeze({
4756
find: {'*': true},
4857
get: {'*': true},
@@ -53,14 +62,14 @@ const defaultCLPS = Object.freeze({
5362
});
5463

5564
function mongoSchemaToParseSchema(mongoSchema) {
56-
let clpsFromMongoObject = {};
65+
let clps = defaultCLPS;
5766
if (mongoSchema._metadata && mongoSchema._metadata.class_permissions) {
58-
clpsFromMongoObject = mongoSchema._metadata.class_permissions;
67+
clps = {...emptyCLPS, ...mongoSchema._metadata.class_permissions};
5968
}
6069
return {
6170
className: mongoSchema._id,
6271
fields: mongoSchemaFieldsToParseSchemaFields(mongoSchema),
63-
classLevelPermissions: {...defaultCLPS, ...clpsFromMongoObject},
72+
classLevelPermissions: clps,
6473
};
6574
}
6675

src/Controllers/DatabaseController.js

+5
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,11 @@ DatabaseController.prototype.deleteSchema = function(className) {
704704
}
705705

706706
DatabaseController.prototype.addPointerPermissions = function(schema, className, operation, query, aclGroup = []) {
707+
// Check if class has public permission for operation
708+
// If the BaseCLP pass, let go through
709+
if (schema.testBaseCLP(className, aclGroup, operation)) {
710+
return query;
711+
}
707712
let perms = schema.perms[className];
708713
let field = ['get', 'find'].indexOf(operation) > -1 ? 'readUserFields' : 'writeUserFields';
709714
let userACL = aclGroup.filter((acl) => {

src/Controllers/SchemaController.js

+18-11
Original file line numberDiff line numberDiff line change
@@ -632,30 +632,36 @@ class SchemaController {
632632
}
633633
return Promise.resolve(this);
634634
}
635-
636-
// Validates an operation passes class-level-permissions set in the schema
637-
validatePermission(className, aclGroup, operation) {
635+
636+
// Validates the base CLP for an operation
637+
testBaseCLP(className, aclGroup, operation) {
638638
if (!this.perms[className] || !this.perms[className][operation]) {
639-
return Promise.resolve();
639+
return true;
640640
}
641641
let classPerms = this.perms[className];
642642
let perms = classPerms[operation];
643643
// Handle the public scenario quickly
644644
if (perms['*']) {
645-
return Promise.resolve();
645+
return true;
646646
}
647647
// Check permissions against the aclGroup provided (array of userId/roles)
648-
let found = false;
649-
for (let i = 0; i < aclGroup.length && !found; i++) {
650-
if (perms[aclGroup[i]]) {
651-
found = true;
652-
}
648+
if (aclGroup.some(acl => { return perms[acl] === true })) {
649+
return true;
653650
}
651+
return false;
652+
}
654653

655-
if (found) {
654+
// Validates an operation passes class-level-permissions set in the schema
655+
validatePermission(className, aclGroup, operation) {
656+
if (this.testBaseCLP(className, aclGroup, operation)) {
656657
return Promise.resolve();
657658
}
658659

660+
if (!this.perms[className] || !this.perms[className][operation]) {
661+
return true;
662+
}
663+
let classPerms = this.perms[className];
664+
let perms = classPerms[operation];
659665
// No matching CLP, let's check the Pointer permissions
660666
// And handle those later
661667
let permissionField = ['get', 'find'].indexOf(operation) > -1 ? 'readUserFields' : 'writeUserFields';
@@ -666,6 +672,7 @@ class SchemaController {
666672
'Permission denied for this action.');
667673
}
668674

675+
// Process the readUserFields later
669676
if (Array.isArray(classPerms[permissionField]) && classPerms[permissionField].length > 0) {
670677
return Promise.resolve();
671678
}

0 commit comments

Comments
 (0)