2016-11-22 18:14:51 -05:00
// 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.
2016-08-10 10:40:17 +09:00
import Telescope from 'meteor/nova:lib' ;
2016-07-19 17:30:59 +09:00
import Users from './collection.js' ;
2016-07-20 10:25:05 +09:00
/ * *
* @ summary Users . groups object
* /
Users . groups = { } ;
2016-07-19 17:30:59 +09:00
/ * *
* @ summary Group class
* /
class Group {
constructor ( ) {
this . actions = [ ] ;
}
can ( actions ) {
2016-09-11 14:49:56 +08:00
actions = Array . isArray ( actions ) ? actions : [ actions ] ;
2016-07-19 17:30:59 +09:00
this . actions = this . actions . concat ( actions ) ;
}
cannot ( actions ) {
2016-09-11 14:49:56 +08:00
actions = Array . isArray ( actions ) ? actions : [ actions ] ;
2016-07-19 17:30:59 +09:00
this . actions = _ . difference ( this . actions , actions ) ;
}
}
2016-07-21 15:02:20 +09:00
////////////////////
// Helpers //
////////////////////
2016-07-19 17:30:59 +09:00
/ * *
* @ 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" ] ;
2016-11-10 14:22:47 +01:00
if ( user . _ _groups ) { // custom groups
userGroups = userGroups . concat ( user . _ _groups ) ;
2016-07-19 17:30:59 +09:00
}
2016-07-21 14:51:58 +09:00
if ( Users . isAdmin ( user ) ) { // admin
2016-07-19 17:30:59 +09:00
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 ) ;
2016-07-21 12:38:11 +09:00
const groupActions = userGroups . map ( groupName => {
// note: make sure groupName corresponds to an actual group
const group = Users . groups [ groupName ] ;
return group && group . actions ;
} ) ;
2016-07-19 17:30:59 +09:00
return _ . unique ( _ . flatten ( groupActions ) ) ;
} ;
2016-11-22 16:15:26 +09:00
/ * *
* @ 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
} ;
2016-07-19 17:30:59 +09:00
/ * *
* @ 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 ;
} ;
2016-07-20 10:25:05 +09:00
/ * *
* @ 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 ) {
2016-08-10 10:40:17 +09:00
const status = _ . findWhere ( Telescope . statuses , { value : document . status } ) . label ;
2016-10-19 17:38:21 +02:00
// note(apollo): use of `__typename` given by react-apollo
//const collectionName = document.getCollectionName();
const collectionName = document . _ _typename ? Telescope . utils . getCollectionNameFromTypename ( document . _ _typename ) : document . getCollectionName ( ) ;
2016-07-20 10:25:05 +09:00
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 ` ) ;
}
} ;
2016-10-29 14:17:57 +09:00
/ * *
* @ 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 ) ;
} ;
2016-07-20 10:25:05 +09:00
/ * *
* @ 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 ;
2016-10-19 17:38:21 +02:00
// note(apollo): use of `__typename` given by react-apollo
//const collectionName = document.getCollectionName();
2016-11-22 16:15:26 +09:00
const collectionName = document . _ _typename ? Telescope . utils . getCollectionNameFromTypename ( document . _ _typename ) : document . getCollectionName ( ) ;
2016-10-19 17:38:21 +02:00
2016-07-20 10:25:05 +09:00
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 ` ) ;
}
} ;
2016-07-21 15:02:20 +09:00
/ * *
* @ 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
}
} ;
2016-11-22 18:14:51 -05:00
// Users.helpers({owns: function (document) {return Users.owns(this, document);}});
2016-07-21 15:02:20 +09:00
/ * *
* @ 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
2016-11-22 18:14:51 -05:00
// Users.helpers({_isAdmin: function () {return Users.isAdmin(this);}});
2016-07-21 15:02:20 +09:00
2016-07-20 10:25:05 +09:00
/ * *
* @ 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 ) ;
} ;
/ * * @ f u n c t i o n
* 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 ) ;
} ;
2016-07-19 17:30:59 +09:00
2016-07-21 15:02:20 +09:00
////////////////////
// Initialize //
////////////////////
2016-07-19 17:30:59 +09:00
/ * *
* @ summary initialize the 3 out - of - the - box groups
* /
Users . createGroup ( "anonymous" ) ; // non-logged-in users
Users . createGroup ( "default" ) ; // regular users
2016-11-22 18:14:51 -05:00
Users . createGroup ( "admins" ) ; // admin users