Skip to content
Merged
8 changes: 5 additions & 3 deletions lib-es5/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,20 +111,22 @@ exports.resource = function resource(public_id, callback) {
resource_type = options.resource_type || "image";
type = options.type || "upload";
uri = ["resources", resource_type, type, public_id];
return call_api("get", uri, pickOnlyExistingValues(options, "exif", "colors", "derived_next_cursor", "faces", "image_metadata", "pages", "phash", "coordinates", "max_results"), callback, options);
return call_api("get", uri, pickOnlyExistingValues(options, "exif", "colors", "derived_next_cursor", "faces", "image_metadata", "pages", "phash", "coordinates", "max_results", "versions"), callback, options);
};

exports.restore = function restore(public_ids, callback) {
var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};

options.content_type = 'json';
var resource_type = void 0,
type = void 0,
uri = void 0;
resource_type = options.resource_type || "image";
type = options.type || "upload";
uri = ["resources", resource_type, type, "restore"];
return call_api("post", uri, {
public_ids: public_ids
public_ids: public_ids,
versions: options.versions
}, callback, options);
};

Expand Down Expand Up @@ -661,4 +663,4 @@ exports.restore_metadata_field_datasource = function restore_metadata_field_data
options.content_type = "json";
var params = { external_ids: entries_external_id };
return call_api("post", ["metadata_fields", field_external_id, "datasource_restore"], params, callback, options);
};
};
4 changes: 3 additions & 1 deletion lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,18 @@ exports.resource = function resource(public_id, callback, options = {}) {
resource_type = options.resource_type || "image";
type = options.type || "upload";
uri = ["resources", resource_type, type, public_id];
return call_api("get", uri, pickOnlyExistingValues(options, "exif", "colors", "derived_next_cursor", "faces", "image_metadata", "pages", "phash", "coordinates", "max_results"), callback, options);
return call_api("get", uri, pickOnlyExistingValues(options, "exif", "colors", "derived_next_cursor", "faces", "image_metadata", "pages", "phash", "coordinates", "max_results", "versions"), callback, options);
};

exports.restore = function restore(public_ids, callback, options = {}) {
options.content_type = 'json';
let resource_type, type, uri;
resource_type = options.resource_type || "image";
type = options.type || "upload";
uri = ["resources", resource_type, type, "restore"];
return call_api("post", uri, {
public_ids: public_ids,
versions: options.versions,
}, callback, options);
};

Expand Down
94 changes: 94 additions & 0 deletions test/api_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ const {
PUBLIC_ID_4,
PUBLIC_ID_5,
PUBLIC_ID_6,
PUBLIC_ID_BACKUP_1,
PUBLIC_ID_BACKUP_2,
PUBLIC_ID_BACKUP_3,
} = PUBLIC_IDS;

const {
Expand Down Expand Up @@ -340,6 +343,35 @@ describe("api", function () {
});
});
});
describe("backup resource", function () {
this.timeout(TIMEOUT.MEDIUM);

const publicId = "api_test_backup" + UNIQUE_JOB_SUFFIX_ID;
before(() => uploadImage({
public_id: publicId,
backup: true,
}).then(() => cloudinary.v2.api.resource(publicId)).then((resource) => {
expect(resource).not.to.be(null);
}));
after(function () {
return cloudinary.v2.api.delete_resources(publicId).then((response) => {
expect(response).to.have.property("deleted");
});
});
it("should return the asset details together with all of its backed up versions when versions is true", function () {
return cloudinary.v2.api.resource(publicId, { versions: true })
.then((resource) => {
expect(resource.versions).to.be.an('array');
});
});

it("should return the asset details together without backed up versions when versions is false", function () {
return cloudinary.v2.api.resource(publicId, { versions: false })
.then((resource) => {
expect(resource.versions).to.be(undefined);
});
});
});
describe("delete", function () {
it("should allow deleting derived resource", function () {
this.timeout(TIMEOUT.MEDIUM);
Expand Down Expand Up @@ -972,6 +1004,68 @@ describe("api", function () {
expect(resource).not.to.be(null);
expect(resource.bytes).to.eql(3381);
}));
it('should restore a deleted resource by versions', function () {
return uploadImage({
public_id: PUBLIC_ID_BACKUP_1,
backup: true,
}).then(() => uploadImage({
public_id: PUBLIC_ID_BACKUP_2,
backup: true,
}).then(wait(TIMEOUT.SHORT))).then((uploadResponse) => {
expect(uploadResponse).not.to.be(null);
}).then(wait(TIMEOUT.SHORT))
.then(() => cloudinary.v2.api.delete_resources([PUBLIC_ID_BACKUP_1, PUBLIC_ID_BACKUP_2]))
.then((deleteResponse) => {
expect(deleteResponse).to.have.property("deleted");
})
.then(wait(TIMEOUT.SHORT))
.then(() => Q.all([
cloudinary.v2.api.resource(PUBLIC_ID_BACKUP_1, { versions: true }),
cloudinary.v2.api.resource(PUBLIC_ID_BACKUP_2, { versions: true })]))
.then((resources) => {
expect(resources.length).to.be(2);

const version_1 = resources[0].versions[0].version_id;
const version_2 = resources[1].versions[0].version_id;
return cloudinary.v2.api.restore([PUBLIC_ID_BACKUP_1, PUBLIC_ID_BACKUP_2], { versions: [version_1, version_2] });
}).then((restoreResponse) => {
expect(restoreResponse[PUBLIC_ID_BACKUP_1].bytes).to.eql(3381);
expect(restoreResponse[PUBLIC_ID_BACKUP_2].bytes).to.eql(3381);
}).then(() => cloudinary.v2.api.delete_resources([PUBLIC_ID_BACKUP_1, PUBLIC_ID_BACKUP_2]))
.then((deleteResponse) => {
expect(deleteResponse).to.have.property("deleted");
});
});
it('should restore an old deleted resource by versions', function () {
return uploadImage({
public_id: PUBLIC_ID_BACKUP_3,
backup: true,
}).then(() => uploadImage({
public_id: PUBLIC_ID_BACKUP_3,
angle: '0',
backup: true,
}).then(wait(TIMEOUT.SHORT))).then((uploadResponse) => {
expect(uploadResponse).not.to.be(null);
}).then(wait(TIMEOUT.SHORT))
.then(() => cloudinary.v2.api.delete_resources([PUBLIC_ID_BACKUP_3]))
.then((deleteResponse) => {
expect(deleteResponse).to.have.property("deleted");
})
.then(wait(TIMEOUT.SHORT))
.then(() => cloudinary.v2.api.resource(PUBLIC_ID_BACKUP_3, { versions: true }))
.then((resources) => {
expect(resources.versions.length).to.be(2);

const old_version = resources.versions[0].version_id;
return cloudinary.v2.api.restore(PUBLIC_ID_BACKUP_3, { versions: old_version });
}).then((restoreResponse) => {
expect(restoreResponse[PUBLIC_ID_BACKUP_3].bytes).to.eql(2353);
})
.then(() => cloudinary.v2.api.delete_resources([PUBLIC_ID_BACKUP_3]))
.then((deleteResponse) => {
expect(deleteResponse).to.have.property("deleted");
});
});
});
describe('mapping', function () {
before(function () {
Expand Down
4 changes: 4 additions & 0 deletions test/testUtils/testConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ module.exports = {
PUBLIC_ID_4: `${PUBLIC_ID}_4`,
PUBLIC_ID_5: `${PUBLIC_ID}_5`,
PUBLIC_ID_6: `${PUBLIC_ID}_6`,
PUBLIC_ID_BACKUP_1: `${PUBLIC_ID_PREFIX}backup_1${Date.now()}`,
PUBLIC_ID_BACKUP_2: `${PUBLIC_ID_PREFIX}backup_2${Date.now()}`,
PUBLIC_ID_BACKUP_3: `${PUBLIC_ID_PREFIX}backup_3${Date.now()}`,

},
PRESETS: {
API_TEST_UPLOAD_PRESET1: `npm_api_test_upload_preset_1_${UNIQUE_JOB_SUFFIX_ID}`,
Expand Down