Allow to manage passwords for a collective

This commit is contained in:
eikek
2021-09-30 10:35:38 +02:00
parent 3c93b63c8a
commit f74624485f
11 changed files with 190 additions and 9 deletions

View File

@ -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
)

View File

@ -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
)

View File

@ -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
)

View File

@ -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])
}

View File

@ -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
}