Skip to content

Commit

Permalink
storage: acls
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenplusplus committed Nov 17, 2014
1 parent d04c190 commit 9b85196
Show file tree
Hide file tree
Showing 6 changed files with 493 additions and 4 deletions.
14 changes: 12 additions & 2 deletions docs/components/docs/docs.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,19 @@ angular
return obj.ctx && obj.isPrivate === false && obj.ignore === false;
})
.map(function(obj) {
var alias = obj.tags.filter(function(tag) {
return tag.type === 'alias';
})[0];

if (alias && alias.string.indexOf('module:') !== 0) {
alias = alias.string;
} else {
alias = false
}

return {
data: obj,
name: obj.ctx.name,
name: (alias || obj.ctx.name).trim(),
constructor: obj.tags.some(function(tag) {
return tag.type === 'constructor';
}),
Expand Down Expand Up @@ -172,7 +182,7 @@ angular
function getMixIns($sce, $q, $http, version, baseUrl) {
return function(data) {
var methodWithMixIns = data.filter(function(method) {
return method.mixes;
return method.mixes.length > 0;
})[0];
if (!methodWithMixIns) {
return data;
Expand Down
248 changes: 248 additions & 0 deletions lib/storage/acl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
/*!
* Copyright 2014 Google Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/*!
* @module storage/acl
*/

'use strict';

/**
* @type module:common/util
* @private
*/
var util = require('../common/util.js');

/**
* Google Cloud Storage uses access control lists (ACLs) to manage object and
* bucket access. ACLs are the mechanism you use to share objects with other
* users and allow other users to access your buckets and objects.
*
* An ACL consists of one or more entries, where each entry grants permissions
* to a scope. Permissions define the actions that can be performed against an
* object or bucket (for example, `READ` or `WRITE`); the scope defines who the
* permission applies to (for example, a specific user or group of users).
*
* For more detailed information, see
* [About Access Control Lists](http://goo.gl/6qBBPO).
*
* @constructor
* @alias module:storage/acl
*/
function Acl(module) {
this.assignAccessMethods_(this, '/acl');

if (module.constructor.name === 'Bucket') {
this.default = {};
this.assignAccessMethods_(this.default, '/defaultObjectAcl');

this.bucket = module;
} else {
this.bucket = module.bucket;
this.file = module;
}
}

/**
* Add access controls on a {module:storage/bucket} or {module:storage/file}.
*
* @alias acl.add
*
* @param {string} scope - Whose permissions will be updated.
* @param {string} role - Permissions allowed for the defined scope.
* @param {function} callback - The callback function.
*
* @example
* var scope = '[email protected]';
* var role = 'owner';
*
* myBucket.acl.add(scope, role, function(err, aclObject) {});
*/
Acl.prototype.add_ = function(path, scope, role, callback) {
var that = this;

var body = {
entity: scope,
role: role.toUpperCase()
};

this.makeReq_('POST', path, null, body, function(err, resp) {
if (err) {
callback(err);
return;
}

callback(null, that.makeAclObject_(resp));
});
};

/**
* Delete access controls on a {module:storage/bucket} or {module:storage/file}.
*
* @alias acl.delete
*
* @param {string} scope - Whose permissions will be revoked.
* @param {function} callback - The callback function.
*
* @example
* var scope = '[email protected]';
*
* myBucket.acl.delete(scope, function(err) {});
*/
Acl.prototype.delete_ = function(path, scope, callback) {
path += '/' + encodeURIComponent(scope);
this.makeReq_('DELETE', path, null, null, callback);
};

/**
* Get access controls on a {module:storage/bucket} or {module:storage/file}. If
* an scope is omitted, you will receive an array of all applicable access
* controls.
*
* @alias acl.get
*
* @param {string=} scope - Whose permissions will be fetched.
* @param {function} callback - The callback function.
*
* @example
* var scope = '[email protected]';
*
* myBucket.acl.get(scope, function(err, aclObject) {});
*
* //-
* // Get all access controls.
* //-
* myBucket.acl.get(function(err, aclObjects) {
* // aclObjects = [
* // {
* // scope: '[email protected]',
* // role: 'owner'
* // }
* // ]
* });
*/
Acl.prototype.get_ = function(path, scope, callback) {
var that = this;

if (util.is(scope, 'string')) {
path += '/' + encodeURIComponent(scope);
} else if (util.is(scope, 'function')) {
callback = scope;
}

this.makeReq_('GET', path, null, null, function(err, resp) {
if (err) {
callback(err);
return;
}

var results = resp;

if (resp.items) {
results = (resp.items || []).map(that.makeAclObject_);
} else {
results = that.makeAclObject_(results);
}

callback(null, results);
});
};

/**
* Update access controls on a {module:storage/bucket} or {module:storage/file}.
*
* @alias acl.update
*
* @param {string} scope - Whose permissions will be updated.
* @param {string} role - Permissions allowed for the defined scope.
* @param {function} callback - The callback function.
*
* @example
* var scope = '[email protected]';
* var role = 'writer';
*
* myBucket.acl.update(scope, role, function(err) {});
*/
Acl.prototype.update_ = function(path, scope, role, callback) {
var that = this;

path += '/' + encodeURIComponent(scope);

var body = {
role: role.toUpperCase()
};

this.makeReq_('PUT', path, null, body, function(err, resp) {
if (err) {
callback(err);
return;
}

callback(null, that.makeAclObject_(resp));
});
};

/**
* Iterate over the access methods, and apply them to the specified object.
*
* @private
*/
Acl.prototype.assignAccessMethods_ = function(destObj, path) {
var that = this;

['add', 'delete', 'get', 'update'].forEach(function(method) {
destObj[method] = that[method + '_'].bind(that, path);
});
};

/**
* Transform API responses to a consistent object format.
*
* @private
*/
Acl.prototype.makeAclObject_ = function(accessControlObject) {
var obj = {
scope: accessControlObject.scope,
role: accessControlObject.role.toLowerCase()
};

if (accessControlObject.projectTeam) {
obj.projectTeam = accessControlObject.projectTeam;
}

return obj;
};

/**
* Patch requests up to the bucket's request object.
*
* @private
*
* @param {string} method - Action.
* @param {string} path - Request path.
* @param {*} query - Request query object.
* @param {*} body - Request body contents.
* @param {function} callback - The callback function.
*/
Acl.prototype.makeReq_ = function(method, path, query, body, callback) {
if (this.file) {
path = '/o/' + encodeURIComponent(this.file.name) + path;
}

this.bucket.makeReq_(method, path, query, body, callback);
};

module.exports = Acl;
78 changes: 76 additions & 2 deletions lib/storage/bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ var fs = require('fs');
var mime = require('mime');
var path = require('path');

/**
* @type module:storage/acl
* @private
*/
var Acl = require('./acl.js');

/**
* @type module:storage/file
* @private
Expand Down Expand Up @@ -72,6 +78,7 @@ var STORAGE_BASE_URL = 'https://www.googleapis.com/storage/v1/b';
* });
*/
function Bucket(storage, name) {
this.acl = new Acl(this);
this.metadata = {};
this.name = name;
this.storage = storage;
Expand All @@ -81,6 +88,74 @@ function Bucket(storage, name) {
}
}

/**
* Google Cloud Storage uses access control lists (ACLs) to manage object and
* bucket access. ACLs are the mechanism you use to share objects with other
* users and allow other users to access your buckets and objects.
*
* An ACL consists of one or more entries, where each entry grants permissions
* to a scope. Permissions define the actions that can be performed against an
* object or bucket (for example, `READ` or `WRITE`); the scope defines who the
* permission applies to (for example, a specific user or group of users).
*
* For more detailed information, see
* [About Access Control Lists](http://goo.gl/6qBBPO).
*
* The `acl` object on a Bucket instance provides methods to get you a list of
* the ACLs defined on your bucket, as well as set, update, and delete them.
*
* Buckets also have
* [default ACLs](https://cloud.google.com/storage/docs/accesscontrol#default)
* for all created files. You can add, delete, get, and update scopes and
* permissions for these as well. See {module:storage/acl#acl.default}.
*
* @mixes module:storage/acl
*/
Bucket.prototype.acl = {};

/* jshint ignore:start */
/*! Developer Documentation
*
* Sadly, to generate the documentation properly, this comment block describes a
* useless variable named `ignored` and aliases it to `acl.default`. This is
* done so the doc building process picks this up, without adding cruft to the
* Bucket class itself.
*/
/**
* Google Cloud Storage Buckets have [default ACLs](http://goo.gl/YpGdyv)
* for all created files. You can add, delete, get, and update scopes and
* permissions for these as well. The method signatures and examples are all
* the same, after only prefixing the method call with `default`.
*
* @alias acl.default
*/
var aclDefault = true;

/**
* Maps to {module:storage/bucket#acl.add}.
* @alias acl.default.add
*/
var aclDefaultAdd = true;

/**
* Maps to {module:storage/bucket#acl.delete}.
* @alias acl.default.delete
*/
var aclDefaultDelete = true;

/**
* Maps to {module:storage/bucket#acl.get}.
* @alias acl.default.get
*/
var aclDefaultGet = true;

/**
* Maps to {module:storage/bucket#acl.update}.
* @alias acl.default.update
*/
var aclDefaultUpdate = true;
/* jshint ignore:end */

/**
* Delete the bucket.
*
Expand Down Expand Up @@ -211,8 +286,7 @@ Bucket.prototype.getMetadata = function(callback) {
*/
Bucket.prototype.setMetadata = function(metadata, callback) {
callback = callback || util.noop;
this.makeReq_(
'PATCH', '/b/' + this.name, null, metadata, function(err, resp) {
this.makeReq_('PATCH', '', null, metadata, function(err, resp) {
if (err) {
callback(err);
return;
Expand Down
Loading

0 comments on commit 9b85196

Please sign in to comment.