Vulcan/packages/nova-users/lib/groups.js

243 lines
No EOL
6.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Note: something weird is happening here, and I don't f***ing get it. Try to assign something to the Users namespace (like Users.test = {};) and call it in modules.js -> undefined.
import Telescope from 'meteor/nova:lib';
import Users from './collection.js';
/**
* @summary Users.groups object
*/
Users.groups = {};
/**
* @summary Group class
*/
class Group {
constructor() {
this.actions = [];
}
can(actions) {
actions = Array.isArray(actions) ? actions : [actions];
this.actions = this.actions.concat(actions);
}
cannot(actions) {
actions = Array.isArray(actions) ? actions : [actions];
this.actions = _.difference(this.actions, actions);
}
}
////////////////////
// Helpers //
////////////////////
/**
* @summary create a new group
* @param {String} groupName
*/
Users.createGroup = groupName => {
Users.groups[groupName] = new Group();
};
/**
* @summary get a list of a user's groups
* @param {Object} user
*/
Users.getGroups = user => {
let userGroups = [];
if (!user) { // anonymous user
userGroups = ["anonymous"];
} else {
userGroups = ["default"];
if (user.__groups) { // custom groups
userGroups = userGroups.concat(user.__groups);
}
if (Users.isAdmin(user)) { // admin
userGroups.push("admins");
}
}
return userGroups;
};
/**
* @summary get a list of all the actions a user can perform
* @param {Object} user
*/
Users.getActions = user => {
const userGroups = Users.getGroups(user);
const groupActions = userGroups.map(groupName => {
// note: make sure groupName corresponds to an actual group
const group = Users.groups[groupName];
return group && group.actions;
});
return _.unique(_.flatten(groupActions));
};
/**
* @summary check if a user can perform a specific action on a specific document
* @param {Object} user
* @param {String} action
*/
Users.can = (user, action, document) => {
// TODO
};
/**
* @summary check if a user can perform a specific action
* @param {Object} user
* @param {String} action
*/
Users.canDo = (user, action) => {
return Users.getActions(user).indexOf(action) !== -1;
};
/**
* @summary Check if a given user can view a specific document
* @param {Object} user - can be undefined!
* @param {Object} document - Note: only actually works with posts for now
*/
Users.canView = function (user, document) {
const status = _.findWhere(Telescope.statuses, {value: document.status}).label;
// note(apollo): use of `__typename` given by react-apollo
//const collectionName = document.getCollectionName();
const collectionName = document.__typename ? Telescope.utils.getCollectionNameFromTypename(document.__typename) : document.getCollectionName();
if (!document) {
return false;
}
if (Users.owns(user, document)) {
return Users.canDo(user, `${collectionName}.view.${status}.own`);
} else {
return Users.canDo(user, `${collectionName}.view.${status}.all`);
}
};
/**
* @summary Check if a given user can view a specific field
* @param {Object} user - can be undefined!
* @param {Object} collection
* @param {String} fieldName
*/
Users.canViewField = function (user, collection, fieldName) {
const schema = collection.simpleSchema()._schema;
const field = schema[fieldName];
return field.viewableIf(user);
};
/**
* @summary Check if a user can edit a document
* @param {Object} user - The user performing the action
* @param {Object} document - The document being edited
*/
Users.canEdit = function (user, document) {
user = (typeof user === 'undefined') ? Meteor.user() : user;
// note(apollo): use of `__typename` given by react-apollo
//const collectionName = document.getCollectionName();
const collectionName = document.__typename ? Telescope.utils.getCollectionNameFromTypename(document.__typename) : document.getCollectionName();
if (!user || !document) {
return false;
}
if (document.hasOwnProperty('isDeleted') && document.isDeleted) return false;
if (Users.owns(user, document)) {
// if this is user's document, check if user can edit own documents
return Users.canDo(user, `${collectionName}.edit.own`);
} else {
// if this is not user's document, check if they can edit all documents
return Users.canDo(user, `${collectionName}.edit.all`);
}
};
/**
* @summary Check if a user owns a document
* @param {Object|string} userOrUserId - The user or their userId
* @param {Object} document - The document to check (post, comment, user object, etc.)
*/
Users.owns = function (user, document) {
try {
if (!!document.userId) {
// case 1: document is a post or a comment, use userId to check
return user._id === document.userId;
} else {
// case 2: document is a user, use _id to check
return user._id === document._id;
}
} catch (e) {
return false; // user not logged in
}
};
// Users.helpers({owns: function (document) {return Users.owns(this, document);}});
/**
* @summary Check if a user is an admin
* @param {Object|string} userOrUserId - The user or their userId
*/
Users.isAdmin = function (userOrUserId) {
try {
var user = Users.getUser(userOrUserId);
return !!user && !!user.isAdmin;
} catch (e) {
return false; // user not logged in
}
};
Users.isAdminById = Users.isAdmin;
// use _isAdmin because there is an isAdmin property on the User schema already
// Users.helpers({_isAdmin: function () {return Users.isAdmin(this);}});
/**
* @summary Check if a user can submit a field
* @param {Object} user - The user performing the action
* @param {Object} field - The field being edited or inserted
*/
Users.canSubmitField = function (user, field) {
return user && field.insertableIf && field.insertableIf(user);
};
/** @function
* Check if a user can edit a field for now, identical to Users.canSubmitField
* @param {Object} user - The user performing the action
* @param {Object} field - The field being edited or inserted
*/
Users.canEditField = function (user, field, document) {
return user && field.editableIf && field.editableIf(user, document);
};
////////////////////
// Initialize //
////////////////////
/**
* @summary initialize the 3 out-of-the-box groups
*/
Users.createGroup("anonymous"); // non-logged-in users
Users.createGroup("default"); // regular users
Users.createGroup("admins"); // admin users