diff --git a/lib/www/client/source/src/lib/organisations/operations.js b/lib/www/client/source/src/lib/organisations/operations.js new file mode 120000 index 0000000..0532ad1 --- /dev/null +++ b/lib/www/client/source/src/lib/organisations/operations.js @@ -0,0 +1 @@ +../../../../../server/lib/organisations/operations.js \ No newline at end of file diff --git a/lib/www/server/lib/db/project/organisations.js b/lib/www/server/lib/db/project/organisations.js index 40d28de..b34b50b 100644 --- a/lib/www/server/lib/db/project/organisations.js +++ b/lib/www/server/lib/db/project/organisations.js @@ -1,6 +1,6 @@ const { setSurvey, pool } = require('../connection'); const { vessel } = require('../vesel'); -const { access } = require('../../organisations'); +const { access, operations } = require('../../organisations'); const { ALERT, ERROR, WARNING, NOTICE, INFO, DEBUG } = require('DOUGAL_ROOT/debug')(__filename); // Cache the per-project organisations access here @@ -62,15 +62,23 @@ async function orgAccess (userOrgs, pid, operation) { return access(userOrgs, itemOrgs, operation); } +/** Check to which operations the user has access to in the + * project given by 'pid`. + * + * If `pid` is `null`, check against vessel access. + */ +async function allowedOperations (userOrgs, pid) { + const itemOrgs = pid === null + ? await vesselOrganisations() + : await projectOrganisations(pid); + + return operations(userOrgs, itemOrgs); +} + /* * Filter an array of objects by organisation access to a given operation */ function orgFilter (userOrgs, list, operation, fn = (item) => item.organisations ) { - console.log("orgFilter"); - console.log("userOrgs", userOrgs); - console.log("list", list); - console.log("operation", operation); - console.log("fn", fn); return list.filter ( (item) => access(userOrgs, fn(item), operation) ); } @@ -79,5 +87,6 @@ module.exports = { projectOrganisations, vesselOrganisations, orgAccess, + allowedOperations, orgFilter }; diff --git a/lib/www/server/lib/organisations/index.js b/lib/www/server/lib/organisations/index.js index 1ffb374..075ee24 100644 --- a/lib/www/server/lib/organisations/index.js +++ b/lib/www/server/lib/organisations/index.js @@ -1,3 +1,4 @@ module.exports = { - access: require('./access.js') + access: require('./access.js'), + operations: require('./operations.js'), }; diff --git a/lib/www/server/lib/organisations/operations.js b/lib/www/server/lib/organisations/operations.js new file mode 100644 index 0000000..dc5d5c9 --- /dev/null +++ b/lib/www/server/lib/organisations/operations.js @@ -0,0 +1,46 @@ + +/** List the operations to which the user has access + * + * @a userOrgs is the user's organisations + * @a itemOrgs is the item's organisations + * + */ +function operations (userOrgs = {}, itemOrgs = {}) { + // console.log("userOrgs", userOrgs); + // console.log("itemOrgs", itemOrgs); + const ops = []; + + for (const userOrg in userOrgs) { + for (const operation in userOrgs[userOrg]) { + if (userOrg in itemOrgs) { + // Found an organisation in common between user and project + // (there might be many) + if (itemOrgs[userOrg][operation] == true && userOrgs[userOrg][operation] == true) { + ops.push[operation]; + } + } + } + } + if ("*" in userOrgs) { + // Aha! A wildcard user + // Return true if at least one organisation grants access + // to this operation + // console.log("Checking via wildcard"); + for (const operation in userOrgs["*"]) { + if (Object.values(itemOrgs).some( org => org[operation] )) { + ops.push(operation); + } + } + } + return ops; + +} + +if (typeof module !== 'undefined' && module.exports) { + module.exports = operations; // CJS export +} + +// ESM export +if (typeof exports !== 'undefined' && !exports.default) { + exports.default = operations; // ESM export +}