Files
kami-parse-server/spec/ParseRole.spec.js
Florent Vilmart c0249283ac Advancements with postgres (#2510)
* Start DB runner from tests

* Connect GridstoreAdapter only when needed

* removes unused package

* better test errors reporting

* Adds support for __op.Delete

* Better test error reporting

* Makes sure all tests can run without crashing

* Use xdescribe to skip test suite

* Removes unused dependencies

* Let volatiles classes be created with PG on start

* Do not fail if class dont exist

* adds index.spec.js to the pg suite

* Use a new config each test to prevent side effects

* Enable EmailVerificationToken specs with pg

* Makes sure failure output is not cut

* Reduces number of ignored tests in ParseObject.spec

* Inspect reconfiguration errors

* Mark GlobalConfig is incompatible with PG

- Problem is with nested updates (param.prop = value)

* PG: Nested JSON queries and updates

- Adds support for nested json and . operator queries
- Adds debug support for PG adapter
- Adds loglevel support in helper

* Enable working specs in ParseUser

* Sets default logLevel in tests to undefined

* Adds File type support, retores purchaseValidation specs

* Adds support for updating jsonb objects

- Restores PushController tests

* Proper implementation of deleteByQuery and ORs

- Adds ParseInstallation spec to the test suite

* xit only failing tests

* Nit on ParseAPI spec

* add sorting operator

* properly bound order keys

* reverts describe_only_db behavior

* Enables passing tests

* Adds basic support for relations, upsertOneObject aliased to createObject

* progress on queries options

* Fix ACL update related problems

* Creates relation tables on class creation

* Adds Relation tests

* remove flaky tests

* use promises instead of CB

* disable flaky test

* nits

* Fixes on schema spec

- Next thing is to implemenet geopoint and files correctly

* fix failues

* Basic GeoPoint support

* Adds support for $nearSphere/$maxDistance geopoint queries

* enable passing tests

* drop tables afterEach for PG, clean up relation tables too

* Better initialization/dropTables
2016-08-15 16:48:39 -04:00

351 lines
12 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use strict";
// Roles are not accessible without the master key, so they are not intended
// for use by clients. We can manually test them using the master key.
var RestQuery = require("../src/RestQuery");
var Auth = require("../src/Auth").Auth;
var Config = require("../src/Config");
describe('Parse Role testing', () => {
it('Do a bunch of basic role testing', done => {
var user;
var role;
createTestUser().then((x) => {
user = x;
let acl = new Parse.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(false);
role = new Parse.Object('_Role');
role.set('name', 'Foos');
role.setACL(acl);
var users = role.relation('users');
users.add(user);
return role.save({}, { useMasterKey: true });
}).then((x) => {
var query = new Parse.Query('_Role');
return query.find({ useMasterKey: true });
}).then((x) => {
expect(x.length).toEqual(1);
var relation = x[0].relation('users').query();
return relation.first({ useMasterKey: true });
}).then((x) => {
expect(x.id).toEqual(user.id);
// Here we've got a valid role and a user assigned.
// Lets create an object only the role can read/write and test
// the different scenarios.
var obj = new Parse.Object('TestObject');
var acl = new Parse.ACL();
acl.setPublicReadAccess(false);
acl.setPublicWriteAccess(false);
acl.setRoleReadAccess('Foos', true);
acl.setRoleWriteAccess('Foos', true);
obj.setACL(acl);
return obj.save();
}).then((x) => {
var query = new Parse.Query('TestObject');
return query.find({ sessionToken: user.getSessionToken() });
}).then((x) => {
expect(x.length).toEqual(1);
var objAgain = x[0];
objAgain.set('foo', 'bar');
// This should succeed:
return objAgain.save({}, {sessionToken: user.getSessionToken()});
}).then((x) => {
x.set('foo', 'baz');
// This should fail:
return x.save({},{sessionToken: ""});
}).then((x) => {
fail('Should not have been able to save.');
}, (e) => {
expect(e.code).toEqual(Parse.Error.OBJECT_NOT_FOUND);
done();
});
});
var createRole = function(name, sibling, user) {
var role = new Parse.Role(name, new Parse.ACL());
if (user) {
var users = role.relation('users');
users.add(user);
}
if (sibling) {
role.relation('roles').add(sibling);
}
return role.save({}, { useMasterKey: true });
};
it("should not recursively load the same role multiple times", (done) => {
var rootRole = "RootRole";
var roleNames = ["FooRole", "BarRole", "BazRole"];
var allRoles = [rootRole].concat(roleNames);
var roleObjs = {};
var createAllRoles = function(user) {
var promises = allRoles.map(function(roleName) {
return createRole(roleName, null, user)
.then(function(roleObj) {
roleObjs[roleName] = roleObj;
return roleObj;
});
});
return Promise.all(promises);
};
var restExecute = spyOn(RestQuery.prototype, "execute").and.callThrough();
var user,
auth,
getAllRolesSpy;
createTestUser().then( (newUser) => {
user = newUser;
return createAllRoles(user);
}).then ( (roles) => {
var rootRoleObj = roleObjs[rootRole];
roles.forEach(function(role, i) {
// Add all roles to the RootRole
if (role.id !== rootRoleObj.id) {
role.relation("roles").add(rootRoleObj);
}
// Add all "roleNames" roles to the previous role
if (i > 0) {
role.relation("roles").add(roles[i - 1]);
}
});
return Parse.Object.saveAll(roles, { useMasterKey: true });
}).then( () => {
auth = new Auth({config: new Config("test"), isMaster: true, user: user});
getAllRolesSpy = spyOn(auth, "_getAllRolesNamesForRoleIds").and.callThrough();
return auth._loadRoles();
}).then ( (roles) => {
expect(roles.length).toEqual(4);
allRoles.forEach(function(name) {
expect(roles.indexOf("role:"+name)).not.toBe(-1);
});
// 1 Query for the initial setup
// 1 query for the parent roles
expect(restExecute.calls.count()).toEqual(2);
// 1 call for the 1st layer of roles
// 1 call for the 2nd layer
expect(getAllRolesSpy.calls.count()).toEqual(2);
done()
}).catch( (err) => {
fail("should succeed");
done();
});
});
it("should recursively load roles", (done) => {
var rolesNames = ["FooRole", "BarRole", "BazRole"];
var roleIds = {};
createTestUser().then( (user) => {
// Put the user on the 1st role
return createRole(rolesNames[0], null, user).then( (aRole) => {
roleIds[aRole.get("name")] = aRole.id;
// set the 1st role as a sibling of the second
// user will should have 2 role now
return createRole(rolesNames[1], aRole, null);
}).then( (anotherRole) => {
roleIds[anotherRole.get("name")] = anotherRole.id;
// set this role as a sibling of the last
// the user should now have 3 roles
return createRole(rolesNames[2], anotherRole, null);
}).then( (lastRole) => {
roleIds[lastRole.get("name")] = lastRole.id;
var auth = new Auth({ config: new Config("test"), isMaster: true, user: user });
return auth._loadRoles();
})
}).then( (roles) => {
expect(roles.length).toEqual(3);
rolesNames.forEach( (name) => {
expect(roles.indexOf('role:'+name)).not.toBe(-1);
});
done();
}, function(err){
fail("should succeed")
done();
});
});
it("_Role object should not save without name.", (done) => {
var role = new Parse.Role();
role.save(null,{useMasterKey:true})
.then((r) => {
fail("_Role object should not save without name.");
}, (error) => {
expect(error.code).toEqual(111);
role.set('name','testRole');
role.save(null,{useMasterKey:true})
.then((r2)=>{
fail("_Role object should not save without ACL.");
}, (error2) =>{
expect(error2.code).toEqual(111);
done();
});
});
});
it("Should properly resolve roles", (done) => {
let admin = new Parse.Role("Admin", new Parse.ACL());
let moderator = new Parse.Role("Moderator", new Parse.ACL());
let superModerator = new Parse.Role("SuperModerator", new Parse.ACL());
let contentManager = new Parse.Role('ContentManager', new Parse.ACL());
let superContentManager = new Parse.Role('SuperContentManager', new Parse.ACL());
Parse.Object.saveAll([admin, moderator, contentManager, superModerator, superContentManager], {useMasterKey: true}).then(() => {
contentManager.getRoles().add([moderator, superContentManager]);
moderator.getRoles().add([admin, superModerator]);
superContentManager.getRoles().add(superModerator);
return Parse.Object.saveAll([admin, moderator, contentManager, superModerator, superContentManager], {useMasterKey: true});
}).then(() => {
var auth = new Auth({ config: new Config("test"), isMaster: true });
// For each role, fetch their sibling, what they inherit
// return with result and roleId for later comparison
let promises = [admin, moderator, contentManager, superModerator].map((role) => {
return auth._getAllRolesNamesForRoleIds([role.id]).then((result) => {
return Parse.Promise.as({
id: role.id,
name: role.get('name'),
roleNames: result
});
})
});
return Parse.Promise.when(promises);
}).then((results) => {
results.forEach((result) => {
let id = result.id;
let roleNames = result.roleNames;
if (id == admin.id) {
expect(roleNames.length).toBe(2);
expect(roleNames.indexOf("Moderator")).not.toBe(-1);
expect(roleNames.indexOf("ContentManager")).not.toBe(-1);
} else if (id == moderator.id) {
expect(roleNames.length).toBe(1);
expect(roleNames.indexOf("ContentManager")).toBe(0);
} else if (id == contentManager.id) {
expect(roleNames.length).toBe(0);
} else if (id == superModerator.id) {
expect(roleNames.length).toBe(3);
expect(roleNames.indexOf("Moderator")).not.toBe(-1);
expect(roleNames.indexOf("ContentManager")).not.toBe(-1);
expect(roleNames.indexOf("SuperContentManager")).not.toBe(-1);
}
});
done();
}).fail((err) => {
done();
})
});
it('can create role and query empty users', (done)=> {
var roleACL = new Parse.ACL();
roleACL.setPublicReadAccess(true);
var role = new Parse.Role('subscribers', roleACL);
role.save({}, {useMasterKey : true})
.then((x)=>{
var query = role.relation('users').query();
query.find({useMasterKey : true})
.then((users)=>{
done();
}, (e)=>{
fail('should not have errors');
done();
});
}, (e) => {
fail('should not have errored');
});
});
// Based on various scenarios described in issues #827 and #683,
it('should properly handle role permissions on objects', (done) => {
var user, user2, user3;
var role, role2, role3;
var obj, obj2;
var prACL = new Parse.ACL();
prACL.setPublicReadAccess(true);
var adminACL, superACL, customerACL;
createTestUser().then((x) => {
user = x;
user2 = new Parse.User();
return user2.save({ username: 'user2', password: 'omgbbq' });
}).then((x) => {
user3 = new Parse.User();
return user3.save({ username: 'user3', password: 'omgbbq' });
}).then((x) => {
role = new Parse.Role('Admin', prACL);
role.getUsers().add(user);
return role.save({}, { useMasterKey: true });
}).then(() => {
adminACL = new Parse.ACL();
adminACL.setRoleReadAccess("Admin", true);
adminACL.setRoleWriteAccess("Admin", true);
role2 = new Parse.Role('Super', prACL);
role2.getUsers().add(user2);
return role2.save({}, { useMasterKey: true });
}).then(() => {
superACL = new Parse.ACL();
superACL.setRoleReadAccess("Super", true);
superACL.setRoleWriteAccess("Super", true);
role.getRoles().add(role2);
return role.save({}, { useMasterKey: true });
}).then(() => {
role3 = new Parse.Role('Customer', prACL);
role3.getUsers().add(user3);
role3.getRoles().add(role);
return role3.save({}, { useMasterKey: true });
}).then(() => {
customerACL = new Parse.ACL();
customerACL.setRoleReadAccess("Customer", true);
customerACL.setRoleWriteAccess("Customer", true);
var query = new Parse.Query('_Role');
return query.find({ useMasterKey: true });
}).then((x) => {
expect(x.length).toEqual(3);
obj = new Parse.Object('TestObjectRoles');
obj.set('ACL', customerACL);
return obj.save(null, { useMasterKey: true });
}).then(() => {
// Above, the Admin role was added to the Customer role.
// An object secured by the Customer ACL should be able to be edited by the Admin user.
obj.set('changedByAdmin', true);
return obj.save(null, { sessionToken: user.getSessionToken() });
}).then(() => {
obj2 = new Parse.Object('TestObjectRoles');
obj2.set('ACL', adminACL);
return obj2.save(null, { useMasterKey: true });
}, (e) => {
fail('Admin user should have been able to save.');
done();
}).then(() => {
// An object secured by the Admin ACL should not be able to be edited by a Customer role user.
obj2.set('changedByCustomer', true);
return obj2.save(null, { sessionToken: user3.getSessionToken() });
}).then(() => {
fail('Customer user should not have been able to save.');
done();
}, (e) => {
if (e) {
expect(e.code).toEqual(101);
} else {
fail('should return an error');
}
done();
})
});
});