groups: add app access tests

This commit is contained in:
Girish Ramakrishnan
2025-02-12 14:09:09 +01:00
parent fda0a918f0
commit bd44bb4534
5 changed files with 153 additions and 15 deletions
+1 -1
View File
@@ -310,7 +310,7 @@ async function registerCloudron(data) {
// app could already have been installed if we deleted the cloudron.io record and user re-registers
for (const app of await apps.list()) {
await purchaseApp({ appId: app.id, appstoreId: app.appStoreId, manifestId: app.manifest.id || 'customapp' });
await safe(purchaseApp({ appId: app.id, appstoreId: app.appStoreId, manifestId: app.manifest.id || 'customapp' }), { debug });
}
}
+16 -11
View File
@@ -83,7 +83,7 @@ async function add(group, auditSource) {
await eventlog.add(eventlog.ACTION_GROUP_ADD, auditSource, { id, name, source });
return { id, name, source };
return { id, name, source, appIds: [] };
}
async function del(group, auditSource) {
@@ -101,12 +101,21 @@ async function del(group, auditSource) {
await eventlog.add(eventlog.ACTION_GROUP_REMOVE, auditSource, { group });
}
async function postProcess(group) {
assert.strictEqual(typeof group, 'object');
const results = await database.query('SELECT id FROM apps WHERE JSON_CONTAINS(accessRestrictionJson, ?, "$.groups")', [ `"${group.id}"` ]);
group.appIds = results.map(r => r.id);
}
async function get(id) {
assert.strictEqual(typeof id, 'string');
const result = await database.query(`SELECT ${GROUPS_FIELDS} FROM userGroups WHERE id = ? ORDER BY name`, [ id ]);
if (result.length === 0) return null;
await postProcess(result[0]);
return result[0];
}
@@ -116,16 +125,11 @@ async function getByName(name) {
const result = await database.query(`SELECT ${GROUPS_FIELDS} FROM userGroups WHERE name = ?`, [ name ]);
if (result.length === 0) return null;
await postProcess(result[0]);
return result[0];
}
async function getAppIds(groupId) {
assert.strictEqual(typeof groupId, 'string');
const results = await database.query('SELECT id FROM apps WHERE JSON_CONTAINS(accessRestrictionJson, ?, "$.groups")', [ `"${groupId}"` ]);
return results.map(r => r.id);
}
async function getWithMembers(id) {
assert.strictEqual(typeof id, 'string');
@@ -138,7 +142,8 @@ async function getWithMembers(id) {
const result = results[0];
result.userIds = result.userIds ? result.userIds.split(',') : [ ];
result.appIds = await getAppIds(result.id);
await postProcess(result);
return result;
}
@@ -147,7 +152,7 @@ async function list() {
const results = await database.query('SELECT ' + GROUPS_FIELDS + ' FROM userGroups ORDER BY name');
for (const r of results) {
r.appIds = await getAppIds(r.id);
await postProcess(r);
}
return results;
@@ -161,7 +166,7 @@ async function listWithMembers() {
results.forEach(function (result) { result.userIds = result.userIds ? result.userIds.split(',') : [ ]; });
for (const r of results) {
r.appIds = await getAppIds(r.id);
await postProcess(r);
}
return results;
+52 -1
View File
@@ -1,6 +1,7 @@
'use strict';
const appstore = require('../../appstore.js'),
const apps = require('../../apps.js'),
appstore = require('../../appstore.js'),
debug = require('debug')('box:test/common'),
constants = require('../../constants.js'),
database = require('../../database.js'),
@@ -17,6 +18,34 @@ const appstore = require('../../appstore.js'),
timers = require('timers/promises'),
tokens = require('../../tokens.js');
const manifest = {
'id': 'io.cloudron.test',
'author': 'The Presidents Of the United States Of America',
'title': 'test title',
'description': 'test description',
'tagline': 'test rocks',
'website': 'http://test.cloudron.io',
'contactEmail': 'test@cloudron.io',
'version': '0.1.0',
'manifestVersion': 2,
'dockerImage': 'cloudron/test:25.2.0',
'healthCheckPath': '/',
'httpPort': 7777,
'tcpPorts': {
'ECHO_SERVER_PORT': {
'title': 'Echo Server Port',
'description': 'Echo server',
'containerPort': 7778
}
},
'addons': {
'oauth': { },
'redis': { },
'mysql': { },
'postgresql': { }
}
};
exports = module.exports = {
setup,
setupServer,
@@ -50,6 +79,25 @@ exports = module.exports = {
token: null
},
app: {
id: 'appid',
appStoreId: 'appStoreId',
installationState: apps.ISTATE_PENDING_INSTALL,
runState: 'running',
subdomain: 'app',
domain: 'test.example.com',
fqdn: 'app.test.example.com',
manifest,
containerId: 'someid',
portBindings: {},
accessRestriction: null,
memoryLimit: 0,
mailboxDomain: 'test.example.com',
secondaryDomains: [],
redirectDomains: [],
aliasDomains: []
},
mockApiServerOrigin: 'http://localhost:6060',
dashboardDomain: 'test.example.com',
dashboardFqdn: 'my.test.example.com',
@@ -114,6 +162,9 @@ async function setup() {
const token2 = await tokens.add({ identifier: user.id, clientId: tokens.ID_WEBADMIN, expires: Date.now() + (60 * 60 * 1000), name: 'fromtest' });
user.token = token2.accessToken;
// create app object
await apps.add(exports.app.id, exports.app.appStoreId, exports.app.manifest, exports.app.subdomain, exports.app.domain, exports.app.portBindings, exports.app);
await settings._set(settings.APPSTORE_API_TOKEN_KEY, exports.appstoreToken); // appstore token
debug('Setup complete');
+26 -1
View File
@@ -14,7 +14,7 @@ const GROUP_NAME = 'externals';
let group0Object, group1Object;
describe('Groups API', function () {
const { setup, cleanup, serverUrl, owner, user } = common;
const { setup, cleanup, serverUrl, owner, user, app } = common;
before(setup);
after(cleanup);
@@ -176,6 +176,31 @@ describe('Groups API', function () {
expect(response.statusCode).to.equal(200);
});
it('cannot set unknown app access', async function () {
const response = await superagent.put(`${serverUrl}/api/v1/groups/${group1Object.id}/apps`)
.query({ access_token: owner.token })
.send({ appIds: ['app-id' ] })
.ok(() => true);
expect(response.statusCode).to.equal(200); // bad appId is just ignored
});
it('can set app access', async function () {
const response = await superagent.put(`${serverUrl}/api/v1/groups/${group1Object.id}/apps`)
.query({ access_token: owner.token })
.send({ appIds: [app.id] });
expect(response.statusCode).to.equal(200);
});
it('did set app access', async function () {
const response = await superagent.get(`${serverUrl}/api/v1/groups`)
.query({ access_token: owner.token });
const group1 = response.body.groups.filter(g => g.id === group1Object.id)[0];
expect(group1.appIds).to.eql([app.id]);
});
it('remove user from group', async function () {
const response = await superagent.put(`${serverUrl}/api/v1/users/${user.id}/groups`)
.query({ access_token: owner.token })
+58 -1
View File
@@ -13,7 +13,7 @@ const BoxError = require('../boxerror.js'),
safe = require('safetydance');
describe('Groups', function () {
const { setup, cleanup, admin, user, auditSource } = common;
const { setup, cleanup, admin, user, auditSource, app } = common;
before(setup);
after(cleanup);
@@ -196,6 +196,63 @@ describe('Groups', function () {
});
});
describe('app access', function () {
let groupObject;
before(async function () {
const [error, result] = await safe(groups.add({ name: 'kootam' }, auditSource));
expect(error).to.be(null);
groupObject = result;
});
it('has no app access', async function () {
expect(groupObject.appIds).to.eql([]);
const g1 = await groups.get(groupObject.id);
expect(g1.appIds).to.eql([]);
const g2 = await groups.getByName(groupObject.name);
expect(g2.appIds).to.eql([]);
const g3 = await groups.getWithMembers(groupObject.id);
expect(g3.appIds).to.eql([]);
});
it('set app access', async function () {
await groups.setAllowedApps(groupObject, [ app.id ], auditSource);
const g1 = await groups.get(groupObject.id);
expect(g1.appIds).to.eql([ app.id ]);
const g2 = await groups.getByName(groupObject.name);
expect(g2.appIds).to.eql([ app.id ]);
const g3 = await groups.getWithMembers(groupObject.id);
expect(g3.appIds).to.eql([ app.id ]);
const allGroups = await groups.listWithMembers();
const g4 = allGroups.filter(g => g.id === groupObject.id)[0];
expect(g4.appIds).to.eql([ app.id ]);
});
it('cleared app access', async function () {
await groups.setAllowedApps(groupObject, [ ], auditSource);
const g1 = await groups.get(groupObject.id);
expect(g1.appIds).to.eql([ ]);
const g2 = await groups.getByName(groupObject.name);
expect(g2.appIds).to.eql([ ]);
const g3 = await groups.getWithMembers(groupObject.id);
expect(g3.appIds).to.eql([ ]);
const allGroups = await groups.listWithMembers();
const g4 = allGroups.filter(g => g.id === groupObject.id)[0];
expect(g4.appIds).to.eql([ ]);
});
});
describe('ldap group', function () {
let ldapGroup;