fix(api): filter referential data by access rights

closes #492
This commit is contained in:
Gauthier Roebroeck 2021-04-21 17:42:26 +08:00
parent e2b190859b
commit 09fa5e95a5
8 changed files with 240 additions and 97 deletions

View file

@ -70,19 +70,48 @@ export default class KomgaReferentialService {
} }
} }
async getTags(libraryId?: string, seriesId?: string, collectionId?: string): Promise<string[]> { async getTags(): Promise<string[]> {
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<string[]> {
try { try {
const params = {} as any const params = {} as any
if (libraryId) params.library_id = libraryId if (libraryId) params.library_id = libraryId
if (seriesId) params.series_id = seriesId
if (collectionId) params.collection_id = collectionId 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, params: params,
paramsSerializer: params => qs.stringify(params, {indices: false}), paramsSerializer: params => qs.stringify(params, {indices: false}),
})).data })).data
} catch (e) { } 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<string[]> {
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) { if (e.response.data.message) {
msg += `: ${e.response.data.message}` msg += `: ${e.response.data.message}`
} }

View file

@ -258,7 +258,7 @@ export default Vue.extend({
value: x.id, value: x.id,
}))) })))
this.$set(this.filterOptions, 'genre', toNameValue(await this.$komgaReferential.getGenres(undefined, collectionId))) 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, 'publisher', toNameValue(await this.$komgaReferential.getPublishers(undefined, collectionId)))
this.$set(this.filterOptions, 'language', (await this.$komgaReferential.getLanguages(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))) this.$set(this.filterOptions, 'ageRating', toNameValue(await this.$komgaReferential.getAgeRatings(undefined, collectionId)))

View file

@ -283,7 +283,7 @@ export default Vue.extend({
// load dynamic filters // load dynamic filters
this.$set(this.filterOptions, 'genre', toNameValue(await this.$komgaReferential.getGenres(requestLibraryId))) 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, 'publisher', toNameValue(await this.$komgaReferential.getPublishers(requestLibraryId)))
this.$set(this.filterOptions, 'language', (await this.$komgaReferential.getLanguages(requestLibraryId))) this.$set(this.filterOptions, 'language', (await this.$komgaReferential.getLanguages(requestLibraryId)))
this.$set(this.filterOptions, 'ageRating', toNameValue(await this.$komgaReferential.getAgeRatings(requestLibraryId))) this.$set(this.filterOptions, 'ageRating', toNameValue(await this.$komgaReferential.getAgeRatings(requestLibraryId)))

View file

@ -567,7 +567,7 @@ export default Vue.extend({
this.sortActive = this.parseQuerySortOrDefault(route.query.sort) this.sortActive = this.parseQuerySortOrDefault(route.query.sort)
// load dynamic filters // 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)) const grouped = groupAuthorsByRole(await this.$komgaReferential.getAuthors(undefined, undefined, undefined, seriesId))
authorRoles.forEach((role: string) => { authorRoles.forEach((role: string) => {
this.$set(this.filterOptions, role, role in grouped ? toNameValue(grouped[role]) : []) this.$set(this.filterOptions, role, role in grouped ? toNameValue(grouped[role]) : [])

View file

@ -4,36 +4,37 @@ import org.gotson.komga.domain.model.Author
import java.time.LocalDate import java.time.LocalDate
interface ReferentialRepository { interface ReferentialRepository {
fun findAuthorsByName(search: String): List<Author> fun findAuthorsByName(search: String, filterOnLibraryIds: Collection<String>?): List<Author>
fun findAuthorsByNameAndLibrary(search: String, libraryId: String): List<Author> fun findAuthorsByNameAndLibrary(search: String, libraryId: String, filterOnLibraryIds: Collection<String>?): List<Author>
fun findAuthorsByNameAndCollection(search: String, collectionId: String): List<Author> fun findAuthorsByNameAndCollection(search: String, collectionId: String, filterOnLibraryIds: Collection<String>?): List<Author>
fun findAuthorsByNameAndSeries(search: String, seriesId: String): List<Author> fun findAuthorsByNameAndSeries(search: String, seriesId: String, filterOnLibraryIds: Collection<String>?): List<Author>
fun findAuthorsNamesByName(search: String): List<String> fun findAuthorsNamesByName(search: String, filterOnLibraryIds: Collection<String>?): List<String>
fun findAuthorsRoles(): List<String> fun findAuthorsRoles(filterOnLibraryIds: Collection<String>?): List<String>
fun findAllGenres(): Set<String> fun findAllGenres(filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllGenresByLibrary(libraryId: String): Set<String> fun findAllGenresByLibrary(libraryId: String, filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllGenresByCollection(collectionId: String): Set<String> fun findAllGenresByCollection(collectionId: String, filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllTags(): Set<String> fun findAllSeriesAndBookTags(filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllTagsByLibrary(libraryId: String): Set<String> fun findAllSeriesTags(filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllTagsBySeries(seriesId: String): Set<String> fun findAllSeriesTagsByLibrary(libraryId: String, filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllTagsByCollection(collectionId: String): Set<String> fun findAllSeriesTagsByCollection(collectionId: String, filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllBookTags(filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllBookTagsBySeries(seriesId: String, filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllLanguages(): Set<String> fun findAllLanguages(filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllLanguagesByLibrary(libraryId: String): Set<String> fun findAllLanguagesByLibrary(libraryId: String, filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllLanguagesByCollection(collectionId: String): Set<String> fun findAllLanguagesByCollection(collectionId: String, filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllPublishers(): Set<String> fun findAllPublishers(filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllPublishersByLibrary(libraryId: String): Set<String> fun findAllPublishersByLibrary(libraryId: String, filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllPublishersByLibraries(libraryIds: Set<String>): Set<String> fun findAllPublishersByCollection(collectionId: String, filterOnLibraryIds: Collection<String>?): Set<String>
fun findAllPublishersByCollection(collectionId: String): Set<String>
fun findAllAgeRatings(): Set<Int?> fun findAllAgeRatings(filterOnLibraryIds: Collection<String>?): Set<Int?>
fun findAllAgeRatingsByLibrary(libraryId: String): Set<Int?> fun findAllAgeRatingsByLibrary(libraryId: String, filterOnLibraryIds: Collection<String>?): Set<Int?>
fun findAllAgeRatingsByCollection(collectionId: String): Set<Int?> fun findAllAgeRatingsByCollection(collectionId: String, filterOnLibraryIds: Collection<String>?): Set<Int?>
fun findAllSeriesReleaseDates(): Set<LocalDate> fun findAllSeriesReleaseDates(filterOnLibraryIds: Collection<String>?): Set<LocalDate>
fun findAllSeriesReleaseDatesByLibrary(libraryId: String): Set<LocalDate> fun findAllSeriesReleaseDatesByLibrary(libraryId: String, filterOnLibraryIds: Collection<String>?): Set<LocalDate>
fun findAllSeriesReleaseDatesByCollection(collectionId: String): Set<LocalDate> fun findAllSeriesReleaseDatesByCollection(collectionId: String, filterOnLibraryIds: Collection<String>?): Set<LocalDate>
} }

View file

@ -27,215 +27,295 @@ class ReferentialDao(
private val st = Tables.SERIES_METADATA_TAG private val st = Tables.SERIES_METADATA_TAG
private val cs = Tables.COLLECTION_SERIES private val cs = Tables.COLLECTION_SERIES
override fun findAuthorsByName(search: String): List<Author> = override fun findAuthorsByName(search: String, filterOnLibraryIds: Collection<String>?): List<Author> =
dsl.selectDistinct(a.NAME, a.ROLE) dsl.selectDistinct(a.NAME, a.ROLE)
.from(a) .from(a)
.apply { filterOnLibraryIds?.let { leftJoin(b).on(a.BOOK_ID.eq(b.ID)) } }
.where(a.NAME.containsIgnoreCase(search)) .where(a.NAME.containsIgnoreCase(search))
.apply { filterOnLibraryIds?.let { and(b.LIBRARY_ID.`in`(it)) } }
.orderBy(a.NAME, a.ROLE) .orderBy(a.NAME, a.ROLE)
.fetchInto(a) .fetchInto(a)
.map { it.toDomain() } .map { it.toDomain() }
override fun findAuthorsByNameAndLibrary(search: String, libraryId: String): List<Author> = override fun findAuthorsByNameAndLibrary(search: String, libraryId: String, filterOnLibraryIds: Collection<String>?): List<Author> =
dsl.selectDistinct(bmaa.NAME, bmaa.ROLE) dsl.selectDistinct(bmaa.NAME, bmaa.ROLE)
.from(bmaa) .from(bmaa)
.leftJoin(s).on(bmaa.SERIES_ID.eq(s.ID)) .leftJoin(s).on(bmaa.SERIES_ID.eq(s.ID))
.where(bmaa.NAME.containsIgnoreCase(search)) .where(bmaa.NAME.containsIgnoreCase(search))
.and(s.LIBRARY_ID.eq(libraryId)) .and(s.LIBRARY_ID.eq(libraryId))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(bmaa.NAME, bmaa.ROLE) .orderBy(bmaa.NAME, bmaa.ROLE)
.fetchInto(bmaa) .fetchInto(bmaa)
.map { it.toDomain() } .map { it.toDomain() }
override fun findAuthorsByNameAndCollection(search: String, collectionId: String): List<Author> = override fun findAuthorsByNameAndCollection(search: String, collectionId: String, filterOnLibraryIds: Collection<String>?): List<Author> =
dsl.selectDistinct(bmaa.NAME, bmaa.ROLE) dsl.selectDistinct(bmaa.NAME, bmaa.ROLE)
.from(bmaa) .from(bmaa)
.leftJoin(cs).on(bmaa.SERIES_ID.eq(cs.SERIES_ID)) .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)) .where(bmaa.NAME.containsIgnoreCase(search))
.and(cs.COLLECTION_ID.eq(collectionId)) .and(cs.COLLECTION_ID.eq(collectionId))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(bmaa.NAME, bmaa.ROLE) .orderBy(bmaa.NAME, bmaa.ROLE)
.fetchInto(bmaa) .fetchInto(bmaa)
.map { it.toDomain() } .map { it.toDomain() }
override fun findAuthorsByNameAndSeries(search: String, seriesId: String): List<Author> = override fun findAuthorsByNameAndSeries(search: String, seriesId: String, filterOnLibraryIds: Collection<String>?): List<Author> =
dsl.selectDistinct(bmaa.NAME, bmaa.ROLE) dsl.selectDistinct(bmaa.NAME, bmaa.ROLE)
.from(bmaa) .from(bmaa)
.apply { filterOnLibraryIds?.let { leftJoin(s).on(bmaa.SERIES_ID.eq(s.ID)) } }
.where(bmaa.NAME.containsIgnoreCase(search)) .where(bmaa.NAME.containsIgnoreCase(search))
.and(bmaa.SERIES_ID.eq(seriesId)) .and(bmaa.SERIES_ID.eq(seriesId))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(bmaa.NAME, bmaa.ROLE) .orderBy(bmaa.NAME, bmaa.ROLE)
.fetchInto(bmaa) .fetchInto(bmaa)
.map { it.toDomain() } .map { it.toDomain() }
override fun findAuthorsNamesByName(search: String): List<String> = override fun findAuthorsNamesByName(search: String, filterOnLibraryIds: Collection<String>?): List<String> =
dsl.selectDistinct(a.NAME) dsl.selectDistinct(a.NAME)
.from(a) .from(a)
.apply { filterOnLibraryIds?.let { leftJoin(b).on(a.BOOK_ID.eq(b.ID)) } }
.where(a.NAME.containsIgnoreCase(search)) .where(a.NAME.containsIgnoreCase(search))
.apply { filterOnLibraryIds?.let { and(b.LIBRARY_ID.`in`(it)) } }
.orderBy(a.NAME) .orderBy(a.NAME)
.fetch(a.NAME) .fetch(a.NAME)
override fun findAuthorsRoles(): List<String> = override fun findAuthorsRoles(filterOnLibraryIds: Collection<String>?): List<String> =
dsl.selectDistinct(a.ROLE) dsl.selectDistinct(a.ROLE)
.from(a) .from(a)
.apply {
filterOnLibraryIds?.let {
leftJoin(b).on(a.BOOK_ID.eq(b.ID))
.where(b.LIBRARY_ID.`in`(it))
}
}
.orderBy(a.ROLE) .orderBy(a.ROLE)
.fetch(a.ROLE) .fetch(a.ROLE)
override fun findAllGenres(): Set<String> = override fun findAllGenres(filterOnLibraryIds: Collection<String>?): Set<String> =
dsl.selectDistinct(g.GENRE) dsl.selectDistinct(g.GENRE)
.from(g) .from(g)
.apply {
filterOnLibraryIds?.let {
leftJoin(s).on(g.SERIES_ID.eq(s.ID))
.where(s.LIBRARY_ID.`in`(it))
}
}
.orderBy(lower(g.GENRE)) .orderBy(lower(g.GENRE))
.fetchSet(g.GENRE) .fetchSet(g.GENRE)
override fun findAllGenresByLibrary(libraryId: String): Set<String> = override fun findAllGenresByLibrary(libraryId: String, filterOnLibraryIds: Collection<String>?): Set<String> =
dsl.selectDistinct(g.GENRE) dsl.selectDistinct(g.GENRE)
.from(g) .from(g)
.leftJoin(s).on(g.SERIES_ID.eq(s.ID)) .leftJoin(s).on(g.SERIES_ID.eq(s.ID))
.where(s.LIBRARY_ID.eq(libraryId)) .where(s.LIBRARY_ID.eq(libraryId))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(lower(g.GENRE)) .orderBy(lower(g.GENRE))
.fetchSet(g.GENRE) .fetchSet(g.GENRE)
override fun findAllGenresByCollection(collectionId: String): Set<String> = override fun findAllGenresByCollection(collectionId: String, filterOnLibraryIds: Collection<String>?): Set<String> =
dsl.selectDistinct(g.GENRE) dsl.selectDistinct(g.GENRE)
.from(g) .from(g)
.leftJoin(cs).on(g.SERIES_ID.eq(cs.SERIES_ID)) .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)) .where(cs.COLLECTION_ID.eq(collectionId))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(lower(g.GENRE)) .orderBy(lower(g.GENRE))
.fetchSet(g.GENRE) .fetchSet(g.GENRE)
override fun findAllTags(): Set<String> = override fun findAllSeriesAndBookTags(filterOnLibraryIds: Collection<String>?): Set<String> =
dsl.select(bt.TAG.`as`("tag")) dsl.select(bt.TAG.`as`("tag"))
.from(bt) .from(bt)
.apply {
filterOnLibraryIds?.let {
leftJoin(b).on(bt.BOOK_ID.eq(b.ID))
.where(b.LIBRARY_ID.`in`(it))
}
}
.union( .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) .fetchSet(0, String::class.java)
.sortedBy { it.toLowerCase() } .sortedBy { it.toLowerCase() }
.toSet() .toSet()
override fun findAllTagsByLibrary(libraryId: String): Set<String> = override fun findAllSeriesTags(filterOnLibraryIds: Collection<String>?): Set<String> =
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<String>?): Set<String> =
dsl.select(st.TAG) dsl.select(st.TAG)
.from(st) .from(st)
.leftJoin(s).on(st.SERIES_ID.eq(s.ID)) .leftJoin(s).on(st.SERIES_ID.eq(s.ID))
.where(s.LIBRARY_ID.eq(libraryId)) .where(s.LIBRARY_ID.eq(libraryId))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(lower(st.TAG)) .orderBy(lower(st.TAG))
.fetchSet(st.TAG) .fetchSet(st.TAG)
override fun findAllTagsBySeries(seriesId: String): Set<String> = override fun findAllBookTagsBySeries(seriesId: String, filterOnLibraryIds: Collection<String>?): Set<String> =
dsl.select(bt.TAG) dsl.select(bt.TAG)
.from(bt) .from(bt)
.leftJoin(b).on(bt.BOOK_ID.eq(b.ID)) .leftJoin(b).on(bt.BOOK_ID.eq(b.ID))
.where(b.SERIES_ID.eq(seriesId)) .where(b.SERIES_ID.eq(seriesId))
.apply { filterOnLibraryIds?.let { and(b.LIBRARY_ID.`in`(it)) } }
.orderBy(lower(bt.TAG)) .orderBy(lower(bt.TAG))
.fetchSet(bt.TAG) .fetchSet(bt.TAG)
override fun findAllTagsByCollection(collectionId: String): Set<String> = override fun findAllSeriesTagsByCollection(collectionId: String, filterOnLibraryIds: Collection<String>?): Set<String> =
dsl.select(st.TAG) dsl.select(st.TAG)
.from(st) .from(st)
.leftJoin(cs).on(st.SERIES_ID.eq(cs.SERIES_ID)) .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)) .where(cs.COLLECTION_ID.eq(collectionId))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(lower(st.TAG)) .orderBy(lower(st.TAG))
.fetchSet(st.TAG) .fetchSet(st.TAG)
override fun findAllLanguages(): Set<String> = override fun findAllBookTags(filterOnLibraryIds: Collection<String>?): Set<String> =
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<String>?): Set<String> =
dsl.selectDistinct(sd.LANGUAGE) dsl.selectDistinct(sd.LANGUAGE)
.from(sd) .from(sd)
.apply { filterOnLibraryIds?.let { leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) } }
.where(sd.LANGUAGE.ne("")) .where(sd.LANGUAGE.ne(""))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(sd.LANGUAGE) .orderBy(sd.LANGUAGE)
.fetchSet(sd.LANGUAGE) .fetchSet(sd.LANGUAGE)
override fun findAllLanguagesByLibrary(libraryId: String): Set<String> = override fun findAllLanguagesByLibrary(libraryId: String, filterOnLibraryIds: Collection<String>?): Set<String> =
dsl.selectDistinct(sd.LANGUAGE) dsl.selectDistinct(sd.LANGUAGE)
.from(sd) .from(sd)
.leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) .leftJoin(s).on(sd.SERIES_ID.eq(s.ID))
.where(sd.LANGUAGE.ne("")) .where(sd.LANGUAGE.ne(""))
.and(s.LIBRARY_ID.eq(libraryId)) .and(s.LIBRARY_ID.eq(libraryId))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(sd.LANGUAGE) .orderBy(sd.LANGUAGE)
.fetchSet(sd.LANGUAGE) .fetchSet(sd.LANGUAGE)
override fun findAllLanguagesByCollection(collectionId: String): Set<String> = override fun findAllLanguagesByCollection(collectionId: String, filterOnLibraryIds: Collection<String>?): Set<String> =
dsl.selectDistinct(sd.LANGUAGE) dsl.selectDistinct(sd.LANGUAGE)
.from(sd) .from(sd)
.leftJoin(cs).on(sd.SERIES_ID.eq(cs.SERIES_ID)) .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("")) .where(sd.LANGUAGE.ne(""))
.and(cs.COLLECTION_ID.eq(collectionId)) .and(cs.COLLECTION_ID.eq(collectionId))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(sd.LANGUAGE) .orderBy(sd.LANGUAGE)
.fetchSet(sd.LANGUAGE) .fetchSet(sd.LANGUAGE)
override fun findAllPublishers(): Set<String> = override fun findAllPublishers(filterOnLibraryIds: Collection<String>?): Set<String> =
dsl.selectDistinct(sd.PUBLISHER) dsl.selectDistinct(sd.PUBLISHER)
.from(sd) .from(sd)
.apply { filterOnLibraryIds?.let { leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) } }
.where(sd.PUBLISHER.ne("")) .where(sd.PUBLISHER.ne(""))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(sd.PUBLISHER) .orderBy(sd.PUBLISHER)
.fetchSet(sd.PUBLISHER) .fetchSet(sd.PUBLISHER)
override fun findAllPublishersByLibrary(libraryId: String): Set<String> = override fun findAllPublishersByLibrary(libraryId: String, filterOnLibraryIds: Collection<String>?): Set<String> =
dsl.selectDistinct(sd.PUBLISHER) dsl.selectDistinct(sd.PUBLISHER)
.from(sd) .from(sd)
.leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) .leftJoin(s).on(sd.SERIES_ID.eq(s.ID))
.where(sd.PUBLISHER.ne("")) .where(sd.PUBLISHER.ne(""))
.and(s.LIBRARY_ID.eq(libraryId)) .and(s.LIBRARY_ID.eq(libraryId))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(sd.PUBLISHER) .orderBy(sd.PUBLISHER)
.fetchSet(sd.PUBLISHER) .fetchSet(sd.PUBLISHER)
override fun findAllPublishersByLibraries(libraryIds: Set<String>): Set<String> = override fun findAllPublishersByCollection(collectionId: String, filterOnLibraryIds: Collection<String>?): Set<String> =
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<String> =
dsl.selectDistinct(sd.PUBLISHER) dsl.selectDistinct(sd.PUBLISHER)
.from(sd) .from(sd)
.leftJoin(cs).on(sd.SERIES_ID.eq(cs.SERIES_ID)) .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("")) .where(sd.PUBLISHER.ne(""))
.and(cs.COLLECTION_ID.eq(collectionId)) .and(cs.COLLECTION_ID.eq(collectionId))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(sd.PUBLISHER) .orderBy(sd.PUBLISHER)
.fetchSet(sd.PUBLISHER) .fetchSet(sd.PUBLISHER)
override fun findAllAgeRatings(): Set<Int> = override fun findAllAgeRatings(filterOnLibraryIds: Collection<String>?): Set<Int> =
dsl.selectDistinct(sd.AGE_RATING) dsl.selectDistinct(sd.AGE_RATING)
.from(sd) .from(sd)
.apply {
filterOnLibraryIds?.let {
leftJoin(s).on(sd.SERIES_ID.eq(s.ID))
.where(s.LIBRARY_ID.`in`(it))
}
}
.orderBy(sd.AGE_RATING) .orderBy(sd.AGE_RATING)
.fetchSet(sd.AGE_RATING) .fetchSet(sd.AGE_RATING)
override fun findAllAgeRatingsByLibrary(libraryId: String): Set<Int> = override fun findAllAgeRatingsByLibrary(libraryId: String, filterOnLibraryIds: Collection<String>?): Set<Int> =
dsl.selectDistinct(sd.AGE_RATING) dsl.selectDistinct(sd.AGE_RATING)
.from(sd) .from(sd)
.leftJoin(s).on(sd.SERIES_ID.eq(s.ID)) .leftJoin(s).on(sd.SERIES_ID.eq(s.ID))
.where(s.LIBRARY_ID.eq(libraryId)) .where(s.LIBRARY_ID.eq(libraryId))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(sd.AGE_RATING) .orderBy(sd.AGE_RATING)
.fetchSet(sd.AGE_RATING) .fetchSet(sd.AGE_RATING)
override fun findAllAgeRatingsByCollection(collectionId: String): Set<Int?> = override fun findAllAgeRatingsByCollection(collectionId: String, filterOnLibraryIds: Collection<String>?): Set<Int?> =
dsl.selectDistinct(sd.AGE_RATING) dsl.selectDistinct(sd.AGE_RATING)
.from(sd) .from(sd)
.leftJoin(cs).on(sd.SERIES_ID.eq(cs.SERIES_ID)) .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)) .where(cs.COLLECTION_ID.eq(collectionId))
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(sd.AGE_RATING) .orderBy(sd.AGE_RATING)
.fetchSet(sd.AGE_RATING) .fetchSet(sd.AGE_RATING)
override fun findAllSeriesReleaseDates(): Set<LocalDate> = override fun findAllSeriesReleaseDates(filterOnLibraryIds: Collection<String>?): Set<LocalDate> =
dsl.selectDistinct(bma.RELEASE_DATE) dsl.selectDistinct(bma.RELEASE_DATE)
.from(bma) .from(bma)
.apply { filterOnLibraryIds?.let { leftJoin(s).on(bma.SERIES_ID.eq(s.ID)) } }
.where(bma.RELEASE_DATE.isNotNull) .where(bma.RELEASE_DATE.isNotNull)
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(bma.RELEASE_DATE.desc()) .orderBy(bma.RELEASE_DATE.desc())
.fetchSet(bma.RELEASE_DATE) .fetchSet(bma.RELEASE_DATE)
override fun findAllSeriesReleaseDatesByLibrary(libraryId: String): Set<LocalDate> = override fun findAllSeriesReleaseDatesByLibrary(libraryId: String, filterOnLibraryIds: Collection<String>?): Set<LocalDate> =
dsl.selectDistinct(bma.RELEASE_DATE) dsl.selectDistinct(bma.RELEASE_DATE)
.from(bma) .from(bma)
.leftJoin(s).on(bma.SERIES_ID.eq(s.ID)) .leftJoin(s).on(bma.SERIES_ID.eq(s.ID))
.where(s.LIBRARY_ID.eq(libraryId)) .where(s.LIBRARY_ID.eq(libraryId))
.and(bma.RELEASE_DATE.isNotNull) .and(bma.RELEASE_DATE.isNotNull)
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(bma.RELEASE_DATE.desc()) .orderBy(bma.RELEASE_DATE.desc())
.fetchSet(bma.RELEASE_DATE) .fetchSet(bma.RELEASE_DATE)
override fun findAllSeriesReleaseDatesByCollection(collectionId: String): Set<LocalDate> = override fun findAllSeriesReleaseDatesByCollection(collectionId: String, filterOnLibraryIds: Collection<String>?): Set<LocalDate> =
dsl.selectDistinct(bma.RELEASE_DATE) dsl.selectDistinct(bma.RELEASE_DATE)
.from(bma) .from(bma)
.leftJoin(cs).on(bma.SERIES_ID.eq(cs.SERIES_ID)) .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)) .where(cs.COLLECTION_ID.eq(collectionId))
.and(bma.RELEASE_DATE.isNotNull) .and(bma.RELEASE_DATE.isNotNull)
.apply { filterOnLibraryIds?.let { and(s.LIBRARY_ID.`in`(it)) } }
.orderBy(bma.RELEASE_DATE.desc()) .orderBy(bma.RELEASE_DATE.desc())
.fetchSet(bma.RELEASE_DATE) .fetchSet(bma.RELEASE_DATE)

View file

@ -338,9 +338,7 @@ class OpdsController(
fun getPublishers( fun getPublishers(
@AuthenticationPrincipal principal: KomgaPrincipal @AuthenticationPrincipal principal: KomgaPrincipal
): OpdsFeed { ): OpdsFeed {
val publishers = val publishers = referentialRepository.findAllPublishers(principal.user.getAuthorizedLibraryIds(null))
if (principal.user.sharedAllLibraries) referentialRepository.findAllPublishers()
else referentialRepository.findAllPublishersByLibraries(principal.user.sharedLibrariesIds)
return OpdsFeedNavigation( return OpdsFeedNavigation(
id = ID_PUBLISHERS_ALL, id = ID_PUBLISHERS_ALL,

View file

@ -1,9 +1,11 @@
package org.gotson.komga.interfaces.rest package org.gotson.komga.interfaces.rest
import org.gotson.komga.domain.persistence.ReferentialRepository 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.AuthorDto
import org.gotson.komga.interfaces.rest.dto.toDto import org.gotson.komga.interfaces.rest.dto.toDto
import org.springframework.http.MediaType 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.GetMapping
import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RequestParam
@ -17,6 +19,7 @@ class ReferentialController(
@GetMapping("/authors") @GetMapping("/authors")
fun getAuthors( fun getAuthors(
@AuthenticationPrincipal principal: KomgaPrincipal,
@RequestParam(name = "search", defaultValue = "") search: String, @RequestParam(name = "search", defaultValue = "") search: String,
@RequestParam(name = "library_id", required = false) libraryId: String?, @RequestParam(name = "library_id", required = false) libraryId: String?,
@RequestParam(name = "collection_id", required = false) collectionId: String?, @RequestParam(name = "collection_id", required = false) collectionId: String?,
@ -24,87 +27,119 @@ class ReferentialController(
): List<AuthorDto> = ): List<AuthorDto> =
when { when {
libraryId != null -> referentialRepository.findAuthorsByNameAndLibrary(search, libraryId) libraryId != null -> referentialRepository.findAuthorsByNameAndLibrary(search, libraryId, principal.user.getAuthorizedLibraryIds(null))
collectionId != null -> referentialRepository.findAuthorsByNameAndCollection(search, collectionId) collectionId != null -> referentialRepository.findAuthorsByNameAndCollection(search, collectionId, principal.user.getAuthorizedLibraryIds(null))
seriesId != null -> referentialRepository.findAuthorsByNameAndSeries(search, seriesId) seriesId != null -> referentialRepository.findAuthorsByNameAndSeries(search, seriesId, principal.user.getAuthorizedLibraryIds(null))
else -> referentialRepository.findAuthorsByName(search) else -> referentialRepository.findAuthorsByName(search, principal.user.getAuthorizedLibraryIds(null))
}.map { it.toDto() } }.map { it.toDto() }
@GetMapping("/authors/names") @GetMapping("/authors/names")
fun getAuthorsNames( fun getAuthorsNames(
@AuthenticationPrincipal principal: KomgaPrincipal,
@RequestParam(name = "search", defaultValue = "") search: String @RequestParam(name = "search", defaultValue = "") search: String
): List<String> = ): List<String> =
referentialRepository.findAuthorsNamesByName(search) referentialRepository.findAuthorsNamesByName(search, principal.user.getAuthorizedLibraryIds(null))
@GetMapping("/authors/roles") @GetMapping("/authors/roles")
fun getAuthorsRoles(): List<String> = fun getAuthorsRoles(
referentialRepository.findAuthorsRoles() @AuthenticationPrincipal principal: KomgaPrincipal,
): List<String> =
referentialRepository.findAuthorsRoles(principal.user.getAuthorizedLibraryIds(null))
@GetMapping("/genres") @GetMapping("/genres")
fun getGenres( fun getGenres(
@AuthenticationPrincipal principal: KomgaPrincipal,
@RequestParam(name = "library_id", required = false) libraryId: String?, @RequestParam(name = "library_id", required = false) libraryId: String?,
@RequestParam(name = "collection_id", required = false) collectionId: String? @RequestParam(name = "collection_id", required = false) collectionId: String?
): Set<String> = ): Set<String> =
when { when {
libraryId != null -> referentialRepository.findAllGenresByLibrary(libraryId) libraryId != null -> referentialRepository.findAllGenresByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null))
collectionId != null -> referentialRepository.findAllGenresByCollection(collectionId) collectionId != null -> referentialRepository.findAllGenresByCollection(collectionId, principal.user.getAuthorizedLibraryIds(null))
else -> referentialRepository.findAllGenres() else -> referentialRepository.findAllGenres(principal.user.getAuthorizedLibraryIds(null))
} }
@GetMapping("/tags") @GetMapping("/tags")
fun getTags( 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 = "library_id", required = false) libraryId: String?,
@RequestParam(name = "series_id", required = false) seriesId: String?, @RequestParam(name = "series_id", required = false) seriesId: String?,
@RequestParam(name = "collection_id", required = false) collectionId: String? @RequestParam(name = "collection_id", required = false) collectionId: String?
): Set<String> = ): Set<String> =
when { when {
libraryId != null -> referentialRepository.findAllTagsByLibrary(libraryId) libraryId != null -> referentialRepository.findAllSeriesTagsByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null))
seriesId != null -> referentialRepository.findAllTagsBySeries(seriesId) seriesId != null -> referentialRepository.findAllBookTagsBySeries(seriesId, principal.user.getAuthorizedLibraryIds(null))
collectionId != null -> referentialRepository.findAllTagsByCollection(collectionId) collectionId != null -> referentialRepository.findAllSeriesTagsByCollection(collectionId, principal.user.getAuthorizedLibraryIds(null))
else -> referentialRepository.findAllTags() else -> referentialRepository.findAllSeriesAndBookTags(principal.user.getAuthorizedLibraryIds(null))
}
@GetMapping("/tags/book")
fun getBookTags(
@AuthenticationPrincipal principal: KomgaPrincipal,
@RequestParam(name = "series_id", required = false) seriesId: String?,
): Set<String> =
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<String> =
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") @GetMapping("/languages")
fun getLanguages( fun getLanguages(
@AuthenticationPrincipal principal: KomgaPrincipal,
@RequestParam(name = "library_id", required = false) libraryId: String?, @RequestParam(name = "library_id", required = false) libraryId: String?,
@RequestParam(name = "collection_id", required = false) collectionId: String? @RequestParam(name = "collection_id", required = false) collectionId: String?
): Set<String> = ): Set<String> =
when { when {
libraryId != null -> referentialRepository.findAllLanguagesByLibrary(libraryId) libraryId != null -> referentialRepository.findAllLanguagesByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null))
collectionId != null -> referentialRepository.findAllLanguagesByCollection(collectionId) collectionId != null -> referentialRepository.findAllLanguagesByCollection(collectionId, principal.user.getAuthorizedLibraryIds(null))
else -> referentialRepository.findAllLanguages() else -> referentialRepository.findAllLanguages(principal.user.getAuthorizedLibraryIds(null))
} }
@GetMapping("/publishers") @GetMapping("/publishers")
fun getPublishers( fun getPublishers(
@AuthenticationPrincipal principal: KomgaPrincipal,
@RequestParam(name = "library_id", required = false) libraryId: String?, @RequestParam(name = "library_id", required = false) libraryId: String?,
@RequestParam(name = "collection_id", required = false) collectionId: String? @RequestParam(name = "collection_id", required = false) collectionId: String?
): Set<String> = ): Set<String> =
when { when {
libraryId != null -> referentialRepository.findAllPublishersByLibrary(libraryId) libraryId != null -> referentialRepository.findAllPublishersByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null))
collectionId != null -> referentialRepository.findAllPublishersByCollection(collectionId) collectionId != null -> referentialRepository.findAllPublishersByCollection(collectionId, principal.user.getAuthorizedLibraryIds(null))
else -> referentialRepository.findAllPublishers() else -> referentialRepository.findAllPublishers(principal.user.getAuthorizedLibraryIds(null))
} }
@GetMapping("/age-ratings") @GetMapping("/age-ratings")
fun getAgeRatings( fun getAgeRatings(
@AuthenticationPrincipal principal: KomgaPrincipal,
@RequestParam(name = "library_id", required = false) libraryId: String?, @RequestParam(name = "library_id", required = false) libraryId: String?,
@RequestParam(name = "collection_id", required = false) collectionId: String? @RequestParam(name = "collection_id", required = false) collectionId: String?
): Set<String> = ): Set<String> =
when { when {
libraryId != null -> referentialRepository.findAllAgeRatingsByLibrary(libraryId) libraryId != null -> referentialRepository.findAllAgeRatingsByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null))
collectionId != null -> referentialRepository.findAllAgeRatingsByCollection(collectionId) collectionId != null -> referentialRepository.findAllAgeRatingsByCollection(collectionId, principal.user.getAuthorizedLibraryIds(null))
else -> referentialRepository.findAllAgeRatings() else -> referentialRepository.findAllAgeRatings(principal.user.getAuthorizedLibraryIds(null))
}.map { it?.toString() ?: "None" }.toSet() }.map { it?.toString() ?: "None" }.toSet()
@GetMapping("/series/release-dates") @GetMapping("/series/release-dates")
fun getSeriesReleaseDates( fun getSeriesReleaseDates(
@AuthenticationPrincipal principal: KomgaPrincipal,
@RequestParam(name = "library_id", required = false) libraryId: String?, @RequestParam(name = "library_id", required = false) libraryId: String?,
@RequestParam(name = "collection_id", required = false) collectionId: String? @RequestParam(name = "collection_id", required = false) collectionId: String?
): Set<String> = ): Set<String> =
when { when {
libraryId != null -> referentialRepository.findAllSeriesReleaseDatesByLibrary(libraryId) libraryId != null -> referentialRepository.findAllSeriesReleaseDatesByLibrary(libraryId, principal.user.getAuthorizedLibraryIds(null))
collectionId != null -> referentialRepository.findAllSeriesReleaseDatesByCollection(collectionId) collectionId != null -> referentialRepository.findAllSeriesReleaseDatesByCollection(collectionId, principal.user.getAuthorizedLibraryIds(null))
else -> referentialRepository.findAllSeriesReleaseDates() else -> referentialRepository.findAllSeriesReleaseDates(principal.user.getAuthorizedLibraryIds(null))
}.map { it.year.toString() }.toSet() }.map { it.year.toString() }.toSet()
} }