// Copyright (C) 2021-2022 Intel Corporation // // SPDX-License-Identifier: MIT (() => { const PluginRegistry = require('./plugins'); const serverProxy = require('./server-proxy'); const { isBrowser, isNode } = require('browser-or-node'); const { ArgumentError } = require('./exceptions'); const { CloudStorageCredentialsType, CloudStorageProviderType } = require('./enums'); function validateNotEmptyString(value) { if (typeof value !== 'string') { throw new ArgumentError(`Value must be a string. ${typeof value} was found`); } else if (!value.trim().length) { throw new ArgumentError('Value mustn\'t be empty string'); } } /** * Class representing a cloud storage * @memberof module:API.cvat.classes */ class CloudStorage { constructor(initialData) { const data = { id: undefined, display_name: undefined, description: undefined, credentials_type: undefined, provider_type: undefined, resource: undefined, account_name: undefined, key: undefined, secret_key: undefined, session_token: undefined, key_file: undefined, specific_attributes: undefined, owner: undefined, created_date: undefined, updated_date: undefined, manifest_path: undefined, manifests: undefined, }; for (const property in data) { if (Object.prototype.hasOwnProperty.call(data, property) && property in initialData) { data[property] = initialData[property]; } } Object.defineProperties( this, Object.freeze({ /** * @name id * @type {number} * @memberof module:API.cvat.classes.CloudStorage * @readonly * @instance */ id: { get: () => data.id, }, /** * Storage name * @name displayName * @type {string} * @memberof module:API.cvat.classes.CloudStorage * @instance * @throws {module:API.cvat.exceptions.ArgumentError} */ displayName: { get: () => data.display_name, set: (value) => { validateNotEmptyString(value); data.display_name = value; }, }, /** * Storage description * @name description * @type {string} * @memberof module:API.cvat.classes.CloudStorage * @instance * @throws {module:API.cvat.exceptions.ArgumentError} */ description: { get: () => data.description, set: (value) => { if (typeof value !== 'string') { throw new ArgumentError('Value must be string'); } data.description = value; }, }, /** * Azure account name * @name accountName * @type {string} * @memberof module:API.cvat.classes.CloudStorage * @instance * @throws {module:API.cvat.exceptions.ArgumentError} */ accountName: { get: () => data.account_name, set: (value) => { validateNotEmptyString(value); data.account_name = value; }, }, /** * AWS access key id * @name accessKey * @type {string} * @memberof module:API.cvat.classes.CloudStorage * @instance * @throws {module:API.cvat.exceptions.ArgumentError} */ accessKey: { get: () => data.key, set: (value) => { validateNotEmptyString(value); data.key = value; }, }, /** * AWS secret key * @name secretKey * @type {string} * @memberof module:API.cvat.classes.CloudStorage * @instance * @throws {module:API.cvat.exceptions.ArgumentError} */ secretKey: { get: () => data.secret_key, set: (value) => { validateNotEmptyString(value); data.secret_key = value; }, }, /** * Session token * @name token * @type {string} * @memberof module:API.cvat.classes.CloudStorage * @instance * @throws {module:API.cvat.exceptions.ArgumentError} */ token: { get: () => data.session_token, set: (value) => { validateNotEmptyString(value); data.session_token = value; }, }, /** * Key file * @name keyFile * @type {File} * @memberof module:API.cvat.classes.CloudStorage * @instance * @throws {module:API.cvat.exceptions.ArgumentError} */ keyFile: { get: () => data.key_file, set: (file) => { if (file instanceof File) { data.key_file = file; } else { throw new ArgumentError(`Should be a file. ${typeof file} was found`); } }, }, /** * Unique resource name * @name resource * @type {string} * @memberof module:API.cvat.classes.CloudStorage * @instance * @throws {module:API.cvat.exceptions.ArgumentError} */ resource: { get: () => data.resource, set: (value) => { validateNotEmptyString(value); data.resource = value; }, }, /** * @name manifestPath * @type {string} * @memberof module:API.cvat.classes.CloudStorage * @instance * @throws {module:API.cvat.exceptions.ArgumentError} */ manifestPath: { get: () => data.manifest_path, set: (value) => { validateNotEmptyString(value); data.manifest_path = value; }, }, /** * @name providerType * @type {module:API.cvat.enums.ProviderType} * @memberof module:API.cvat.classes.CloudStorage * @instance * @throws {module:API.cvat.exceptions.ArgumentError} */ providerType: { get: () => data.provider_type, set: (key) => { if (key !== undefined && !!CloudStorageProviderType[key]) { data.provider_type = CloudStorageProviderType[key]; } else { throw new ArgumentError('Value must be one CloudStorageProviderType keys'); } }, }, /** * @name credentialsType * @type {module:API.cvat.enums.CloudStorageCredentialsType} * @memberof module:API.cvat.classes.CloudStorage * @instance * @throws {module:API.cvat.exceptions.ArgumentError} */ credentialsType: { get: () => data.credentials_type, set: (key) => { if (key !== undefined && !!CloudStorageCredentialsType[key]) { data.credentials_type = CloudStorageCredentialsType[key]; } else { throw new ArgumentError('Value must be one CloudStorageCredentialsType keys'); } }, }, /** * @name specificAttributes * @type {string} * @memberof module:API.cvat.classes.CloudStorage * @instance * @throws {module:API.cvat.exceptions.ArgumentError} */ specificAttributes: { get: () => data.specific_attributes, set: (attributesValue) => { if (typeof attributesValue === 'string') { const attrValues = new URLSearchParams( Array.from(new URLSearchParams(attributesValue).entries()).filter( ([key, value]) => !!key && !!value, ), ).toString(); if (!attrValues) { throw new ArgumentError('Value must match the key1=value1&key2=value2'); } data.specific_attributes = attributesValue; } else { throw new ArgumentError('Value must be a string'); } }, }, /** * Instance of a user who has created the cloud storage * @name owner * @type {module:API.cvat.classes.User} * @memberof module:API.cvat.classes.CloudStorage * @readonly * @instance */ owner: { get: () => data.owner, }, /** * @name createdDate * @type {string} * @memberof module:API.cvat.classes.CloudStorage * @readonly * @instance */ createdDate: { get: () => data.created_date, }, /** * @name updatedDate * @type {string} * @memberof module:API.cvat.classes.CloudStorage * @readonly * @instance */ updatedDate: { get: () => data.updated_date, }, /** * @name manifests * @type {string[]} * @memberof module:API.cvat.classes.CloudStorage * @instance * @throws {module:API.cvat.exceptions.ArgumentError} */ manifests: { get: () => data.manifests, set: (manifests) => { if (Array.isArray(manifests)) { for (const elem of manifests) { if (typeof elem !== 'string') { throw new ArgumentError('Each element of the manifests array must be a string'); } } data.manifests = manifests; } else { throw new ArgumentError('Value must be an array'); } }, }, }), ); } /** * Method updates data of a created cloud storage or creates new cloud storage * @method save * @returns {module:API.cvat.classes.CloudStorage} * @memberof module:API.cvat.classes.CloudStorage * @readonly * @instance * @async * @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.PluginError} */ async save() { const result = await PluginRegistry.apiWrapper.call(this, CloudStorage.prototype.save); return result; } /** * Method deletes a cloud storage from a server * @method delete * @memberof module:API.cvat.classes.CloudStorage * @readonly * @instance * @async * @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.PluginError} */ async delete() { const result = await PluginRegistry.apiWrapper.call(this, CloudStorage.prototype.delete); return result; } /** * Method returns cloud storage content * @method getContent * @memberof module:API.cvat.classes.CloudStorage * @readonly * @instance * @async * @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.PluginError} */ async getContent() { const result = await PluginRegistry.apiWrapper.call(this, CloudStorage.prototype.getContent); return result; } /** * Method returns the cloud storage preview * @method getPreview * @memberof module:API.cvat.classes.CloudStorage * @readonly * @instance * @async * @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.PluginError} */ async getPreview() { const result = await PluginRegistry.apiWrapper.call(this, CloudStorage.prototype.getPreview); return result; } /** * Method returns cloud storage status * @method getStatus * @memberof module:API.cvat.classes.CloudStorage * @readonly * @instance * @async * @throws {module:API.cvat.exceptions.ServerError} * @throws {module:API.cvat.exceptions.PluginError} */ async getStatus() { const result = await PluginRegistry.apiWrapper.call(this, CloudStorage.prototype.getStatus); return result; } } CloudStorage.prototype.save.implementation = async function () { function prepareOptionalFields(cloudStorageInstance) { const data = {}; if (cloudStorageInstance.description !== undefined) { data.description = cloudStorageInstance.description; } if (cloudStorageInstance.accountName) { data.account_name = cloudStorageInstance.accountName; } if (cloudStorageInstance.accessKey) { data.key = cloudStorageInstance.accessKey; } if (cloudStorageInstance.secretKey) { data.secret_key = cloudStorageInstance.secretKey; } if (cloudStorageInstance.token) { data.session_token = cloudStorageInstance.token; } if (cloudStorageInstance.keyFile) { data.key_file = cloudStorageInstance.keyFile; } if (cloudStorageInstance.specificAttributes !== undefined) { data.specific_attributes = cloudStorageInstance.specificAttributes; } return data; } // update if (typeof this.id !== 'undefined') { // provider_type and recource should not change; // send to the server only the values that have changed const initialData = {}; if (this.displayName) { initialData.display_name = this.displayName; } if (this.credentialsType) { initialData.credentials_type = this.credentialsType; } if (this.manifests) { initialData.manifests = this.manifests; } const cloudStorageData = { ...initialData, ...prepareOptionalFields(this), }; await serverProxy.cloudStorages.update(this.id, cloudStorageData); return this; } // create const initialData = { display_name: this.displayName, credentials_type: this.credentialsType, provider_type: this.providerType, resource: this.resource, manifests: this.manifests, }; const cloudStorageData = { ...initialData, ...prepareOptionalFields(this), }; const cloudStorage = await serverProxy.cloudStorages.create(cloudStorageData); return new CloudStorage(cloudStorage); }; CloudStorage.prototype.delete.implementation = async function () { const result = await serverProxy.cloudStorages.delete(this.id); return result; }; CloudStorage.prototype.getContent.implementation = async function () { const result = await serverProxy.cloudStorages.getContent(this.id, this.manifestPath); return result; }; CloudStorage.prototype.getPreview.implementation = async function getPreview() { return new Promise((resolve, reject) => { serverProxy.cloudStorages .getPreview(this.id) .then((result) => { if (isNode) { resolve(global.Buffer.from(result, 'binary').toString('base64')); } else if (isBrowser) { const reader = new FileReader(); reader.onload = () => { resolve(reader.result); }; reader.readAsDataURL(result); } }) .catch((error) => { reject(error); }); }); }; CloudStorage.prototype.getStatus.implementation = async function () { const result = await serverProxy.cloudStorages.getStatus(this.id); return result; }; module.exports = { CloudStorage, }; })();