mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-02 13:32:51 +00:00
Return member count and if current user is owner or member
This commit is contained in:
parent
ea4ab11195
commit
60a08fc786
@ -10,12 +10,12 @@ import docspell.store.queries.QSpace
|
||||
trait OSpace[F[_]] {
|
||||
|
||||
def findAll(
|
||||
collective: Ident,
|
||||
account: AccountId,
|
||||
ownerLogin: Option[Ident],
|
||||
nameQuery: Option[String]
|
||||
): F[Vector[OSpace.SpaceItem]]
|
||||
|
||||
def findById(id: Ident, collective: Ident): F[Option[OSpace.SpaceDetail]]
|
||||
def findById(id: Ident, account: AccountId): F[Option[OSpace.SpaceDetail]]
|
||||
|
||||
/** Adds a new space. If `login` is non-empty, the `space.user`
|
||||
* property is ignored and the user-id is determined by the given
|
||||
@ -58,14 +58,14 @@ object OSpace {
|
||||
def apply[F[_]: Effect](store: Store[F]): Resource[F, OSpace[F]] =
|
||||
Resource.pure[F, OSpace[F]](new OSpace[F] {
|
||||
def findAll(
|
||||
collective: Ident,
|
||||
account: AccountId,
|
||||
ownerLogin: Option[Ident],
|
||||
nameQuery: Option[String]
|
||||
): F[Vector[SpaceItem]] =
|
||||
store.transact(QSpace.findAll(collective, None, ownerLogin, nameQuery))
|
||||
store.transact(QSpace.findAll(account, None, ownerLogin, nameQuery))
|
||||
|
||||
def findById(id: Ident, collective: Ident): F[Option[SpaceDetail]] =
|
||||
store.transact(QSpace.findById(id, collective))
|
||||
def findById(id: Ident, account: AccountId): F[Option[SpaceDetail]] =
|
||||
store.transact(QSpace.findById(id, account))
|
||||
|
||||
def add(space: RSpace, login: Option[Ident]): F[AddResult] = {
|
||||
val insert = login match {
|
||||
|
@ -2510,6 +2510,8 @@ components:
|
||||
- name
|
||||
- owner
|
||||
- created
|
||||
- isMember
|
||||
- memberCount
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
@ -2521,6 +2523,11 @@ components:
|
||||
created:
|
||||
type: integer
|
||||
format: date-time
|
||||
isMember:
|
||||
type: boolean
|
||||
memberCount:
|
||||
type: integer
|
||||
format: int32
|
||||
NewSpace:
|
||||
description: |
|
||||
Data required to create a new space.
|
||||
@ -2537,6 +2544,8 @@ components:
|
||||
- name
|
||||
- owner
|
||||
- created
|
||||
- isMember
|
||||
- memberCount
|
||||
- members
|
||||
properties:
|
||||
id:
|
||||
@ -2549,6 +2558,11 @@ components:
|
||||
created:
|
||||
type: integer
|
||||
format: date-time
|
||||
isMember:
|
||||
type: boolean
|
||||
memberCount:
|
||||
type: integer
|
||||
format: int32
|
||||
members:
|
||||
type: array
|
||||
items:
|
||||
|
@ -15,8 +15,8 @@ import docspell.common.syntax.all._
|
||||
import docspell.ftsclient.FtsResult
|
||||
import docspell.restapi.model._
|
||||
import docspell.restserver.conv.Conversions._
|
||||
import docspell.store.{AddResult, UpdateResult}
|
||||
import docspell.store.records._
|
||||
import docspell.store.{AddResult, UpdateResult}
|
||||
|
||||
import bitpeace.FileMeta
|
||||
import org.http4s.headers.`Content-Type`
|
||||
|
@ -8,10 +8,10 @@ import docspell.backend.BackendApp
|
||||
import docspell.backend.auth.AuthToken
|
||||
import docspell.backend.ops.OSpace
|
||||
import docspell.common._
|
||||
import docspell.store.records.RSpace
|
||||
import docspell.restapi.model._
|
||||
import docspell.restserver.conv.Conversions
|
||||
import docspell.restserver.http4s._
|
||||
import docspell.store.records.RSpace
|
||||
|
||||
import org.http4s.HttpRoutes
|
||||
import org.http4s.circe.CirceEntityDecoder._
|
||||
@ -29,7 +29,7 @@ object SpaceRoutes {
|
||||
val login =
|
||||
owning.filter(identity).map(_ => user.account.user)
|
||||
for {
|
||||
all <- backend.space.findAll(user.account.collective, login, q.map(_.q))
|
||||
all <- backend.space.findAll(user.account, login, q.map(_.q))
|
||||
resp <- Ok(SpaceList(all.map(mkSpace).toList))
|
||||
} yield resp
|
||||
|
||||
@ -43,7 +43,7 @@ object SpaceRoutes {
|
||||
|
||||
case GET -> Root / Ident(id) =>
|
||||
(for {
|
||||
space <- OptionT(backend.space.findById(id, user.account.collective))
|
||||
space <- OptionT(backend.space.findById(id, user.account))
|
||||
resp <- OptionT.liftF(Ok(mkSpaceDetail(space)))
|
||||
} yield resp).getOrElseF(NotFound())
|
||||
|
||||
@ -82,7 +82,9 @@ object SpaceRoutes {
|
||||
item.id,
|
||||
item.name,
|
||||
Conversions.mkIdName(item.owner),
|
||||
item.created
|
||||
item.created,
|
||||
item.member,
|
||||
item.memberCount
|
||||
)
|
||||
|
||||
private def mkSpaceDetail(item: OSpace.SpaceDetail): SpaceDetail =
|
||||
@ -91,6 +93,8 @@ object SpaceRoutes {
|
||||
item.name,
|
||||
Conversions.mkIdName(item.owner),
|
||||
item.created,
|
||||
item.member,
|
||||
item.memberCount,
|
||||
item.members.map(Conversions.mkIdName)
|
||||
)
|
||||
|
||||
|
@ -16,10 +16,12 @@ object QSpace {
|
||||
id: Ident,
|
||||
name: String,
|
||||
owner: IdRef,
|
||||
created: Timestamp
|
||||
created: Timestamp,
|
||||
member: Boolean,
|
||||
memberCount: Int
|
||||
) {
|
||||
def withMembers(members: List[IdRef]): SpaceDetail =
|
||||
SpaceDetail(id, name, owner, created, members)
|
||||
SpaceDetail(id, name, owner, created, member, memberCount, members)
|
||||
}
|
||||
|
||||
final case class SpaceDetail(
|
||||
@ -27,6 +29,8 @@ object QSpace {
|
||||
name: String,
|
||||
owner: IdRef,
|
||||
created: Timestamp,
|
||||
member: Boolean,
|
||||
memberCount: Int,
|
||||
members: List[IdRef]
|
||||
)
|
||||
|
||||
@ -130,7 +134,7 @@ object QSpace {
|
||||
} yield res).getOrElse(SpaceChangeResult.notFound)
|
||||
}
|
||||
|
||||
def findById(id: Ident, collective: Ident): ConnectionIO[Option[SpaceDetail]] = {
|
||||
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")
|
||||
@ -145,44 +149,99 @@ object QSpace {
|
||||
val memberQ = selectSimple(
|
||||
Seq(uId, uLogin),
|
||||
from,
|
||||
and(mSpaceId.is(id), sColl.is(collective))
|
||||
and(mSpaceId.is(id), sColl.is(account.collective))
|
||||
).query[IdRef].to[Vector]
|
||||
|
||||
(for {
|
||||
space <- OptionT(findAll(collective, Some(id), None, None).map(_.headOption))
|
||||
space <- OptionT(findAll(account, Some(id), None, None).map(_.headOption))
|
||||
memb <- OptionT.liftF(memberQ)
|
||||
} yield space.withMembers(memb.toList)).value
|
||||
}
|
||||
|
||||
def findAll(
|
||||
collective: Ident,
|
||||
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,
|
||||
sName,
|
||||
uId,
|
||||
RUser.Columns.login.prefix("u"),
|
||||
RSpace.Columns.created.prefix("s")
|
||||
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(collective) :: idQ.toList.map(id => sId.is(id)) ::: nameQ.toList.map(q =>
|
||||
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))
|
||||
|
||||
selectSimple(cols, from, and(where) ++ orderBy(sName.asc)).query[SpaceItem].to[Vector]
|
||||
(cte ++ selectSimple(commas(cols), from, and(where) ++ orderBy(sName.asc)))
|
||||
.query[SpaceItem]
|
||||
.to[Vector]
|
||||
}
|
||||
|
||||
private def findUserId(account: AccountId): ConnectionIO[Option[Ident]] =
|
||||
|
Loading…
x
Reference in New Issue
Block a user