Browse Source

storage-node: cli: Add parameters validation for the ‘upload’ command.

Shamil Gadelshin 4 years ago
parent
commit
dfa67d3d61

+ 3 - 0
storage-node/packages/cli/package.json

@@ -41,6 +41,9 @@
   },
   "dependencies": {
     "@joystream/storage-runtime-api": "^0.1.0",
+    "@joystream/service-discovery": "^0.1.0",
+    "@joystream/storage-utils": "^0.1.0",
+    "@joystream/types": "^0.11.0",
     "axios": "^0.19.2",
     "chalk": "^2.4.2",
     "lodash": "^4.17.11",

+ 19 - 1
storage-node/packages/cli/src/commands/base.ts

@@ -1,4 +1,3 @@
-// Composes an asset URL and logs it to console.
 import chalk from "chalk";
 import removeEndingForwardSlash from "@joystream/storage-utils/stripEndingSlash";
 
@@ -13,6 +12,25 @@ export abstract class BaseCommand {
         return assetUrl;
     }
 
+    // Abstract method to provide parameter validation.
+    protected abstract validateParameters() : boolean;
+
+    // Abstract method to show command usage.
+    protected abstract showUsage();
+
+    // Checks command parameters and shows the usage if necessary.
+    protected assertParameters() : boolean {
+        // Create, validate and show parameters.
+        if (!this.validateParameters()) {
+            console.log(chalk.yellow(`Invalid parameters for 'download' command:`));
+            this.showUsage();
+
+            return false;
+        }
+
+        return true;
+    }
+
     // Shows the error message and ends the process with error code.
     protected fail(message: string) {
         console.log(chalk.red(message));

+ 11 - 8
storage-node/packages/cli/src/commands/download.ts

@@ -19,23 +19,26 @@ export class DownloadCommand extends BaseCommand{
         this.filePath = filePath;
     }
 
-    validateDownloadParameters(url: string, contentId: string, filePath: string): boolean {
-        return url && url !== "" && contentId && contentId !== "" && filePath && filePath !== "";
+    // Provides parameter validation. Overrides the abstract method from the base class.
+    protected validateParameters(): boolean {
+        return this.storageNodeUrl && this.storageNodeUrl !== ""
+            && this.contentId && this.contentId !== ""
+            && this.filePath && this.filePath !== "";
     }
 
-    showDownloadUsage() {
+    // Shows command usage. Overrides the abstract method from the base class.
+    protected showUsage() {
         console.log(chalk.yellow(`
-        Invalid parameters for 'download' command.
         Usage:   storage-cli download colossusURL contentID filePath
         Example: storage-cli download http://localhost:3001 0x7a6ba7e9157e5fba190dc146fe1baa8180e29728a5c76779ed99655500cff795 ./movie.mp4
       `));
     }
 
+    // Command executor.
     async run() {
-        // Create, validate and show parameters.
-        if (!this.validateDownloadParameters(this.storageNodeUrl, this.contentId, this.filePath)) {
-            return this.showDownloadUsage();
-        }
+        // Checks for input parameters, shows usage if they are invalid.
+        if (!this.assertParameters()) return;
+
         const assetUrl = this.createAndLogAssetUrl(this.storageNodeUrl, this.contentId);
         console.log(chalk.yellow('File path:', this.filePath));
 

+ 9 - 7
storage-node/packages/cli/src/commands/head.ts

@@ -16,22 +16,24 @@ export class HeadCommand extends BaseCommand{
         this.contentId = contentId;
     }
 
-    validateHeadParameters(url: string, contentId: string): boolean {
-        return url && url !== "" && contentId && contentId !== "";
+    // Provides parameter validation. Overrides the abstract method from the base class.
+    protected validateParameters(): boolean {
+        return this.storageNodeUrl && this.storageNodeUrl !== "" && this.contentId && this.contentId !== "";
     }
 
-    showHeadUsage() {
+    // Shows command usage. Overrides the abstract method from the base class.
+    protected showUsage() {
         console.log(chalk.yellow(`
-        Invalid parameters for 'head' command.
         Usage:   storage-cli head colossusURL contentID
         Example: storage-cli head http://localhost:3001 0x7a6ba7e9157e5fba190dc146fe1baa8180e29728a5c76779ed99655500cff795
       `));
     }
 
+    // Command executor.
     async run() {
-        if (!this.validateHeadParameters(this.storageNodeUrl, this.contentId)) {
-            return this.showHeadUsage();
-        }
+        // Checks for input parameters, shows usage if they are invalid.
+        if (!this.assertParameters()) return;
+
         const assetUrl = this.createAndLogAssetUrl(this.storageNodeUrl, this.contentId);
 
         try {

+ 28 - 7
storage-node/packages/cli/src/commands/upload.ts

@@ -7,6 +7,7 @@ import { Option } from '@polkadot/types/codec';
 import {BaseCommand} from "./base";
 import {discover} from "@joystream/service-discovery/discover";
 import Debug from "debug";
+import chalk from "chalk";
 const debug = Debug('joystream:storage-cli:upload');
 
 // Defines maximum content length for the assets (files). Limits the upload.
@@ -48,8 +49,18 @@ export class UploadCommand extends BaseCommand{
         this.memberId = memberId;
     }
 
+    // Provides parameter validation. Overrides the abstract method from the base class.
+    protected validateParameters(): boolean {
+        return this.mediaSourceFilePath && this.mediaSourceFilePath !== ""
+            && this.dataObjectTypeId && this.dataObjectTypeId !== ""
+            && this.keyFile && this.keyFile !== ""
+            && this.passPhrase && this.passPhrase !== ""
+            && this.memberId && this.memberId !== ""
+
+    }
+
     // Reads the file from the filesystem and computes IPFS hash.
-    async computeIpfsHash(): Promise<string> {
+    private async computeIpfsHash(): Promise<string> {
         const file = fs.createReadStream(this.mediaSourceFilePath)
             .on('error', (err) => {
                 this.fail(`File read failed: ${err}`);
@@ -59,13 +70,13 @@ export class UploadCommand extends BaseCommand{
     }
 
     // Read the file size from the file system.
-    getFileSize(): number {
+    private getFileSize(): number {
         const stats = fs.statSync(this.mediaSourceFilePath);
         return stats.size;
     }
 
     // Creates parameters for the AddContent runtime tx.
-    async getAddContentParams(): Promise<AddContentParams> {
+    private async getAddContentParams(): Promise<AddContentParams> {
         const identity = await this.loadIdentity();
         const accountId = identity.address;
 
@@ -90,7 +101,7 @@ export class UploadCommand extends BaseCommand{
     }
 
     // Creates the DataObject in the runtime.
-    async createContent(p: AddContentParams): Promise<DataObject> {
+    private async createContent(p: AddContentParams): Promise<DataObject> {
         try {
             const dataObject: Option<DataObject> = await this.api.assets.createDataObject(
                 p.accountId,
@@ -112,7 +123,7 @@ export class UploadCommand extends BaseCommand{
     }
 
     // Uploads file to given asset URL.
-    async uploadFile(assetUrl: string) {
+    private async uploadFile(assetUrl: string) {
         // Create file read stream and set error handler.
         const file = fs.createReadStream(this.mediaSourceFilePath)
             .on('error', (err) => {
@@ -138,7 +149,7 @@ export class UploadCommand extends BaseCommand{
     }
 
     // Requests the runtime and obtains the storage node endpoint URL.
-    async discoverStorageProviderEndpoint(storageProviderId: string): Promise<string> {
+    private async discoverStorageProviderEndpoint(storageProviderId: string): Promise<string> {
         try {
             const serviceInfo = await discover(storageProviderId, this.api);
 
@@ -157,7 +168,7 @@ export class UploadCommand extends BaseCommand{
     }
 
     // Loads and unlocks the runtime identity using the key file and pass phrase.
-    async loadIdentity(): Promise<any> {
+    private async loadIdentity(): Promise<any> {
         try {
             await fs.promises.access(this.keyFile);
         } catch (error) {
@@ -167,9 +178,19 @@ export class UploadCommand extends BaseCommand{
         return this.api.identities.loadUnlock(this.keyFile, this.passPhrase);
     }
 
+    // Shows command usage. Overrides the abstract method from the base class.
+    protected showUsage() {
+        console.log(chalk.yellow(`
+        Usage:   storage-cli upload mediaSourceFilePath dataObjectTypeId keyFilePath passPhrase memberId
+        Example: storage-cli upload ./movie.mp4 1 ./keyFile.json secretPhrase 1
+      `));
+    }
 
     // Command executor.
     async run() {
+        // Checks for input parameters, shows usage if they are invalid.
+        if (!this.assertParameters()) return;
+
         let addContentParams = await this.getAddContentParams();
         debug(`AddContent Tx params: ${JSON.stringify(addContentParams)}`);
         debug(`Decoded CID: ${ContentId.decode(addContentParams.contentId).toString()}`);

+ 1 - 6
yarn.lock

@@ -22800,16 +22800,11 @@ typescript-formatter@^7.2.2:
     commandpost "^1.0.0"
     editorconfig "^0.15.0"
 
-typescript@3.7.2, typescript@3.7.x, typescript@^3.0.3, typescript@^3.6.4, typescript@^3.7.2:
+typescript@3.7.2, typescript@3.7.x, typescript@^3.0.3, typescript@^3.6.4, typescript@^3.7.2, typescript@^3.8.3, typescript@^3.9.6:
   version "3.7.2"
   resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb"
   integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==
 
-typescript@^3.8.3, typescript@^3.9.6:
-  version "3.9.6"
-  resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.6.tgz#8f3e0198a34c3ae17091b35571d3afd31999365a"
-  integrity sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==
-
 u2f-api@0.2.7:
   version "0.2.7"
   resolved "https://registry.yarnpkg.com/u2f-api/-/u2f-api-0.2.7.tgz#17bf196b242f6bf72353d9858e6a7566cc192720"