Open Source Web Application Framework for ASP.NET Core
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

280 lines
12 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging;
using Volo.Abp;
using Volo.Abp.Uow;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Caching;
using Volo.Docs.Caching;
using Volo.Docs.Documents;
using Volo.Docs.Documents.Filter;
using Volo.Docs.Documents.FullSearch.Elastic;
using Volo.Docs.Localization;
using Volo.Docs.Projects;
using Volo.Extensions;
namespace Volo.Docs.Admin.Documents
{
[Authorize(DocsAdminPermissions.Documents.Default)]
public class DocumentAdminAppService : ApplicationService, IDocumentAdminAppService
{
private readonly IProjectRepository _projectRepository;
private readonly IDocumentRepository _documentRepository;
private readonly IDocumentSourceFactory _documentStoreFactory;
private readonly IDistributedCache<DocumentUpdateInfo> _documentUpdateCache;
private readonly IDistributedCache<List<VersionInfo>> _versionCache;
private readonly IDistributedCache<LanguageConfig> _languageCache;
private readonly IDocumentFullSearch _elasticSearchService;
public DocumentAdminAppService(IProjectRepository projectRepository,
IDocumentRepository documentRepository,
IDocumentSourceFactory documentStoreFactory,
IDistributedCache<DocumentUpdateInfo> documentUpdateCache,
IDistributedCache<List<VersionInfo>> versionCache,
IDistributedCache<LanguageConfig> languageCache,
IDocumentFullSearch elasticSearchService)
{
_projectRepository = projectRepository;
_documentRepository = documentRepository;
_documentStoreFactory = documentStoreFactory;
_documentUpdateCache = documentUpdateCache;
_versionCache = versionCache;
_languageCache = languageCache;
_elasticSearchService = elasticSearchService;
LocalizationResource = typeof(DocsResource);
}
public async Task ClearCacheAsync(ClearCacheInput input)
{
var project = await _projectRepository.GetAsync(input.ProjectId);
var languageCacheKey = CacheKeyGenerator.GenerateProjectLanguageCacheKey(project);
await _languageCache.RemoveAsync(languageCacheKey, true);
var versionCacheKey = CacheKeyGenerator.GenerateProjectVersionsCacheKey(project);
await _versionCache.RemoveAsync(versionCacheKey, true);
var documents = await _documentRepository.GetListByProjectId(project.Id);
foreach (var document in documents)
{
var documentUpdateInfoCacheKey = CacheKeyGenerator.GenerateDocumentUpdateInfoCacheKey(
project: project,
documentName: document.Name,
languageCode: document.LanguageCode,
version: document.Version
);
await _documentUpdateCache.RemoveAsync(documentUpdateInfoCacheKey);
document.LastCachedTime = DateTime.MinValue;
await _documentRepository.UpdateAsync(document);
}
}
public async Task PullAllAsync(PullAllDocumentInput input)
{
var project = await _projectRepository.GetAsync(input.ProjectId);
var navigationDocument = await GetDocumentAsync(
project,
project.NavigationDocumentName,
input.LanguageCode,
input.Version
);
if (!DocsJsonSerializerHelper.TryDeserialize<NavigationNode>(navigationDocument.Content, out var navigation))
{
throw new UserFriendlyException($"Cannot validate navigation file '{project.NavigationDocumentName}' for the project {project.Name}.");
}
var leafs = navigation.Items.GetAllNodes(x => x.Items)
.Where(x => x.IsLeaf && !x.Path.IsNullOrWhiteSpace())
.ToList();
var source = _documentStoreFactory.Create(project.DocumentStoreType);
var documents = new List<Document>();
foreach (var leaf in leafs)
{
if (leaf.Path.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ||
leaf.Path.StartsWith("https://", StringComparison.OrdinalIgnoreCase) ||
(leaf.Path.StartsWith("{{") && leaf.Path.EndsWith("}}")))
{
continue;
}
try
{
var sourceDocument = await source.GetDocumentAsync(project, leaf.Path, input.LanguageCode, input.Version);
documents.Add(sourceDocument);
}
catch (Exception e)
{
Logger.LogException(e);
}
}
foreach (var document in documents)
{
await _documentRepository.DeleteAsync(document.ProjectId, document.Name,
document.LanguageCode,
document.Version);
await _documentRepository.InsertAsync(document, true);
await UpdateDocumentUpdateInfoCache(document);
}
}
public async Task PullAsync(PullDocumentInput input)
{
var project = await _projectRepository.GetAsync(input.ProjectId);
var source = _documentStoreFactory.Create(project.DocumentStoreType);
var sourceDocument = await source.GetDocumentAsync(project, input.Name, input.LanguageCode, input.Version);
await _documentRepository.DeleteAsync(sourceDocument.ProjectId, sourceDocument.Name,
sourceDocument.LanguageCode, sourceDocument.Version);
await _documentRepository.InsertAsync(sourceDocument, true);
await UpdateDocumentUpdateInfoCache(sourceDocument);
}
public async Task<PagedResultDto<DocumentDto>> GetAllAsync(GetAllInput input)
{
var totalCount = await _documentRepository.GetAllCountAsync(
projectId: input.ProjectId,
name: input.Name,
version: input.Version,
languageCode: input.LanguageCode,
fileName: input.FileName,
format: input.Format,
creationTimeMin: input.CreationTimeMin,
creationTimeMax: input.CreationTimeMax,
lastUpdatedTimeMin: input.LastUpdatedTimeMin,
lastUpdatedTimeMax: input.LastUpdatedTimeMax,
lastSignificantUpdateTimeMin: input.LastSignificantUpdateTimeMin,
lastSignificantUpdateTimeMax: input.LastSignificantUpdateTimeMax,
lastCachedTimeMin: input.LastCachedTimeMin,
lastCachedTimeMax: input.LastCachedTimeMax,
sorting: input.Sorting,
maxResultCount: input.MaxResultCount,
skipCount: input.SkipCount
);
var docs = await _documentRepository.GetAllAsync(
projectId: input.ProjectId,
name: input.Name,
version: input.Version,
languageCode: input.LanguageCode,
fileName: input.FileName,
format: input.Format,
creationTimeMin: input.CreationTimeMin,
creationTimeMax: input.CreationTimeMax,
lastUpdatedTimeMin: input.LastUpdatedTimeMin,
lastUpdatedTimeMax: input.LastUpdatedTimeMax,
lastSignificantUpdateTimeMin: input.LastSignificantUpdateTimeMin,
lastSignificantUpdateTimeMax: input.LastSignificantUpdateTimeMax,
lastCachedTimeMin: input.LastCachedTimeMin,
lastCachedTimeMax: input.LastCachedTimeMax,
sorting: input.Sorting,
maxResultCount: input.MaxResultCount,
skipCount: input.SkipCount
);
return new PagedResultDto<DocumentDto>
{
TotalCount = totalCount,
Items = ObjectMapper.Map<List<DocumentWithoutContent>, List<DocumentDto>>(docs)
};
}
public async Task RemoveFromCacheAsync(Guid documentId)
{
var document = await _documentRepository.GetAsync(documentId);
var project = await _projectRepository.GetAsync(document.ProjectId);
var documentUpdateInfoCacheKey = CacheKeyGenerator.GenerateDocumentUpdateInfoCacheKey(
project: project,
documentName: document.Name,
languageCode: document.LanguageCode,
version: document.Version
);
await _documentUpdateCache.RemoveAsync(documentUpdateInfoCacheKey);
await _documentRepository.DeleteAsync(document);
}
public async Task ReindexAsync(Guid documentId)
{
_elasticSearchService.ValidateElasticSearchEnabled();
await _elasticSearchService.DeleteAsync(documentId);
var document = await _documentRepository.GetAsync(documentId);
await _elasticSearchService.AddOrUpdateAsync(document);
}
public Task<FilterItems> GetFilterItemsAsync()
{
// return _filterItemsCache.GetAsync(
// CacheKeyGenerator.GenerateFilterItemsCacheKey(),
// async () =>
// {
// var filterItems = new FilterItems();
// var projects = await _projectRepository.GetListAsync();
// foreach (var project in projects)
// {
// var projectFilterItems = new FilterItems();
// var documents = await _documentRepository.GetListByProjectId(project.Id);
// foreach (var document in documents)
// {
// projectFilterItems.Add(new FilterItem
// {
// Name = document.Name,
// Value = document.Name
// });
// }
//
// filterItems.Add(new FilterItem
// {
// Name = project.Name,
// Value = project.Name,
// Items = projectFilterItems
// });
// }
//
// return filterItems;
// }
// );
return _documentRepository.GetFilterItemsAsync();
}
private async Task UpdateDocumentUpdateInfoCache(Document document)
{
var cacheKey = $"DocumentUpdateInfo{document.ProjectId}#{document.Name}#{document.LanguageCode}#{document.Version}";
await _documentUpdateCache.SetAsync(cacheKey, new DocumentUpdateInfo
{
Name = document.Name,
CreationTime = document.CreationTime,
LastUpdatedTime = document.LastUpdatedTime
});
}
private async Task<Document> GetDocumentAsync(
Project project,
string documentName,
string languageCode,
string version)
{
version = string.IsNullOrWhiteSpace(version) ? project.LatestVersionBranchName : version;
var source = _documentStoreFactory.Create(project.DocumentStoreType);
var document = await source.GetDocumentAsync(project, documentName, languageCode, version);
return document;
}
}
}