diff --git a/API/Controllers/ImageController.cs b/API/Controllers/ImageController.cs
index 4dd538c14..a158c3bfb 100644
--- a/API/Controllers/ImageController.cs
+++ b/API/Controllers/ImageController.cs
@@ -34,9 +34,10 @@ public class ImageController : BaseApiController
///
///
[HttpGet("chapter-cover")]
- [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"chapterId"})]
- public async Task GetChapterCoverImage(int chapterId)
+ [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"chapterId", "apiKey"})]
+ public async Task GetChapterCoverImage(int chapterId, string apiKey)
{
+ if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
var path = Path.Join(_directoryService.CoverImageDirectory, await _unitOfWork.ChapterRepository.GetChapterCoverImageAsync(chapterId));
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest($"No cover image");
var format = _directoryService.FileSystem.Path.GetExtension(path);
@@ -50,9 +51,10 @@ public class ImageController : BaseApiController
///
///
[HttpGet("library-cover")]
- [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"libraryId"})]
- public async Task GetLibraryCoverImage(int libraryId)
+ [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"libraryId", "apiKey"})]
+ public async Task GetLibraryCoverImage(int libraryId, string apiKey)
{
+ if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
var path = Path.Join(_directoryService.CoverImageDirectory, await _unitOfWork.LibraryRepository.GetLibraryCoverImageAsync(libraryId));
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest($"No cover image");
var format = _directoryService.FileSystem.Path.GetExtension(path);
@@ -66,9 +68,10 @@ public class ImageController : BaseApiController
///
///
[HttpGet("volume-cover")]
- [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"volumeId"})]
- public async Task GetVolumeCoverImage(int volumeId)
+ [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"volumeId", "apiKey"})]
+ public async Task GetVolumeCoverImage(int volumeId, string apiKey)
{
+ if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
var path = Path.Join(_directoryService.CoverImageDirectory, await _unitOfWork.VolumeRepository.GetVolumeCoverImageAsync(volumeId));
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest($"No cover image");
var format = _directoryService.FileSystem.Path.GetExtension(path);
@@ -81,10 +84,11 @@ public class ImageController : BaseApiController
///
/// Id of Series
///
- [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"seriesId"})]
+ [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"seriesId", "apiKey"})]
[HttpGet("series-cover")]
- public async Task GetSeriesCoverImage(int seriesId)
+ public async Task GetSeriesCoverImage(int seriesId, string apiKey)
{
+ if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
var path = Path.Join(_directoryService.CoverImageDirectory, await _unitOfWork.SeriesRepository.GetSeriesCoverImageAsync(seriesId));
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest($"No cover image");
var format = _directoryService.FileSystem.Path.GetExtension(path);
@@ -100,9 +104,10 @@ public class ImageController : BaseApiController
///
///
[HttpGet("collection-cover")]
- [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"collectionTagId"})]
- public async Task GetCollectionCoverImage(int collectionTagId)
+ [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"collectionTagId", "apiKey"})]
+ public async Task GetCollectionCoverImage(int collectionTagId, string apiKey)
{
+ if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
var path = Path.Join(_directoryService.CoverImageDirectory, await _unitOfWork.CollectionTagRepository.GetCoverImageAsync(collectionTagId));
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest($"No cover image");
var format = _directoryService.FileSystem.Path.GetExtension(path);
@@ -116,9 +121,10 @@ public class ImageController : BaseApiController
///
///
[HttpGet("readinglist-cover")]
- [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"readingListId"})]
- public async Task GetReadingListCoverImage(int readingListId)
+ [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"readingListId", "apiKey"})]
+ public async Task GetReadingListCoverImage(int readingListId, string apiKey)
{
+ if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
var path = Path.Join(_directoryService.CoverImageDirectory, await _unitOfWork.ReadingListRepository.GetCoverImageAsync(readingListId));
if (string.IsNullOrEmpty(path) || !_directoryService.FileSystem.File.Exists(path)) return BadRequest($"No cover image");
var format = _directoryService.FileSystem.Path.GetExtension(path);
@@ -139,6 +145,7 @@ public class ImageController : BaseApiController
public async Task GetBookmarkImage(int chapterId, int pageNum, string apiKey)
{
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
+ if (userId == 0) return BadRequest();
var bookmark = await _unitOfWork.UserRepository.GetBookmarkForPage(pageNum, chapterId, userId);
if (bookmark == null) return BadRequest("Bookmark does not exist");
@@ -157,9 +164,10 @@ public class ImageController : BaseApiController
///
[Authorize(Policy="RequireAdminRole")]
[HttpGet("cover-upload")]
- [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"filename"})]
- public ActionResult GetCoverUploadImage(string filename)
+ [ResponseCache(CacheProfileName = ResponseCacheProfiles.Images, VaryByQueryKeys = new []{"filename", "apiKey"})]
+ public async Task GetCoverUploadImage(string filename, string apiKey)
{
+ if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
if (filename.Contains("..")) return BadRequest("Invalid Filename");
var path = Path.Join(_directoryService.TempDirectory, filename);
diff --git a/API/Controllers/ReaderController.cs b/API/Controllers/ReaderController.cs
index ded9345b0..4311448b3 100644
--- a/API/Controllers/ReaderController.cs
+++ b/API/Controllers/ReaderController.cs
@@ -57,9 +57,10 @@ public class ReaderController : BaseApiController
///
///
[HttpGet("pdf")]
- [ResponseCache(CacheProfileName = ResponseCacheProfiles.Hour)]
- public async Task GetPdf(int chapterId)
+ [ResponseCache(CacheProfileName = ResponseCacheProfiles.Hour, VaryByQueryKeys = new []{"chapterId", "apiKey"})]
+ public async Task GetPdf(int chapterId, string apiKey)
{
+ if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
var chapter = await _cacheService.Ensure(chapterId);
if (chapter == null) return BadRequest("There was an issue finding pdf file for reading");
@@ -89,14 +90,16 @@ public class ReaderController : BaseApiController
/// This will cache the chapter images for reading
/// Chapter Id
/// Page in question
+ /// User's API Key for authentication
/// Should Kavita extract pdf into images. Defaults to false.
///
[HttpGet("image")]
- [ResponseCache(CacheProfileName = ResponseCacheProfiles.Hour)]
+ [ResponseCache(CacheProfileName = ResponseCacheProfiles.Hour, VaryByQueryKeys = new []{"chapterId","page", "extractPdf", "apiKey"})]
[AllowAnonymous]
- public async Task GetImage(int chapterId, int page, bool extractPdf = false)
+ public async Task GetImage(int chapterId, int page, string apiKey, bool extractPdf = false)
{
if (page < 0) page = 0;
+ if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
var chapter = await _cacheService.Ensure(chapterId, extractPdf);
if (chapter == null) return BadRequest("There was an issue finding image file for reading");
@@ -116,10 +119,11 @@ public class ReaderController : BaseApiController
}
[HttpGet("thumbnail")]
- [ResponseCache(CacheProfileName = ResponseCacheProfiles.Hour)]
+ [ResponseCache(CacheProfileName = ResponseCacheProfiles.Hour, VaryByQueryKeys = new []{"chapterId", "pageNum", "apiKey"})]
[AllowAnonymous]
- public async Task GetThumbnail(int chapterId, int pageNum)
+ public async Task GetThumbnail(int chapterId, int pageNum, string apiKey)
{
+ if (await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey) == 0) return BadRequest();
var chapter = await _cacheService.Ensure(chapterId, true);
if (chapter == null) return BadRequest("There was an issue extracting images from chapter");
var images = _cacheService.GetCachedPages(chapterId);
@@ -138,12 +142,13 @@ public class ReaderController : BaseApiController
/// We must use api key as bookmarks could be leaked to other users via the API
///
[HttpGet("bookmark-image")]
- [ResponseCache(CacheProfileName = ResponseCacheProfiles.Hour)]
+ [ResponseCache(CacheProfileName = ResponseCacheProfiles.Hour, VaryByQueryKeys = new []{"seriesId", "page", "apiKey"})]
[AllowAnonymous]
public async Task GetBookmarkImage(int seriesId, string apiKey, int page)
{
if (page < 0) page = 0;
var userId = await _unitOfWork.UserRepository.GetUserIdByApiKeyAsync(apiKey);
+ if (userId == 0) return BadRequest();
var totalPages = await _cacheService.CacheBookmarkForSeries(userId, seriesId);
if (page > totalPages)
@@ -750,6 +755,7 @@ public class ReaderController : BaseApiController
///
///
[HttpGet("time-left")]
+ [ResponseCache(CacheProfileName = "Hour", VaryByQueryKeys = new string[] { "seriesId"})]
public async Task> GetEstimateToCompletion(int seriesId)
{
var userId = await _unitOfWork.UserRepository.GetUserIdByUsernameAsync(User.GetUsername());
diff --git a/UI/Web/src/_manga-reader-common.scss b/UI/Web/src/_manga-reader-common.scss
index 631310e54..5e385274d 100644
--- a/UI/Web/src/_manga-reader-common.scss
+++ b/UI/Web/src/_manga-reader-common.scss
@@ -1,3 +1,5 @@
+$scrollbarHeight: 34px;
+
img {
user-select: none;
}
@@ -12,8 +14,9 @@ img {
}
&.full-height {
- height: calc(100vh - 34px); // 34px is the height of the horizontal scrollbar that will appear
- display: flex; // changed from inline-block to fix the centering on tablets not working
+ height: calc(100vh - $scrollbarHeight);
+ display: flex;
+ align-content: center;
}
&.original {
diff --git a/UI/Web/src/app/_services/image.service.ts b/UI/Web/src/app/_services/image.service.ts
index 3cc3a0355..0a54b00ac 100644
--- a/UI/Web/src/app/_services/image.service.ts
+++ b/UI/Web/src/app/_services/image.service.ts
@@ -13,6 +13,7 @@ export class ImageService implements OnDestroy {
baseUrl = environment.apiUrl;
apiKey: string = '';
+ encodedKey: string = '';
public placeholderImage = 'assets/images/image-placeholder-min.png';
public errorImage = 'assets/images/error-placeholder2-min.png';
public resetCoverImage = 'assets/images/image-reset-cover-min.png';
@@ -33,6 +34,7 @@ export class ImageService implements OnDestroy {
this.accountService.currentUser$.pipe(takeUntil(this.onDestroy)).subscribe(user => {
if (user) {
this.apiKey = user.apiKey;
+ this.encodedKey = encodeURIComponent(this.apiKey);
}
});
}
@@ -62,35 +64,35 @@ export class ImageService implements OnDestroy {
}
getLibraryCoverImage(libraryId: number) {
- return this.baseUrl + 'image/library-cover?libraryId=' + libraryId;
+ return `${this.baseUrl}image/library-cover?libraryId=${libraryId}&apiKey=${this.encodedKey}`;
}
getVolumeCoverImage(volumeId: number) {
- return this.baseUrl + 'image/volume-cover?volumeId=' + volumeId;
+ return `${this.baseUrl}image/volume-cover?volumeId=${volumeId}&apiKey=${this.encodedKey}`;
}
getSeriesCoverImage(seriesId: number) {
- return this.baseUrl + 'image/series-cover?seriesId=' + seriesId;
+ return `${this.baseUrl}image/series-cover?seriesId=${seriesId}&apiKey=${this.encodedKey}`;
}
getCollectionCoverImage(collectionTagId: number) {
- return this.baseUrl + 'image/collection-cover?collectionTagId=' + collectionTagId;
+ return `${this.baseUrl}image/collection-cover?collectionTagId=${collectionTagId}&apiKey=${this.encodedKey}`;
}
getReadingListCoverImage(readingListId: number) {
- return this.baseUrl + 'image/readinglist-cover?readingListId=' + readingListId;
+ return `${this.baseUrl}image/readinglist-cover?readingListId=${readingListId}&apiKey=${this.encodedKey}`;
}
getChapterCoverImage(chapterId: number) {
- return this.baseUrl + 'image/chapter-cover?chapterId=' + chapterId;
+ return `${this.baseUrl}image/chapter-cover?chapterId=${chapterId}&apiKey=${this.encodedKey}`;
}
getBookmarkedImage(chapterId: number, pageNum: number) {
- return this.baseUrl + 'image/bookmark?chapterId=' + chapterId + '&pageNum=' + pageNum + '&apiKey=' + encodeURIComponent(this.apiKey);
+ return `${this.baseUrl}image/bookmark?chapterId=${chapterId}&apiKey=${this.encodedKey}&pageNum=${pageNum}`;
}
getCoverUploadImage(filename: string) {
- return this.baseUrl + 'image/cover-upload?filename=' + encodeURIComponent(filename);
+ return `${this.baseUrl}image/cover-upload?filename=${encodeURIComponent(filename)}&apiKey=${this.encodedKey}`;
}
updateErroredImage(event: any) {
diff --git a/UI/Web/src/app/_services/reader.service.ts b/UI/Web/src/app/_services/reader.service.ts
index e435afd35..7da1e85bc 100644
--- a/UI/Web/src/app/_services/reader.service.ts
+++ b/UI/Web/src/app/_services/reader.service.ts
@@ -16,6 +16,9 @@ import { FilterUtilitiesService } from '../shared/_services/filter-utilities.ser
import { FileDimension } from '../manga-reader/_models/file-dimension';
import screenfull from 'screenfull';
import { TextResonse } from '../_types/text-response';
+import { AccountService } from './account.service';
+import { Subject, takeUntil } from 'rxjs';
+import { OnDestroy } from '@angular/core';
export const CHAPTER_ID_DOESNT_EXIST = -1;
export const CHAPTER_ID_NOT_FETCHED = -2;
@@ -23,16 +26,29 @@ export const CHAPTER_ID_NOT_FETCHED = -2;
@Injectable({
providedIn: 'root'
})
-export class ReaderService {
+export class ReaderService implements OnDestroy {
baseUrl = environment.apiUrl;
+ encodedKey: string = '';
+ private onDestroy: Subject = new Subject();
// Override background color for reader and restore it onDestroy
private originalBodyColor!: string;
constructor(private httpClient: HttpClient, private router: Router,
private location: Location, private utilityService: UtilityService,
- private filterUtilitySerivce: FilterUtilitiesService) { }
+ private filterUtilitySerivce: FilterUtilitiesService, private accountService: AccountService) {
+ this.accountService.currentUser$.pipe(takeUntil(this.onDestroy)).subscribe(user => {
+ if (user) {
+ this.encodedKey = encodeURIComponent(user.apiKey);
+ }
+ });
+ }
+
+ ngOnDestroy() {
+ this.onDestroy.next();
+ this.onDestroy.complete();
+ }
getNavigationArray(libraryId: number, seriesId: number, chapterId: number, format: MangaFormat) {
if (format === undefined) format = MangaFormat.ARCHIVE;
@@ -47,7 +63,7 @@ export class ReaderService {
}
downloadPdf(chapterId: number) {
- return this.baseUrl + 'reader/pdf?chapterId=' + chapterId;
+ return `${this.baseUrl}reader/pdf?chapterId=${chapterId}&apiKey=${this.encodedKey}`;
}
bookmark(seriesId: number, volumeId: number, chapterId: number, page: number) {
@@ -98,11 +114,11 @@ export class ReaderService {
}
getPageUrl(chapterId: number, page: number) {
- return this.baseUrl + 'reader/image?chapterId=' + chapterId + '&page=' + page;
+ return `${this.baseUrl}reader/image?chapterId=${chapterId}&apiKey=${this.encodedKey}&page=${page}`;
}
getThumbnailUrl(chapterId: number, page: number) {
- return this.baseUrl + 'reader/thumbnail?chapterId=' + chapterId + '&page=' + page;
+ return `${this.baseUrl}reader/thumbnail?chapterId=${chapterId}&apiKey=${this.encodedKey}&page=${page}`;
}
getBookmarkPageUrl(seriesId: number, apiKey: string, page: number) {
diff --git a/UI/Web/src/app/cards/series-info-cards/series-info-cards.component.html b/UI/Web/src/app/cards/series-info-cards/series-info-cards.component.html
index 09c5cac07..524745e1d 100644
--- a/UI/Web/src/app/cards/series-info-cards/series-info-cards.component.html
+++ b/UI/Web/src/app/cards/series-info-cards/series-info-cards.component.html
@@ -12,7 +12,7 @@
- {{metadataService.getAgeRating(this.seriesMetadata.ageRating) | async}}
+ {{this.seriesMetadata.ageRating | ageRating | async}}
diff --git a/UI/Web/src/app/manga-reader/_components/canvas-renderer/canvas-renderer.component.html b/UI/Web/src/app/manga-reader/_components/canvas-renderer/canvas-renderer.component.html
index c72f27f42..bf2da9d5e 100644
--- a/UI/Web/src/app/manga-reader/_components/canvas-renderer/canvas-renderer.component.html
+++ b/UI/Web/src/app/manga-reader/_components/canvas-renderer/canvas-renderer.component.html
@@ -1,6 +1,6 @@
-
+
diff --git a/UI/Web/src/app/manga-reader/_components/canvas-renderer/canvas-renderer.component.ts b/UI/Web/src/app/manga-reader/_components/canvas-renderer/canvas-renderer.component.ts
index b759d5f68..f6aca4bdc 100644
--- a/UI/Web/src/app/manga-reader/_components/canvas-renderer/canvas-renderer.component.ts
+++ b/UI/Web/src/app/manga-reader/_components/canvas-renderer/canvas-renderer.component.ts
@@ -51,7 +51,7 @@ export class CanvasRendererComponent implements OnInit, AfterViewInit, OnDestroy
constructor(private readonly cdRef: ChangeDetectorRef, private mangaReaderService: ManagaReaderService, private readerService: ReaderService) { }
ngOnInit(): void {
- this.readerSettings$.pipe(takeUntil(this.onDestroy), tap(value => {
+ this.readerSettings$.pipe(takeUntil(this.onDestroy), tap((value: ReaderSetting) => {
this.fit = value.fitting;
this.pageSplit = value.pageSplit;
this.layoutMode = value.layoutMode;
@@ -70,9 +70,9 @@ export class CanvasRendererComponent implements OnInit, AfterViewInit, OnDestroy
this.imageFitClass$ = this.readerSettings$.pipe(
takeUntil(this.onDestroy),
- map(values => values.fitting),
+ map((values: ReaderSetting) => values.fitting),
map(fit => {
- if (fit === FITTING_OPTION.WIDTH || this.layoutMode === LayoutMode.Single) return fit;
+ if (fit === FITTING_OPTION.WIDTH) return fit; // || this.layoutMode === LayoutMode.Single (so that we can check the wide stuff)
if (this.canvasImage === null) return fit;
// Would this ever execute given that we perform splitting only in this renderer?
@@ -181,9 +181,10 @@ export class CanvasRendererComponent implements OnInit, AfterViewInit, OnDestroy
const needsSplitting = this.updateSplitPage();
if (!needsSplitting) return;
- if (this.currentImageSplitPart === SPLIT_PAGE_PART.NO_SPLIT) return;
this.renderWithCanvas = true;
+ if (this.currentImageSplitPart === SPLIT_PAGE_PART.NO_SPLIT) return;
+
this.setCanvasSize();
if (needsSplitting && this.currentImageSplitPart === SPLIT_PAGE_PART.LEFT_PART) {
diff --git a/UI/Web/src/app/manga-reader/_components/manga-reader/manga-reader.component.ts b/UI/Web/src/app/manga-reader/_components/manga-reader/manga-reader.component.ts
index 0545953bb..b6ed5d048 100644
--- a/UI/Web/src/app/manga-reader/_components/manga-reader/manga-reader.component.ts
+++ b/UI/Web/src/app/manga-reader/_components/manga-reader/manga-reader.component.ts
@@ -392,7 +392,6 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy {
}
get SplitIconClass() {
- // TODO: make this a pipe
if (this.mangaReaderService.isSplitLeftToRight(this.pageSplitOption)) {
return 'left-side';
} else if (this.mangaReaderService.isNoSplit(this.pageSplitOption)) {
diff --git a/UI/Web/src/app/pipe/age-rating.pipe.ts b/UI/Web/src/app/pipe/age-rating.pipe.ts
index f810692d9..eee1b9e32 100644
--- a/UI/Web/src/app/pipe/age-rating.pipe.ts
+++ b/UI/Web/src/app/pipe/age-rating.pipe.ts
@@ -2,23 +2,38 @@ import { Pipe, PipeTransform } from '@angular/core';
import { Observable, of } from 'rxjs';
import { AgeRating } from '../_models/metadata/age-rating';
import { AgeRatingDto } from '../_models/metadata/age-rating-dto';
-import { MetadataService } from '../_services/metadata.service';
@Pipe({
name: 'ageRating'
})
export class AgeRatingPipe implements PipeTransform {
- constructor(private metadataService: MetadataService) {}
+ constructor() {}
transform(value: AgeRating | AgeRatingDto | undefined): Observable {
- if (value === undefined || value === null) return of('undefined');
+ if (value === undefined || value === null) return of('Unknown');
if (value.hasOwnProperty('title')) {
return of((value as AgeRatingDto).title);
}
- return this.metadataService.getAgeRating((value as AgeRating));
+ switch(value) {
+ case AgeRating.Unknown: return of('Unknown');
+ case AgeRating.EarlyChildhood: return of('Early Childhood');
+ case AgeRating.AdultsOnly: return of('Adults Only 18+');
+ case AgeRating.Everyone: return of('Everyone');
+ case AgeRating.Everyone10Plus: return of('Everyone 10+');
+ case AgeRating.G: return of('G');
+ case AgeRating.KidsToAdults: return of('Kids to Adults');
+ case AgeRating.Mature: return of('Mature');
+ case AgeRating.Mature17Plus: return of('M');
+ case AgeRating.RatingPending: return of('Rating Pending');
+ case AgeRating.Teen: return of('Teen');
+ case AgeRating.X18Plus: return of('X18+');
+ case AgeRating.NotApplicable: return of('Not Applicable');
+ }
+
+ return of('Unknown');
}
}
diff --git a/openapi.json b/openapi.json
index 304d3ffdc..58ed0b45a 100644
--- a/openapi.json
+++ b/openapi.json
@@ -7,7 +7,7 @@
"name": "GPL-3.0",
"url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE"
},
- "version": "0.7.1.28"
+ "version": "0.7.1.32"
},
"servers": [
{
@@ -1845,6 +1845,13 @@
"type": "integer",
"format": "int32"
}
+ },
+ {
+ "name": "apiKey",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
@@ -1869,6 +1876,13 @@
"type": "integer",
"format": "int32"
}
+ },
+ {
+ "name": "apiKey",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
@@ -1893,6 +1907,13 @@
"type": "integer",
"format": "int32"
}
+ },
+ {
+ "name": "apiKey",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
@@ -1917,6 +1938,13 @@
"type": "integer",
"format": "int32"
}
+ },
+ {
+ "name": "apiKey",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
@@ -1941,6 +1969,13 @@
"type": "integer",
"format": "int32"
}
+ },
+ {
+ "name": "apiKey",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
@@ -1965,6 +2000,13 @@
"type": "integer",
"format": "int32"
}
+ },
+ {
+ "name": "apiKey",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
@@ -2030,6 +2072,13 @@
"schema": {
"type": "string"
}
+ },
+ {
+ "name": "apiKey",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
@@ -3579,6 +3628,13 @@
"type": "integer",
"format": "int32"
}
+ },
+ {
+ "name": "apiKey",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {
@@ -3614,6 +3670,14 @@
"format": "int32"
}
},
+ {
+ "name": "apiKey",
+ "in": "query",
+ "description": "User's API Key for authentication",
+ "schema": {
+ "type": "string"
+ }
+ },
{
"name": "extractPdf",
"in": "query",
@@ -3652,6 +3716,13 @@
"type": "integer",
"format": "int32"
}
+ },
+ {
+ "name": "apiKey",
+ "in": "query",
+ "schema": {
+ "type": "string"
+ }
}
],
"responses": {