Skip to content

Commit

Permalink
Object locking API support
Browse files Browse the repository at this point in the history
  • Loading branch information
prakashsvmx committed Apr 8, 2021
1 parent 9994dea commit dd8da4f
Show file tree
Hide file tree
Showing 11 changed files with 501 additions and 8 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ The full API Reference is available here.
* [`listIncompleteUploads`](https://docs.min.io/docs/javascript-client-api-reference#listIncompleteUploads)
* [`getBucketVersioning`](https://docs.min.io/docs/javascript-client-api-reference#getBucketVersioning)
* [`setBucketVersioning`](https://docs.min.io/docs/javascript-client-api-reference#setBucketVersioning)
* [`getObjectLockConfig`](https://docs.min.io/docs/javascript-client-api-reference#getObjectLockConfig)
* [`setObjectLockConfig`](https://docs.min.io/docs/javascript-client-api-reference#setObjectLockConfig)

### API Reference : File Object Operations

Expand Down Expand Up @@ -176,6 +178,8 @@ The full API Reference is available here.
* [list-incomplete-uploads.js](https://github.com/minio/minio-js/blob/master/examples/list-incomplete-uploads.js)
* [get-bucket-versioning.js](https://github.com/minio/minio-js/blob/master/examples/get-bucket-versioning.js)
* [set-bucket-versioning.js](https://github.com/minio/minio-js/blob/master/examples/set-bucket-versioning.js)
* [get-object-lock-config.js](https://github.com/minio/minio-js/blob/master/examples/get-object-lock-config.js)
* [set-object-lock-config.js](https://github.com/minio/minio-js/blob/master/examples/set-object-lock-config.js)

#### Full Examples : File Object Operations
* [fput-object.js](https://github.com/minio/minio-js/blob/master/examples/fput-object.js)
Expand Down
73 changes: 73 additions & 0 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ __Parameters__
|---|---|---|
|`bucketName` | _string_ | Name of the bucket. |
| `region` | _string_ | Region where the bucket is created. This parameter is optional. Default value is us-east-1. |
| `makeOpts` | _object_ | Options to create a bucket. e.g `{ObjectLocking:true}` (Optional)
|`callback(err)` |_function_ | Callback function with `err` as the error argument. `err` is null if the bucket is successfully created. If no callback is passed, a `Promise` is returned. |


Expand All @@ -137,6 +138,16 @@ minioClient.makeBucket('mybucket', 'us-east-1', function(err) {
})
```

__Example 1__
Create a bucket with object locking enabled.

```js
minioClient.makeBucket('mybucket', 'us-east-1', { ObjectLocking:true }, function(err) {
if (err) return console.log('Error creating bucket with object lock .', err)
console.log('Bucket created successfully in "us-east-1" and enabled object lock')
})
```

<a name="listBuckets"></a>
### listBuckets([callback])

Expand Down Expand Up @@ -451,6 +462,68 @@ minioClient.setBucketVersioning('bucketname',versioningConfig, function (err){
})
```

<a name="setObjectLockConfig"></a>
### setObjectLockConfig(bucketName, lockConfig [, callback])

Set Object lock config on a Bucket

__Parameters__


| Param | Type | Description |
| ---| ---|---|
| `bucketname` | _string_ | Name of the bucket. |
| `lockConfig` | _object_ | Versioning Configuration can be either `{}` to reset or object with all of the following keys: `{mode , unit , validity:number}` `mode` - accepts either COMPLIANCE or COMPLIANCE , `unit` accepts either Days or Years `validity` accepts any valid number in respective unit specified |
|`callback(err)` | _function_ | Callback is called with `err` in case of error.|

__Example 1__

```js
s3Client.setObjectLockConfig('my-bucketname', {mode:"COMPLIANCE",unit:'Days', validity:10 }, function (err){
if (err) {
return console.log(err)
}
console.log("Success")
})
```

__Example 2__
To reset/remove object lock config on a bucket.

```js
s3Client.setObjectLockConfig('my-bucketname', {}, function (err){
if (err) {
return console.log(err)
}
console.log("Success")
})
```


<a name="getObjectLockConfig"></a>
### getObjectLockConfig(bucketName, [, callback])

Get Lock config on a Bucket

__Parameters__


| Param | Type | Description |
| ---| ---|---|
| `bucketname` | _string_ | Name of the bucket. |
|`callback(err)` | _function_ | Callback is called with `err` in case of error.|

__Example __
Get object lock on a Bucket

```js
s3Client.getObjectLockConfig('my-bucketname', function (err, lockConfig){
if (err) {
return console.log(err)
}
console.log("Success",lockConfig)
})
```
## 3. Object operations

<a name="getObject"></a>
Expand Down
34 changes: 34 additions & 0 deletions examples/get-object-lock-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* MinIO Javascript Library for Amazon S3 Compatible Cloud Storage, (C) 2021 MinIO, Inc.
*
* 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.
*/

// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
// dummy values, please replace them with original values.

var Minio = require('minio')

var s3Client = new Minio.Client({
endPoint: 's3.amazonaws.com',
accessKey: 'YOUR-ACCESSKEYID',
secretKey: 'YOUR-SECRETACCESSKEY'
})


s3Client.getObjectLockConfig('my-bucketname', function (err,lockConfig){
if (err) {
return console.log(err)
}
console.log("Success", lockConfig)
})
10 changes: 8 additions & 2 deletions examples/make-bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
* limitations under the License.
*/

// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
// dummy values, please replace them with original values.
// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
// dummy values, please replace them with original values.

var Minio = require('minio')

Expand All @@ -31,3 +31,9 @@ s3Client.makeBucket('my-bucketname', 'us-west-1', function(e) {
}
console.log("Success")
})

// Create a bucket with object locking enabled.
s3Client.makeBucket('mybucket', 'us-east-1', { ObjectLocking:true }, function(err) {
if (err) return console.log('Error creating bucket with lock .', err)
console.log('Bucket created successfully in "us-east-1" and enabled object lock')
})
42 changes: 42 additions & 0 deletions examples/set-object-lock-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* MinIO Javascript Library for Amazon S3 Compatible Cloud Storage, (C) 2021 MinIO, Inc.
*
* 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.
*/

// Note: YOUR-ACCESSKEYID, YOUR-SECRETACCESSKEY and my-bucketname are
// dummy values, please replace them with original values.

var Minio = require('minio')

var s3Client = new Minio.Client({
endPoint: 's3.amazonaws.com',
accessKey: 'YOUR-ACCESSKEYID',
secretKey: 'YOUR-SECRETACCESSKEY'
})

//Set Object lock on a bucket
s3Client.setObjectLockConfig('my-bucketname', {mode:"COMPLIANCE",unit:'Days', validity:10 }, function (err){
if (err) {
return console.log(err)
}
console.log("Success")
})

//To reset/remove object lock config.
s3Client.setObjectLockConfig('my-bucketname', {}, function (err){
if (err) {
return console.log(err)
}
console.log("Success")
})
12 changes: 11 additions & 1 deletion src/main/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,4 +368,14 @@ export function sanitizeETag(etag='') {
var replaceChars = {'"':'','&quot;':'','&#34;':'','&QUOT;':'','&#x00022':''}
return etag.replace(/^("|&quot;|&#34;)|("|&quot;|&#34;)$/g, m => replaceChars[m])

}
}

export const RETENTION_MODES ={
GOVERNANCE:"GOVERNANCE",
COMPLIANCE:"COMPLIANCE"
}

export const RETENTION_VALIDITY_UNITS={
DAYS:"Days",
YEARS:"Years"
}
106 changes: 104 additions & 2 deletions src/main/minio.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ import {
uriEscape, uriResourceEscape, isBoolean, isFunction, isNumber,
isString, isObject, isArray, isValidDate, pipesetup,
readableStream, isReadableStream, isVirtualHostStyle,
insertContentType, makeDateLong, promisify, getVersionId, sanitizeETag
insertContentType, makeDateLong, promisify, getVersionId, sanitizeETag,
RETENTION_MODES, RETENTION_VALIDITY_UNITS
} from './helpers.js'

import { signV4, presignSignatureV4, postPresignSignatureV4 } from './signing.js'
Expand Down Expand Up @@ -520,20 +521,35 @@ export class Client {
// __Arguments__
// * `bucketName` _string_ - Name of the bucket
// * `region` _string_ - region valid values are _us-west-1_, _us-west-2_, _eu-west-1_, _eu-central-1_, _ap-southeast-1_, _ap-northeast-1_, _ap-southeast-2_, _sa-east-1_.
// * `makeOpts` _object_ - Options to create a bucket. e.g {ObjectLocking:true} (Optional)
// * `callback(err)` _function_ - callback function with `err` as the error argument. `err` is null if the bucket is successfully created.
makeBucket(bucketName, region, cb) {
makeBucket(bucketName, region, makeOpts={}, cb) {
if (!isValidBucketName(bucketName)) {
throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName)
}

//Backward Compatibility
if(isObject(region)){
cb= makeOpts
makeOpts=region
region = ''
}
if (isFunction(region)) {
cb = region
region = ''
makeOpts={}
}
if(isFunction(makeOpts)){
cb=makeOpts
makeOpts={}
}

if (!isString(region)) {
throw new TypeError('region should be of type "string"')
}
if (!isObject(makeOpts)) {
throw new TypeError('makeOpts should be of type "object"')
}
if (!isFunction(cb)) {
throw new TypeError('callback should be of type "function"')
}
Expand Down Expand Up @@ -567,6 +583,11 @@ export class Client {
}
var method = 'PUT'
var headers = {}

if(makeOpts.ObjectLocking){
headers["x-amz-bucket-object-lock-enabled"]=true
}

if (!region) region = 'us-east-1'
this.makeRequest({method, bucketName, headers}, payload, 200, region, false, cb)
}
Expand Down Expand Up @@ -2259,6 +2280,85 @@ export class Client {
this.makeRequest({method, bucketName, query}, payload, 200, '', false, cb)
}

setObjectLockConfig(bucketName, lockConfigOpts={}, cb) {

const retentionModes = [RETENTION_MODES.COMPLIANCE, RETENTION_MODES.GOVERNANCE]
const validUnits = [RETENTION_VALIDITY_UNITS.DAYS, RETENTION_VALIDITY_UNITS.YEARS]

if (!isValidBucketName(bucketName)) {
throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName)
}

if (lockConfigOpts.mode && !retentionModes.includes(lockConfigOpts.mode)) {
throw new TypeError(`lockConfigOpts.mode should be one of ${retentionModes}`)
}
if (lockConfigOpts.unit && !validUnits.includes(lockConfigOpts.unit)){
throw new TypeError(`lockConfigOpts.unit should be one of ${validUnits}`)
}
if (lockConfigOpts.validity && !isNumber(lockConfigOpts.validity)){
throw new TypeError(`lockConfigOpts.validity should be a number`)
}

const method = 'PUT'
const query = "object-lock"

let config={
ObjectLockEnabled:"Enabled"
}
const configKeys = Object.keys(lockConfigOpts)
//Check if keys are present and all keys are present.
if(configKeys.length > 0){
if(_.difference(configKeys, ['unit','mode','validity']).length !== 0){
throw new TypeError(`lockConfigOpts.mode,lockConfigOpts.unit,lockConfigOpts.validity all the properties should be specified.`)
} else {
config.Rule={
DefaultRetention:{}
}
if (lockConfigOpts.mode) {
config.Rule.DefaultRetention.Mode = lockConfigOpts.mode
}
if (lockConfigOpts.unit) {
config.Rule.DefaultRetention.Unit = lockConfigOpts.unit
}
if (lockConfigOpts.unit === RETENTION_VALIDITY_UNITS.DAYS) {
config.Rule.DefaultRetention.Days = lockConfigOpts.validity
} else if (lockConfigOpts.unit === RETENTION_VALIDITY_UNITS.YEARS) {
config.Rule.DefaultRetention.Years = lockConfigOpts.validity
}
}
}

const builder = new xml2js.Builder({rootName:'ObjectLockConfiguration', renderOpts:{'pretty':false}, headless:true})
const payload = builder.buildObject(config)

this.makeRequest({method, bucketName, query}, payload, 200, '', false, cb)
}

getObjectLockConfig(bucketName, cb) {
if (!isValidBucketName(bucketName)) {
throw new errors.InvalidBucketNameError('Invalid bucket name: ' + bucketName)
}
if (!isFunction(cb)) {
throw new errors.InvalidArgumentError('callback should be of type "function"')
}
const method = 'GET'
const query = "object-lock"

this.makeRequest({method, bucketName, query}, '', 200, '', true, (e, response) => {
if (e) return cb(e)

let objectLockConfig = Buffer.from('')
pipesetup(response, transformers.objectLockTransformer())
.on('data', data => {
objectLockConfig = data
})
.on('error', cb)
.on('end', () => {
cb(null, objectLockConfig)
})
})
}

get extensions() {
if(!this.clientExtensions)
{
Expand Down Expand Up @@ -2296,6 +2396,8 @@ Client.prototype.setBucketPolicy = promisify(Client.prototype.setBucketPolicy)
Client.prototype.removeIncompleteUpload = promisify(Client.prototype.removeIncompleteUpload)
Client.prototype.getBucketVersioning = promisify((Client.prototype.getBucketVersioning))
Client.prototype.setBucketVersioning=promisify((Client.prototype.setBucketVersioning))
Client.prototype.setObjectLockConfig=promisify((Client.prototype.setObjectLockConfig))
Client.prototype.getObjectLockConfig=promisify((Client.prototype.getObjectLockConfig))

export class CopyConditions {
constructor() {
Expand Down
4 changes: 4 additions & 0 deletions src/main/transformers.js
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,8 @@ export function getNotificationTransformer() {

export function bucketVersioningTransformer(){
return getConcater(xmlParsers.parseBucketVersioningConfig)
}

export function objectLockTransformer(){
return getConcater(xmlParsers.parseObjectLockConfig)
}
Loading

0 comments on commit dd8da4f

Please sign in to comment.