2023-12-26 13:41:19 +00:00
|
|
|
import axios from 'axios';
|
|
|
|
import * as chai from 'chai';
|
|
|
|
|
|
|
|
import {configForUser} from 'test/gen-server/testUtils';
|
|
|
|
import * as testUtils from 'test/server/testUtils';
|
|
|
|
|
2024-07-05 14:02:39 +00:00
|
|
|
import {HomeDBManager} from 'app/gen-server/lib/homedb/HomeDBManager';
|
2023-12-26 13:41:19 +00:00
|
|
|
|
|
|
|
import {TestServer} from 'test/gen-server/apiUtils';
|
|
|
|
|
|
|
|
const assert = chai.assert;
|
|
|
|
|
|
|
|
let server: TestServer;
|
|
|
|
let dbManager: HomeDBManager;
|
|
|
|
let homeUrl: string;
|
|
|
|
|
|
|
|
const charon = configForUser('Charon');
|
|
|
|
const chimpy = configForUser('Chimpy');
|
|
|
|
const kiwi = configForUser('Kiwi');
|
|
|
|
|
|
|
|
const chimpyEmail = 'chimpy@getgrist.com';
|
|
|
|
const kiwiEmail = 'kiwi@getgrist.com';
|
|
|
|
const charonEmail = 'charon@getgrist.com';
|
|
|
|
|
|
|
|
// Tests specific complex scenarios that may have previously resulted in wrong behavior.
|
|
|
|
describe('ApiServerBugs', function() {
|
|
|
|
|
|
|
|
testUtils.setTmpLogLevel('error');
|
|
|
|
let userRef: (email: string) => Promise<string>;
|
|
|
|
|
|
|
|
before(async function() {
|
|
|
|
server = new TestServer(this);
|
|
|
|
homeUrl = await server.start();
|
|
|
|
dbManager = server.dbManager;
|
|
|
|
userRef = (email) => server.dbManager.getUserByLogin(email).then((user) => user!.ref);
|
|
|
|
});
|
|
|
|
|
|
|
|
after(async function() {
|
|
|
|
await server.stop();
|
|
|
|
});
|
|
|
|
|
|
|
|
// Re-create a bug scenario in which users being in normal groups and guests groups at the
|
|
|
|
// same time resulted in them being dropped from groups arbitrarily on subsequent patches.
|
|
|
|
it('should properly handle users in multiple groups at once', async function() {
|
|
|
|
// Add Chimpy/Charon/Kiwi to 'Herring' doc and set inheritance to none. They
|
|
|
|
// will become guests in the 'Fish' org along with their owner/viewer roles.
|
|
|
|
const fishOrg = await dbManager.testGetId('Fish');
|
|
|
|
const herringDoc = await dbManager.testGetId('Herring');
|
|
|
|
const delta1 = {
|
|
|
|
maxInheritedRole: null,
|
|
|
|
users: {
|
|
|
|
[kiwiEmail]: 'editors',
|
|
|
|
[charonEmail]: 'viewers'
|
|
|
|
}
|
|
|
|
};
|
|
|
|
let resp = await axios.patch(`${homeUrl}/api/docs/${herringDoc}/access`, {
|
|
|
|
delta: delta1
|
|
|
|
}, chimpy);
|
|
|
|
assert.equal(resp.status, 200);
|
|
|
|
// Ensure that the doc access is as expected.
|
|
|
|
resp = await axios.get(`${homeUrl}/api/docs/${herringDoc}/access`, chimpy);
|
|
|
|
assert.equal(resp.status, 200);
|
|
|
|
assert.deepEqual(resp.data, {
|
|
|
|
maxInheritedRole: null,
|
|
|
|
users: [{
|
|
|
|
id: 1,
|
|
|
|
name: 'Chimpy',
|
|
|
|
email: chimpyEmail,
|
|
|
|
ref: await userRef(chimpyEmail),
|
|
|
|
picture: null,
|
|
|
|
parentAccess: "owners",
|
|
|
|
access: "owners",
|
|
|
|
isMember: true,
|
|
|
|
}, {
|
|
|
|
id: 2,
|
|
|
|
name: 'Kiwi',
|
|
|
|
email: kiwiEmail,
|
|
|
|
ref: await userRef(kiwiEmail),
|
|
|
|
picture: null,
|
|
|
|
parentAccess: "editors",
|
|
|
|
access: "editors",
|
|
|
|
isMember: true,
|
|
|
|
}, {
|
|
|
|
id: 3,
|
|
|
|
name: 'Charon',
|
|
|
|
email: charonEmail,
|
|
|
|
ref: await userRef(charonEmail),
|
|
|
|
picture: null,
|
|
|
|
parentAccess: "viewers",
|
|
|
|
access: "viewers",
|
|
|
|
isMember: true,
|
|
|
|
}]
|
|
|
|
});
|
|
|
|
|
|
|
|
// Remove Charon from the 'Fish' org and ensure that Chimpy and Kiwi still have
|
|
|
|
// owner/editor roles on 'Fish'. Charon should no longer have guest access to the org.
|
|
|
|
const delta2 = {
|
|
|
|
users: {
|
|
|
|
[charonEmail]: null
|
|
|
|
}
|
|
|
|
};
|
|
|
|
resp = await axios.patch(`${homeUrl}/api/orgs/${fishOrg}/access`, {
|
|
|
|
delta: delta2
|
|
|
|
}, chimpy);
|
|
|
|
assert.equal(resp.status, 200);
|
|
|
|
resp = await axios.get(`${homeUrl}/api/orgs/${fishOrg}/access`, chimpy);
|
|
|
|
assert.equal(resp.status, 200);
|
|
|
|
assert.deepEqual(resp.data, {
|
|
|
|
users: [{
|
|
|
|
id: 1,
|
|
|
|
name: 'Chimpy',
|
|
|
|
email: chimpyEmail,
|
|
|
|
ref: await userRef(chimpyEmail),
|
|
|
|
picture: null,
|
|
|
|
access: "owners",
|
|
|
|
isMember: true,
|
|
|
|
}, {
|
|
|
|
id: 2,
|
|
|
|
name: 'Kiwi',
|
|
|
|
email: kiwiEmail,
|
|
|
|
ref: await userRef(kiwiEmail),
|
|
|
|
picture: null,
|
|
|
|
access: "editors",
|
|
|
|
isMember: true,
|
|
|
|
}]
|
|
|
|
});
|
|
|
|
|
|
|
|
// Charon should no longer have access to the 'Herring' doc, now that user access
|
|
|
|
// is wiped entirely when removed from org.
|
|
|
|
resp = await axios.get(`${homeUrl}/api/docs/${herringDoc}`, charon);
|
|
|
|
assert.equal(resp.status, 403);
|
|
|
|
resp = await axios.get(`${homeUrl}/api/orgs/${fishOrg}`, charon);
|
|
|
|
assert.equal(resp.status, 403);
|
|
|
|
|
|
|
|
// Remove Kiwi as an editor from the 'Fish' org and ensure that Kiwi no longer has
|
|
|
|
// access to 'Fish' or 'Herring'
|
|
|
|
const delta3 = {
|
|
|
|
users: {
|
|
|
|
[kiwiEmail]: null
|
|
|
|
}
|
|
|
|
};
|
|
|
|
resp = await axios.patch(`${homeUrl}/api/orgs/${fishOrg}/access`, {
|
|
|
|
delta: delta3
|
|
|
|
}, chimpy);
|
|
|
|
assert.equal(resp.status, 200);
|
|
|
|
resp = await axios.get(`${homeUrl}/api/docs/${herringDoc}`, kiwi);
|
|
|
|
assert.equal(resp.status, 403);
|
|
|
|
resp = await axios.get(`${homeUrl}/api/orgs/${fishOrg}`, kiwi);
|
|
|
|
assert.equal(resp.status, 403);
|
|
|
|
|
|
|
|
// Restore initial access.
|
|
|
|
const delta4 = {
|
|
|
|
maxInheritedRole: "owners",
|
|
|
|
users: {
|
|
|
|
[charonEmail]: null,
|
|
|
|
[kiwiEmail]: null
|
|
|
|
}
|
|
|
|
};
|
|
|
|
resp = await axios.patch(`${homeUrl}/api/docs/${herringDoc}/access`, {
|
|
|
|
delta: delta4
|
|
|
|
}, chimpy);
|
|
|
|
assert.equal(resp.status, 200);
|
|
|
|
const delta5 = {
|
|
|
|
users: {
|
|
|
|
[kiwiEmail]: "editors",
|
|
|
|
[charonEmail]: "viewers"
|
|
|
|
}
|
|
|
|
};
|
|
|
|
resp = await axios.patch(`${homeUrl}/api/orgs/${fishOrg}/access`, {
|
|
|
|
delta: delta5
|
|
|
|
}, chimpy);
|
|
|
|
assert.equal(resp.status, 200);
|
|
|
|
});
|
|
|
|
});
|