Skip to content

Commit

Permalink
Revert "Revert "Support Bucket/Object lock operations (#320)" (#373)"
Browse files Browse the repository at this point in the history
This reverts commit 702d7bd.
  • Loading branch information
stephenplusplus authored and JustinBeckwith committed Oct 9, 2018
1 parent a3f2ee3 commit b6268e5
Show file tree
Hide file tree
Showing 6 changed files with 533 additions and 0 deletions.
122 changes: 122 additions & 0 deletions src/bucket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1876,6 +1876,48 @@ class Bucket extends ServiceObject {
});
}

/**
* Lock a previously-defined retention policy. This will prevent changes to
* the policy.
*
* @throws {Error} if a metageneration is not provided.
*
* @param {Number|String} metageneration The bucket's metageneration. This is
* accesssible from calling {@link File#getMetadata}.
* @param {SetBucketMetadataCallback} [callback] Callback function.
* @returns {Promise<SetBucketMetadataResponse>}
*
* @example
* const storage = require('@google-cloud/storage')();
* const bucket = storage.bucket('albums');
*
* const metageneration = 2;
*
* bucket.lock(metageneration, function(err, apiResponse) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* bucket.lock(metageneration).then(function(data) {
* const apiResponse = data[0];
* });
*/
lock(metageneration, callback) {
if (!is.number(metageneration) && !is.string(metageneration)) {
throw new Error('A metageneration must be provided.');
}

this.request(
{
method: 'POST',
uri: '/lockRetentionPolicy',
qs: {
ifMetagenerationMatch: metageneration,
},
},
callback);
}

/**
* @typedef {array} MakeBucketPrivateResponse
* @property {File[]} 0 List of files made private.
Expand Down Expand Up @@ -2148,6 +2190,34 @@ class Bucket extends ServiceObject {
return new Notification(this, id);
}

/**
* Remove an already-existing retention policy from this bucket, if it is not
* locked.
*
* @param {SetBucketMetadataCallback} [callback] Callback function.
* @returns {Promise<SetBucketMetadataResponse>}
*
* @example
* const storage = require('@google-cloud/storage')();
* const bucket = storage.bucket('albums');
*
* bucket.removeRetentionPeriod(function(err, apiResponse) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* bucket.removeRetentionPeriod().then(function(data) {
* const apiResponse = data[0];
* });
*/
removeRetentionPeriod(callback) {
this.setMetadata(
{
retentionPolicy: null,
},
callback);
}

/**
* Makes request and applies userProject query parameter if necessary.
*
Expand Down Expand Up @@ -2281,6 +2351,13 @@ class Bucket extends ServiceObject {
* }, function(err, apiResponse) {});
*
* //-
* // Set the default event-based hold value for new objects in this bucket.
* //-
* bucket.setMetadata({
* defaultEventBasedHold: true
* }, function(err, apiResponse) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* bucket.setMetadata(metadata).then(function(data) {
Expand Down Expand Up @@ -2314,6 +2391,51 @@ class Bucket extends ServiceObject {
});
}

/**
* Lock all objects contained in the bucket, based on their creation time. Any
* attempt to overwrite or delete objects younger than the retention period
* will result in a `PERMISSION_DENIED` error.
*
* An unlocked retention policy can be modified or removed from the bucket via
* {@link File#removeRetentionPeriod} and {@link File#setRetentionPeriod}. A
* locked retention policy cannot be removed or shortened in duration for the
* lifetime of the bucket. Attempting to remove or decrease period of a locked
* retention policy will result in a `PERMISSION_DENIED` error. You can still
* increase the policy.
*
* @param {*} duration In seconds, the minimum retention time for all objects
* contained in this bucket.
* @param {SetBucketMetadataCallback} [callback] Callback function.
* @returns {Promise<SetBucketMetadataResponse>}
*
* @example
* const storage = require('@google-cloud/storage')();
* const bucket = storage.bucket('albums');
*
* const DURATION_SECONDS = 15780000; // 6 months.
*
* //-
* // Lock the objects in this bucket for 6 months.
* //-
* bucket.setRetentionPeriod(DURATION_SECONDS, function(err, apiResponse) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* bucket.setRetentionPeriod(DURATION_SECONDS).then(function(data) {
* const apiResponse = data[0];
* });
*/
setRetentionPeriod(duration, callback) {
this.setMetadata(
{
retentionPolicy: {
retentionPeriod: duration,
},
},
callback);
}

/**
* @callback SetStorageClassCallback
* @param {?Error} err Request error, if any.
Expand Down
74 changes: 74 additions & 0 deletions src/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1730,6 +1730,62 @@ class File extends ServiceObject {
(this.parent as ServiceObject).get.call(this, options, callback);
}

/**
* @typedef {array} GetExpirationDateResponse
* @property {date} 0 A Date object representing the earliest time this file's
* retention policy will expire.
*/
/**
* @callback GetExpirationDateCallback
* @param {?Error} err Request error, if any.
* @param {date} expirationDate A Date object representing the earliest time
* this file's retention policy will expire.
*/
/**
* If this bucket has a retention policy defined, use this method to get a
* Date object representing the earliest time this file will expire.
*
* @param {GetExpirationDateCallback} [callback] Callback function.
* @returns {Promise<GetExpirationDateResponse>}
*
* @example
* const storage = require('@google-cloud/storage')();
* const myBucket = storage.bucket('my-bucket');
*
* const file = myBucket.file('my-file');
*
* file.getExpirationDate(function(err, expirationDate) {
* // expirationDate is a Date object.
* });
*/
getExpirationDate(callback) {
this.getMetadata((err, metadata, apiResponse) => {
if (err) {
callback(err, null, apiResponse);
return;
}

if (!metadata.retentionExpirationTime) {
const error = new Error('An expiration time is not available.');
callback(error, null, apiResponse);
return;
}

callback(null, new Date(metadata.retentionExpirationTime), apiResponse);
});
}

/**
* @typedef {array} GetFileMetadataResponse
* @property {object} 0 The {@link File} metadata.
* @property {object} 1 The full API response.
*/
/**
* @callback GetFileMetadataCallback
* @param {?Error} err Request error, if any.
* @param {object} metadata The {@link File} metadata.
* @param {object} apiResponse The full API response.
*/
/**
* Get the file's metadata.
*
Expand Down Expand Up @@ -2606,6 +2662,24 @@ class File extends ServiceObject {
* });
*
* //-
* // Set a temporary hold on this file from its bucket's retention period
* // configuration.
* //
* file.setMetadata({
* temporaryHold: true
* }, function(err, apiResponse) {});
*
* //-
* // Alternatively, you may set a temporary hold. This will follow the same
* // behavior as an event-based hold, with the exception that the bucket's
* // retention policy will not renew for this file from the time the hold is
* // released.
* //-
* file.setMetadata({
* eventBasedHold: true
* }, function(err, apiResponse) {});
*
* //-
* // If the callback is omitted, we'll return a Promise.
* //-
* file.setMetadata(metadata).then(function(data) {
Expand Down
11 changes: 11 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,17 @@ class Storage extends Service {
* storage.createBucket('new-bucket', metadata, callback);
*
* //-
* // Create a bucket with a retention policy of 6 months.
* //-
* const metadata = {
* retentionPolicy: {
* retentionPeriod: 15780000 // 6 months in seconds.
* }
* };
*
* storage.createBucket('new-bucket', metadata, callback);
*
* //-
* // Enable versioning on a new bucket.
* //-
* const metadata = {
Expand Down
Loading

0 comments on commit b6268e5

Please sign in to comment.