From 415b8c033b74363828ebbb06d2bd9ce459a0b731 Mon Sep 17 00:00:00 2001 From: Joseph Milazzo Date: Sat, 17 Sep 2022 10:02:25 -0500 Subject: [PATCH] Fixed a RBS permission issue with Series Detail allowing a user to access a series without library access due to crafting a url with a library they do have access to. --- API/Data/Repositories/LibraryRepository.cs | 14 ++++++++++++++ API/Services/SeriesService.cs | 4 ++++ .../app/series-detail/series-detail.component.ts | 8 ++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/API/Data/Repositories/LibraryRepository.cs b/API/Data/Repositories/LibraryRepository.cs index 410c3b81b..ce31660c3 100644 --- a/API/Data/Repositories/LibraryRepository.cs +++ b/API/Data/Repositories/LibraryRepository.cs @@ -38,6 +38,7 @@ public interface ILibraryRepository Task> GetLibrariesAsync(LibraryIncludes includes = LibraryIncludes.None); Task DeleteLibrary(int libraryId); Task> GetLibrariesForUserIdAsync(int userId); + Task> GetLibraryIdsForUserIdAsync(int userId); Task GetLibraryTypeAsync(int libraryId); Task> GetLibraryForIdsAsync(IEnumerable libraryIds, LibraryIncludes includes = LibraryIncludes.None); Task GetTotalFiles(); @@ -111,6 +112,11 @@ public async Task DeleteLibrary(int libraryId) return await _context.SaveChangesAsync() > 0; } + /// + /// This does not track + /// + /// + /// public async Task> GetLibrariesForUserIdAsync(int userId) { return await _context.Library @@ -120,6 +126,14 @@ public async Task> GetLibrariesForUserIdAsync(int userId) .ToListAsync(); } + public async Task> GetLibraryIdsForUserIdAsync(int userId) + { + return await _context.Library + .Where(l => l.AppUsers.Select(ap => ap.Id).Contains(userId)) + .Select(l => l.Id) + .ToListAsync(); + } + public async Task GetLibraryTypeAsync(int libraryId) { return await _context.Library diff --git a/API/Services/SeriesService.cs b/API/Services/SeriesService.cs index 471cb2b16..c072266bb 100644 --- a/API/Services/SeriesService.cs +++ b/API/Services/SeriesService.cs @@ -13,6 +13,7 @@ using API.Entities.Enums; using API.Helpers; using API.SignalR; +using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; namespace API.Services; @@ -462,6 +463,9 @@ public async Task DeleteMultipleSeries(IList seriesIds) public async Task GetSeriesDetail(int seriesId, int userId) { var series = await _unitOfWork.SeriesRepository.GetSeriesDtoByIdAsync(seriesId, userId); + var libraryIds = (await _unitOfWork.LibraryRepository.GetLibraryIdsForUserIdAsync(userId)); + if (!libraryIds.Contains(series.LibraryId)) + throw new UnauthorizedAccessException("User does not have access to the library this series belongs to"); var libraryType = await _unitOfWork.LibraryRepository.GetLibraryTypeAsync(series.LibraryId); var volumes = (await _unitOfWork.VolumeRepository.GetVolumesDtoAsync(seriesId, userId)) diff --git a/UI/Web/src/app/series-detail/series-detail.component.ts b/UI/Web/src/app/series-detail/series-detail.component.ts index 41c6bdc4d..9b42022bc 100644 --- a/UI/Web/src/app/series-detail/series-detail.component.ts +++ b/UI/Web/src/app/series-detail/series-detail.component.ts @@ -3,7 +3,7 @@ import { Title } from '@angular/platform-browser'; import { ActivatedRoute, Router } from '@angular/router'; import { NgbModal, NgbNavChangeEvent, NgbOffcanvas } from '@ng-bootstrap/ng-bootstrap'; import { ToastrService } from 'ngx-toastr'; -import { forkJoin, Subject } from 'rxjs'; +import { catchError, forkJoin, of, Subject } from 'rxjs'; import { take, takeUntil } from 'rxjs/operators'; import { BulkSelectionService } from '../cards/bulk-selection.service'; import { EditSeriesModalComponent } from '../cards/_modals/edit-series-modal/edit-series-modal.component'; @@ -511,7 +511,11 @@ export class SeriesDetailComponent implements OnInit, OnDestroy, AfterContentChe } }); - this.seriesService.getSeriesDetail(this.seriesId).subscribe(detail => { + this.seriesService.getSeriesDetail(this.seriesId).pipe(catchError(err => { + this.router.navigateByUrl('/libraries'); + return of(null); + })).subscribe(detail => { + if (detail == null) return; this.hasSpecials = detail.specials.length > 0; this.specials = detail.specials;