182 lines
4.3 KiB
JavaScript
182 lines
4.3 KiB
JavaScript
import { includes } from 'lodash';
|
|
import fetchDocByRef from '/imports/api/parenting/fetchDocByRef.js';
|
|
|
|
function assertIdValid(userId) {
|
|
if (!userId || typeof userId !== 'string') {
|
|
throw new Meteor.Error('Permission denied',
|
|
'No user ID. Are you logged in?');
|
|
}
|
|
}
|
|
|
|
function assertdocExists(doc) {
|
|
if (!doc) {
|
|
throw new Meteor.Error('Permission denied',
|
|
'Permission denied: No such document exists');
|
|
}
|
|
}
|
|
|
|
export function assertOwnership(doc, userId) {
|
|
assertIdValid(userId);
|
|
assertdocExists(doc);
|
|
|
|
if (doc.owner === userId) {
|
|
return true;
|
|
} else {
|
|
throw new Meteor.Error('Permission denied',
|
|
'You are not the owner of this document');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Assert that the user can edit the root document which manages its own sharing
|
|
* permissions.
|
|
*
|
|
* Warning: the doc and userId must be set by a trusted source
|
|
*/
|
|
export function assertEditPermission(doc, userId) {
|
|
assertIdValid(userId);
|
|
assertdocExists(doc);
|
|
const user = Meteor.users.findOne(userId, {
|
|
fields: {
|
|
'roles': 1,
|
|
}
|
|
});
|
|
|
|
// Admin override
|
|
if (user.roles && user.roles.includes('admin')) {
|
|
return true;
|
|
}
|
|
|
|
// Ensure the user is authorized for this specific document
|
|
if (
|
|
doc.owner === userId ||
|
|
includes(doc.writers, userId)
|
|
) {
|
|
return true;
|
|
} else {
|
|
throw new Meteor.Error('Edit permission denied',
|
|
'You do not have permission to edit this document');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Assert that the user can edit the root document which manages its own sharing
|
|
* permissions.
|
|
*
|
|
* Warning: the doc and userId must be set by a trusted source
|
|
*/
|
|
export function assertCopyPermission(doc, userId) {
|
|
assertIdValid(userId);
|
|
assertdocExists(doc);
|
|
const user = Meteor.users.findOne(userId, {
|
|
fields: {
|
|
'roles': 1,
|
|
}
|
|
});
|
|
|
|
// Admin override
|
|
if (user.roles && user.roles.includes('admin')) {
|
|
return true;
|
|
}
|
|
|
|
// Ensure the user is authorized for this specific document
|
|
if (
|
|
doc.owner === userId ||
|
|
includes(doc.writers, userId)
|
|
) {
|
|
return true;
|
|
} else if (
|
|
(includes(doc.readers, userId) || doc.public) &&
|
|
doc.readersCanCopy
|
|
) {
|
|
return true;
|
|
} else {
|
|
throw new Meteor.Error('Copy permission denied',
|
|
'You do not have permission to copy this document');
|
|
}
|
|
}
|
|
|
|
function getRoot(doc) {
|
|
assertdocExists(doc);
|
|
if (doc.ancestors && doc.ancestors.length && doc.ancestors[0]) {
|
|
return fetchDocByRef(doc.ancestors[0]);
|
|
} else {
|
|
return doc;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Assert that the user can edit a descendant document whose root ancestor
|
|
* implements sharing permissions.
|
|
*
|
|
* Warning: the doc and userId must be set by a trusted source
|
|
*/
|
|
export function assertDocEditPermission(doc, userId) {
|
|
let root = getRoot(doc);
|
|
assertEditPermission(root, userId);
|
|
}
|
|
|
|
/**
|
|
* Assert that the user can copy a descendant document whose root ancestor
|
|
* implements sharing permissions.
|
|
*
|
|
* Warning: the doc and userId must be set by a trusted source
|
|
*/
|
|
export function assertDocCopyPermission(doc, userId) {
|
|
let root = getRoot(doc);
|
|
assertCopyPermission(root, userId);
|
|
}
|
|
|
|
export function assertViewPermission(doc, userId) {
|
|
assertdocExists(doc);
|
|
if (doc.public) return true;
|
|
assertIdValid(userId);
|
|
|
|
if (
|
|
doc.owner === userId ||
|
|
includes(doc.readers, userId) ||
|
|
includes(doc.writers, userId)
|
|
) {
|
|
return true;
|
|
} else {
|
|
|
|
// Admin override
|
|
const user = Meteor.users.findOne(userId, {
|
|
fields: {
|
|
'roles': 1,
|
|
}
|
|
});
|
|
if (user.roles && user.roles.includes('admin')) {
|
|
return true;
|
|
}
|
|
|
|
throw new Meteor.Error('View permission denied',
|
|
'You do not have permission to view this document');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Assert that the user can view a descendant document whose root ancestor
|
|
* implements sharing permissions.
|
|
*
|
|
* Warning: the doc and userId must be set by a trusted source
|
|
*/
|
|
export function assertDocViewPermission(doc, userId) {
|
|
let root = getRoot(doc);
|
|
assertViewPermission(root, userId);
|
|
}
|
|
|
|
export function assertAdmin(userId) {
|
|
assertIdValid(userId);
|
|
let user = Meteor.users.findOne(userId, { fields: { roles: 1 } });
|
|
if (!user) {
|
|
throw new Meteor.Error('Permission denied',
|
|
'UserId does not match any existing user');
|
|
}
|
|
let isAdmin = user.roles && user.roles.includes('admin')
|
|
if (!isAdmin) {
|
|
throw new Meteor.Error('Permission denied',
|
|
'User does not have the admin role');
|
|
}
|
|
}
|