mirror of
https://github.com/vale981/Vulcan
synced 2025-03-08 19:11:38 -05:00
243 lines
No EOL
6.3 KiB
JavaScript
243 lines
No EOL
6.3 KiB
JavaScript
|
||
|
||
|
||
|
||
|
||
// 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
|