public async Task <Either <ActionResult, Unit> > Delete(Guid releaseId, IEnumerable <Guid> ids, bool forceDelete = false) { return(await _persistenceHelper .CheckEntityExists <Release>(releaseId) .OnSuccess(async release => await _userService.CheckCanUpdateRelease(release, ignoreCheck: forceDelete)) .OnSuccess(async release => await ids.Select(id => _releaseFileRepository.CheckFileExists(releaseId, id, DeletableFileTypes)).OnSuccessAll()) .OnSuccessVoid(async files => { foreach (var file in files) { await _releaseFileRepository.Delete(releaseId, file.Id); if (!await _releaseFileRepository.FileIsLinkedToOtherReleases(releaseId, file.Id)) { await _blobStorageService.DeleteBlob( PrivateReleaseFiles, file.Path()); await _fileRepository.Delete(file.Id); } } })); }
public async Task <ActionResult <ReleaseStatusPermissionsViewModel> > GetReleaseStatusPermissions(Guid releaseId) { return(await _persistenceHelper.CheckEntityExists <Release, Guid>(releaseId) .OnSuccess(release => new ReleaseStatusPermissionsViewModel { CanMarkDraft = _userService.CheckCanMarkReleaseAsDraft(release).Result.IsRight, CanMarkHigherLevelReview = _userService.CheckCanSubmitReleaseToHigherApproval(release).Result.IsRight, CanMarkApproved = _userService.CheckCanApproveRelease(release).Result.IsRight, }) .OrElse(() => new ReleaseStatusPermissionsViewModel())); }
public async Task <Either <ActionResult, TableBuilderResultViewModel> > Query( Guid releaseId, ObservationQueryContext queryContext) { return(await _statisticsPersistenceHelper.CheckEntityExists <ReleaseSubject>( query => query .Include(rs => rs.Release) .Where(rs => rs.ReleaseId == releaseId && rs.SubjectId == queryContext.SubjectId) ) .OnSuccess(rs => Query(rs.Release, queryContext))); }
public async Task <Either <ActionResult, Unit> > DeleteFootnote(Guid releaseId, Guid id) { return(await _contentPersistenceHelper .CheckEntityExists <Release>(releaseId) .OnSuccess(_userService.CheckCanUpdateRelease) .OnSuccess(_ => _statisticsPersistenceHelper.CheckEntityExists <Footnote>(id) .OnSuccess(async footnote => { await _footnoteRepository.DeleteFootnote(releaseId, footnote.Id); await _context.SaveChangesAsync(); return Unit.Instance; }))); }
public Task <Either <ActionResult, CommentViewModel> > SetResolved(Guid commentId, bool resolve) { return(_persistenceHelper.CheckEntityExists <Comment>(commentId) .OnSuccessDo(_userService.CheckCanResolveComment) .OnSuccess(async comment => { _context.Comment.Update(comment); comment.Resolved = resolve ? DateTime.UtcNow : (DateTime?)null; comment.ResolvedById = resolve ? _userService.GetUserId() : (Guid?)null; await _context.SaveChangesAsync(); return await GetCommentAsync(comment.Id); })); }
public async Task <ActionResult> Stream(string releaseId, string fileId) { if (Guid.TryParse(releaseId, out var releaseGuid) && Guid.TryParse(fileId, out var fileGuid)) { return(await _persistenceHelper.CheckEntityExists <Release>(releaseGuid) .OnSuccessDo(release => this.CacheWithLastModified(release.Published)) .OnSuccess(release => _releaseFileService.StreamFile(release.Id, fileGuid)) .OnSuccessDo(result => this.CacheWithETag(result.FileStream.ComputeMd5Hash())) .HandleFailures()); } return(NotFound()); }
public async Task <Either <ActionResult, ManageContentPageViewModel> > GetManageContentPageViewModel( Guid releaseId) { return(await _persistenceHelper .CheckEntityExists <Release>(releaseId) .OnSuccess(HydrateReleaseForReleaseViewModel) .OnSuccess(_userService.CheckCanViewRelease) .OnSuccessCombineWith(release => _contentService.GetUnattachedContentBlocks <DataBlock>(releaseId)) .OnSuccessCombineWith(releaseAndBlocks => _releaseFileService.ListAll( releaseId, Ancillary, FileType.Data)) .OnSuccess(async releaseBlocksAndFiles => { var(release, blocks, files) = releaseBlocksAndFiles; var methodologies = await _methodologyVersionRepository.GetLatestVersionByPublication(release.PublicationId); var releaseViewModel = _mapper.Map <ManageContentPageViewModel.ReleaseViewModel>(release); releaseViewModel.DownloadFiles = files.ToList(); releaseViewModel.Publication.Methodologies = _mapper.Map <List <TitleAndIdViewModel> >(methodologies); return new ManageContentPageViewModel { Release = releaseViewModel, AvailableDataBlocks = blocks }; })); }
public async Task <Either <ActionResult, FileStreamResult> > StreamFile(Guid releaseId, Guid fileId) { return(await _persistenceHelper .CheckEntityExists <ReleaseFile>(q => q .Include(rf => rf.File) .Include(rf => rf.Release) .ThenInclude(release => release.Publication) .Where(rf => rf.ReleaseId == releaseId && rf.FileId == fileId) ) .OnSuccessDo(rf => _userService.CheckCanViewRelease(rf.Release)) .OnSuccess(async rf => { return await GetBlob(rf.PublicPath()) .OnSuccess(blob => DownloadToStreamResult(blob, rf.File.Filename)); })); }
public async Task <Either <ActionResult, UserViewModel> > GetUser(Guid id) { return(await _userService .CheckCanManageAllUsers() .OnSuccess(async() => { return await _usersAndRolesPersistenceHelper .CheckEntityExists <ApplicationUser, string>(id.ToString()) .OnSuccess(async user => { return await _userRoleService.GetGlobalRoles(user.Id) .OnSuccessCombineWith(globalRoles => _userRoleService.GetPublicationRoles(id)) .OnSuccessCombineWith(globalAndPublicationRoles => _userRoleService.GetReleaseRoles(id)) .OnSuccess(tuple => { var(globalRoles, publicationRoles, releaseRoles) = tuple; // Currently we only allow a user to have a maximum of one global role var globalRole = globalRoles.First(); return new UserViewModel { Id = id, Name = user.FirstName + " " + user.LastName, Email = user.Email, Role = globalRole.Id, UserPublicationRoles = publicationRoles, UserReleaseRoles = releaseRoles }; }); }); })); }
public async Task <Either <ActionResult, MyPublicationViewModel> > GetMyPublication(Guid publicationId) { var userId = _userService.GetUserId(); return(await _persistenceHelper .CheckEntityExists <Publication>(publicationId) .OnSuccess(_userService.CheckCanAccessSystem) .OnSuccess(_ => _userService.CheckCanViewAllReleases() .OnSuccess(_ => _publicationRepository.GetPublicationWithAllReleases(publicationId)) .OrElse(async() => { var publication = _context.Find <Publication>(publicationId); return await _userService.CheckCanViewPublication(publication) .OnSuccess(_ => _publicationRepository.GetPublicationForUser(publicationId, userId)); }))); }
public async Task <Either <ActionResult, List <MetaGuidanceSubjectViewModel> > > GetSubjects(Guid releaseId, List <Guid> subjectIds = null) { return(await _persistenceHelper.CheckEntityExists <Release>(releaseId) .OnSuccess(async release => { var releaseSubjectsQueryable = _context .ReleaseSubject .Include(s => s.Subject) .Where(rs => rs.ReleaseId == releaseId); if (subjectIds != null) { releaseSubjectsQueryable = releaseSubjectsQueryable.Where(rs => subjectIds.Contains(rs.SubjectId)); } var releaseSubjects = await releaseSubjectsQueryable .OrderBy(rs => rs.Subject.Name) .ToListAsync(); var result = new List <MetaGuidanceSubjectViewModel>(); await releaseSubjects.ForEachAsync(async releaseSubject => { result.Add(await BuildSubjectViewModel(releaseSubject)); }); return result; }) // Currently we expect a failure checking the Release exists and succeed with an empty list. // StatisticsDb Releases are not always in sync with ContentDb Releases. // Until the first Subject is imported, no StatisticsDb Release exists. .OnFailureSucceedWith(result => Task.FromResult(new List <MetaGuidanceSubjectViewModel>()))); }
public async Task <Either <ActionResult, List <PreReleaseUserViewModel> > > GetPreReleaseUsers(Guid releaseId) { return(await _persistenceHelper .CheckEntityExists <Release>(releaseId) .OnSuccess(_userService.CheckCanAssignPrereleaseContactsToRelease) .OnSuccess( async _ => { var activePrereleaseContacts = await _context .UserReleaseRoles .Include(r => r.User) .Where(r => r.Role == ReleaseRole.PrereleaseViewer && r.ReleaseId == releaseId) .Select(r => r.User.Email.ToLower()) .Distinct() .Select( email => new PreReleaseUserViewModel { Email = email } ) .ToListAsync(); var invitedPrereleaseContacts = await _context .UserReleaseInvites .Where( r => r.Role == ReleaseRole.PrereleaseViewer && !r.Accepted && r.ReleaseId == releaseId ) .Select(i => i.Email.ToLower()) .Distinct() .Select( email => new PreReleaseUserViewModel { Email = email } ) .ToListAsync(); return activePrereleaseContacts .Concat(invitedPrereleaseContacts) .Distinct() .OrderBy(c => c.Email) .ToList(); } )); }
public Task <Either <ActionResult, List <ContentSectionViewModel> > > GetContentSectionsAsync( Guid releaseId) { return(_persistenceHelper .CheckEntityExists <Release>(releaseId, HydrateContentSectionsAndBlocks) .OnSuccess(OrderedContentSections)); }
public Task <Either <ActionResult, ResultSubjectMetaViewModel> > GetSubjectMeta(Guid releaseId, SubjectMetaQueryContext query, IQueryable <Observation> observations) { return(_persistenceHelper.CheckEntityExists <Subject>(query.SubjectId) .OnSuccess(CheckCanViewSubjectData) .OnSuccess(async subject => { var stopwatch = Stopwatch.StartNew(); stopwatch.Start(); var observationalUnits = _locationService.GetObservationalUnits(observations); _logger.LogTrace("Got Observational Units in {Time} ms", stopwatch.Elapsed.TotalMilliseconds); stopwatch.Restart(); var filters = GetFilters(query.SubjectId, observations, true); _logger.LogTrace("Got Filters in {Time} ms", stopwatch.Elapsed.TotalMilliseconds); stopwatch.Restart(); var footnotes = GetFilteredFootnotes(releaseId, observations, query); _logger.LogTrace("Got Footnotes in {Time} ms", stopwatch.Elapsed.TotalMilliseconds); stopwatch.Restart(); var geoJsonAvailable = HasBoundaryLevelDataForAnyObservationalUnits(observationalUnits); _logger.LogTrace("Got GeoJsonAvailable in {Time} ms", stopwatch.Elapsed.TotalMilliseconds); stopwatch.Restart(); var boundaryLevels = GetBoundaryLevelOptions(query.BoundaryLevel, observationalUnits.Keys); var indicators = GetIndicators(query); _logger.LogTrace("Got Indicators in {Time} ms", stopwatch.Elapsed.TotalMilliseconds); stopwatch.Restart(); var locations = GetGeoJsonObservationalUnits(observationalUnits, query.IncludeGeoJson ?? false, query.BoundaryLevel); _logger.LogTrace("Got Observational Units in {Time} ms", stopwatch.Elapsed.TotalMilliseconds); stopwatch.Restart(); var timePeriodRange = GetTimePeriodRange(observations); _logger.LogTrace("Got Time Periods in {Time} ms", stopwatch.Elapsed.TotalMilliseconds); stopwatch.Stop(); var publication = await _subjectService.GetPublicationForSubject(subject.Id); return new ResultSubjectMetaViewModel { Filters = filters, Footnotes = footnotes, GeoJsonAvailable = geoJsonAvailable, Indicators = indicators, Locations = locations, BoundaryLevels = boundaryLevels, PublicationName = publication.Title, SubjectName = subject.Name, TimePeriodRange = timePeriodRange }; })); }
public async Task <Either <ActionResult, DataBlockTableResultCacheKey> > CreateCacheKeyForDataBlock(Guid releaseId, Guid dataBlockId) { return(await _contentPersistenceHelper .CheckEntityExists <ReleaseContentBlock>(query => query .Include(rcb => rcb.Release) .Include(rcb => rcb.ContentBlock) .Where(rcb => rcb.ContentBlockId == dataBlockId && rcb.ReleaseId == releaseId)) .OnSuccess(releaseContentBlock => new DataBlockTableResultCacheKey(releaseContentBlock))); }
public Task <Either <ActionResult, MethodologyNoteViewModel> > AddNote( Guid methodologyVersionId, MethodologyNoteAddRequest request) { return(_persistenceHelper .CheckEntityExists <MethodologyVersion>(methodologyVersionId) .OnSuccess(_userService.CheckCanUpdateMethodology) .OnSuccess(async methodologyVersion => { var addedNote = await _methodologyNoteRepository.AddNote( methodologyVersionId: methodologyVersion.Id, createdByUserId: _userService.GetUserId(), content: request.Content, displayDate: request.DisplayDate ?? DateTime.Today.ToUniversalTime()); return BuildMethodologyNoteViewModel(addedNote); })); }
public async Task <Either <ActionResult, MethodologyVersionSummaryViewModel> > CreateMethodologyAmendment( Guid originalMethodologyVersionId) { return(await _persistenceHelper.CheckEntityExists <MethodologyVersion>(originalMethodologyVersionId) .OnSuccess(_userService.CheckCanMakeAmendmentOfMethodology) .OnSuccess(HydrateMethodologyVersionForAmendment) .OnSuccess(CreateAndSaveAmendment) .OnSuccessDo(LinkOriginalMethodologyFilesToAmendment) .OnSuccess(amendment => _methodologyService.GetSummary(amendment.Id))); }
public Task <Either <ActionResult, List <ReleaseNoteViewModel> > > AddReleaseNoteAsync(Guid releaseId, CreateOrUpdateReleaseNoteRequest request) { return(_persistenceHelper .CheckEntityExists <Release>(releaseId, HydrateReleaseForUpdates) .OnSuccess(_userService.CheckCanUpdateRelease) .OnSuccess(async release => { _context.Update.Add(new Update { On = request.On ?? DateTime.Now, Reason = request.Reason, ReleaseId = release.Id }); await _context.SaveChangesAsync(); return GetReleaseNoteViewModels(release.Id); })); }
/// <summary> /// Retry a stage of the publishing workflow /// </summary> /// <remarks> /// This results in the Publisher updating the latest ReleaseStatus for this Release rather than creating a new one. /// </remarks> /// <param name="releaseId"></param> /// <param name="stage"></param> /// <returns></returns> public async Task <Either <ActionResult, Unit> > RetryReleaseStage(Guid releaseId, RetryStage stage) { return(await _persistenceHelper .CheckEntityExists <Release>(releaseId) .OnSuccess(release => _userService.CheckCanPublishRelease(release)) .OnSuccess(async release => { if (release.Status != ReleaseStatus.Approved) { return ValidationActionResult(ReleaseNotApproved); } await _storageQueueService.AddMessageAsync( RetryStageQueue, new RetryStageMessage(releaseId, stage)); _logger.LogTrace($"Sent retry stage message for Release: {releaseId}"); return new Either <ActionResult, Unit>(Unit.Instance); })); }
public async Task <Either <ActionResult, DataBlockViewModel> > Create(Guid releaseId, DataBlockCreateViewModel dataBlockCreate) { return(await _persistenceHelper .CheckEntityExists <Release>(releaseId) .OnSuccess(_userService.CheckCanUpdateRelease) .OnSuccess(async release => { var dataBlock = _mapper.Map <DataBlock>(dataBlockCreate); dataBlock.Created = DateTime.UtcNow; var added = (await _context.DataBlocks.AddAsync(dataBlock)).Entity; release.AddContentBlock(added); _context.Releases.Update(release); await _context.SaveChangesAsync(); return await Get(added.Id); })); }
public async Task <Either <ActionResult, ReleaseChecklistViewModel> > GetChecklist(Guid releaseId) { return(await _persistenceHelper.CheckEntityExists <Release>(releaseId, HydrateReleaseForChecklist) .OnSuccess(_userService.CheckCanViewRelease) .OnSuccess( async release => new ReleaseChecklistViewModel( await GetErrors(release), await GetWarnings(release) ) )); }
public async Task <Either <ActionResult, FileStreamResult> > Stream(Guid releaseId, Guid fileId) { return(await _persistenceHelper .CheckEntityExists <ReleaseFile>(q => q .Include(rf => rf.File) .Where(rf => rf.ReleaseId == releaseId && rf.FileId == fileId)) .OnSuccess(async releaseFile => { var path = releaseFile.Path(); var blob = await _blobStorageService.GetBlob(PrivateReleaseFiles, path); var stream = new MemoryStream(); await _blobStorageService.DownloadToStream(PrivateReleaseFiles, path, stream); return new FileStreamResult(stream, blob.ContentType) { FileDownloadName = releaseFile.File.Filename }; })); }
public async Task <Either <ActionResult, FileStreamResult> > Stream(Guid methodologyId, Guid fileId) { return(await _persistenceHelper .CheckEntityExists <MethodologyFile>(q => q .Include(mf => mf.File) .Where(mf => mf.MethodologyVersionId == methodologyId && mf.FileId == fileId)) .OnSuccess(async mf => { return await GetBlob(mf.Path()) .OnSuccess(blob => DownloadToStream(blob, mf.File.Filename)); })); }
public async Task <Either <ActionResult, GlossaryEntryViewModel> > GetGlossaryEntry(string slug) { return(await _persistenceHelper .CheckEntityExists <GlossaryEntry>(query => query .Where(e => e.Slug == slug)) .OnSuccess(e => new GlossaryEntryViewModel { Title = e.Title, Slug = e.Slug, Body = e.Body, })); }
public async Task <Either <ActionResult, Footnote> > CreateFootnote( Guid releaseId, string content, IReadOnlyCollection <Guid> filterIds, IReadOnlyCollection <Guid> filterGroupIds, IReadOnlyCollection <Guid> filterItemIds, IReadOnlyCollection <Guid> indicatorIds, IReadOnlyCollection <Guid> subjectIds) { return(await _contentPersistenceHelper .CheckEntityExists <Release>(releaseId) .OnSuccess(_userService.CheckCanUpdateRelease) .OnSuccess(async() => { var newFootnoteId = _guidGenerator.NewGuid(); var footnote = new Footnote { Id = newFootnoteId, Content = content, Subjects = CreateSubjectLinks(newFootnoteId, subjectIds), Filters = CreateFilterLinks(newFootnoteId, filterIds), FilterGroups = CreateFilterGroupLinks(newFootnoteId, filterGroupIds), FilterItems = CreateFilterItemLinks(newFootnoteId, filterItemIds), Indicators = CreateIndicatorsLinks(newFootnoteId, indicatorIds) }; await _context.Footnote.AddAsync(footnote); await _context.ReleaseFootnote.AddAsync(new ReleaseFootnote { ReleaseId = releaseId, Footnote = footnote }); await _context.SaveChangesAsync(); return await GetFootnote(releaseId, footnote.Id); })); }
public async Task <Either <ActionResult, Unit> > InviteContributor(string email, Guid publicationId, List <Guid> releaseIds) { return(await _contentPersistenceHelper .CheckEntityExists <Publication>(publicationId, query => query .Include(p => p.Releases)) .OnSuccessDo( publication => _userService.CheckCanUpdateReleaseRole(publication, Contributor)) .OnSuccess(publication => ValidateReleaseIds(publication, releaseIds)) .OnSuccess(async publication => { email = email.Trim(); var user = await _userRepository.FindByEmail(email); if (user == null) { return await CreateNewUserContributorInvite(releaseIds, email, publication.Title); } return await CreateExistingUserContributorInvite(releaseIds, user.Id, email, publication.Title); })); }
public async Task <Either <ActionResult, SubjectsMetaViewModel> > GetSubjects(Guid releaseId) { return(await _contentPersistenceHelper .CheckEntityExists <Release>(releaseId) .OnSuccess(_userService.CheckCanViewRelease) .OnSuccess(release => { var files = _contentDbContext.ReleaseFiles .Include(file => file.File) .Where(file => file.ReleaseId == releaseId && file.File.Type == FileType.Data) .Select(file => file.File); // Exclude files that are replacements in progress var filesExcludingReplacements = files .Where(file => !file.ReplacingId.HasValue) .ToList(); var subjectIds = filesExcludingReplacements .WhereAsync( async file => { // Not optimal, ideally we should be able to fetch // the status with the file reference itself. // TODO EES-1231 Move imports table into database var importStatus = await _importStatusService .GetImportStatus(file.ReleaseId, file.Filename); return importStatus.Status == IStatus.COMPLETE; } ) .Select(file => file.SubjectId) .ToList(); var subjects = _statisticsDbContext.ReleaseSubject .Include(subject => subject.Subject) .Where(subject => subject.ReleaseId == releaseId && subjectIds.Contains(subject.SubjectId)) .Select(subject => new IdLabel( subject.Subject.Id, subject.Subject.Name)) .ToList(); return new SubjectsMetaViewModel { ReleaseId = releaseId, Subjects = subjects }; })); }
public async Task <Either <ActionResult, PreReleaseSummaryViewModel> > GetPreReleaseSummaryViewModelAsync( Guid releaseId) { return(await _persistenceHelper .CheckEntityExists <Release>(releaseId, queryable => queryable.Include(r => r.Publication) .ThenInclude(publication => publication.Contact)) .OnSuccess(_userService.CheckCanViewPreReleaseSummary) .OnSuccess(release => new PreReleaseSummaryViewModel( release.Publication.Slug, release.Publication.Title, release.Slug, release.Title, release.Publication.Contact.TeamEmail))); }
public async Task <Either <ActionResult, ReleaseStatusViewModel> > GetReleaseStatusAsync(Guid releaseId) { return(await _persistenceHelper .CheckEntityExists <Release>(releaseId) .OnSuccess(_userService.CheckCanViewRelease) .OnSuccess(async _ => { var query = new TableQuery <ReleaseStatus>() .Where(TableQuery.GenerateFilterCondition(nameof(ReleaseStatus.PartitionKey), QueryComparisons.Equal, releaseId.ToString())); var result = await _publisherTableStorageService.ExecuteQueryAsync(PublisherReleaseStatusTableName, query); var first = result.OrderByDescending(releaseStatus => releaseStatus.Created).FirstOrDefault(); return _mapper.Map <ReleaseStatusViewModel>(first); })); }
public async Task <ActionResult <TableBuilderResultViewModel> > QueryForDataBlock( Guid releaseId, Guid dataBlockId) { return(await _contentPersistenceHelper.CheckEntityExists <ReleaseContentBlock>( query => query .Include(rcb => rcb.ContentBlock) .Include(rcb => rcb.Release) .Where( rcb => rcb.ReleaseId == releaseId && rcb.ContentBlockId == dataBlockId ) ) .OnSuccessDo(block => this.CacheWithLastModifiedAndETag(block.Release.Published, ApiVersion)) .OnSuccess(block => _dataBlockService.GetDataBlockTableResult(block)) .HandleFailuresOrOk()); }