mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-21 18:08:25 +00:00
Rename space -> folder
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
CREATE TABLE "space" (
|
||||
CREATE TABLE "folder" (
|
||||
"id" varchar(254) not null primary key,
|
||||
"name" varchar(254) not null,
|
||||
"cid" varchar(254) not null,
|
||||
@ -9,15 +9,15 @@ CREATE TABLE "space" (
|
||||
foreign key ("owner") references "user_"("uid")
|
||||
);
|
||||
|
||||
CREATE TABLE "space_member" (
|
||||
CREATE TABLE "folder_member" (
|
||||
"id" varchar(254) not null primary key,
|
||||
"space_id" varchar(254) not null,
|
||||
"folder_id" varchar(254) not null,
|
||||
"user_id" varchar(254) not null,
|
||||
"created" timestamp not null,
|
||||
unique ("space_id", "user_id"),
|
||||
foreign key ("space_id") references "space"("id"),
|
||||
unique ("folder_id", "user_id"),
|
||||
foreign key ("folder_id") references "folder"("id"),
|
||||
foreign key ("user_id") references "user_"("uid")
|
||||
);
|
||||
|
||||
ALTER TABLE "item"
|
||||
ADD COLUMN "space_id" varchar(254) NULL;
|
||||
ADD COLUMN "folder_id" varchar(254) NULL;
|
@ -0,0 +1,249 @@
|
||||
package docspell.store.queries
|
||||
|
||||
import cats.data.OptionT
|
||||
import cats.implicits._
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.records._
|
||||
|
||||
import doobie._
|
||||
import doobie.implicits._
|
||||
|
||||
object QFolder {
|
||||
|
||||
final case class FolderItem(
|
||||
id: Ident,
|
||||
name: String,
|
||||
owner: IdRef,
|
||||
created: Timestamp,
|
||||
member: Boolean,
|
||||
memberCount: Int
|
||||
) {
|
||||
def withMembers(members: List[IdRef]): FolderDetail =
|
||||
FolderDetail(id, name, owner, created, member, memberCount, members)
|
||||
}
|
||||
|
||||
final case class FolderDetail(
|
||||
id: Ident,
|
||||
name: String,
|
||||
owner: IdRef,
|
||||
created: Timestamp,
|
||||
member: Boolean,
|
||||
memberCount: Int,
|
||||
members: List[IdRef]
|
||||
)
|
||||
|
||||
sealed trait FolderChangeResult
|
||||
object FolderChangeResult {
|
||||
case object Success extends FolderChangeResult
|
||||
def success: FolderChangeResult = Success
|
||||
case object NotFound extends FolderChangeResult
|
||||
def notFound: FolderChangeResult = NotFound
|
||||
case object Forbidden extends FolderChangeResult
|
||||
def forbidden: FolderChangeResult = Forbidden
|
||||
case object Exists extends FolderChangeResult
|
||||
def exists: FolderChangeResult = Exists
|
||||
}
|
||||
|
||||
def delete(id: Ident, account: AccountId): ConnectionIO[FolderChangeResult] = {
|
||||
def tryDelete =
|
||||
for {
|
||||
_ <- RItem.removeFolder(id)
|
||||
_ <- RFolderMember.deleteAll(id)
|
||||
_ <- RFolder.delete(id)
|
||||
} yield FolderChangeResult.success
|
||||
|
||||
(for {
|
||||
uid <- OptionT(findUserId(account))
|
||||
folder <- OptionT(RFolder.findById(id))
|
||||
res <- OptionT.liftF(
|
||||
if (folder.owner == uid) tryDelete
|
||||
else FolderChangeResult.forbidden.pure[ConnectionIO]
|
||||
)
|
||||
} yield res).getOrElse(FolderChangeResult.notFound)
|
||||
}
|
||||
|
||||
def changeName(
|
||||
folder: Ident,
|
||||
account: AccountId,
|
||||
name: String
|
||||
): ConnectionIO[FolderChangeResult] = {
|
||||
def tryUpdate(ns: RFolder): ConnectionIO[FolderChangeResult] =
|
||||
for {
|
||||
n <- RFolder.update(ns)
|
||||
res =
|
||||
if (n == 0) FolderChangeResult.notFound
|
||||
else FolderChangeResult.Success
|
||||
} yield res
|
||||
|
||||
(for {
|
||||
uid <- OptionT(findUserId(account))
|
||||
folder <- OptionT(RFolder.findById(folder))
|
||||
res <- OptionT.liftF(
|
||||
if (folder.owner == uid) tryUpdate(folder.copy(name = name))
|
||||
else FolderChangeResult.forbidden.pure[ConnectionIO]
|
||||
)
|
||||
} yield res).getOrElse(FolderChangeResult.notFound)
|
||||
}
|
||||
|
||||
def removeMember(
|
||||
folder: Ident,
|
||||
account: AccountId,
|
||||
member: Ident
|
||||
): ConnectionIO[FolderChangeResult] = {
|
||||
def tryRemove: ConnectionIO[FolderChangeResult] =
|
||||
for {
|
||||
n <- RFolderMember.delete(member, folder)
|
||||
res =
|
||||
if (n == 0) FolderChangeResult.notFound
|
||||
else FolderChangeResult.Success
|
||||
} yield res
|
||||
|
||||
(for {
|
||||
uid <- OptionT(findUserId(account))
|
||||
folder <- OptionT(RFolder.findById(folder))
|
||||
res <- OptionT.liftF(
|
||||
if (folder.owner == uid) tryRemove
|
||||
else FolderChangeResult.forbidden.pure[ConnectionIO]
|
||||
)
|
||||
} yield res).getOrElse(FolderChangeResult.notFound)
|
||||
}
|
||||
|
||||
def addMember(
|
||||
folder: Ident,
|
||||
account: AccountId,
|
||||
member: Ident
|
||||
): ConnectionIO[FolderChangeResult] = {
|
||||
def tryAdd: ConnectionIO[FolderChangeResult] =
|
||||
for {
|
||||
spm <- RFolderMember.findByUserId(member, folder)
|
||||
mem <- RFolderMember.newMember[ConnectionIO](folder, member)
|
||||
res <-
|
||||
if (spm.isDefined) FolderChangeResult.exists.pure[ConnectionIO]
|
||||
else RFolderMember.insert(mem).map(_ => FolderChangeResult.Success)
|
||||
} yield res
|
||||
|
||||
(for {
|
||||
uid <- OptionT(findUserId(account))
|
||||
folder <- OptionT(RFolder.findById(folder))
|
||||
res <- OptionT.liftF(
|
||||
if (folder.owner == uid) tryAdd
|
||||
else FolderChangeResult.forbidden.pure[ConnectionIO]
|
||||
)
|
||||
} yield res).getOrElse(FolderChangeResult.notFound)
|
||||
}
|
||||
|
||||
def findById(id: Ident, account: AccountId): ConnectionIO[Option[FolderDetail]] = {
|
||||
val mUserId = RFolderMember.Columns.user.prefix("m")
|
||||
val mFolderId = RFolderMember.Columns.folder.prefix("m")
|
||||
val uId = RUser.Columns.uid.prefix("u")
|
||||
val uLogin = RUser.Columns.login.prefix("u")
|
||||
val sColl = RFolder.Columns.collective.prefix("s")
|
||||
val sId = RFolder.Columns.id.prefix("s")
|
||||
|
||||
val from = RFolderMember.table ++ fr"m INNER JOIN" ++
|
||||
RUser.table ++ fr"u ON" ++ mUserId.is(uId) ++ fr"INNER JOIN" ++
|
||||
RFolder.table ++ fr"s ON" ++ mFolderId.is(sId)
|
||||
|
||||
val memberQ = selectSimple(
|
||||
Seq(uId, uLogin),
|
||||
from,
|
||||
and(mFolderId.is(id), sColl.is(account.collective))
|
||||
).query[IdRef].to[Vector]
|
||||
|
||||
(for {
|
||||
folder <- OptionT(findAll(account, Some(id), None, None).map(_.headOption))
|
||||
memb <- OptionT.liftF(memberQ)
|
||||
} yield folder.withMembers(memb.toList)).value
|
||||
}
|
||||
|
||||
def findAll(
|
||||
account: AccountId,
|
||||
idQ: Option[Ident],
|
||||
ownerLogin: Option[Ident],
|
||||
nameQ: Option[String]
|
||||
): ConnectionIO[Vector[FolderItem]] = {
|
||||
// with memberlogin as
|
||||
// (select m.folder_id,u.login
|
||||
// from folder_member m
|
||||
// inner join user_ u on u.uid = m.user_id
|
||||
// inner join folder s on s.id = m.folder_id
|
||||
// where s.cid = 'eike'
|
||||
// union all
|
||||
// select s.id,u.login
|
||||
// from folder s
|
||||
// inner join user_ u on u.uid = s.owner
|
||||
// where s.cid = 'eike')
|
||||
// select s.id
|
||||
// ,s.name
|
||||
// ,s.owner
|
||||
// ,u.login
|
||||
// ,s.created
|
||||
// ,(select count(*) > 0 from memberlogin where folder_id = s.id and login = 'eike') as member
|
||||
// ,(select count(*) - 1 from memberlogin where folder_id = s.id) as member_count
|
||||
// from folder s
|
||||
// inner join user_ u on u.uid = s.owner
|
||||
// where s.cid = 'eike';
|
||||
|
||||
val uId = RUser.Columns.uid.prefix("u")
|
||||
val uLogin = RUser.Columns.login.prefix("u")
|
||||
val sId = RFolder.Columns.id.prefix("s")
|
||||
val sOwner = RFolder.Columns.owner.prefix("s")
|
||||
val sName = RFolder.Columns.name.prefix("s")
|
||||
val sColl = RFolder.Columns.collective.prefix("s")
|
||||
val mUser = RFolderMember.Columns.user.prefix("m")
|
||||
val mFolder = RFolderMember.Columns.folder.prefix("m")
|
||||
|
||||
//CTE
|
||||
val cte: Fragment = {
|
||||
val from1 = RFolderMember.table ++ fr"m INNER JOIN" ++
|
||||
RUser.table ++ fr"u ON" ++ uId.is(mUser) ++ fr"INNER JOIN" ++
|
||||
RFolder.table ++ fr"s ON" ++ sId.is(mFolder)
|
||||
|
||||
val from2 = RFolder.table ++ fr"s INNER JOIN" ++
|
||||
RUser.table ++ fr"u ON" ++ uId.is(sOwner)
|
||||
|
||||
withCTE(
|
||||
"memberlogin" ->
|
||||
(selectSimple(Seq(mFolder, uLogin), from1, sColl.is(account.collective)) ++
|
||||
fr"UNION ALL" ++
|
||||
selectSimple(Seq(sId, uLogin), from2, sColl.is(account.collective)))
|
||||
)
|
||||
}
|
||||
|
||||
val isMember =
|
||||
fr"SELECT COUNT(*) > 0 FROM memberlogin WHERE" ++ mFolder.prefix("").is(sId) ++
|
||||
fr"AND" ++ uLogin.prefix("").is(account.user)
|
||||
|
||||
val memberCount =
|
||||
fr"SELECT COUNT(*) - 1 FROM memberlogin WHERE" ++ mFolder.prefix("").is(sId)
|
||||
|
||||
//Query
|
||||
val cols = Seq(
|
||||
sId.f,
|
||||
sName.f,
|
||||
sOwner.f,
|
||||
uLogin.f,
|
||||
RFolder.Columns.created.prefix("s").f,
|
||||
fr"(" ++ isMember ++ fr") as mem",
|
||||
fr"(" ++ memberCount ++ fr") as cnt"
|
||||
)
|
||||
|
||||
val from = RFolder.table ++ fr"s INNER JOIN" ++
|
||||
RUser.table ++ fr"u ON" ++ uId.is(sOwner)
|
||||
|
||||
val where =
|
||||
sColl.is(account.collective) :: idQ.toList
|
||||
.map(id => sId.is(id)) ::: nameQ.toList.map(q =>
|
||||
sName.lowerLike(s"%${q.toLowerCase}%")
|
||||
) ::: ownerLogin.toList.map(login => uLogin.is(login))
|
||||
|
||||
(cte ++ selectSimple(commas(cols), from, and(where) ++ orderBy(sName.asc)))
|
||||
.query[FolderItem]
|
||||
.to[Vector]
|
||||
}
|
||||
|
||||
private def findUserId(account: AccountId): ConnectionIO[Option[Ident]] =
|
||||
RUser.findByAccount(account).map(_.map(_.uid))
|
||||
}
|
@ -1,249 +0,0 @@
|
||||
package docspell.store.queries
|
||||
|
||||
import cats.data.OptionT
|
||||
import cats.implicits._
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.records._
|
||||
|
||||
import doobie._
|
||||
import doobie.implicits._
|
||||
|
||||
object QSpace {
|
||||
|
||||
final case class SpaceItem(
|
||||
id: Ident,
|
||||
name: String,
|
||||
owner: IdRef,
|
||||
created: Timestamp,
|
||||
member: Boolean,
|
||||
memberCount: Int
|
||||
) {
|
||||
def withMembers(members: List[IdRef]): SpaceDetail =
|
||||
SpaceDetail(id, name, owner, created, member, memberCount, members)
|
||||
}
|
||||
|
||||
final case class SpaceDetail(
|
||||
id: Ident,
|
||||
name: String,
|
||||
owner: IdRef,
|
||||
created: Timestamp,
|
||||
member: Boolean,
|
||||
memberCount: Int,
|
||||
members: List[IdRef]
|
||||
)
|
||||
|
||||
sealed trait SpaceChangeResult
|
||||
object SpaceChangeResult {
|
||||
case object Success extends SpaceChangeResult
|
||||
def success: SpaceChangeResult = Success
|
||||
case object NotFound extends SpaceChangeResult
|
||||
def notFound: SpaceChangeResult = NotFound
|
||||
case object Forbidden extends SpaceChangeResult
|
||||
def forbidden: SpaceChangeResult = Forbidden
|
||||
case object Exists extends SpaceChangeResult
|
||||
def exists: SpaceChangeResult = Exists
|
||||
}
|
||||
|
||||
def delete(id: Ident, account: AccountId): ConnectionIO[SpaceChangeResult] = {
|
||||
def tryDelete =
|
||||
for {
|
||||
_ <- RItem.removeSpace(id)
|
||||
_ <- RSpaceMember.deleteAll(id)
|
||||
_ <- RSpace.delete(id)
|
||||
} yield SpaceChangeResult.success
|
||||
|
||||
(for {
|
||||
uid <- OptionT(findUserId(account))
|
||||
space <- OptionT(RSpace.findById(id))
|
||||
res <- OptionT.liftF(
|
||||
if (space.owner == uid) tryDelete
|
||||
else SpaceChangeResult.forbidden.pure[ConnectionIO]
|
||||
)
|
||||
} yield res).getOrElse(SpaceChangeResult.notFound)
|
||||
}
|
||||
|
||||
def changeName(
|
||||
space: Ident,
|
||||
account: AccountId,
|
||||
name: String
|
||||
): ConnectionIO[SpaceChangeResult] = {
|
||||
def tryUpdate(ns: RSpace): ConnectionIO[SpaceChangeResult] =
|
||||
for {
|
||||
n <- RSpace.update(ns)
|
||||
res =
|
||||
if (n == 0) SpaceChangeResult.notFound
|
||||
else SpaceChangeResult.Success
|
||||
} yield res
|
||||
|
||||
(for {
|
||||
uid <- OptionT(findUserId(account))
|
||||
space <- OptionT(RSpace.findById(space))
|
||||
res <- OptionT.liftF(
|
||||
if (space.owner == uid) tryUpdate(space.copy(name = name))
|
||||
else SpaceChangeResult.forbidden.pure[ConnectionIO]
|
||||
)
|
||||
} yield res).getOrElse(SpaceChangeResult.notFound)
|
||||
}
|
||||
|
||||
def removeMember(
|
||||
space: Ident,
|
||||
account: AccountId,
|
||||
member: Ident
|
||||
): ConnectionIO[SpaceChangeResult] = {
|
||||
def tryRemove: ConnectionIO[SpaceChangeResult] =
|
||||
for {
|
||||
n <- RSpaceMember.delete(member, space)
|
||||
res =
|
||||
if (n == 0) SpaceChangeResult.notFound
|
||||
else SpaceChangeResult.Success
|
||||
} yield res
|
||||
|
||||
(for {
|
||||
uid <- OptionT(findUserId(account))
|
||||
space <- OptionT(RSpace.findById(space))
|
||||
res <- OptionT.liftF(
|
||||
if (space.owner == uid) tryRemove
|
||||
else SpaceChangeResult.forbidden.pure[ConnectionIO]
|
||||
)
|
||||
} yield res).getOrElse(SpaceChangeResult.notFound)
|
||||
}
|
||||
|
||||
def addMember(
|
||||
space: Ident,
|
||||
account: AccountId,
|
||||
member: Ident
|
||||
): ConnectionIO[SpaceChangeResult] = {
|
||||
def tryAdd: ConnectionIO[SpaceChangeResult] =
|
||||
for {
|
||||
spm <- RSpaceMember.findByUserId(member, space)
|
||||
mem <- RSpaceMember.newMember[ConnectionIO](space, member)
|
||||
res <-
|
||||
if (spm.isDefined) SpaceChangeResult.exists.pure[ConnectionIO]
|
||||
else RSpaceMember.insert(mem).map(_ => SpaceChangeResult.Success)
|
||||
} yield res
|
||||
|
||||
(for {
|
||||
uid <- OptionT(findUserId(account))
|
||||
space <- OptionT(RSpace.findById(space))
|
||||
res <- OptionT.liftF(
|
||||
if (space.owner == uid) tryAdd
|
||||
else SpaceChangeResult.forbidden.pure[ConnectionIO]
|
||||
)
|
||||
} yield res).getOrElse(SpaceChangeResult.notFound)
|
||||
}
|
||||
|
||||
def findById(id: Ident, account: AccountId): ConnectionIO[Option[SpaceDetail]] = {
|
||||
val mUserId = RSpaceMember.Columns.user.prefix("m")
|
||||
val mSpaceId = RSpaceMember.Columns.space.prefix("m")
|
||||
val uId = RUser.Columns.uid.prefix("u")
|
||||
val uLogin = RUser.Columns.login.prefix("u")
|
||||
val sColl = RSpace.Columns.collective.prefix("s")
|
||||
val sId = RSpace.Columns.id.prefix("s")
|
||||
|
||||
val from = RSpaceMember.table ++ fr"m INNER JOIN" ++
|
||||
RUser.table ++ fr"u ON" ++ mUserId.is(uId) ++ fr"INNER JOIN" ++
|
||||
RSpace.table ++ fr"s ON" ++ mSpaceId.is(sId)
|
||||
|
||||
val memberQ = selectSimple(
|
||||
Seq(uId, uLogin),
|
||||
from,
|
||||
and(mSpaceId.is(id), sColl.is(account.collective))
|
||||
).query[IdRef].to[Vector]
|
||||
|
||||
(for {
|
||||
space <- OptionT(findAll(account, Some(id), None, None).map(_.headOption))
|
||||
memb <- OptionT.liftF(memberQ)
|
||||
} yield space.withMembers(memb.toList)).value
|
||||
}
|
||||
|
||||
def findAll(
|
||||
account: AccountId,
|
||||
idQ: Option[Ident],
|
||||
ownerLogin: Option[Ident],
|
||||
nameQ: Option[String]
|
||||
): ConnectionIO[Vector[SpaceItem]] = {
|
||||
// with memberlogin as
|
||||
// (select m.space_id,u.login
|
||||
// from space_member m
|
||||
// inner join user_ u on u.uid = m.user_id
|
||||
// inner join space s on s.id = m.space_id
|
||||
// where s.cid = 'eike'
|
||||
// union all
|
||||
// select s.id,u.login
|
||||
// from space s
|
||||
// inner join user_ u on u.uid = s.owner
|
||||
// where s.cid = 'eike')
|
||||
// select s.id
|
||||
// ,s.name
|
||||
// ,s.owner
|
||||
// ,u.login
|
||||
// ,s.created
|
||||
// ,(select count(*) > 0 from memberlogin where space_id = s.id and login = 'eike') as member
|
||||
// ,(select count(*) - 1 from memberlogin where space_id = s.id) as member_count
|
||||
// from space s
|
||||
// inner join user_ u on u.uid = s.owner
|
||||
// where s.cid = 'eike';
|
||||
|
||||
val uId = RUser.Columns.uid.prefix("u")
|
||||
val uLogin = RUser.Columns.login.prefix("u")
|
||||
val sId = RSpace.Columns.id.prefix("s")
|
||||
val sOwner = RSpace.Columns.owner.prefix("s")
|
||||
val sName = RSpace.Columns.name.prefix("s")
|
||||
val sColl = RSpace.Columns.collective.prefix("s")
|
||||
val mUser = RSpaceMember.Columns.user.prefix("m")
|
||||
val mSpace = RSpaceMember.Columns.space.prefix("m")
|
||||
|
||||
//CTE
|
||||
val cte: Fragment = {
|
||||
val from1 = RSpaceMember.table ++ fr"m INNER JOIN" ++
|
||||
RUser.table ++ fr"u ON" ++ uId.is(mUser) ++ fr"INNER JOIN" ++
|
||||
RSpace.table ++ fr"s ON" ++ sId.is(mSpace)
|
||||
|
||||
val from2 = RSpace.table ++ fr"s INNER JOIN" ++
|
||||
RUser.table ++ fr"u ON" ++ uId.is(sOwner)
|
||||
|
||||
withCTE(
|
||||
"memberlogin" ->
|
||||
(selectSimple(Seq(mSpace, uLogin), from1, sColl.is(account.collective)) ++
|
||||
fr"UNION ALL" ++
|
||||
selectSimple(Seq(sId, uLogin), from2, sColl.is(account.collective)))
|
||||
)
|
||||
}
|
||||
|
||||
val isMember =
|
||||
fr"SELECT COUNT(*) > 0 FROM memberlogin WHERE" ++ mSpace.prefix("").is(sId) ++
|
||||
fr"AND" ++ uLogin.prefix("").is(account.user)
|
||||
|
||||
val memberCount =
|
||||
fr"SELECT COUNT(*) - 1 FROM memberlogin WHERE" ++ mSpace.prefix("").is(sId)
|
||||
|
||||
//Query
|
||||
val cols = Seq(
|
||||
sId.f,
|
||||
sName.f,
|
||||
sOwner.f,
|
||||
uLogin.f,
|
||||
RSpace.Columns.created.prefix("s").f,
|
||||
fr"(" ++ isMember ++ fr") as mem",
|
||||
fr"(" ++ memberCount ++ fr") as cnt"
|
||||
)
|
||||
|
||||
val from = RSpace.table ++ fr"s INNER JOIN" ++
|
||||
RUser.table ++ fr"u ON" ++ uId.is(sOwner)
|
||||
|
||||
val where =
|
||||
sColl.is(account.collective) :: idQ.toList
|
||||
.map(id => sId.is(id)) ::: nameQ.toList.map(q =>
|
||||
sName.lowerLike(s"%${q.toLowerCase}%")
|
||||
) ::: ownerLogin.toList.map(login => uLogin.is(login))
|
||||
|
||||
(cte ++ selectSimple(commas(cols), from, and(where) ++ orderBy(sName.asc)))
|
||||
.query[SpaceItem]
|
||||
.to[Vector]
|
||||
}
|
||||
|
||||
private def findUserId(account: AccountId): ConnectionIO[Option[Ident]] =
|
||||
RUser.findByAccount(account).map(_.map(_.uid))
|
||||
}
|
@ -9,7 +9,7 @@ import docspell.store.impl.Implicits._
|
||||
import doobie._
|
||||
import doobie.implicits._
|
||||
|
||||
case class RSpace(
|
||||
case class RFolder(
|
||||
id: Ident,
|
||||
name: String,
|
||||
collectiveId: Ident,
|
||||
@ -17,15 +17,15 @@ case class RSpace(
|
||||
created: Timestamp
|
||||
)
|
||||
|
||||
object RSpace {
|
||||
object RFolder {
|
||||
|
||||
def newSpace[F[_]: Sync](name: String, account: AccountId): F[RSpace] =
|
||||
def newFolder[F[_]: Sync](name: String, account: AccountId): F[RFolder] =
|
||||
for {
|
||||
nId <- Ident.randomId[F]
|
||||
now <- Timestamp.current[F]
|
||||
} yield RSpace(nId, name, account.collective, account.user, now)
|
||||
} yield RFolder(nId, name, account.collective, account.user, now)
|
||||
|
||||
val table = fr"space"
|
||||
val table = fr"folder"
|
||||
|
||||
object Columns {
|
||||
|
||||
@ -40,7 +40,7 @@ object RSpace {
|
||||
|
||||
import Columns._
|
||||
|
||||
def insert(value: RSpace): ConnectionIO[Int] = {
|
||||
def insert(value: RFolder): ConnectionIO[Int] = {
|
||||
val sql = insertRow(
|
||||
table,
|
||||
all,
|
||||
@ -49,37 +49,37 @@ object RSpace {
|
||||
sql.update.run
|
||||
}
|
||||
|
||||
def update(v: RSpace): ConnectionIO[Int] =
|
||||
def update(v: RFolder): ConnectionIO[Int] =
|
||||
updateRow(
|
||||
table,
|
||||
and(id.is(v.id), collective.is(v.collectiveId), owner.is(v.owner)),
|
||||
name.setTo(v.name)
|
||||
).update.run
|
||||
|
||||
def existsByName(coll: Ident, spaceName: String): ConnectionIO[Boolean] =
|
||||
selectCount(id, table, and(collective.is(coll), name.is(spaceName)))
|
||||
def existsByName(coll: Ident, folderName: String): ConnectionIO[Boolean] =
|
||||
selectCount(id, table, and(collective.is(coll), name.is(folderName)))
|
||||
.query[Int]
|
||||
.unique
|
||||
.map(_ > 0)
|
||||
|
||||
def findById(spaceId: Ident): ConnectionIO[Option[RSpace]] = {
|
||||
val sql = selectSimple(all, table, id.is(spaceId))
|
||||
sql.query[RSpace].option
|
||||
def findById(folderId: Ident): ConnectionIO[Option[RFolder]] = {
|
||||
val sql = selectSimple(all, table, id.is(folderId))
|
||||
sql.query[RFolder].option
|
||||
}
|
||||
|
||||
def findAll(
|
||||
coll: Ident,
|
||||
nameQ: Option[String],
|
||||
order: Columns.type => Column
|
||||
): ConnectionIO[Vector[RSpace]] = {
|
||||
): ConnectionIO[Vector[RFolder]] = {
|
||||
val q = Seq(collective.is(coll)) ++ (nameQ match {
|
||||
case Some(str) => Seq(name.lowerLike(s"%${str.toLowerCase}%"))
|
||||
case None => Seq.empty
|
||||
})
|
||||
val sql = selectSimple(all, table, and(q)) ++ orderBy(order(Columns).f)
|
||||
sql.query[RSpace].to[Vector]
|
||||
sql.query[RFolder].to[Vector]
|
||||
}
|
||||
|
||||
def delete(spaceId: Ident): ConnectionIO[Int] =
|
||||
deleteFrom(table, id.is(spaceId)).update.run
|
||||
def delete(folderId: Ident): ConnectionIO[Int] =
|
||||
deleteFrom(table, id.is(folderId)).update.run
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package docspell.store.records
|
||||
|
||||
import cats.effect._
|
||||
import cats.implicits._
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Column
|
||||
import docspell.store.impl.Implicits._
|
||||
|
||||
import doobie._
|
||||
import doobie.implicits._
|
||||
|
||||
case class RFolderMember(
|
||||
id: Ident,
|
||||
folderId: Ident,
|
||||
userId: Ident,
|
||||
created: Timestamp
|
||||
)
|
||||
|
||||
object RFolderMember {
|
||||
|
||||
def newMember[F[_]: Sync](folder: Ident, user: Ident): F[RFolderMember] =
|
||||
for {
|
||||
nId <- Ident.randomId[F]
|
||||
now <- Timestamp.current[F]
|
||||
} yield RFolderMember(nId, folder, user, now)
|
||||
|
||||
val table = fr"folder_member"
|
||||
|
||||
object Columns {
|
||||
|
||||
val id = Column("id")
|
||||
val folder = Column("folder_id")
|
||||
val user = Column("user_id")
|
||||
val created = Column("created")
|
||||
|
||||
val all = List(id, folder, user, created)
|
||||
}
|
||||
|
||||
import Columns._
|
||||
|
||||
def insert(value: RFolderMember): ConnectionIO[Int] = {
|
||||
val sql = insertRow(
|
||||
table,
|
||||
all,
|
||||
fr"${value.id},${value.folderId},${value.userId},${value.created}"
|
||||
)
|
||||
sql.update.run
|
||||
}
|
||||
|
||||
def findByUserId(userId: Ident, folderId: Ident): ConnectionIO[Option[RFolderMember]] =
|
||||
selectSimple(all, table, and(folder.is(folderId), user.is(userId)))
|
||||
.query[RFolderMember]
|
||||
.option
|
||||
|
||||
def delete(userId: Ident, folderId: Ident): ConnectionIO[Int] =
|
||||
deleteFrom(table, and(folder.is(folderId), user.is(userId))).update.run
|
||||
|
||||
def deleteAll(folderId: Ident): ConnectionIO[Int] =
|
||||
deleteFrom(table, folder.is(folderId)).update.run
|
||||
}
|
@ -28,7 +28,7 @@ case class RItem(
|
||||
created: Timestamp,
|
||||
updated: Timestamp,
|
||||
notes: Option[String],
|
||||
spaceId: Option[Ident]
|
||||
folderId: Option[Ident]
|
||||
) {}
|
||||
|
||||
object RItem {
|
||||
@ -82,7 +82,7 @@ object RItem {
|
||||
val created = Column("created")
|
||||
val updated = Column("updated")
|
||||
val notes = Column("notes")
|
||||
val space = Column("space_id")
|
||||
val folder = Column("folder_id")
|
||||
val all = List(
|
||||
id,
|
||||
cid,
|
||||
@ -100,7 +100,7 @@ object RItem {
|
||||
created,
|
||||
updated,
|
||||
notes,
|
||||
space
|
||||
folder
|
||||
)
|
||||
}
|
||||
import Columns._
|
||||
@ -111,7 +111,7 @@ object RItem {
|
||||
all,
|
||||
fr"${v.id},${v.cid},${v.name},${v.itemDate},${v.source},${v.direction},${v.state}," ++
|
||||
fr"${v.corrOrg},${v.corrPerson},${v.concPerson},${v.concEquipment},${v.inReplyTo},${v.dueDate}," ++
|
||||
fr"${v.created},${v.updated},${v.notes},${v.spaceId}"
|
||||
fr"${v.created},${v.updated},${v.notes},${v.folderId}"
|
||||
).update.run
|
||||
|
||||
def getCollective(itemId: Ident): ConnectionIO[Option[Ident]] =
|
||||
@ -300,8 +300,8 @@ object RItem {
|
||||
def findByIdAndCollective(itemId: Ident, coll: Ident): ConnectionIO[Option[RItem]] =
|
||||
selectSimple(all, table, and(id.is(itemId), cid.is(coll))).query[RItem].option
|
||||
|
||||
def removeSpace(spaceId: Ident): ConnectionIO[Int] = {
|
||||
def removeFolder(folderId: Ident): ConnectionIO[Int] = {
|
||||
val empty: Option[Ident] = None
|
||||
updateRow(table, space.is(spaceId), space.setTo(empty)).update.run
|
||||
updateRow(table, folder.is(folderId), folder.setTo(empty)).update.run
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +0,0 @@
|
||||
package docspell.store.records
|
||||
|
||||
import cats.effect._
|
||||
import cats.implicits._
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Column
|
||||
import docspell.store.impl.Implicits._
|
||||
|
||||
import doobie._
|
||||
import doobie.implicits._
|
||||
|
||||
case class RSpaceMember(
|
||||
id: Ident,
|
||||
spaceId: Ident,
|
||||
userId: Ident,
|
||||
created: Timestamp
|
||||
)
|
||||
|
||||
object RSpaceMember {
|
||||
|
||||
def newMember[F[_]: Sync](space: Ident, user: Ident): F[RSpaceMember] =
|
||||
for {
|
||||
nId <- Ident.randomId[F]
|
||||
now <- Timestamp.current[F]
|
||||
} yield RSpaceMember(nId, space, user, now)
|
||||
|
||||
val table = fr"space_member"
|
||||
|
||||
object Columns {
|
||||
|
||||
val id = Column("id")
|
||||
val space = Column("space_id")
|
||||
val user = Column("user_id")
|
||||
val created = Column("created")
|
||||
|
||||
val all = List(id, space, user, created)
|
||||
}
|
||||
|
||||
import Columns._
|
||||
|
||||
def insert(value: RSpaceMember): ConnectionIO[Int] = {
|
||||
val sql = insertRow(
|
||||
table,
|
||||
all,
|
||||
fr"${value.id},${value.spaceId},${value.userId},${value.created}"
|
||||
)
|
||||
sql.update.run
|
||||
}
|
||||
|
||||
def findByUserId(userId: Ident, spaceId: Ident): ConnectionIO[Option[RSpaceMember]] =
|
||||
selectSimple(all, table, and(space.is(spaceId), user.is(userId)))
|
||||
.query[RSpaceMember]
|
||||
.option
|
||||
|
||||
def delete(userId: Ident, spaceId: Ident): ConnectionIO[Int] =
|
||||
deleteFrom(table, and(space.is(spaceId), user.is(userId))).update.run
|
||||
|
||||
def deleteAll(spaceId: Ident): ConnectionIO[Int] =
|
||||
deleteFrom(table, space.is(spaceId)).update.run
|
||||
}
|
Reference in New Issue
Block a user