mirror of
https://github.com/gotson/komga.git
synced 2025-12-16 13:33:49 +01:00
feat: persist user content restriction
This commit is contained in:
parent
c7c5592c50
commit
f1ab136b5e
4 changed files with 127 additions and 11 deletions
|
|
@ -0,0 +1,13 @@
|
|||
CREATE TABLE USER_SHARING
|
||||
(
|
||||
LABEL varchar NOT NULL,
|
||||
ALLOW boolean NOT NULL,
|
||||
USER_ID varchar NOT NULL,
|
||||
PRIMARY KEY (LABEL, ALLOW, USER_ID),
|
||||
FOREIGN KEY (USER_ID) REFERENCES USER (ID)
|
||||
);
|
||||
|
||||
ALTER TABLE USER
|
||||
add column AGE_RESTRICTION integer NULL;
|
||||
ALTER TABLE USER
|
||||
add column AGE_RESTRICTION_ALLOW_ONLY boolean NULL;
|
||||
|
|
@ -17,7 +17,7 @@ sealed class ContentRestriction {
|
|||
class ExcludeOver(age: Int) : AgeRestriction(age)
|
||||
}
|
||||
|
||||
sealed class LabelsRestriction(val labels: Collection<String>) : ContentRestriction() {
|
||||
sealed class LabelsRestriction(val labels: Set<String>) : ContentRestriction() {
|
||||
/**
|
||||
* Allow only content that has at least one of the provided sharing [labels]
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package org.gotson.komga.infrastructure.jooq
|
||||
|
||||
import org.gotson.komga.domain.model.ContentRestriction
|
||||
import org.gotson.komga.domain.model.ContentRestrictions
|
||||
import org.gotson.komga.domain.model.KomgaUser
|
||||
import org.gotson.komga.domain.persistence.KomgaUserRepository
|
||||
import org.gotson.komga.jooq.Tables
|
||||
|
|
@ -18,6 +20,7 @@ class KomgaUserDao(
|
|||
|
||||
private val u = Tables.USER
|
||||
private val ul = Tables.USER_LIBRARY_SHARING
|
||||
private val us = Tables.USER_SHARING
|
||||
|
||||
override fun count(): Long = dsl.fetchCount(u).toLong()
|
||||
|
||||
|
|
@ -41,6 +44,9 @@ class KomgaUserDao(
|
|||
private fun ResultQuery<Record>.fetchAndMap() =
|
||||
this.fetchGroups({ it.into(u) }, { it.into(ul) })
|
||||
.map { (ur, ulr) ->
|
||||
val usr = dsl.selectFrom(us)
|
||||
.where(us.USER_ID.eq(ur.id))
|
||||
.toList()
|
||||
KomgaUser(
|
||||
email = ur.email,
|
||||
password = ur.password,
|
||||
|
|
@ -49,6 +55,14 @@ class KomgaUserDao(
|
|||
rolePageStreaming = ur.rolePageStreaming,
|
||||
sharedLibrariesIds = ulr.mapNotNull { it.libraryId }.toSet(),
|
||||
sharedAllLibraries = ur.sharedAllLibraries,
|
||||
restrictions = ContentRestrictions(
|
||||
ageRestriction = if (ur.ageRestriction != null && ur.ageRestrictionAllowOnly != null)
|
||||
if (ur.ageRestrictionAllowOnly) ContentRestriction.AgeRestriction.AllowOnlyUnder(ur.ageRestriction)
|
||||
else ContentRestriction.AgeRestriction.ExcludeOver(ur.ageRestriction)
|
||||
else null,
|
||||
labelsAllow = usr.filter { it.allow }.map { it.label }.toSet(),
|
||||
labelsExclude = usr.filterNot { it.allow }.map { it.label }.toSet(),
|
||||
),
|
||||
id = ur.id,
|
||||
createdDate = ur.createdDate.toCurrentTimeZone(),
|
||||
lastModifiedDate = ur.lastModifiedDate.toCurrentTimeZone(),
|
||||
|
|
@ -65,14 +79,19 @@ class KomgaUserDao(
|
|||
.set(u.ROLE_FILE_DOWNLOAD, user.roleFileDownload)
|
||||
.set(u.ROLE_PAGE_STREAMING, user.rolePageStreaming)
|
||||
.set(u.SHARED_ALL_LIBRARIES, user.sharedAllLibraries)
|
||||
.set(u.AGE_RESTRICTION, user.restrictions.ageRestriction?.age)
|
||||
.set(
|
||||
u.AGE_RESTRICTION_ALLOW_ONLY,
|
||||
when (user.restrictions.ageRestriction) {
|
||||
is ContentRestriction.AgeRestriction.AllowOnlyUnder -> true
|
||||
is ContentRestriction.AgeRestriction.ExcludeOver -> false
|
||||
null -> null
|
||||
},
|
||||
)
|
||||
.execute()
|
||||
|
||||
user.sharedLibrariesIds.forEach {
|
||||
dsl.insertInto(ul)
|
||||
.columns(ul.USER_ID, ul.LIBRARY_ID)
|
||||
.values(user.id, it)
|
||||
.execute()
|
||||
}
|
||||
insertSharedLibraries(user)
|
||||
insertSharingRestrictions(user)
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
|
@ -84,6 +103,15 @@ class KomgaUserDao(
|
|||
.set(u.ROLE_FILE_DOWNLOAD, user.roleFileDownload)
|
||||
.set(u.ROLE_PAGE_STREAMING, user.rolePageStreaming)
|
||||
.set(u.SHARED_ALL_LIBRARIES, user.sharedAllLibraries)
|
||||
.set(u.AGE_RESTRICTION, user.restrictions.ageRestriction?.age)
|
||||
.set(
|
||||
u.AGE_RESTRICTION_ALLOW_ONLY,
|
||||
when (user.restrictions.ageRestriction) {
|
||||
is ContentRestriction.AgeRestriction.AllowOnlyUnder -> true
|
||||
is ContentRestriction.AgeRestriction.ExcludeOver -> false
|
||||
null -> null
|
||||
},
|
||||
)
|
||||
.set(u.LAST_MODIFIED_DATE, LocalDateTime.now(ZoneId.of("Z")))
|
||||
.where(u.ID.eq(user.id))
|
||||
.execute()
|
||||
|
|
@ -92,6 +120,15 @@ class KomgaUserDao(
|
|||
.where(ul.USER_ID.eq(user.id))
|
||||
.execute()
|
||||
|
||||
dsl.deleteFrom(us)
|
||||
.where(us.USER_ID.eq(user.id))
|
||||
.execute()
|
||||
|
||||
insertSharedLibraries(user)
|
||||
insertSharingRestrictions(user)
|
||||
}
|
||||
|
||||
private fun insertSharedLibraries(user: KomgaUser) {
|
||||
user.sharedLibrariesIds.forEach {
|
||||
dsl.insertInto(ul)
|
||||
.columns(ul.USER_ID, ul.LIBRARY_ID)
|
||||
|
|
@ -100,14 +137,32 @@ class KomgaUserDao(
|
|||
}
|
||||
}
|
||||
|
||||
private fun insertSharingRestrictions(user: KomgaUser) {
|
||||
user.restrictions.labelsAllowRestriction?.labels?.forEach { label ->
|
||||
dsl.insertInto(us)
|
||||
.columns(us.USER_ID, us.ALLOW, us.LABEL)
|
||||
.values(user.id, true, label)
|
||||
.execute()
|
||||
}
|
||||
|
||||
user.restrictions.labelsExcludeRestriction?.labels?.forEach { label ->
|
||||
dsl.insertInto(us)
|
||||
.columns(us.USER_ID, us.ALLOW, us.LABEL)
|
||||
.values(user.id, false, label)
|
||||
.execute()
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
override fun delete(userId: String) {
|
||||
dsl.deleteFrom(us).where(us.USER_ID.equal(userId)).execute()
|
||||
dsl.deleteFrom(ul).where(ul.USER_ID.equal(userId)).execute()
|
||||
dsl.deleteFrom(u).where(u.ID.equal(userId)).execute()
|
||||
}
|
||||
|
||||
@Transactional
|
||||
override fun deleteAll() {
|
||||
dsl.deleteFrom(us).execute()
|
||||
dsl.deleteFrom(ul).execute()
|
||||
dsl.deleteFrom(u).execute()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package org.gotson.komga.infrastructure.jooq
|
||||
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.gotson.komga.domain.model.ContentRestriction
|
||||
import org.gotson.komga.domain.model.ContentRestrictions
|
||||
import org.gotson.komga.domain.model.KomgaUser
|
||||
import org.gotson.komga.domain.model.makeLibrary
|
||||
import org.gotson.komga.domain.persistence.LibraryRepository
|
||||
|
|
@ -59,9 +61,12 @@ class KomgaUserDaoTest(
|
|||
assertThat(lastModifiedDate).isCloseTo(now, offset)
|
||||
assertThat(email).isEqualTo("user@example.org")
|
||||
assertThat(password).isEqualTo("password")
|
||||
assertThat(roleAdmin).isFalse()
|
||||
assertThat(roleAdmin).isFalse
|
||||
assertThat(sharedLibrariesIds).containsExactly(library.id)
|
||||
assertThat(sharedAllLibraries).isFalse()
|
||||
assertThat(sharedAllLibraries).isFalse
|
||||
assertThat(restrictions.ageRestriction).isNull()
|
||||
assertThat(restrictions.labelsAllowRestriction).isNull()
|
||||
assertThat(restrictions.labelsExcludeRestriction).isNull()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -73,10 +78,29 @@ class KomgaUserDaoTest(
|
|||
roleAdmin = false,
|
||||
sharedLibrariesIds = setOf(library.id),
|
||||
sharedAllLibraries = false,
|
||||
restrictions = ContentRestrictions(
|
||||
ageRestriction = ContentRestriction.AgeRestriction.AllowOnlyUnder(10),
|
||||
labelsAllow = setOf("allow"),
|
||||
labelsExclude = setOf("exclude"),
|
||||
)
|
||||
)
|
||||
|
||||
komgaUserDao.insert(user)
|
||||
val created = komgaUserDao.findByIdOrNull(user.id)!!
|
||||
with(created) {
|
||||
assertThat(restrictions.ageRestriction)
|
||||
.isNotNull
|
||||
.isExactlyInstanceOf(ContentRestriction.AgeRestriction.AllowOnlyUnder::class.java)
|
||||
assertThat(restrictions.ageRestriction!!.age).isEqualTo(10)
|
||||
assertThat(restrictions.labelsAllowRestriction)
|
||||
.isNotNull
|
||||
.isExactlyInstanceOf(ContentRestriction.LabelsRestriction.AllowOnly::class.java)
|
||||
assertThat(restrictions.labelsAllowRestriction!!.labels).containsExactly("allow")
|
||||
assertThat(restrictions.labelsExcludeRestriction)
|
||||
.isNotNull
|
||||
.isExactlyInstanceOf(ContentRestriction.LabelsRestriction.Exclude::class.java)
|
||||
assertThat(restrictions.labelsExcludeRestriction!!.labels).containsExactly("exclude")
|
||||
}
|
||||
|
||||
val modified = created.copy(
|
||||
email = "user2@example.org",
|
||||
|
|
@ -84,6 +108,11 @@ class KomgaUserDaoTest(
|
|||
roleAdmin = true,
|
||||
sharedLibrariesIds = emptySet(),
|
||||
sharedAllLibraries = true,
|
||||
restrictions = ContentRestrictions(
|
||||
ageRestriction = ContentRestriction.AgeRestriction.ExcludeOver(16),
|
||||
labelsAllow = setOf("allow2"),
|
||||
labelsExclude = setOf("exclude2"),
|
||||
),
|
||||
)
|
||||
val modifiedDate = LocalDateTime.now()
|
||||
komgaUserDao.update(modified)
|
||||
|
|
@ -97,9 +126,28 @@ class KomgaUserDaoTest(
|
|||
.isNotEqualTo(modified.createdDate)
|
||||
assertThat(email).isEqualTo("user2@example.org")
|
||||
assertThat(password).isEqualTo("password2")
|
||||
assertThat(roleAdmin).isTrue()
|
||||
assertThat(roleAdmin).isTrue
|
||||
assertThat(sharedLibrariesIds).isEmpty()
|
||||
assertThat(sharedAllLibraries).isTrue()
|
||||
assertThat(sharedAllLibraries).isTrue
|
||||
assertThat(restrictions.ageRestriction)
|
||||
.isNotNull
|
||||
.isExactlyInstanceOf(ContentRestriction.AgeRestriction.ExcludeOver::class.java)
|
||||
assertThat(restrictions.ageRestriction!!.age).isEqualTo(16)
|
||||
assertThat(restrictions.labelsAllowRestriction)
|
||||
.isNotNull
|
||||
.isExactlyInstanceOf(ContentRestriction.LabelsRestriction.AllowOnly::class.java)
|
||||
assertThat(restrictions.labelsAllowRestriction!!.labels).containsExactly("allow2")
|
||||
assertThat(restrictions.labelsExcludeRestriction)
|
||||
.isNotNull
|
||||
.isExactlyInstanceOf(ContentRestriction.LabelsRestriction.Exclude::class.java)
|
||||
assertThat(restrictions.labelsExcludeRestriction!!.labels).containsExactly("exclude2")
|
||||
}
|
||||
|
||||
komgaUserDao.update(modifiedSaved.copy(restrictions = ContentRestrictions()))
|
||||
with(komgaUserDao.findByIdOrNull(modified.id)!!) {
|
||||
assertThat(restrictions.ageRestriction).isNull()
|
||||
assertThat(restrictions.labelsAllowRestriction).isNull()
|
||||
assertThat(restrictions.labelsExcludeRestriction).isNull()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue