Skip to content

Commit

Permalink
Merge pull request #24 from dimer47/dev-shared-link
Browse files Browse the repository at this point in the history
✨ Add temporary download link feature for object.
  • Loading branch information
dimer47 authored Nov 20, 2021
2 parents daeed92 + c58d1d8 commit 3d9d400
Show file tree
Hide file tree
Showing 21 changed files with 1,209 additions and 837 deletions.
727 changes: 340 additions & 387 deletions README.md

Large diffs are not rendered by default.

105 changes: 98 additions & 7 deletions doc/Account.html

Large diffs are not rendered by default.

37 changes: 35 additions & 2 deletions doc/Account.js.html

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions doc/AccountMeta.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions doc/AccountMeta.js.html

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions doc/Containers.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions doc/Containers.js.html

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions doc/ContainersMeta.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions doc/ContainersMeta.js.html

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions doc/OVHObjectStorage.js.html

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions doc/OVHStorage.html

Large diffs are not rendered by default.

272 changes: 246 additions & 26 deletions doc/Objects.html

Large diffs are not rendered by default.

75 changes: 63 additions & 12 deletions doc/Objects.js.html

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions doc/ObjectsMeta.html

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions doc/ObjectsMeta.js.html

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions doc/global.html

Large diffs are not rendered by default.

643 changes: 288 additions & 355 deletions doc/index.html

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "node-ovh-objectstorage",
"version": "2.0.3",
"version": "2.0.4",
"description": "Simple library to use OVH Public Cloud Object Storage.",
"main": "index.js",
"scripts": {
Expand All @@ -27,6 +27,7 @@
"swift"
],
"dependencies": {
"crypto-js": "^4.1.1",
"lodash": "latest",
"md5": "latest",
"moment": "^2.25.3",
Expand Down
33 changes: 33 additions & 0 deletions src/Account.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const _ = require("../tools/lodash");
const request = require('../tools/request');

const CryptoJS = require('crypto-js');
const AccountMeta = require('./AccountMeta');

/**
Expand Down Expand Up @@ -80,6 +81,38 @@ class Account {
return a['containers'];
}

/**
* Generate key for temporary download
*
* @return {Promise<{key: String, headers: Objects}>}
*/
generateKey() {
this.context.key = CryptoJS.SHA512(Math.floor(new Date() / 1000)+'').toString(CryptoJS.enc.Hex);

return new Promise(async (resolve, reject) => {
try {
// delete file
request({
method: 'POST',
uri: encodeURI(this.context.endpoint.url),
headers: {
"X-Account-Meta-Temp-URL-Key": this.context.key,
"X-Auth-Token": this.context.token,
"Accept": "application/json"
}
}, (err, res) => {
err = err || request.checkIfResponseIsError(res);
if (err) // noinspection ExceptionCaughtLocallyJS
throw new Error(err);

return resolve({ key: this.context.key, headers: res.headers });
});
} catch (e) {
return reject(e);
}
});
}

/**
* Manage meta data of account
* Available methods : create(), update(), delete(), all(), has(), get()
Expand Down
5 changes: 4 additions & 1 deletion src/OVHObjectStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ class OVHStorage {
* @return {Promise<boolean|Error>}
*/
connection() {
this.key = this.config?.key !== undefined ? this.config.key : null;

return new Promise((resolve, reject) => {
request({
method: 'POST',
Expand Down Expand Up @@ -154,10 +156,11 @@ class OVHStorage {
* }
*
* @async
* @return {{endpoint: *, token: *, connected_at : *}}
* @return {{key: String, endpoint: *, token: *, connected_at : *}}
*/
getConnectionDetails() {
return {
"key": this.key,
"token": this.token,
"endpoint": this.endpoint,
"connected_at": this.connected_at.format("YYYY-MM-DD HH:mm:ss")
Expand Down
77 changes: 64 additions & 13 deletions src/Objects.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const fs = require('fs');
const _ = require("../tools/lodash");
const request = require('../tools/request');
const moment = require('moment');
const CryptoJS = require('crypto-js');

const ObjectsMeta = require('./ObjectsMeta');

Expand Down Expand Up @@ -70,7 +71,7 @@ class Objects {
"X-Auth-Token": this.context.token,
"Accept": "application/json"
}
}, (err, res, body) => {
}, (err, res) => {
err = err || request.checkIfResponseIsError(res);
if (err) // noinspection ExceptionCaughtLocallyJS
throw new Error(err);
Expand Down Expand Up @@ -132,7 +133,7 @@ class Objects {
headers: {
"X-Auth-Token": this.context.token,
"Accept": "application/json"
},
},
encoding: encoding
}, (err, res, body) => {
err = err || request.checkIfResponseIsError(res);
Expand Down Expand Up @@ -163,11 +164,11 @@ class Objects {
save(file, path) {
return this.saveFile(file, path);
}

/**
* Save file data
*
* @param {Buffer|Uint8Array|Blob|string|Readable} file data to save
* @param {Buffer|Uint8Array|Blob|string|Readable} data data to save
* @param {String} path Path where to store the file
*
* @async
Expand Down Expand Up @@ -212,7 +213,7 @@ class Objects {
"Accept": "application/json"
},
body: data
}, (err, res, body) => {
}, (err, res) => {
err = err || request.checkIfResponseIsError(res);
if (err) // noinspection ExceptionCaughtLocallyJS
throw new Error(err);
Expand All @@ -224,7 +225,7 @@ class Objects {
}
});
}

/**
* Save file
*
Expand Down Expand Up @@ -277,7 +278,7 @@ class Objects {
"X-Auth-Token": this.context.token,
"Accept": "application/json"
}
}, (err, res, body) => {
}, (err, res) => {
err = err || request.checkIfResponseIsError(res);
if (err) // noinspection ExceptionCaughtLocallyJS
throw new Error(err);
Expand Down Expand Up @@ -407,7 +408,7 @@ class Objects {
"Accept": "application/json",
"Destination": '/' + pathToPasteFile
}
}, (err, res, body) => {
}, (err, res) => {
err = err || request.checkIfResponseIsError(res);
if (err) // noinspection ExceptionCaughtLocallyJS
throw new Error(err);
Expand Down Expand Up @@ -438,6 +439,56 @@ class Objects {
}
}

/**
* Generate temporary link to download files in private containers
*
* @param {String} path
* @param {Number} validityDurationInSeconds
* @param {Boolean} checkContainer
* @returns {Promise<String>}
*/
getTempLink(path, validityDurationInSeconds, checkContainer = true) {
return new Promise(async (resolve, reject) => {
try {
// check args
if (_.isUndefined(path)) // noinspection ExceptionCaughtLocallyJS
throw new Error("File path parameter is expected.");
if (!_.isString(path)) // noinspection ExceptionCaughtLocallyJS
throw new Error("File path parameter is not a string.");
if (!_.includes(path, '/')) // noinspection ExceptionCaughtLocallyJS
throw new Error("File path parameter isn't valid : container/filename.ext.");

// remove first path separator if is send with parameter
path = (() => {
let p = path.split('/');
if (p[0] === '')
delete p[0];

return _.filter(p, (e) => {
return (!_.isUndefined(e))
}).join('/');
})()

// check if file exist
if (!(await this.context.objects().exist(path))) // noinspection ExceptionCaughtLocallyJS
throw new Error("File path does not seem to exist.");

let baseUrl = this.context.endpoint.url.split('/v1')[0];
let pathUrl = '/v1'+this.context.endpoint.url.split('/v1')[1];
let seconds = Math.floor(((validityDurationInSeconds * 1000) || 36e5) / 1000);
let method = 'GET';
let objectPath = pathUrl + '/' + path;
let expires = Math.floor(Date.now()/1000) + seconds;
let hmacBody = method + '\n' + expires + '\n' + objectPath;
let sig = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA1, this.context.key).update(hmacBody).finalize().toString(CryptoJS.enc.Hex);

resolve(baseUrl + objectPath + '?temp_url_sig=' + sig + '&temp_url_expires=' + expires);
} catch (e) {
return reject(e);
}
});
}

/**
* Delete file object
*
Expand Down Expand Up @@ -481,7 +532,7 @@ class Objects {
"X-Auth-Token": this.context.token,
"Accept": "application/json"
}
}, (err, res, body) => {
}, (err, res) => {
err = err || request.checkIfResponseIsError(res);
if (err) // noinspection ExceptionCaughtLocallyJS
throw new Error(err);
Expand Down Expand Up @@ -618,7 +669,7 @@ class Objects {
"X-Auth-Token": this.context.token,
"Accept": "application/json"
}
}, (err, res, body) => {
}, (err, res) => {
if (parseInt(res.statusCode) === 404) {
return resolve(false);
}
Expand Down Expand Up @@ -677,7 +728,7 @@ class Objects {
"X-Auth-Token": this.context.token,
"Accept": "application/json"
}
}, (err, res, body) => {
}, (err, res) => {
err = err || request.checkIfResponseIsError(res);
if (err) // noinspection ExceptionCaughtLocallyJS
throw new Error(err);
Expand Down Expand Up @@ -730,7 +781,7 @@ class Objects {
"X-Delete-At": Math.round(expire_date.toDate().getTime() / 1000),
"Accept": "application/json"
}
}, (err, res, body) => {
}, (err, res) => {
err = err || request.checkIfResponseIsError(res);
if (err) // noinspection ExceptionCaughtLocallyJS
throw new Error(err);
Expand Down Expand Up @@ -798,7 +849,7 @@ class Objects {
"X-Delete-After": parseInt(delete_seconds),
"Accept": "application/json"
}
}, (err, res, body) => {
}, (err, res) => {
err = err || request.checkIfResponseIsError(res);
if (err) // noinspection ExceptionCaughtLocallyJS
throw new Error(err);
Expand Down

0 comments on commit 3d9d400

Please sign in to comment.