From a2915c82d41e5e97d25ba6ecbbe9c767249036b3 Mon Sep 17 00:00:00 2001 From: Ryan Seys Date: Wed, 11 Feb 2015 16:45:50 -0500 Subject: [PATCH] Make files public and private --- lib/storage/file.js | 67 +++++++++++++++++++++++++++++++++++++++++++ regression/storage.js | 26 +++++++++++++++++ test/storage/file.js | 53 ++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+) diff --git a/lib/storage/file.js b/lib/storage/file.js index c073fe23868..c57688112a4 100644 --- a/lib/storage/file.js +++ b/lib/storage/file.js @@ -797,6 +797,73 @@ File.prototype.setMetadata = function(metadata, callback) { }); }; +/** + * Make a file private to the project and remove all other permissions. + * Set `options.strict` to true to make the file private to only the owner. + * + * @param {object=} options - The configuration object. + * @param {boolean=} options.strict - If true, set the file to be private to + * only the owner user. Otherwise, it will be private to the project. + * @param {function=} callback - The callback function. + * + * @example + * + * //- + * // Set the file private so only project maintainers can see and modify it. + * //- + * file.makePrivate(function(err) {}); + * + * //- + * // Set the file private so only the owner can see and modify it. + * //- + * file.makePrivate({ strict: true }, function(err) {}); + */ +File.prototype.makePrivate = function(options, callback) { + var that = this; + if (util.is(options, 'function')) { + callback = options; + options = {}; + } + var path = '/o/' + encodeURIComponent(this.name); + var query = { predefinedAcl: options.strict ? 'private' : 'projectPrivate' }; + + // You aren't allowed to set both predefinedAcl & acl properties on a file, so + // acl must explicitly be nullified, destroying all previous acls on the file. + var metadata = { acl: null }; + + callback = callback || util.noop; + + this.makeReq_('PATCH', path, query, metadata, function(err, resp) { + if (err) { + callback(err); + return; + } + + that.metadata = resp; + + callback(null); + }); +}; + +/** + * Set a file to be publicly readable and maintain all previous permissions. + * + * @param {function=} callback - The callback function. + * + * @example + * file.makePublic(function(err) {}); + */ +File.prototype.makePublic = function(callback) { + callback = callback || util.noop; + + this.acl.add({ + entity: 'allUsers', + role: 'READER' + }, function(err) { + callback(err); + }); +}; + /** * `startResumableUpload_` uses the Resumable Upload API: http://goo.gl/jb0e9D. * diff --git a/regression/storage.js b/regression/storage.js index dc8f7efc4d7..86af43b657e 100644 --- a/regression/storage.js +++ b/regression/storage.js @@ -236,6 +236,32 @@ describe('storage', function() { }); }); }); + + it('should be made public', function(done) { + file.makePublic(function(err) { + assert.ifError(err); + file.acl.get({ entity: 'allUsers' }, function(err, aclObject) { + assert.ifError(err); + assert.deepEqual(aclObject, { entity: 'allUsers', role: 'READER' }); + file.acl.delete({ entity: 'allUsers' }, done); + }); + }); + }); + + it('should be made private', function(done) { + file.makePublic(function(err) { + assert.ifError(err); + file.makePrivate(function(err) { + assert.ifError(err); + file.acl.get({ entity: 'allUsers' }, function(err, aclObject) { + assert.equal(err.code, 404); + assert.equal(err.message, 'Not Found'); + assert.equal(aclObject, null); + done(); + }); + }); + }); + }); }); }); diff --git a/test/storage/file.js b/test/storage/file.js index ba29f478807..d4f2c5da5bb 100644 --- a/test/storage/file.js +++ b/test/storage/file.js @@ -1025,6 +1025,59 @@ describe('File', function() { }); }); + describe('makePublic', function() { + it('should execute callback', function(done) { + file.acl.add = function(options, callback) { + callback(); + }; + + file.makePublic(done); + }); + + it('should make the file public', function(done) { + file.acl.add = function(options) { + assert.deepEqual(options, { entity: 'allUsers', role: 'READER' }); + done(); + }; + + file.makePublic(util.noop); + }); + }); + + describe('makePrivate', function() { + it('should execute callback', function(done) { + file.makeReq_ = function(method, path, query, body, callback) { + callback(); + }; + + file.makePrivate(done); + }); + + it('should make the file private to project by default', function(done) { + file.makeReq_ = function(method, path, query, body) { + assert.equal(method, 'PATCH'); + assert.equal(path, '/o/' + encodeURIComponent(file.name)); + assert.deepEqual(query, { predefinedAcl: 'projectPrivate' }); + assert.deepEqual(body, { acl: null }); + done(); + }; + + file.makePrivate(util.noop); + }); + + it('should make the file private to user if strict = true', function(done) { + file.makeReq_ = function(method, path, query, body) { + assert.equal(method, 'PATCH'); + assert.equal(path, '/o/' + encodeURIComponent(file.name)); + assert.deepEqual(query, { predefinedAcl: 'private' }); + assert.deepEqual(body, { acl: null }); + done(); + }; + + file.makePrivate({ strict: true }, util.noop); + }); + }); + describe('startResumableUpload_', function() { var RESUMABLE_URI = 'http://resume';