<commit_before>/* global ObjectACLSvc: true */

/** @constructor
 *  
 *  @param {Object} collection - The Mongo.Collection to attach the ACL to
 *  @param {Object} [permissions] - A mapping of permission types to interger
 *    values. Each permission with a higher value than another automatically
 *    implies the lower -- e.g. if the permissions are {read: 10, write: 20},
 *    then anyone with write permission automatically has read permisison.
 *  @param {String} [options.superPermission=_super] - Name of the permission
 *    that has access to everything else.
 *  @param {String} [options.permissionListVar=permissions] - Name of field on 
 *    the collection on which to use for our ACL
 *  @param {String} [options.superListVar=superIds] - Name of field on the
 *    collection which gets populated with a list of userIds with the super
 *    permission. This is used to ensure that we can never unset the number
 *    users with super permissions below zero.
 *  @param {[String]} [options.defaultPermissions=super] - List of permissions 
 *    to assign to users by default if no others are given. Default to the 
 *    super permission
 */
ObjectACLSvc = function(collection, permissions, options) {
  'use strict';
  if (! collection) {
    throw new Meteor.Error(500, "missing-collection");
  }

  options = options || {};
  check(options, {
    superPermission: Match.Optional(String),
    permissionListVar: Match.Optional(String),
    superListVar: Match.Optional(String),
    defaultPermissions: Match.Optional([String])
  });

  this.superPermission = options.superPermission || '_super';
  this._permissionListVar = options.permissionListVar || 'permissions';
  this._superListVar = options.superListVar || 'superIds';
  this._defaultPermissions = (options.defaultPermissions || 
                              [options.superPermission]);
  this._collection = collection;
  this._permissions = permissions || {};
  this._permissions[this.superPermission] = Infinity;

  if (Meteor.isServer) {
    var self = this;
    Meteor.startup(function() {
      collection._ensureIndex([
        [self._permissionListVar + ".userId", 1],
        [self._permissionListVar + ".permissions", 1]
      ]);
    });
  }
};

(function() {
  'use strict';

  /** Sets permissions for a given user on an object
   *  @param {String} objectId - _id of the object we're controlling access to
   *  @param {String} userId - _id of user
   *  @param {[String]} [permissions=defaultPermissions] - List of permissions
   *    to set for user
   *  @returns {Number} - Number of objects updated. 1 if update was 
   *    successful, 0 otherwise
   */
  ObjectACLSvc.prototype.set = function(objectId, userId, permissions) {
    var self = this;
    check(objectId, String);
    check(userId, String);
    check(permissions, Match.Optional([
      Match.Where(function(permission) {
        check(permission, String);
        return self._permissions.hasOwnProperty(permission);
      })
    ]));
    permissions = permissions || this._defaultPermissions;
    
    var ret, selector, superUpdate, update;
    var permissionObj = {
      userId: userId,
      permissions: permissions
    };

    // Super, add user ID to special list
    if (_.contains(permissions, this.superPermission)) {
      superUpdate = {$addToSet: {}};
      superUpdate.$addToSet[this._superListVar] = userId;
    }

    // Not super, ensure not in super list
    else {
      superUpdate = {$pull: {}};
      superUpdate.$pull[this._superListVar] = userId;
    }

    // Try update first
    selector = { _id: objectId };
    selector[this._permissionListVar + ".userId"] = userId;

    // Make sure not just one admin left
    if (superUpdate.$pull) {
      selector[this._superListVar] = {$ne: [userId]};
    }

    update = _.extend({$set: {}}, superUpdate);
    update.$set[this._permissionListVar + ".$"] = permissionObj;
    ret = this._collection.update(selector, update);

    // ret === 0 implies update failed, so insert instead
    if (! ret) {  
      selector = { _id: objectId };
      // If inserting, check doesn't already exist (e.g. b/c of a race 
      // between prior update and this one)
      selector[this._permissionListVar + ".userId"] = {$ne: userId};
      update = _.extend({$push: {}}, superUpdate);
      update.$push[this._permissionListVar] = permissionObj;
      ret = this._collection.update(selector, update);
    }
    return ret;
  };

  /** Removes all permissions for a given user on an object
   *  @param {String} objectId - _id of the object we're controlling access to
   *  @param {String} userId - _id of user
   *  @returns {Number} - Number of objects updated. 1 if update was 
   *    successful, 0 otherwise
   */
  ObjectACLSvc.prototype.unset = function(objectId, userId) {
    check(objectId, String);
    check(userId, String);
<commit_msg>Input block helpers, workspace creation<commit_after>/* global ObjectACLSvc: true */

/** @constructor
 *  
 *  @param {Object} collection - The Mongo.Collection to attach the ACL to
 *  @param {Object} [permissions] - A mapping of permission types to interger
 *    values. Each permission with a higher value than another automatically
 *    implies the lower -- e.g. if the permissions are {read: 10, write: 20},
 *    then anyone with write permission automatically has read permisison.
 *  @param {String} [options.superPermission=_super] - Name of the permission
 *    that has access to everything else.
 *  @param {String} [options.permissionListVar=permissions] - Name of field on 
 *    the collection on which to use for our ACL
 *  @param {String} [options.superListVar=superIds] - Name of field on the
 *    collection which gets populated with a list of userIds with the super
 *    permission. This is used to ensure that we can never unset the number
 *    users with super permissions below zero.
 *  @param {[String]} [options.defaultPermissions=super] - List of permissions 
 *    to assign to users by default if no others are given. Default to the 
 *    super permission
 */
ObjectACLSvc = function(collection, permissions, options) {
  'use strict';
  if (! collection) {
    throw new Meteor.Error(500, "missing-collection");
  }

  options = options || {};
  check(options, {
    superPermission: Match.Optional(String),
    permissionListVar: Match.Optional(String),
    superListVar: Match.Optional(String),
    defaultPermissions: Match.Optional([String])
  });

  this.superPermission = options.superPermission || '_super';
  this._permissionListVar = options.permissionListVar || 'permissions';
  this._superListVar = options.superListVar || 'superIds';
  this._defaultPermissions = (options.defaultPermissions || 
                              [options.superPermission]);
  this._collection = collection;
  this._permissions = permissions || {};
  this._permissions[this.superPermission] = Infinity;

  if (Meteor.isServer) {
    var self = this;
    Meteor.startup(function() {
      collection._ensureIndex([
        [self._permissionListVar + ".userId", 1],
        [self._permissionListVar + ".permissions", 1]
      ]);
    });
  }
};

(function() {
  'use strict';

  /** Sets permissions for a given user on an object
   *  @param {String} objectId - _id of the object we're controlling access to
   *  @param {String} userId - _id of user
   *  @param {[String]} [permissions=defaultPermissions] - List of permissions
   *    to set for user
   *  @returns {Number} - Number of objects updated. 1 if update was 
   *    successful, 0 otherwise
   */
  ObjectACLSvc.prototype.set = function(objectId, userId, permissions) {
    check(objectId, String);
    permissions = permissions || this._defaultPermissions;
    
    var permissionObj = this.permissionObj(userId, permissions);
    var ret, selector, superUpdate, update;

    // Super, add user ID to special list
    if (_.contains(permissions, this.superPermission)) {
      superUpdate = {$addToSet: {}};
      superUpdate.$addToSet[this._superListVar] = userId;
    }

    // Not super, ensure not in super list
    else {
      superUpdate = {$pull: {}};
      superUpdate.$pull[this._superListVar] = userId;
    }

    // Try update first
    selector = { _id: objectId };
    selector[this._permissionListVar + ".userId"] = userId;

    // Make sure not just one admin left
    if (superUpdate.$pull) {
      selector[this._superListVar] = {$ne: [userId]};
    }

    update = _.extend({$set: {}}, superUpdate);
    update.$set[this._permissionListVar + ".$"] = permissionObj;
    ret = this._collection.update(selector, update);

    // ret === 0 implies update failed, so insert instead
    if (! ret) {  
      selector = { _id: objectId };
      // If inserting, check doesn't already exist (e.g. b/c of a race 
      // between prior update and this one)
      selector[this._permissionListVar + ".userId"] = {$ne: userId};
      update = _.extend({$push: {}}, superUpdate);
      update.$push[this._permissionListVar] = permissionObj;
      ret = this._collection.update(selector, update);
    }
    return ret;
  };

  // Returns an object representing permissions for a given user. This gets
  // inserted into an array on the actual object we're controlling access for.
  ObjectACLSvc.prototype.permissionObj = function(userId, permissions) {
    var self = this;
    check(userId, String);
    check(permissions, Match.Optional([
      Match.Where(function(permission) {
        check(permission, String);
        return self._permissions.hasOwnProperty(permission);
      })
    ]));

    return {
      userId: userId,
      permissions: permissions
    };
  };

  /** Removes all permissions for a given user on an object
   *  @param {String} objectId - _id of the object we're controlling access to
   *  @param {String} userId - _id of user
   *  @returns {Number} - Number of objects updated. 1 if update was 
   *    successful, 0 otherwise
   */
  ObjectACLSvc.prototype.unset = function(objectId, userId) {
    check(objectId, String);
    check(userId, String);

{'fraction_non_alphanumeric': 0.11359793096588083, 'fraction_numerical': 0.0027852382373420867, 'mean_word_length': 3.147689768976898, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6291490', 'n_tokens_mistral': 2834, 'n_tokens_neox': 2806, 'n_words': 893}