diff --git a/komga-webui/src/services/komga-referential.service.ts b/komga-webui/src/services/komga-referential.service.ts index 03bacaaad..f63ce7f0c 100644 --- a/komga-webui/src/services/komga-referential.service.ts +++ b/komga-webui/src/services/komga-referential.service.ts @@ -70,19 +70,48 @@ export default class KomgaReferentialService { } } - async getTags(libraryId?: string, seriesId?: string, collectionId?: string): Promise { + async getTags(): Promise { + try { + return (await this.http.get('/api/v1/tags')).data + } catch (e) { + let msg = 'An error occurred while trying to retrieve tags' + if (e.response.data.message) { + msg += `: ${e.response.data.message}` + } + throw new Error(msg) + } + } + + async getSeriesTags(libraryId?: string, collectionId?: string): Promise { try { const params = {} as any if (libraryId) params.library_id = libraryId - if (seriesId) params.series_id = seriesId if (collectionId) params.collection_id = collectionId - return (await this.http.get('/api/v1/tags', { + return (await this.http.get('/api/v1/tags/series', { params: params, paramsSerializer: params => qs.stringify(params, {indices: false}), })).data } catch (e) { - let msg = 'An error occurred while trying to retrieve tags' + let msg = 'An error occurred while trying to retrieve series tags' + if (e.response.data.message) { + msg += `: ${e.response.data.message}` + } + throw new Error(msg) + } + } + + async getBookTags(seriesId?: string): Promise { + try { + const params = {} as any + if (seriesId) params.series_id = seriesId + + return (await this.http.get('/api/v1/tags/book', { + params: params, + paramsSerializer: params => qs.stringify(params, {indices: false}), + })).data + } catch (e) { + let msg = 'An error occurred while trying to retrieve book tags' if (e.response.data.message) { msg += `: ${e.response.data.message}` } diff --git a/komga-webui/src/views/BrowseCollection.vue b/komga-webui/src/views/BrowseCollection.vue index 365a77fb6..4c3e8ae66 100644 --- a/komga-webui/src/views/BrowseCollection.vue +++ b/komga-webui/src/views/BrowseCollection.vue @@ -258,7 +258,7 @@ export default Vue.extend({ value: x.id, }))) this.$set(this.filterOptions, 'genre', toNameValue(await this.$komgaReferential.getGenres(undefined, collectionId))) - this.$set(this.filterOptions, 'tag', toNameValue(await this.$komgaReferential.getTags(undefined, undefined, collectionId))) + this.$set(this.filterOptions, 'tag', toNameValue(await this.$komgaReferential.getSeriesTags(undefined, collectionId))) this.$set(this.filterOptions, 'publisher', toNameValue(await this.$komgaReferential.getPublishers(undefined, collectionId))) this.$set(this.filterOptions, 'language', (await this.$komgaReferential.getLanguages(undefined, collectionId))) this.$set(this.filterOptions, 'ageRating', toNameValue(await this.$komgaReferential.getAgeRatings(undefined, collectionId))) diff --git a/komga-webui/src/views/BrowseLibraries.vue b/komga-webui/src/views/BrowseLibraries.vue index e0b9df984..8dd1b8527 100644 --- a/komga-webui/src/views/BrowseLibraries.vue +++ b/komga-webui/src/views/BrowseLibraries.vue @@ -283,7 +283,7 @@ export default Vue.extend({ // load dynamic filters this.$set(this.filterOptions, 'genre', toNameValue(await this.$komgaReferential.getGenres(requestLibraryId))) - this.$set(this.filterOptions, 'tag', toNameValue(await this.$komgaReferential.getTags(requestLibraryId))) + this.$set(this.filterOptions, 'tag', toNameValue(await this.$komgaReferential.getSeriesTags(requestLibraryId))) this.$set(this.filterOptions, 'publisher', toNameValue(await this.$komgaReferential.getPublishers(requestLibraryId))) this.$set(this.filterOptions, 'language', (await this.$komgaReferential.getLanguages(requestLibraryId))) this.$set(this.filterOptions, 'ageRating', toNameValue(await this.$komgaReferential.getAgeRatings(requestLibraryId))) diff --git a/komga-webui/src/views/BrowseSeries.vue b/komga-webui/src/views/BrowseSeries.vue index 3e5f02043..027adc8f0 100644 --- a/komga-webui/src/views/BrowseSeries.vue +++ b/komga-webui/src/views/BrowseSeries.vue @@ -567,7 +567,7 @@ export default Vue.extend({ this.sortActive = this.parseQuerySortOrDefault(route.query.sort) // load dynamic filters - this.$set(this.filterOptions, 'tag', toNameValue(await this.$komgaReferential.getTags(undefined, seriesId))) + this.$set(this.filterOptions, 'tag', toNameValue(await this.$komgaReferential.getBookTags(seriesId))) const grouped = groupAuthorsByRole(await this.$komgaReferential.getAuthors(undefined, undefined, undefined, seriesId)) authorRoles.forEach((role: string) => { this.$set(this.filterOptions, role, role in grouped ? toNameValue(grouped[role]) : []) diff --git a/komga/src/main/kotlin/org/gotson/komga/domain/persistence/ReferentialRepository.kt b/komga/src/main/kotlin/org/gotson/komga/domain/persistence/ReferentialRepository.kt index 37d5505cf..bb67e3296 100644 --- a/komga/src/main/kotlin/org/gotson/komga/domain/persistence/ReferentialRepository.kt +++ b/komga/src/main/kotlin/org/gotson/komga/domain/persistence/ReferentialRepository.kt @@ -4,36 +4,37 @@ import org.gotson.komga.domain.model.Author import java.time.LocalDate interface ReferentialRepository { - fun findAuthorsByName(search: String): List - fun findAuthorsByNameAndLibrary(search: String, libraryId: String): List - fun findAuthorsByNameAndCollection(search: String, collectionId: String): List - fun findAuthorsByNameAndSeries(search: String, seriesId: String): List - fun findAuthorsNamesByName(search: String): List - fun findAuthorsRoles(): List + fun findAuthorsByName(search: String, filterOnLibraryIds: Collection?): List + fun findAuthorsByNameAndLibrary(search: String, libraryId: String, filterOnLibraryIds: Collection?): List + fun findAuthorsByNameAndCollection(search: String, collectionId: String, filterOnLibraryIds: Collection?): List + fun findAuthorsByNameAndSeries(search: String, seriesId: String, filterOnLibraryIds: Collection?): List + fun findAuthorsNamesByName(search: String, filterOnLibraryIds: Collection?): List + fun findAuthorsRoles(filterOnLibraryIds: Collection?): List - fun findAllGenres(): Set - fun findAllGenresByLibrary(libraryId: String): Set - fun findAllGenresByCollection(collectionId: String): Set + fun findAllGenres(filterOnLibraryIds: Collection?): Set + fun findAllGenresByLibrary(libraryId: String, filterOnLibraryIds: Collection?): Set + fun findAllGenresByCollection(collectionId: String, filterOnLibraryIds: Collection?): Set - fun findAllTags(): Set - fun findAllTagsByLibrary(libraryId: String): Set - fun findAllTagsBySeries(seriesId: String): Set - fun findAllTagsByCollection(collectionId: String): Set + fun findAllSeriesAndBookTags(filterOnLibraryIds: Collection?): Set + fun findAllSeriesTags(filterOnLibraryIds: Collection?): Set + fun findAllSeriesTagsByLibrary(libraryId: String, filterOnLibraryIds: Collection?): Set + fun findAllSeriesTagsByCollection(collectionId: String, filterOnLibraryIds: Collection?): Set + fun findAllBookTags(filterOnLibraryIds: Collection?): Set + fun findAllBookTagsBySeries(seriesId: String, filterOnLibraryIds: Collection?): Set - fun findAllLanguages(): Set - fun findAllLanguagesByLibrary(libraryId: String): Set - fun findAllLanguagesByCollection(collectionId: String): Set + fun findAllLanguages(filterOnLibraryIds: Collection?): Set + fun findAllLanguagesByLibrary(libraryId: String, filterOnLibraryIds: Collection?): Set + fun findAllLanguagesByCollection(collectionId: String, filterOnLibraryIds: Collection?): Set - fun findAllPublishers(): Set - fun findAllPublishersByLibrary(libraryId: String): Set - fun findAllPublishersByLibraries(libraryIds: Set): Set - fun findAllPublishersByCollection(collectionId: String): Set + fun findAllPublishers(filterOnLibraryIds: Collection?): Set + fun findAllPublishersByLibrary(libraryId: String, filterOnLibraryIds: Collection?): Set + fun findAllPublishersByCollection(collectionId: String, filterOnLibraryIds: Collection?): Set - fun findAllAgeRatings(): Set - fun findAllAgeRatingsByLibrary(libraryId: String): Set - fun findAllAgeRatingsByCollection(collectionId: String): Set + fun findAllAgeRatings(filterOnLibraryIds: Collection?): Set + fun findAllAgeRatingsByLibrary(libraryId: String, filterOnLibraryIds: Collection?): Set + fun findAllAgeRatingsByCollection(collectionId: String, filterOnLibraryIds: Collection?): Set - fun findAllSeriesReleaseDates(): Set - fun findAllSeriesReleaseDatesByLibrary(libraryId: String): Set - fun findAllSeriesReleaseDatesByCollection(collectionId: String): Set + fun findAllSeriesReleaseDates(filterOnLibraryIds: Collection?): Set + fun findAllSeriesReleaseDatesByLibrary(libraryId: String, filterOnLibraryIds: Collection?): Set + fun findAllSeriesReleaseDatesByCollection(collectionId: String, filterOnLibraryIds: Collection?): Set } diff --git a/komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/ReferentialDao.kt b/komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/ReferentialDao.kt index 8340b7af6..2208ddd02 100644 --- a/komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/ReferentialDao.kt +++ b/komga/src/main/kotlin/org/gotson/komga/infrastructure/jooq/ReferentialDao.kt @@ -27,215 +27,295 @@ class ReferentialDao( private val st = Tables.SERIES_METADATA_TAG private val cs = Tables.COLLECTION_SERIES - override fun findAuthorsByName(search: String): List = + override fun findAuthorsByName(search: String, filterOnLibraryIds: Collection?): List = dsl.selectDistinct(a.NAME, a.ROLE) .from(a) + .apply { filterOnLibraryIds?.let { leftJoin(b).on(a.BOOK_ID.eq(b.ID)) } } .where(a.NAME.containsIgnoreCase(search)) + .apply { filterOnLibraryIds?.let { and(b.LIBRARY_ID.`in`(it)) } } .orderBy(a.NAME, a.ROLE) .fetchInto(a) .map { it.toDomain() } - override fun findAuthorsByNameAndLibrary(search: String, libraryId: String): List = + override fun findAuthorsByNameAndLibrary(search: String, libraryId: String, filterOnLibraryIds: Collection?): List = dsl.selectDistinct(bmaa.NAME, bmaa.ROLE) .from(bmaa) .leftJoin(s).on(bmaa.SERIES_ID.eq(s.ID)) .where(bmaa.NAME.containsIgnoreCase(search)) .and(s.LIBRARY_ID.eq(libraryId)) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(bmaa.NAME, bmaa.ROLE) .fetchInto(bmaa) .map { it.toDomain() } - override fun findAuthorsByNameAndCollection(search: String, collectionId: String): List = + override fun findAuthorsByNameAndCollection(search: String, collectionId: String, filterOnLibraryIds: Collection?): List = dsl.selectDistinct(bmaa.NAME, bmaa.ROLE) .from(bmaa) .leftJoin(cs).on(bmaa.SERIES_ID.eq(cs.SERIES_ID)) + .apply { filterOnLibraryIds?.let { leftJoin(s).on(bmaa.SERIES_ID.eq(s.ID)) } } .where(bmaa.NAME.containsIgnoreCase(search)) .and(cs.COLLECTION_ID.eq(collectionId)) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(bmaa.NAME, bmaa.ROLE) .fetchInto(bmaa) .map { it.toDomain() } - override fun findAuthorsByNameAndSeries(search: String, seriesId: String): List = + override fun findAuthorsByNameAndSeries(search: String, seriesId: String, filterOnLibraryIds: Collection?): List = dsl.selectDistinct(bmaa.NAME, bmaa.ROLE) .from(bmaa) + .apply { filterOnLibraryIds?.let { leftJoin(s).on(bmaa.SERIES_ID.eq(s.ID)) } } .where(bmaa.NAME.containsIgnoreCase(search)) .and(bmaa.SERIES_ID.eq(seriesId)) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(bmaa.NAME, bmaa.ROLE) .fetchInto(bmaa) .map { it.toDomain() } - override fun findAuthorsNamesByName(search: String): List = + override fun findAuthorsNamesByName(search: String, filterOnLibraryIds: Collection?): List = dsl.selectDistinct(a.NAME) .from(a) + .apply { filterOnLibraryIds?.let { leftJoin(b).on(a.BOOK_ID.eq(b.ID)) } } .where(a.NAME.containsIgnoreCase(search)) + .apply { filterOnLibraryIds?.let { and(b.LIBRARY_ID.`in`(it)) } } .orderBy(a.NAME) .fetch(a.NAME) - override fun findAuthorsRoles(): List = + override fun findAuthorsRoles(filterOnLibraryIds: Collection?): List = dsl.selectDistinct(a.ROLE) .from(a) + .apply { + filterOnLibraryIds?.let { + leftJoin(b).on(a.BOOK_ID.eq(b.ID)) + .where(b.LIBRARY_ID.`in`(it)) + } + } .orderBy(a.ROLE) .fetch(a.ROLE) - override fun findAllGenres(): Set = + override fun findAllGenres(filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(g.GENRE) .from(g) + .apply { + filterOnLibraryIds?.let { + leftJoin(s).on(g.SERIES_ID.eq(s.ID)) + .where(s.LIBRARY_ID.`in`(it)) + } + } .orderBy(lower(g.GENRE)) .fetchSet(g.GENRE) - override fun findAllGenresByLibrary(libraryId: String): Set = + override fun findAllGenresByLibrary(libraryId: String, filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(g.GENRE) .from(g) .leftJoin(s).on(g.SERIES_ID.eq(s.ID)) .where(s.LIBRARY_ID.eq(libraryId)) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(lower(g.GENRE)) .fetchSet(g.GENRE) - override fun findAllGenresByCollection(collectionId: String): Set = + override fun findAllGenresByCollection(collectionId: String, filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(g.GENRE) .from(g) .leftJoin(cs).on(g.SERIES_ID.eq(cs.SERIES_ID)) + .apply { filterOnLibraryIds?.let { leftJoin(s).on(g.SERIES_ID.eq(s.ID)) } } .where(cs.COLLECTION_ID.eq(collectionId)) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(lower(g.GENRE)) .fetchSet(g.GENRE) - override fun findAllTags(): Set = + override fun findAllSeriesAndBookTags(filterOnLibraryIds: Collection?): Set = dsl.select(bt.TAG.`as`("tag")) .from(bt) + .apply { + filterOnLibraryIds?.let { + leftJoin(b).on(bt.BOOK_ID.eq(b.ID)) + .where(b.LIBRARY_ID.`in`(it)) + } + } .union( - select(st.TAG.`as`("tag")).from(st) + select(st.TAG.`as`("tag")) + .from(st) + .apply { + filterOnLibraryIds?.let { + leftJoin(s).on(st.SERIES_ID.eq(s.ID)) + .where(s.LIBRARY_ID.`in`(it)) + } + } ) .fetchSet(0, String::class.java) .sortedBy { it.toLowerCase() } .toSet() - override fun findAllTagsByLibrary(libraryId: String): Set = + override fun findAllSeriesTags(filterOnLibraryIds: Collection?): Set = + dsl.select(st.TAG) + .from(st) + .apply { + filterOnLibraryIds?.let { + leftJoin(s).on(st.SERIES_ID.eq(s.ID)) + .where(s.LIBRARY_ID.`in`(it)) + } + } + .orderBy(lower(st.TAG)) + .fetchSet(st.TAG) + + override fun findAllSeriesTagsByLibrary(libraryId: String, filterOnLibraryIds: Collection?): Set = dsl.select(st.TAG) .from(st) .leftJoin(s).on(st.SERIES_ID.eq(s.ID)) .where(s.LIBRARY_ID.eq(libraryId)) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(lower(st.TAG)) .fetchSet(st.TAG) - override fun findAllTagsBySeries(seriesId: String): Set = + override fun findAllBookTagsBySeries(seriesId: String, filterOnLibraryIds: Collection?): Set = dsl.select(bt.TAG) .from(bt) .leftJoin(b).on(bt.BOOK_ID.eq(b.ID)) .where(b.SERIES_ID.eq(seriesId)) + .apply { filterOnLibraryIds?.let { and(b.LIBRARY_ID.`in`(it)) } } .orderBy(lower(bt.TAG)) .fetchSet(bt.TAG) - override fun findAllTagsByCollection(collectionId: String): Set = + override fun findAllSeriesTagsByCollection(collectionId: String, filterOnLibraryIds: Collection?): Set = dsl.select(st.TAG) .from(st) .leftJoin(cs).on(st.SERIES_ID.eq(cs.SERIES_ID)) + .apply { filterOnLibraryIds?.let { leftJoin(s).on(st.SERIES_ID.eq(s.ID)) } } .where(cs.COLLECTION_ID.eq(collectionId)) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(lower(st.TAG)) .fetchSet(st.TAG) - override fun findAllLanguages(): Set = + override fun findAllBookTags(filterOnLibraryIds: Collection?): Set = + dsl.select(bt.TAG) + .from(bt) + .apply { + filterOnLibraryIds?.let { + leftJoin(b).on(bt.BOOK_ID.eq(b.ID)) + .where(b.LIBRARY_ID.`in`(it)) + } + } + .orderBy(lower(st.TAG)) + .fetchSet(st.TAG) + + override fun findAllLanguages(filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(sd.LANGUAGE) .from(sd) + .apply { filterOnLibraryIds?.let { leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) } } .where(sd.LANGUAGE.ne("")) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(sd.LANGUAGE) .fetchSet(sd.LANGUAGE) - override fun findAllLanguagesByLibrary(libraryId: String): Set = + override fun findAllLanguagesByLibrary(libraryId: String, filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(sd.LANGUAGE) .from(sd) .leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) .where(sd.LANGUAGE.ne("")) .and(s.LIBRARY_ID.eq(libraryId)) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(sd.LANGUAGE) .fetchSet(sd.LANGUAGE) - override fun findAllLanguagesByCollection(collectionId: String): Set = + override fun findAllLanguagesByCollection(collectionId: String, filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(sd.LANGUAGE) .from(sd) .leftJoin(cs).on(sd.SERIES_ID.eq(cs.SERIES_ID)) + .apply { filterOnLibraryIds?.let { leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) } } .where(sd.LANGUAGE.ne("")) .and(cs.COLLECTION_ID.eq(collectionId)) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(sd.LANGUAGE) .fetchSet(sd.LANGUAGE) - override fun findAllPublishers(): Set = + override fun findAllPublishers(filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(sd.PUBLISHER) .from(sd) + .apply { filterOnLibraryIds?.let { leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) } } .where(sd.PUBLISHER.ne("")) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(sd.PUBLISHER) .fetchSet(sd.PUBLISHER) - override fun findAllPublishersByLibrary(libraryId: String): Set = + override fun findAllPublishersByLibrary(libraryId: String, filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(sd.PUBLISHER) .from(sd) .leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) .where(sd.PUBLISHER.ne("")) .and(s.LIBRARY_ID.eq(libraryId)) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(sd.PUBLISHER) .fetchSet(sd.PUBLISHER) - override fun findAllPublishersByLibraries(libraryIds: Set): Set = - dsl.selectDistinct(sd.PUBLISHER) - .from(sd) - .leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) - .where(sd.PUBLISHER.ne("")) - .and(s.LIBRARY_ID.`in`(libraryIds)) - .orderBy(sd.PUBLISHER) - .fetchSet(sd.PUBLISHER) - - override fun findAllPublishersByCollection(collectionId: String): Set = + override fun findAllPublishersByCollection(collectionId: String, filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(sd.PUBLISHER) .from(sd) .leftJoin(cs).on(sd.SERIES_ID.eq(cs.SERIES_ID)) + .apply { filterOnLibraryIds?.let { leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) } } .where(sd.PUBLISHER.ne("")) .and(cs.COLLECTION_ID.eq(collectionId)) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(sd.PUBLISHER) .fetchSet(sd.PUBLISHER) - override fun findAllAgeRatings(): Set = + override fun findAllAgeRatings(filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(sd.AGE_RATING) .from(sd) + .apply { + filterOnLibraryIds?.let { + leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) + .where(s.LIBRARY_ID.`in`(it)) + } + } .orderBy(sd.AGE_RATING) .fetchSet(sd.AGE_RATING) - override fun findAllAgeRatingsByLibrary(libraryId: String): Set = + override fun findAllAgeRatingsByLibrary(libraryId: String, filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(sd.AGE_RATING) .from(sd) .leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) .where(s.LIBRARY_ID.eq(libraryId)) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(sd.AGE_RATING) .fetchSet(sd.AGE_RATING) - override fun findAllAgeRatingsByCollection(collectionId: String): Set = + override fun findAllAgeRatingsByCollection(collectionId: String, filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(sd.AGE_RATING) .from(sd) .leftJoin(cs).on(sd.SERIES_ID.eq(cs.SERIES_ID)) + .apply { filterOnLibraryIds?.let { leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) } } .where(cs.COLLECTION_ID.eq(collectionId)) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(sd.AGE_RATING) .fetchSet(sd.AGE_RATING) - override fun findAllSeriesReleaseDates(): Set = + override fun findAllSeriesReleaseDates(filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(bma.RELEASE_DATE) .from(bma) + .apply { filterOnLibraryIds?.let { leftJoin(s).on(bma.SERIES_ID.eq(s.ID)) } } .where(bma.RELEASE_DATE.isNotNull) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(bma.RELEASE_DATE.desc()) .fetchSet(bma.RELEASE_DATE) - override fun findAllSeriesReleaseDatesByLibrary(libraryId: String): Set = + override fun findAllSeriesReleaseDatesByLibrary(libraryId: String, filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(bma.RELEASE_DATE) .from(bma) .leftJoin(s).on(bma.SERIES_ID.eq(s.ID)) .where(s.LIBRARY_ID.eq(libraryId)) .and(bma.RELEASE_DATE.isNotNull) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(bma.RELEASE_DATE.desc()) .fetchSet(bma.RELEASE_DATE) - override fun findAllSeriesReleaseDatesByCollection(collectionId: String): Set = + override fun findAllSeriesReleaseDatesByCollection(collectionId: String, filterOnLibraryIds: Collection?): Set = dsl.selectDistinct(bma.RELEASE_DATE) .from(bma) .leftJoin(cs).on(bma.SERIES_ID.eq(cs.SERIES_ID)) + .apply { filterOnLibraryIds?.let { leftJoin(s).on(bma.SERIES_ID.eq(s.ID)) } } .where(cs.COLLECTION_ID.eq(collectionId)) .and(bma.RELEASE_DATE.isNotNull) + .apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } } .orderBy(bma.RELEASE_DATE.desc()) .fetchSet(bma.RELEASE_DATE) diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/opds/OpdsController.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/opds/OpdsController.kt index c48329956..a84709673 100644 --- a/komga/src/main/kotlin/org/gotson/komga/interfaces/opds/OpdsController.kt +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/opds/OpdsController.kt @@ -338,9 +338,7 @@ class OpdsController( fun getPublishers( @AuthenticationPrincipal principal: KomgaPrincipal ): OpdsFeed { - val publishers = - if (principal.user.sharedAllLibraries) referentialRepository.findAllPublishers() - else referentialRepository.findAllPublishersByLibraries(principal.user.sharedLibrariesIds) + val publishers = referentialRepository.findAllPublishers(principal.user.getAuthorizedLibraryIds(null)) return OpdsFeedNavigation( id = ID_PUBLISHERS_ALL, diff --git a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/ReferentialController.kt b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/ReferentialController.kt index f035d4896..1f764a671 100644 --- a/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/ReferentialController.kt +++ b/komga/src/main/kotlin/org/gotson/komga/interfaces/rest/ReferentialController.kt @@ -1,9 +1,11 @@ package org.gotson.komga.interfaces.rest import org.gotson.komga.domain.persistence.ReferentialRepository +import org.gotson.komga.infrastructure.security.KomgaPrincipal import org.gotson.komga.interfaces.rest.dto.AuthorDto import org.gotson.komga.interfaces.rest.dto.toDto import org.springframework.http.MediaType +import org.springframework.security.core.annotation.AuthenticationPrincipal import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestParam @@ -17,6 +19,7 @@ class ReferentialController( @GetMapping("/authors") fun getAuthors( + @AuthenticationPrincipal principal: KomgaPrincipal, @RequestParam(name = "search", defaultValue = "") search: String, @RequestParam(name = "library_id", required = false) libraryId: String?, @RequestParam(name = "collection_id", required = false) collectionId: String?, @@ -24,87 +27,119 @@ class ReferentialController( ): List = when { - libraryId != null -> referentialRepository.findAuthorsByNameAndLibrary(search, libraryId) - collectionId != null -> referentialRepository.findAuthorsByNameAndCollection(search, collectionId) - seriesId != null -> referentialRepository.findAuthorsByNameAndSeries(search, seriesId) - else -> referentialRepository.findAuthorsByName(search) + libraryId != null -> referentialRepository.findAuthorsByNameAndLibrary(search, libraryId, principal.user.getAuthorizedLibraryIds(null)) + collectionId != null -> referentialRepository.findAuthorsByNameAndCollection(search, collectionId, principal.user.getAuthorizedLibraryIds(null)) + seriesId != null -> referentialRepository.findAuthorsByNameAndSeries(search, seriesId, principal.user.getAuthorizedLibraryIds(null)) + else -> referentialRepository.findAuthorsByName(search, principal.user.getAuthorizedLibraryIds(null)) }.map { it.toDto() } @GetMapping("/authors/names") fun getAuthorsNames( + @AuthenticationPrincipal principal: KomgaPrincipal, @RequestParam(name = "search", defaultValue = "") search: String ): List = - referentialRepository.findAuthorsNamesByName(search) + referentialRepository.findAuthorsNamesByName(search, principal.user.getAuthorizedLibraryIds(null)) @GetMapping("/authors/roles") - fun getAuthorsRoles(): List = - referentialRepository.findAuthorsRoles() + fun getAuthorsRoles( + @AuthenticationPrincipal principal: KomgaPrincipal, + ): List = + referentialRepository.findAuthorsRoles(principal.user.getAuthorizedLibraryIds(null)) @GetMapping("/genres") fun getGenres( + @AuthenticationPrincipal principal: KomgaPrincipal, @RequestParam(name = "library_id", required = false) libraryId: String?, @RequestParam(name = "collection_id", required = false) collectionId: String? ): Set = when { - libraryId != null -> referentialRepository.findAllGenresByLibrary(libraryId) - collectionId != null -> referentialRepository.findAllGenresByCollection(collectionId) - else -> referentialRepository.findAllGenres() + libraryId != null -> referentialRepository.findAllGenresByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null)) + collectionId != null -> referentialRepository.findAllGenresByCollection(collectionId, principal.user.getAuthorizedLibraryIds(null)) + else -> referentialRepository.findAllGenres(principal.user.getAuthorizedLibraryIds(null)) } @GetMapping("/tags") fun getTags( + @AuthenticationPrincipal principal: KomgaPrincipal, + // TODO: remove those parameters once Tachiyomi Extension is using the new /tags/series endpoint @RequestParam(name = "library_id", required = false) libraryId: String?, @RequestParam(name = "series_id", required = false) seriesId: String?, @RequestParam(name = "collection_id", required = false) collectionId: String? ): Set = when { - libraryId != null -> referentialRepository.findAllTagsByLibrary(libraryId) - seriesId != null -> referentialRepository.findAllTagsBySeries(seriesId) - collectionId != null -> referentialRepository.findAllTagsByCollection(collectionId) - else -> referentialRepository.findAllTags() + libraryId != null -> referentialRepository.findAllSeriesTagsByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null)) + seriesId != null -> referentialRepository.findAllBookTagsBySeries(seriesId, principal.user.getAuthorizedLibraryIds(null)) + collectionId != null -> referentialRepository.findAllSeriesTagsByCollection(collectionId, principal.user.getAuthorizedLibraryIds(null)) + else -> referentialRepository.findAllSeriesAndBookTags(principal.user.getAuthorizedLibraryIds(null)) + } + + @GetMapping("/tags/book") + fun getBookTags( + @AuthenticationPrincipal principal: KomgaPrincipal, + @RequestParam(name = "series_id", required = false) seriesId: String?, + ): Set = + when { + seriesId != null -> referentialRepository.findAllBookTagsBySeries(seriesId, principal.user.getAuthorizedLibraryIds(null)) + else -> referentialRepository.findAllBookTags(principal.user.getAuthorizedLibraryIds(null)) + } + + @GetMapping("/tags/series") + fun getSeriesTags( + @AuthenticationPrincipal principal: KomgaPrincipal, + @RequestParam(name = "library_id", required = false) libraryId: String?, + @RequestParam(name = "collection_id", required = false) collectionId: String? + ): Set = + when { + libraryId != null -> referentialRepository.findAllSeriesTagsByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null)) + collectionId != null -> referentialRepository.findAllSeriesTagsByCollection(collectionId, principal.user.getAuthorizedLibraryIds(null)) + else -> referentialRepository.findAllSeriesTags(principal.user.getAuthorizedLibraryIds(null)) } @GetMapping("/languages") fun getLanguages( + @AuthenticationPrincipal principal: KomgaPrincipal, @RequestParam(name = "library_id", required = false) libraryId: String?, @RequestParam(name = "collection_id", required = false) collectionId: String? ): Set = when { - libraryId != null -> referentialRepository.findAllLanguagesByLibrary(libraryId) - collectionId != null -> referentialRepository.findAllLanguagesByCollection(collectionId) - else -> referentialRepository.findAllLanguages() + libraryId != null -> referentialRepository.findAllLanguagesByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null)) + collectionId != null -> referentialRepository.findAllLanguagesByCollection(collectionId, principal.user.getAuthorizedLibraryIds(null)) + else -> referentialRepository.findAllLanguages(principal.user.getAuthorizedLibraryIds(null)) } @GetMapping("/publishers") fun getPublishers( + @AuthenticationPrincipal principal: KomgaPrincipal, @RequestParam(name = "library_id", required = false) libraryId: String?, @RequestParam(name = "collection_id", required = false) collectionId: String? ): Set = when { - libraryId != null -> referentialRepository.findAllPublishersByLibrary(libraryId) - collectionId != null -> referentialRepository.findAllPublishersByCollection(collectionId) - else -> referentialRepository.findAllPublishers() + libraryId != null -> referentialRepository.findAllPublishersByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null)) + collectionId != null -> referentialRepository.findAllPublishersByCollection(collectionId, principal.user.getAuthorizedLibraryIds(null)) + else -> referentialRepository.findAllPublishers(principal.user.getAuthorizedLibraryIds(null)) } @GetMapping("/age-ratings") fun getAgeRatings( + @AuthenticationPrincipal principal: KomgaPrincipal, @RequestParam(name = "library_id", required = false) libraryId: String?, @RequestParam(name = "collection_id", required = false) collectionId: String? ): Set = when { - libraryId != null -> referentialRepository.findAllAgeRatingsByLibrary(libraryId) - collectionId != null -> referentialRepository.findAllAgeRatingsByCollection(collectionId) - else -> referentialRepository.findAllAgeRatings() + libraryId != null -> referentialRepository.findAllAgeRatingsByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null)) + collectionId != null -> referentialRepository.findAllAgeRatingsByCollection(collectionId, principal.user.getAuthorizedLibraryIds(null)) + else -> referentialRepository.findAllAgeRatings(principal.user.getAuthorizedLibraryIds(null)) }.map { it?.toString() ?: "None" }.toSet() @GetMapping("/series/release-dates") fun getSeriesReleaseDates( + @AuthenticationPrincipal principal: KomgaPrincipal, @RequestParam(name = "library_id", required = false) libraryId: String?, @RequestParam(name = "collection_id", required = false) collectionId: String? ): Set = when { - libraryId != null -> referentialRepository.findAllSeriesReleaseDatesByLibrary(libraryId) - collectionId != null -> referentialRepository.findAllSeriesReleaseDatesByCollection(collectionId) - else -> referentialRepository.findAllSeriesReleaseDates() + libraryId != null -> referentialRepository.findAllSeriesReleaseDatesByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null)) + collectionId != null -> referentialRepository.findAllSeriesReleaseDatesByCollection(collectionId, principal.user.getAuthorizedLibraryIds(null)) + else -> referentialRepository.findAllSeriesReleaseDates(principal.user.getAuthorizedLibraryIds(null)) }.map { it.year.toString() }.toSet() }