mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-22 02:18:26 +00:00
Allow to manage passwords for a collective
This commit is contained in:
@ -0,0 +1,7 @@
|
||||
CREATE TABLE "collective_password" (
|
||||
"id" varchar(254) not null primary key,
|
||||
"cid" varchar(254) not null,
|
||||
"pass" varchar(254) not null,
|
||||
"created" timestamp not null,
|
||||
foreign key ("cid") references "collective"("cid") on delete cascade
|
||||
)
|
@ -0,0 +1,7 @@
|
||||
CREATE TABLE `collective_password` (
|
||||
`id` varchar(254) not null primary key,
|
||||
`cid` varchar(254) not null,
|
||||
`pass` varchar(254) not null,
|
||||
`created` timestamp not null,
|
||||
foreign key (`cid`) references `collective`(`cid`) on delete cascade
|
||||
)
|
@ -0,0 +1,7 @@
|
||||
CREATE TABLE "collective_password" (
|
||||
"id" varchar(254) not null primary key,
|
||||
"cid" varchar(254) not null,
|
||||
"pass" varchar(254) not null,
|
||||
"created" timestamp not null,
|
||||
foreign key ("cid") references "collective"("cid") on delete cascade
|
||||
)
|
@ -89,7 +89,8 @@ object RCollective {
|
||||
case None =>
|
||||
REmptyTrashSetting.delete(cid)
|
||||
}
|
||||
} yield n1 + n2 + n3
|
||||
n4 <- RCollectivePassword.replaceAll(cid, settings.passwords)
|
||||
} yield n1 + n2 + n3 + n4
|
||||
|
||||
// this hides categories that have been deleted in the meantime
|
||||
// they are finally removed from the json array once the learn classifier task is run
|
||||
@ -99,10 +100,12 @@ object RCollective {
|
||||
prev <- OptionT.fromOption[ConnectionIO](sett.classifier)
|
||||
cats <- OptionT.liftF(RTag.listCategories(coll))
|
||||
next = prev.copy(categories = prev.categories.intersect(cats))
|
||||
} yield sett.copy(classifier = Some(next))).value
|
||||
pws <- OptionT.liftF(RCollectivePassword.findAll(coll))
|
||||
} yield sett.copy(classifier = Some(next), passwords = pws.map(_.password))).value
|
||||
|
||||
private def getRawSettings(coll: Ident): ConnectionIO[Option[Settings]] = {
|
||||
import RClassifierSetting.stringListMeta
|
||||
|
||||
val c = RCollective.as("c")
|
||||
val cs = RClassifierSetting.as("cs")
|
||||
val es = REmptyTrashSetting.as("es")
|
||||
@ -116,7 +119,8 @@ object RCollective {
|
||||
cs.categories.s,
|
||||
cs.listType.s,
|
||||
es.schedule.s,
|
||||
es.minAge.s
|
||||
es.minAge.s,
|
||||
const(0) //dummy value to load Nil as list of passwords
|
||||
),
|
||||
from(c).leftJoin(cs, cs.cid === c.id).leftJoin(es, es.cid === c.id),
|
||||
c.id === coll
|
||||
@ -170,7 +174,11 @@ object RCollective {
|
||||
language: Language,
|
||||
integrationEnabled: Boolean,
|
||||
classifier: Option[RClassifierSetting.Classifier],
|
||||
emptyTrash: Option[REmptyTrashSetting.EmptyTrash]
|
||||
emptyTrash: Option[REmptyTrashSetting.EmptyTrash],
|
||||
passwords: List[Password]
|
||||
)
|
||||
|
||||
implicit val passwordListMeta: Read[List[Password]] =
|
||||
Read[Int].map(_ => Nil: List[Password])
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,79 @@
|
||||
package docspell.store.records
|
||||
|
||||
import cats.data.NonEmptyList
|
||||
import docspell.common._
|
||||
import docspell.store.qb._
|
||||
import docspell.store.qb.DSL._
|
||||
import doobie._
|
||||
import doobie.implicits._
|
||||
import cats.effect._
|
||||
import cats.implicits._
|
||||
|
||||
final case class RCollectivePassword(
|
||||
id: Ident,
|
||||
cid: Ident,
|
||||
password: Password,
|
||||
created: Timestamp
|
||||
) {}
|
||||
|
||||
object RCollectivePassword {
|
||||
final case class Table(alias: Option[String]) extends TableDef {
|
||||
val tableName: String = "collective_password"
|
||||
|
||||
val id = Column[Ident]("id", this)
|
||||
val cid = Column[Ident]("cid", this)
|
||||
val password = Column[Password]("pass", this)
|
||||
val created = Column[Timestamp]("created", this)
|
||||
|
||||
val all: NonEmptyList[Column[_]] =
|
||||
NonEmptyList.of(id, cid, password, created)
|
||||
}
|
||||
|
||||
val T = Table(None)
|
||||
def as(alias: String): Table =
|
||||
Table(Some(alias))
|
||||
|
||||
def createNew[F[_]: Sync](cid: Ident, pw: Password): F[RCollectivePassword] =
|
||||
for {
|
||||
id <- Ident.randomId[F]
|
||||
time <- Timestamp.current[F]
|
||||
} yield RCollectivePassword(id, cid, pw, time)
|
||||
|
||||
def insert(v: RCollectivePassword): ConnectionIO[Int] =
|
||||
DML.insert(
|
||||
T,
|
||||
T.all,
|
||||
fr"${v.id}, ${v.cid},${v.password},${v.created}"
|
||||
)
|
||||
|
||||
def upsert(v: RCollectivePassword): ConnectionIO[Int] =
|
||||
for {
|
||||
k <- deleteByPassword(v.cid, v.password)
|
||||
n <- insert(v)
|
||||
} yield n + k
|
||||
|
||||
def deleteById(id: Ident): ConnectionIO[Int] =
|
||||
DML.delete(T, T.id === id)
|
||||
|
||||
def deleteByPassword(cid: Ident, pw: Password): ConnectionIO[Int] =
|
||||
DML.delete(T, T.password === pw && T.cid === cid)
|
||||
|
||||
def findAll(cid: Ident): ConnectionIO[List[RCollectivePassword]] =
|
||||
Select(select(T.all), from(T), T.cid === cid).build
|
||||
.query[RCollectivePassword]
|
||||
.to[List]
|
||||
|
||||
def replaceAll(cid: Ident, pws: List[Password]): ConnectionIO[Int] =
|
||||
for {
|
||||
k <- DML.delete(T, T.cid === cid)
|
||||
pw <- pws.traverse(p => createNew[ConnectionIO](cid, p))
|
||||
n <-
|
||||
if (pws.isEmpty) 0.pure[ConnectionIO]
|
||||
else
|
||||
DML.insertMany(
|
||||
T,
|
||||
T.all,
|
||||
pw.map(p => fr"${p.id},${p.cid},${p.password},${p.created}")
|
||||
)
|
||||
} yield k + n
|
||||
}
|
Reference in New Issue
Block a user