Forráskód Böngészése

Console GetDocumentCommand final, fix misc bugs

Dalibor Votruba 4 éve
szülő
commit
093deb1007

+ 1 - 0
AppServer/Business/Mapper/MapperLong.cs

@@ -56,6 +56,7 @@ namespace BO.AppServer.Business.Mapper
                     CreatedBy = src.CreatedByUser.Name,
                     ChangedBy = src.ModifiedByUser != null ? src.ModifiedByUser.Name : string.Empty
                 });
+                builder.Custom(dest => dest.Artifacts, src => src.Artifacts.MapList<Artifact, ArtifactRDto>());
                 //calculate on demand  builder.Custom(dest => dest.BillingPlanCode, src => src.WorkspaceBillings.OrderByDescending(x=>x.Created).FirstOrDefault().BillingPlan.Code);
             });
             

+ 13 - 0
AppServer/Business/Services/DocumentService.cs

@@ -67,6 +67,19 @@ namespace BO.AppServer.Business.Services
 
         }
 
+        public async Task<ResultValueDto<DocumentRDto>> GetDocumentAsync(long workspaceId, IdentificationTypeEnum identificationType, string identificationValue)
+        {
+            var document = identificationType == IdentificationTypeEnum.Id ? 
+                _repoDocument.Get(ArgumentAsLong(nameof(identificationValue), identificationValue)) 
+                : _repoDocument.GetByName(workspaceId, identificationValue);
+
+            if (document == null)
+                throw new NoDataException();
+
+            return new ResultValueDto<DocumentRDto>(document.Map<Metadocument, DocumentRDto>());
+
+        }
+
         public async Task<ResultsValueDto<DocumentRDto>> GetAllDocumentsAsync(long workspaceId,  DocumentsScopeEnums scope, PagingDto paging)
         {
             CheckAndGetWorkspace(workspaceId);

+ 6 - 2
AppServer/Business/Services/StorageService.cs

@@ -108,14 +108,18 @@ namespace BO.AppServer.Business.Services
 
             var buffer = new byte[_config.Value.System.Storage.IoBufferSize];
 
-            var outputStream = new MemoryStream(buffer);
+            //var outputStream = new MemoryStream(buffer);
+            var outputStream = new MemoryStream();
 
             await using (var fs = _fileSystem.File.OpenRead(fullFileName))
             {
-                await fs.CopyToAsync(outputStream, _config.Value.System.Storage.IoBufferSize);
+                //await fs.CopyToAsync(outputStream, _config.Value.System.Storage.IoBufferSize);
+                await fs.CopyToAsync(outputStream);
+                await outputStream.FlushAsync();
                 fs.Close();
             }
 
+            outputStream.Seek(0, SeekOrigin.Begin);
             return new Tuple<Stream, long>(outputStream, outputStream.Length);
         }
 

+ 2 - 3
AppServer/Connector.Console/Connection.cs

@@ -148,15 +148,14 @@ namespace BO.Connector.Console
             return result.HasNoDataException() ? null : result.Value;
         }
 
-        public async Task<DocumentRDto> GetWorkspaceDocumentAsync(string workspaceApiKey,string apiKeyPassword,long documentId, string userNameContext)
+        public async Task<DocumentRDto> GetWorkspaceDocumentAsync(string workspaceApiKey,string apiKeyPassword,IdentificationTypeEnum identificationType, string identificationValue, string userNameContext)
         {
             CheckIsOpen();
             var header = GetUserContextHeaderAttributes(userNameContext, GetApiPasswordHeaderAttributes(apiKeyPassword));
-            var result = await CallRequestAsync<ResultValueDto<DocumentRDto>>($"{Ticket}/workspace/{workspaceApiKey}/document/{documentId}", RestCallTypeEnum.Get,null, header);
+            var result = await CallRequestAsync<ResultValueDto<DocumentRDto>>($"{Ticket}/workspace/{workspaceApiKey}/document/{identificationType}/{identificationValue}", RestCallTypeEnum.Get,null, header);
             return result.Value;
         }
 
-
         public async Task<Stream> GetWorkspaceDocumentContentAsync(string workspaceApiKey,string apiKeyPassword,long documentId, long artifactId, string userNameContext)
         {
             CheckIsOpen();

+ 1 - 2
AppServer/Connector/AbstractConnection.cs

@@ -190,11 +190,10 @@ namespace BO.Connector
                 foreach (var key in headerAttributes.Keys)
                 {
                     _client.DefaultRequestHeaders.Remove(key);
-                    _client.DefaultRequestHeaders.Add(key,headerAttributes[key]);
+                    _client.DefaultRequestHeaders.Add(key, headerAttributes[key]);
                 }
             }
 
-         
             return await _client.GetStreamAsync(relativeUrlApiCall);
         }
 

+ 1 - 0
AppServer/Data/Repository/ArtifactRepo.cs

@@ -12,6 +12,7 @@ namespace BO.AppServer.Data.Repository
     {
         public ArtifactRepo(IUnitOfWork<DataDomain> unitOfWork) : base(unitOfWork)
         {
+            DefaultIncludes.Add("MimeType");
         }
 
         public Artifact GetArtifact(long metadocumentId, long artifactId)

+ 1 - 1
AppServer/Data/Repository/MetadocumentRepo.cs

@@ -1,6 +1,5 @@
 using System.Linq;
 using BO.AppServer.Data.Entity;
-using Microsoft.EntityFrameworkCore;
 using Quadarax.Foundation.Core.Data;
 using Quadarax.Foundation.Core.Data.Domain;
 using Quadarax.Foundation.Core.Data.Interface.Domain;
@@ -10,6 +9,7 @@ public class MetadocumentRepo : EntityRepository<long,  Metadocument>
     {
         public MetadocumentRepo(IUnitOfWork<DataDomain> unitOfWork) : base(unitOfWork)
         {
+            DefaultIncludes.Add("Artifacts");
         }
 
 

+ 12 - 0
AppServer/Web/.config/dotnet-tools.json

@@ -0,0 +1,12 @@
+{
+  "version": 1,
+  "isRoot": true,
+  "tools": {
+    "dotnet-ef": {
+      "version": "5.0.10",
+      "commands": [
+        "dotnet-ef"
+      ]
+    }
+  }
+}

+ 1 - 0
AppServer/Web/Program.cs

@@ -1,6 +1,7 @@
 using AppServer;
 using Microsoft.AspNetCore.Hosting;
 using Microsoft.Extensions.Hosting;
+using Microsoft.AspNetCore.Server.Kestrel.Core;
 
 namespace BO.AppServer.Web
 {

+ 12 - 0
AppServer/Web/Services/ConsoleController.cs

@@ -197,6 +197,18 @@ namespace BO.AppServer.Web.Services
             });
         }
 
+        [HttpGet("{Ticket}/workspace/{wrkspApiKey}/document/{identificationType}/{identificationValue}")]
+        public async Task<ResultValueDto<DocumentRDto>> GetWorkspaceDocumentByIdentification(string ticket, string wrkspApiKey,[FromHeader] string apiKeyPassword, IdentificationTypeEnum identificationType, string identificationValue, [FromHeader] string context)
+        {
+            CheckAccess(ticket);
+            return await Call(async () =>
+            {
+                var id = await _srvWorkspace.GetWorkspaceIdByAPIAccess(wrkspApiKey, apiKeyPassword, context);
+                return await _srvDocument.GetDocumentAsync(id,identificationType,identificationValue);
+
+            });
+        }
+
         [HttpGet("{Ticket}/workspace/{wrkspApiKey}/document/{documentId}/artifact/{artifactId}/content")]
         public async Task<IActionResult> GetWorkspaceDocumentArtifactContent(string ticket, string wrkspApiKey,long documentId,long artifactId,[FromHeader] string apiKeyPassword,  [FromHeader] string context)
         {

+ 9 - 0
AppServer/Web/Web.csproj

@@ -29,4 +29,13 @@
     <ProjectReference Include="..\Data\Data.csproj" />
   </ItemGroup>
 
+  <ItemGroup>
+    <Content Update="appsettings.Development.json">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <Content Update="appsettings.json">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+
 </Project>

+ 3 - 3
AppServer/run_server.cmd

@@ -1,4 +1,4 @@
-rem ** usage run_server.cmd [build] **
+rem ** usage run_server.cmd **
 @echo off
-if "%1%"=="build" dotnet build
-Web\bin\Debug\netcoreapp3.1\BO.AppServer.Web.exe
+echo Use Ctrl+C to close server
+dotnet run --project:Web

+ 6 - 6
Console/Commands/Base/AbstractGetCommand.cs

@@ -4,7 +4,7 @@ using BO.AppServer.Metadata.Enums;
 using Quadarax.Foundation.Core.QConsole;
 using Quadarax.Foundation.Core.QConsole.Argument;
 using Quadarax.Foundation.Core.QConsole.Value;
-using static System.String;
+
 
 namespace BO.Console.Commands.Base
 {
@@ -12,15 +12,15 @@ namespace BO.Console.Commands.Base
     {
         #region *** Constants ***
 
-        private const string CS_ARG_NAME_ID = "id";
+        protected const string CS_ARG_NAME_ID = "id";
         private const string CS_ARG_HINT_ID = "<id>";
         private const string CS_ARG_DESC_ID = "Record identifier (long). Alternative to argument '" + CS_ARG_NAME_NAME + "'.";
 
-        private const string CS_ARG_NAME_NAME = "name";
+        protected const string CS_ARG_NAME_NAME = "name";
         private const string CS_ARG_HINT_NAME = "<name>";
         private const string CS_ARG_DESC_NAME = "Record name or code identifier. Alternative to argument '" + CS_ARG_NAME_ID + "'.";
 
-        private const string CS_ARG_NAME_DETAILS = "details";
+        protected const string CS_ARG_NAME_DETAILS = "details";
         private const string CS_ARG_HINT_DETAILS = "<show_details>";
         private const string CS_ARG_DESC_DETAILS = "Flag if show more details (related tables).";
         #endregion
@@ -68,8 +68,8 @@ namespace BO.Console.Commands.Base
         protected override IEnumerable<AbstractArgument> OnSetupArguments()
         {
             var args =  new List<AbstractArgument>(base.OnSetupArguments());
-            args.Add(new NamedArgument(CS_ARG_NAME_ID, CS_ARG_DESC_ID, CS_ARG_HINT_ID,TypeValuesEnum.Integer,Empty,false));
-            args.Add(new NamedArgument(CS_ARG_NAME_NAME, CS_ARG_DESC_NAME, CS_ARG_HINT_NAME,TypeValuesEnum.String,Empty,false));
+            args.Add(new NamedArgument(CS_ARG_NAME_ID, CS_ARG_DESC_ID, CS_ARG_HINT_ID,TypeValuesEnum.Integer,string.Empty,false));
+            args.Add(new NamedArgument(CS_ARG_NAME_NAME, CS_ARG_DESC_NAME, CS_ARG_HINT_NAME,TypeValuesEnum.String,string.Empty,false));
             args.Add(new FlagArgument(CS_ARG_NAME_DETAILS, CS_ARG_DESC_DETAILS, CS_ARG_HINT_DETAILS, false));
             return args;
         }

+ 2 - 2
Console/Commands/Base/AbstractWorkspaceCommand.cs

@@ -11,11 +11,11 @@ namespace BO.Console.Commands.Base
     {
         #region *** Constants ***
 
-        private const string CS_ARG_NAME_APIK = "akey";
+        protected const string CS_ARG_NAME_APIK = "akey";
         private const string CS_ARG_HINT_APIK = "<api_key>";
         private const string CS_ARG_DESC_APIK = "Workspace related API-KEY, if not defined API-KEY is used from config.";
 
-        private const string CS_ARG_NAME_APIKP = "akeyp";
+        protected const string CS_ARG_NAME_APIKP = "akeyp";
         private const string CS_ARG_HINT_APIKP = "<api_key_password>";
         private const string CS_ARG_DESC_APIKP = "Workspace related API-KEY password, if not defined API-KEY password is used from config.";
 

+ 71 - 0
Console/Commands/Base/AbstractWrkGetCommand.cs

@@ -0,0 +1,71 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Quadarax.Foundation.Core.QConsole;
+using Quadarax.Foundation.Core.QConsole.Argument;
+using Quadarax.Foundation.Core.QConsole.Value;
+
+namespace BO.Console.Commands.Base
+{
+    internal abstract class AbstractWrkGetCommand : AbstractGetCommand
+    {
+        #region *** Constants ***
+
+        protected const string CS_ARG_NAME_APIK = "akey";
+        private const string CS_ARG_HINT_APIK = "<api_key>";
+        private const string CS_ARG_DESC_APIK = "Workspace related API-KEY, if not defined API-KEY is used from config.";
+
+        protected const string CS_ARG_NAME_APIKP = "akeyp";
+        private const string CS_ARG_HINT_APIKP = "<api_key_password>";
+        private const string CS_ARG_DESC_APIKP = "Workspace related API-KEY password, if not defined API-KEY password is used from config.";
+
+        #endregion
+
+
+        #region *** Properties ***
+        protected string ApiKey { get; private set; }
+        protected string ApiKeyPassword { get; private set; }
+        #endregion
+
+        #region *** Constructors ***
+        protected AbstractWrkGetCommand(Engine engine) : base(engine)
+        {
+        }
+        #endregion
+
+        #region *** Protected Overrides ***
+
+        protected override void BeginExecute()
+        {
+            base.BeginExecute();
+            ApiKey = Configuration.Defaults.Workspace.ApiKey;
+            ApiKeyPassword = Configuration.Defaults.Workspace.ApiKeyPassword;
+
+            var apiKey = GetArgumentValueOrDefault<string>(CS_ARG_NAME_APIK);
+            var apiKeyPassword = GetArgumentValueOrDefault<string>(CS_ARG_NAME_APIKP);
+
+            if (!string.IsNullOrEmpty(apiKey))
+                ApiKey = apiKey;
+            if (!string.IsNullOrEmpty(apiKeyPassword))
+                ApiKey = apiKeyPassword;
+
+            if (string.IsNullOrEmpty(ApiKey) || string.IsNullOrEmpty(ApiKeyPassword))
+                throw new ArgumentException(
+                    $"ApiKey or ApiKeyPassword must be specified by argument {Engine.Configuration.CharacterNamedArgumentSeparator}{CS_ARG_NAME_APIK} or {Engine.Configuration.CharacterNamedArgumentSeparator}{CS_ARG_NAME_APIKP} or specified in configuration file {Constants.CS_CONFIGURATION_FILE} in location 'defaults/workspace/api-key' or 'defaults/workspace/api-key-password'.");
+
+            WriteInfo($"Using API-KEY: {ApiKey}");
+            WriteDebugInfo($"Using API-KEY-PASSWORD: {ApiKeyPassword}");
+
+        }
+
+        protected override IEnumerable<AbstractArgument> OnSetupArguments()
+        {
+            var args =  base.OnSetupArguments().ToList();
+            args.Add(new NamedArgument(CS_ARG_NAME_APIK, CS_ARG_DESC_APIK,CS_ARG_HINT_APIK, TypeValuesEnum.String, string.Empty, false));
+            args.Add(new NamedArgument(CS_ARG_NAME_APIKP, CS_ARG_DESC_APIKP,CS_ARG_HINT_APIKP, TypeValuesEnum.String, string.Empty, false));
+            return args;
+        }
+
+        #endregion
+    }
+}

+ 11 - 6
Console/Commands/Base/BaseCommand.cs

@@ -22,19 +22,19 @@ namespace BO.Console.Commands.Base
     {
         #region *** Constants ***
 
-        private const string CS_ARG_NAME_DUMP = "dump";
+        protected const string CS_ARG_NAME_DUMP = "dump";
         private const string CS_ARG_HINT_DUMP = "<is_dump_reponses>";
         private const string CS_ARG_DESC_DUMP = "Flag if set dumps incomming json messages.";
 
-        private const string CS_ARG_NAME_DEBUG = "dbg";
+        protected const string CS_ARG_NAME_DEBUG = "dbg";
         private const string CS_ARG_HINT_DEBUG = "<is_debug_mode>";
         private const string CS_ARG_DESC_DEBUG = "Flag if set writes debug messages.";
 
-        private const string CS_ARG_NAME_USER = "user";
+        protected const string CS_ARG_NAME_USER = "user";
         private const string CS_ARG_HINT_USER = "<user_name>";
         private const string CS_ARG_DESC_USER = "User name context. If not specified use default user context (who is logged in console).";
 
-        private const string CS_ARG_NAME_FORCE = "force";
+        protected const string CS_ARG_NAME_FORCE = "force";
         private const string CS_ARG_HINT_FORCE = "<is_force>";
         private const string CS_ARG_DESC_FORCE = "Flag if set, then overrite existing entity, otherwise cancel operation.";
 
@@ -48,11 +48,11 @@ namespace BO.Console.Commands.Base
         protected string UserName { get; private set; }
         protected bool? IsForce { get; private set; }
 
-        protected IFileSystem FileSystem { get; }
+        protected IFileSystem FileSystem { get; private set; }
 
         protected BaseCommand(Engine engine) : base(engine)
         {
-            FileSystem = new FileSystem();
+            
         }
 
         protected override void OnInitialize()
@@ -70,7 +70,11 @@ namespace BO.Console.Commands.Base
                 UserName = GetArgumentValueOrDefault<string>(CS_ARG_NAME_USER);
 
             if (ContainsArgument(CS_ARG_NAME_FORCE))
+            {
                 IsForce = WasArgumentSpecified(CS_ARG_NAME_FORCE);
+                if (IsForce.GetValueOrDefault(false))
+                    WriteWarning("Force flag is set!");
+            }
 
             if (WasArgumentSpecified(CS_ARG_NAME_DEBUG))
                 DebugConsoleWriter.IsWriteDebugEnabled = true;
@@ -78,6 +82,7 @@ namespace BO.Console.Commands.Base
 
         protected override IEnumerable<AbstractArgument> OnSetupArguments()
         {
+            FileSystem = new FileSystem();
             var args = base.OnSetupArguments().ToList();
             args.Add(new FlagArgument(CS_ARG_NAME_DUMP, CS_ARG_DESC_DUMP, CS_ARG_HINT_DUMP, false));
             args.Add(new FlagArgument(CS_ARG_NAME_DEBUG, CS_ARG_DESC_DEBUG, CS_ARG_HINT_DEBUG, false));

+ 148 - 0
Console/Commands/Document/DocumentGetCommand.cs

@@ -0,0 +1,148 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using BO.AppServer.Metadata.Enums;
+using BO.Console.Commands.Base;
+using BO.Console.Extensions;
+using Quadarax.Foundation.Core.Logging;
+using Quadarax.Foundation.Core.QConsole;
+using Quadarax.Foundation.Core.QConsole.Argument;
+using Quadarax.Foundation.Core.QConsole.Attributes;
+using Quadarax.Foundation.Core.QConsole.Value;
+using Quadarax.Foundation.Core.Value;
+using Quadarax.Foundation.Core.Value.Extensions;
+
+namespace BO.Console.Commands.Document
+{
+    [CommandDefinition]
+    internal class DocumentGetCommand : AbstractWrkGetCommand
+    {
+        #region *** Constants ***
+        private const string CS_CMD_DOCGET_NAME = "document_get";
+        private const string CS_CMD_DOCGET_DESCR = "Get single document with artifacts by specification.";
+
+        protected const string CS_ARG_NAME_NOCONTENT = "nocontent";
+        private const string CS_ARG_HINT_NOCONTENT = "<no_content_saved>";
+        private const string CS_ARG_DESC_NOCONTENT = "Flag if set skip content saving. Related to arguments '" + CS_ARG_NAME_OUTDIR + "' and '" + CS_ARG_NAME_FORCE + "'.";
+
+        protected const string CS_ARG_NAME_OUTDIR = "outdir";
+        private const string CS_ARG_HINT_OUTDIR = "<output_directory>";
+        private const string CS_ARG_DESC_OUTDIR = "Alternative output directory to save content. If not exists attempts to create it. If not set use current directory.";
+        #endregion
+
+        #region *** Properties ***
+
+        public override string Name => CS_CMD_DOCGET_NAME;
+        public override string Description => CS_CMD_DOCGET_DESCR;
+
+        protected bool IsNoContent { get; set; }
+        protected string OutputDirectory { get; set; }
+        #endregion
+
+        #region *** Constructor ***
+        public DocumentGetCommand(Engine engine) : base(engine)
+        {
+        }
+        #endregion
+
+        #region *** EXECUTE ***
+        protected override Result OnExecute()
+        {
+            var document = Client.GetWorkspaceDocumentAsync(ApiKey, ApiKeyPassword,IdentificationType, IdentificationValue,UserName).Result;
+            
+            if (document == null)
+                throw new Exception($"Document {IdentificationType}: '{IdentificationValue}' not found!");
+
+            WriteDtoToConsole(document);
+
+            if (!IsNoContent)
+            {
+                //var tasksDownload = new List<Task>();
+                foreach (var art in document.Artifacts)
+                {
+                    //tasksDownload.Add(Task.Factory.StartNew(async () =>
+                    //{
+                        var bWrite = false;
+                        var fullFileName = art.GetFullFileName(FileSystem, OutputDirectory);
+                        if (FileSystem.File.Exists(fullFileName))
+                        {
+                            if (IsForce.GetValueOrDefault(false))
+                            {
+                                WriteDebugInfo($"Artifact file '{fullFileName}' already exists. Override.");
+                                FileSystem.File.Delete(fullFileName);
+                                WriteDebugInfo($"Artifact file '{fullFileName}' deleted.");
+                                bWrite = true;
+                            }
+                        }
+                        else
+                        {
+                            bWrite = true;
+                        }
+
+                        if (bWrite)
+                        {
+                            using (var fw = FileSystem.File.OpenWrite(fullFileName))
+                            {
+                                var content = Client.GetWorkspaceDocumentContentAsync(ApiKey, ApiKeyPassword,
+                                    document.Id, art.Id, UserName).Result;
+                                if (content != null)
+                                {
+                                    content.CopyTo(fw);
+                                    fw.Flush();
+                                    WriteCaption($"Artifact content file '{art.GetFileName(FileSystem)}' saved.");
+                                }
+                                else
+                                {
+                                    WriteError($"Artifact content file '{art.GetFileName(FileSystem)}' returns empty content! Skip.");
+                                }
+                            }
+                        }
+                        else
+                        {
+                            WriteError($"Artifact content file '{art.GetFileName(FileSystem)}' already exists! Skip.");
+                        }
+                    //}));
+                }
+
+                //Task.WaitAll(tasksDownload.ToArray());
+            }
+            else
+            {
+                WriteInfo("Artifacts content saving skip.");
+            }
+            return new Result();
+        }
+        #endregion
+
+        #region *** Private operations ***
+
+        protected override void OnValidateArguments()
+        {
+            base.OnValidateArguments();
+            IsNoContent = GetArgumentValueOrDefault<bool>(CS_ARG_NAME_NOCONTENT);
+            if (!IsNoContent)
+            {
+                OutputDirectory = GetArgumentValueOrDefault<string>(CS_ARG_NAME_OUTDIR).EnsurePathNonBackslash();
+                if (!FileSystem.Directory.Exists(OutputDirectory))
+                {
+                    Log(LogSeverityEnum.Debug, $"Output directory '{OutputDirectory}' not exists. Creating...");
+                    FileSystem.Directory.CreateDirectory(OutputDirectory);
+                    Log(LogSeverityEnum.Info, $"Output directory '{OutputDirectory}' created.");
+                }
+            }
+        }
+
+        protected override IEnumerable<AbstractArgument> OnSetupArguments()
+        {
+            var result = base.OnSetupArguments().ToList();
+            result.Add(new NamedArgument(CS_ARG_NAME_OUTDIR, CS_ARG_DESC_OUTDIR, CS_ARG_HINT_OUTDIR, TypeValuesEnum.String, FileSystem.Directory.GetCurrentDirectory(), false));
+            result.Add(new FlagArgument(CS_ARG_NAME_NOCONTENT, CS_ARG_DESC_NOCONTENT, CS_ARG_HINT_NOCONTENT, false));
+            AppendUserArgument(result);
+            AppendForceArgument(result);
+            return result;
+        }
+        #endregion
+    }
+}

+ 1 - 1
Console/Commands/Document/DocumentsGetCommand.cs

@@ -16,7 +16,7 @@ namespace BO.Console.Commands.Document
         #region *** Constants ***
 
         private const string CS_CMD_WRKSPGET_NAME = "document_list";
-        private const string CS_CMD_WRKSPGET_DESCR = "Get list of workspaces by specification scope.";
+        private const string CS_CMD_WRKSPGET_DESCR = "Get list of workspace documents by specification scope.";
 
 
         private const string CS_ARG_NAME_USER = "user";

+ 19 - 0
Console/Extensions/ArtifactDtoExt.cs

@@ -0,0 +1,19 @@
+using System.IO.Abstractions;
+using BO.AppServer.Metadata.Dto;
+using Quadarax.Foundation.Core.Value.Extensions;
+
+namespace BO.Console.Extensions
+{
+    internal static class ArtifactDtoExt
+    {
+        public static string GetFileName(this ArtifactRDto artifact, IFileSystem fs)
+        {
+            return artifact.Name + artifact.Extension;
+        }
+
+        public static string GetFullFileName(this ArtifactRDto artifact, IFileSystem fs, string basePath)
+        {
+            return fs.Path.Combine(basePath.EnsurePathNonBackslash(), GetFileName(artifact, fs));
+        }
+    }
+}

+ 1 - 1
Console/Properties/launchSettings.json

@@ -2,7 +2,7 @@
   "profiles": {
     "Console": {
       "commandName": "Project",
-      "commandLineArgs": "document_clear -name:doc1_file1 -force -user:test -dbg -dump"
+      "commandLineArgs": "document_get -name:doc1_file1 -user:test -dbg -force"
     }
   }
 }