Last active
October 9, 2023 14:21
-
-
Save jerodfritz/bfcea3b33bc39e533cd39f4ef788eb69 to your computer and use it in GitHub Desktop.
Strapi isOwners.js policy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
/** | |
* `isOwners` policy that allows for many owners and a private field == false individual querying or sharing with multiple users as readonly | |
*/ | |
const _ = require('lodash'); | |
let compareIDs = (a, b) => { | |
return a.toString() === b.toString(); | |
} | |
var pluralize = require('pluralize') | |
module.exports = async (ctx, next) => { | |
try { | |
let errMsg = "You are not allowed to perform this action."; | |
if (!ctx.state.user) { | |
ctx.state.user = { | |
id: undefined, | |
role: { | |
type: undefined | |
} | |
} | |
} | |
const { | |
id, | |
role, | |
} = ctx.state.user; | |
if (role.type !== 'root') { | |
// [find, count] Only query entities that owned by the current user or findone if private==false | |
if ( | |
//GraphQL Query | |
ctx.request.method == "POST" && ctx.request.url.startsWith("/graphql") || | |
// REST Get | |
ctx.request.method === 'GET' | |
) { | |
// Remove everything about owner in the query eg. owner.id_in, owner.id, owner etc. | |
// Remove everything about readonly in the query eg. readonly.id_in, readonly.id, readonly etc. | |
for (let key in ctx.query) { | |
if (key.includes("owners") || key.includes("readonly")) { | |
delete ctx.query[key]; | |
} | |
} | |
if (_.has(ctx, 'params.id') || _.has(ctx, 'params._where.id') || _.has(ctx, 'query.id')) { | |
// allow to pull single binder if private is false | |
ctx.query = Object.assign({ | |
_where: { | |
_or: [{ | |
'owners_in': id | |
}, { | |
'readonly': id | |
}, { | |
'private': false | |
}] | |
} | |
}, ctx.query); | |
} else { | |
// Reset owners to current user | |
ctx.query = Object.assign({ | |
_where: { | |
_or: [{ | |
'owners_in': id | |
}, { | |
'readonly': id | |
}] | |
} | |
}, ctx.query); | |
} | |
//console.log("GRAPHQL PARAMS", JSON.stringify(ctx.params)); | |
//console.log("GRAPHQL QUERRY", JSON.stringify(ctx.query)); | |
} | |
// [update, delete] Check owner of an existing entity | |
if ((ctx.request.method === 'DELETE' || ctx.request.method === 'PUT') && typeof ctx.params !== "undefined" && ctx.params !== null && typeof ctx.params.id !== "undefined" && ctx.params.id !== null && ctx.params.id !== '') { | |
// Extract model name from request path eg. /messages/15 | |
let path = ctx.request.path; | |
var modelName = path.split("/"); | |
if (Array.isArray(modelName) === false || modelName.length < 2 || modelName[1] === '') { | |
//console.log("isOwners: ctx.request.path", ctx.request.path, modelName) | |
return ctx.unauthorized(`isOwners: Invalid request ${ctx.request.path}`); | |
} | |
// Get existing entity and check for ownership | |
let existingEntity = await strapi.query(pluralize.singular(modelName[1])).findOne({ | |
id: ctx.params.id | |
}); | |
if (typeof existingEntity === "undefined" || existingEntity === null) { | |
return ctx.notFound('Not Found'); | |
} | |
let isAnOwner = _.find(existingEntity.owners, { | |
id: id.toString() | |
}); | |
if (!isAnOwner) { | |
return ctx.unauthorized(`${errMsg} [2]`); | |
} | |
// append owner to current owners | |
let owners = [id.toString()]; | |
owners = _.uniqWith(_.union(owners, existingEntity.owners.map(item => item.id)), compareIDs); | |
ctx.request.body.owners = owners; | |
} | |
// [create] Set owner for a new entity | |
if (!ctx.request.url.startsWith("/graphql") && ctx.request.method === 'POST') { | |
ctx.request.body.owners = [id.toString()]; | |
} | |
await next(); | |
} | |
} catch (error) { | |
strapi.plugins.sentry.services.sentry.sendError(error); | |
console.log("error", error); | |
return ctx.unauthorized(error); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment