const _ = require('underscore');
const AVError = require('./error');
module.exports = function(AV) {
AV.Role = AV.Object.extend(
'_Role',
/** @lends AV.Role.prototype */ {
// Instance Methods
/**
* Represents a Role on the AV server. Roles represent groupings of
* Users for the purposes of granting permissions (e.g. specifying an ACL
* for an Object). Roles are specified by their sets of child users and
* child roles, all of which are granted any permissions that the parent
* role has.
*
* <p>Roles must have a name (which cannot be changed after creation of the
* role), and must specify an ACL.</p>
* An AV.Role is a local representation of a role persisted to the AV
* cloud.
* @class AV.Role
* @param {String} name The name of the Role to create.
* @param {AV.ACL} acl The ACL for this role.
*/
constructor: function(name, acl) {
if (_.isString(name)) {
AV.Object.prototype.constructor.call(this, null, null);
this.setName(name);
} else {
AV.Object.prototype.constructor.call(this, name, acl);
}
if (acl) {
if (!(acl instanceof AV.ACL)) {
throw new TypeError('acl must be an instance of AV.ACL');
} else {
this.setACL(acl);
}
}
},
/**
* Gets the name of the role. You can alternatively call role.get("name")
*
* @return {String} the name of the role.
*/
getName: function() {
return this.get('name');
},
/**
* Sets the name for a role. This value must be set before the role has
* been saved to the server, and cannot be set once the role has been
* saved.
*
* <p>
* A role's name can only contain alphanumeric characters, _, -, and
* spaces.
* </p>
*
* <p>This is equivalent to calling role.set("name", name)</p>
*
* @param {String} name The name of the role.
*/
setName: function(name, options) {
return this.set('name', name, options);
},
/**
* Gets the AV.Relation for the AV.Users that are direct
* children of this role. These users are granted any privileges that this
* role has been granted (e.g. read or write access through ACLs). You can
* add or remove users from the role through this relation.
*
* <p>This is equivalent to calling role.relation("users")</p>
*
* @return {AV.Relation} the relation for the users belonging to this
* role.
*/
getUsers: function() {
return this.relation('users');
},
/**
* Gets the AV.Relation for the AV.Roles that are direct
* children of this role. These roles' users are granted any privileges that
* this role has been granted (e.g. read or write access through ACLs). You
* can add or remove child roles from this role through this relation.
*
* <p>This is equivalent to calling role.relation("roles")</p>
*
* @return {AV.Relation} the relation for the roles belonging to this
* role.
*/
getRoles: function() {
return this.relation('roles');
},
/**
* @ignore
*/
validate: function(attrs, options) {
if ('name' in attrs && attrs.name !== this.getName()) {
var newName = attrs.name;
if (this.id && this.id !== attrs.objectId) {
// Check to see if the objectId being set matches this.id.
// This happens during a fetch -- the id is set before calling fetch.
// Let the name be set in this case.
return new AVError(
AVError.OTHER_CAUSE,
"A role's name can only be set before it has been saved."
);
}
if (!_.isString(newName)) {
return new AVError(
AVError.OTHER_CAUSE,
"A role's name must be a String."
);
}
if (!/^[0-9a-zA-Z\-_ ]+$/.test(newName)) {
return new AVError(
AVError.OTHER_CAUSE,
"A role's name can only contain alphanumeric characters, _," +
' -, and spaces.'
);
}
}
if (AV.Object.prototype.validate) {
return AV.Object.prototype.validate.call(this, attrs, options);
}
return false;
},
}
);
};