| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.IO.Abstractions;
- using System.Linq;
- using System.Security.Principal;
- using System.Threading.Tasks;
- using BO.AppServer.Business.Exceptions;
- using BO.AppServer.Business.Mapper;
- using BO.AppServer.Business.Services.Base;
- using BO.AppServer.Data.Entity;
- using BO.AppServer.Data.Repository;
- using BO.AppServer.Metadata.Configuration;
- using BO.AppServer.Metadata.Dto;
- using BO.AppServer.Metadata.Enums;
- using Microsoft.AspNetCore.Identity;
- using Microsoft.Extensions.Logging;
- using Microsoft.Extensions.Options;
- using Quadarax.Foundation.Core.Data;
- using Quadarax.Foundation.Core.Data.Interface;
- using Quadarax.Foundation.Core.Data.Interface.Entity.Dto;
- namespace BO.AppServer.Business.Services
- {
- public class DocumentService : UserContextService
- {
- #region *** Private fields ***
- private IFileSystem _fileSystem;
- private WorkspaceRepo _repoWorkspace;
- private MetadocumentRepo _repoDocument;
- private MimeTypeRepo _repoMType;
- private ArtifactRepo _repoArtifact;
- private StorageService _srvStorage;
- #endregion
- #region *** Constructors ***
- public DocumentService(
- WorkspaceRepo repoWorkspace,
- MetadocumentRepo repoDocument,
- MimeTypeRepo repoMType,
- ArtifactRepo repoArtifact,
- StorageService srvStorage,
- IFileSystem fileSystem,
- IOptions<Configuration> config,
- UserRepo repoUser,
- UserManager<IdentityUser> userManager,
- IPrincipal currentPrincipal,
- ILoggerFactory logger) : base(config, repoUser, userManager, currentPrincipal, logger)
- {
- _repoWorkspace = repoWorkspace ?? throw new ArgumentNullException(nameof(repoWorkspace));
- _repoDocument = repoDocument ?? throw new ArgumentNullException(nameof(repoDocument));
- _repoMType = repoMType ?? throw new ArgumentNullException(nameof(repoMType));
- _repoArtifact = repoArtifact ?? throw new ArgumentNullException(nameof(repoArtifact));
- _fileSystem = fileSystem ?? throw new ArgumentNullException(nameof(fileSystem));
- _srvStorage = srvStorage ?? throw new ArgumentNullException(nameof(srvStorage));
- }
- #endregion
- #region *** Public Operations ***
- public async Task<ResultValueDto<DocumentRDto>> GetDocumentAsync(long workspaceId, long documentId)
- {
- var document = CheckAndGetDocument(workspaceId, documentId);
- return new ResultValueDto<DocumentRDto>(document.Map<Metadocument, DocumentRDto>());
- }
- 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);
- IList<Metadocument> documents = new List<Metadocument>();
- switch (scope)
- {
- case DocumentsScopeEnums.All:
- documents = _repoDocument.Query(paging).Where(x => x.Structure.WorkspaceId == workspaceId).OrderBy(x => x.Name).ToList();
- break;
- case DocumentsScopeEnums.Pending:
- documents = _repoDocument.Query(paging).Where(x => x.Structure.WorkspaceId == workspaceId && x.Status == (int)DocumentStatusEnum.Pending).OrderBy(x => x.Name).ToList();
- break;
- case DocumentsScopeEnums.Done:
- documents = _repoDocument.Query(paging).Where(x => x.Structure.WorkspaceId == workspaceId && x.Status == (int)DocumentStatusEnum.DoneOk).OrderBy(x => x.Name).ToList();
- break;
- case DocumentsScopeEnums.Working:
- documents = _repoDocument.Query(paging).Where(x => x.Structure.WorkspaceId == workspaceId && x.Status == (int)DocumentStatusEnum.Processing).OrderBy(x => x.Name).ToList();
- break;
- case DocumentsScopeEnums.Failed:
- documents = _repoDocument.Query(paging).Where(x => x.Structure.WorkspaceId == workspaceId && x.Status == (int)DocumentStatusEnum.DoneFail).OrderBy(x => x.Name).ToList();
- break;
- }
- return new ResultsValueDto<DocumentRDto>(documents.MapList<Metadocument, DocumentRDto>());
- }
- public async Task<ResultValueDto<DocumentRDto>> GetDocumentByNameAsync(long workspaceId, string name)
- {
- CheckAndGetWorkspace(workspaceId);
- IList<Metadocument> documents = new List<Metadocument>();
- var document = _repoDocument.GetByName(workspaceId, name);
- if (document == null)
- throw new NoDataException();
- return new ResultValueDto<DocumentRDto>(document.Map<Metadocument, DocumentRDto>());
- }
- public async Task<ResultsValueDto<DocumentRDto>> GetAllDocumentsAsync(DocumentsScopeEnums scope, PagingDto paging)
- {
- IList<Metadocument> documents = new List<Metadocument>();
- switch (scope)
- {
- case DocumentsScopeEnums.All:
- documents = _repoDocument.Query(paging).OrderBy(x => x.Name).ToList();
- break;
- case DocumentsScopeEnums.Pending:
- documents = _repoDocument.Query(paging).Where(x => x.Status == (int)DocumentStatusEnum.Pending).OrderBy(x => x.Name).ToList();
- break;
- case DocumentsScopeEnums.Done:
- documents = _repoDocument.Query(paging).Where(x => x.Status == (int)DocumentStatusEnum.DoneOk).OrderBy(x => x.Name).ToList();
- break;
- case DocumentsScopeEnums.Working:
- documents = _repoDocument.Query(paging).Where(x => x.Status == (int)DocumentStatusEnum.Processing).OrderBy(x => x.Name).ToList();
- break;
- case DocumentsScopeEnums.Failed:
- documents = _repoDocument.Query(paging).Where(x => x.Status == (int)DocumentStatusEnum.DoneFail).OrderBy(x => x.Name).ToList();
- break;
- }
- return new ResultsValueDto<DocumentRDto>(documents.MapList<Metadocument, DocumentRDto>());
- }
- public async Task<ResultValueDto<DocumentRDto>> CreateDocumentAsync(long workspaceId, DocumentCDto document)
- {
- var workspace = CheckAndGetWorkspace(workspaceId);
- var exists = _repoDocument.Query(new Paging())
- .Any(x => x.Structure.WorkspaceId == workspaceId && x.Name == document.Name);
- if (exists)
- {
- var exc = new EntityAlreadyExistsException(typeof(Metadocument), document.Name);
- Log.LogWarning(exc.Message);
- throw exc;
- }
- var newDocument = _repoDocument.New();
- document.CopyToDto(newDocument);
- newDocument.Created = DateTime.Now;
- newDocument.CreatedByUser = GetCurrentUser();
- newDocument.Status = (int)DocumentStatusEnum.New;
- newDocument.StructureId = workspace.Structures.First().Id;
- _repoDocument.Set(newDocument);
- _repoDocument.Commit();
- return new ResultValueDto<DocumentRDto>(newDocument.Map<Metadocument, DocumentRDto>());
- }
- public async Task<ResultsValueDto<ArtifactRDto>> ClearDocumentArtifactsAsync(long workspaceId, long documentId, bool force)
- {
-
- var document = CheckAndGetDocument(workspaceId, documentId);
- CheckDocumentStatusForUpdate(document, force);
- var artifacts = _repoArtifact.GetArtifacts(documentId).ToArray(); // must be to array
- foreach (var artifact in artifacts)
- {
- await _srvStorage.DeleteContent(artifact.Id);
- _repoArtifact.Remove(artifact.Id);
- Log.LogInformation($"Document '{document.Name}' ({documentId}) artifact '{artifact.Name + artifact.Extension}' ({artifact.Id}) removed.");
- }
-
- document.Modified = DateTime.Now;
- document.ModifiedByUser = GetCurrentUser();
- _repoDocument.Set(document);
- _repoArtifact.Commit();
- _repoDocument.Commit();
- return new ResultsValueDto<ArtifactRDto>(artifacts.MapList<Artifact, ArtifactRDto>());
- }
- public async Task<ResultValueDto<ArtifactRDto>> AppendArtifactAsync(long workspaceId, long documentId,
- ArtifactCDto artifact,bool replace, ArtifactTypeEnum type, Stream content)
- {
- //TODO: Rewrite better way - mainly rollback scenario
- var document = CheckAndGetDocument(workspaceId, documentId);
- var existingArtifact = _repoArtifact.GetArtifactByName(documentId, artifact.Name, artifact.Extension);
- if (existingArtifact!=null && !replace)
- {
- var exc = new EntityAlreadyExistsException(typeof(Artifact), artifact.Name + "." + artifact.Extension);
- Log.LogWarning(exc.Message);
- throw exc;
- }
- var mtype = _repoMType.GetByMimeType(artifact.MimeType);
- if (mtype == null)
- {
- var exc = new EntityNotExistsException(typeof(MimeType), artifact.MimeType, 0);
- Log.LogWarning(exc.Message);
- throw exc;
- }
- var newArtifact = (existingArtifact != null && replace) ? existingArtifact : _repoArtifact.New();
-
- newArtifact.Name = artifact.Name;
- newArtifact.Extension = artifact.Extension;
- newArtifact.Length = content.Length;
- newArtifact.Metadocument = document;
- newArtifact.MimeType = mtype;
- newArtifact.Created = DateTime.Now;
- newArtifact.CreatedByUser = GetCurrentUser();
- newArtifact.Type = (int)type;
- _repoArtifact.Set(newArtifact);
- document = _repoDocument.Get(documentId);
- document.Modified = DateTime.Now;
- document.ModifiedByUser = GetCurrentUser();
- _repoDocument.Set(document);
- _repoArtifact.Commit();
- _repoDocument.Commit();
- await _srvStorage.PushContentAsync(newArtifact.Id, content);
- return new ResultValueDto<ArtifactRDto>(newArtifact.Map<Artifact, ArtifactRDto>());
- }
- public async Task<Tuple<Stream, string>> GetArtifactAsync(long workspaceId, long documentId, long artifactId)
- {
- var artifact = CheckAndGetArtifact(workspaceId, documentId, artifactId);
- var result = await _srvStorage.PopContentAsync(artifact.Id);
- return new Tuple<Stream, string>(result.Item1, artifact.MimeType.Mimetype1);
- }
- public ArtifactCDto CreateArtifactDto(string fileName, string contentType)
- {
- var result = new ArtifactCDto();
- result.Extension = _fileSystem.Path.GetExtension(fileName);
- result.MimeType = contentType;
- result.Name = _fileSystem.Path.GetFileNameWithoutExtension(fileName);
- return result;
- }
- #endregion
- #region *** Private Operations ***
- private Workspace CheckAndGetWorkspace(long workspaceId)
- {
- var workspace = _repoWorkspace.Get(workspaceId);
- if (workspace == null)
- {
- var exc = new EntityNotExistsException(typeof(Workspace), nameof(Workspace.Id), workspaceId);
- Log.LogWarning(exc.Message);
- throw exc;
- }
- return workspace;
- }
- private Metadocument CheckAndGetDocument(long workspaceId, long documentId)
- {
- CheckAndGetWorkspace(workspaceId);
- var document = _repoDocument.Get(workspaceId ,documentId);
- if (document == null)
- {
- var exc = new EntityNotExistsException(typeof(Metadocument), nameof(Metadocument.Id), documentId);
- Log.LogWarning(exc.Message);
- throw exc;
- }
- return document;
- }
- private void CheckDocumentStatusForUpdate(Metadocument document, bool force)
- {
- if (document == null)
- throw new ArgumentNullException(nameof(document));
- var currentStatus = (DocumentStatusEnum)document.Status;
- var allowedStatus = new DocumentStatusEnum[]
- {
- DocumentStatusEnum.New,
- DocumentStatusEnum.Pending,
- };
- if (!allowedStatus.Contains(currentStatus))
- {
- var message = $"Document '{document.Name}' [{document.Id}] has not allowed status '{currentStatus}' for operation UPDATE. Allowed statuses are {string.Join(",", allowedStatus)}.";
- Log.LogWarning(message + (force ? " Skip due Force flag." : string.Empty));
- if (!force)
- throw new InvalidDocumentStateException(document.Name, document.Id, currentStatus, "update");
- }
-
- }
-
- private Artifact CheckAndGetArtifact(long workspaceId, long documentId, long artifactId)
- {
- CheckAndGetWorkspace(workspaceId);
- CheckAndGetDocument(workspaceId, documentId);
- var artifact = _repoArtifact.GetArtifact(documentId, artifactId);
- if (artifact == null)
- {
- var exc = new EntityNotExistsException(typeof(Artifact), nameof(Artifact.Id), artifactId);
- Log.LogWarning(exc.Message);
- throw exc;
- }
- return artifact;
- }
- #endregion
- }
- }
|