@websolutespa/payload-plugin-bowl
Version:
Bowl PayloadCms plugin of the BOM Repository
181 lines (180 loc) • 6.52 kB
JavaScript
import { options } from '../../options';
import { roles } from '../../types';
import { isMixerRequest } from '../api';
const isUserWithRoles = (user)=>{
return user ? 'roles' in user && Array.isArray(user.roles) && user.roles.reduce((p, c)=>p && options.rolesList.includes(c), true) : false;
};
const isUserWithTenants = (user)=>{
return user ? user.collection !== undefined && 'tenants' in user && Array.isArray(user.tenants) && user.tenants.length > 0 : false;
};
// !!! temporary fix expect ClientUser also
export const hasRole = (user_, ...roles)=>{
const user = user_;
if (!isUserWithRoles(user)) {
return false;
}
// console.log('isUserWithRoles', roles, user.roles);
// return true if the user has at least one of the roles in the roles arg (or the roles arg is empty and the user has any role at all)
return roles.length === 0 ? user.roles.length > 0 : user.roles.find((x)=>roles.includes(x)) !== undefined;
};
export const isRole = (...roles)=>(args)=>{
const { req: { user } } = args;
// console.log('isRole', user?.roles);
return hasRole(user, ...roles);
};
export const isPageRole = (...roles)=>(args)=>{
const { req } = args;
const { user } = req;
if (!hasRole(user, ...roles)) {
return false;
}
if (isMixerRequest(req) && req.query?.draft !== 'true') {
return {
or: [
{
_status: {
equals: 'published'
}
},
{
_status: {
exists: false
}
}
]
};
} else {
return true;
}
};
export const isAdmin = (args)=>{
// console.log('isAdmin', roles.Admin, args.req.user?.roles);
return isRole(roles.Admin)(args);
};
export const isSelf = (args)=>{
const { req } = args;
const user = req.user;
if (!user) {
return false;
}
if (user.collection !== options.slug.users && !hasRole(user, roles.User)) return false;
return {
id: {
equals: user.id
}
};
};
export const isOwn = (args)=>{
const { req } = args;
const user = req.user;
if (!hasRole(user, roles.User)) return false;
return {
'user.id': {
equals: user.id
}
};
};
export const isAdminOrSelf = (args)=>{
return isAdmin(args) || isSelf(args);
};
export const isAdminOrOwn = (args)=>{
return isAdmin(args) || isOwn(args);
};
export const isTenant = (slug)=>(args)=>{
const { req } = args;
const { payload } = req;
const user = req.user;
if (!isUserWithTenants(user)) {
return false;
}
// find collections used as tenants (es: ['market', 'llmApp'])
const userCollection = payload.config.collections.find((x)=>x.slug === user.collection);
const tenantsField = (userCollection?.fields || []).find((x)=>x.type === 'relationship' && x.name === 'tenants');
const tenantCollections = [];
if (Array.isArray(tenantsField?.relationTo)) {
tenantCollections.push(...tenantsField.relationTo);
} else {
tenantCollections.push(tenantsField.relationTo);
}
const isPolymorphicRel = Array.isArray(tenantsField.relationTo);
const isTenantDoc = tenantCollections.includes(slug);
if (isTenantDoc) {
// the doc itself is a tenant, check if the user has access to it
const query = {
id: {
in: isPolymorphicRel ? user.tenants.filter((x)=>x.relationTo === slug).map((x)=>x.value?.id) : user.tenants.map((x)=>x.id)
}
};
return query;
}
// find fields in the collection that are relationships to tenants collections
const collectionConfig = payload.config.collections.find((x)=>x.slug === slug);
const fields = (collectionConfig?.fields || []).filter((field)=>field.type === 'relationship' && tenantCollections.find((x)=>field.relationTo.includes(x)) !== undefined);
if (!fields.length) {
// the doc is neither a tenant nor has any field that is a relationship to a tenant collection, the user cannot access it
return false;
}
// for each field, check if its value is in the user's tenants (or is empty)
const query = {
and: fields.map((field)=>({
or: [
{
[field.name]: {
in: isPolymorphicRel ? user.tenants.filter((x)=>x.relationTo === field.relationTo).map((x)=>x.value?.id) : user.tenants.map((x)=>x.id)
}
},
// if the doc is not restricted to any tenant, we can access it
{
[field.name]: {
exists: false
}
},
{
[field.name]: {
equals: ''
}
},
{
[field.name]: {
equals: null
}
},
{
[field.name]: {
equals: []
}
}
]
}))
};
return query;
};
export const orAccess = (...access)=>{
return async (args)=>{
const wheres = [];
let result = false;
for (const a of access){
if (result === true) {
return result;
}
const r = await a(args);
if (typeof r === 'boolean') {
result = r;
} else {
wheres.push(r);
}
}
const l = wheres.length;
if (l === 0) {
return false;
} else if (l === 1) {
return wheres[0];
}
const where = {
or: wheres
};
// console.log('where', JSON.stringify(where));
return where;
};
};
//# sourceMappingURL=access.js.map