mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-04-04 10:29:34 +00:00
Moved route definitions in RestApp
This commit is contained in:
parent
1b3b24eb7d
commit
d3ef4b6166
@ -7,8 +7,9 @@
|
||||
package docspell.restserver
|
||||
|
||||
import fs2.Stream
|
||||
|
||||
import docspell.backend.BackendApp
|
||||
import org.http4s.HttpRoutes
|
||||
import org.http4s.server.websocket.WebSocketBuilder2
|
||||
|
||||
trait RestApp[F[_]] {
|
||||
|
||||
@ -25,4 +26,7 @@ trait RestApp[F[_]] {
|
||||
* via websocket.
|
||||
*/
|
||||
def subscriptions: Stream[F, Nothing]
|
||||
|
||||
/** Http4s endpoint definitions. */
|
||||
def routes(wsb: WebSocketBuilder2[F]): HttpRoutes[F]
|
||||
}
|
||||
|
@ -9,22 +9,30 @@ package docspell.restserver
|
||||
import cats.effect._
|
||||
import fs2.Stream
|
||||
import fs2.concurrent.Topic
|
||||
|
||||
import docspell.backend.BackendApp
|
||||
import docspell.backend.auth.{AuthToken, ShareToken}
|
||||
import docspell.ftsclient.FtsClient
|
||||
import docspell.ftssolr.SolrFtsClient
|
||||
import docspell.notification.api.NotificationModule
|
||||
import docspell.notification.impl.NotificationModuleImpl
|
||||
import docspell.oidc.CodeFlowRoutes
|
||||
import docspell.pubsub.api.{PubSub, PubSubT}
|
||||
import docspell.restserver.ws.OutputEvent
|
||||
import docspell.restserver.auth.OpenId
|
||||
import docspell.restserver.http4s.EnvMiddleware
|
||||
import docspell.restserver.routes._
|
||||
import docspell.restserver.webapp.{TemplateRoutes, Templates, WebjarRoutes}
|
||||
import docspell.restserver.ws.{OutputEvent, WebSocketRoutes}
|
||||
import docspell.store.Store
|
||||
|
||||
import emil.javamail.JavaMailEmil
|
||||
import org.http4s.HttpRoutes
|
||||
import org.http4s.client.Client
|
||||
import org.http4s.server.Router
|
||||
import org.http4s.server.websocket.WebSocketBuilder2
|
||||
|
||||
final class RestAppImpl[F[_]: Async](
|
||||
val config: Config,
|
||||
val backend: BackendApp[F],
|
||||
httpClient: Client[F],
|
||||
notificationMod: NotificationModule[F],
|
||||
wsTopic: Topic[F, OutputEvent],
|
||||
pubSub: PubSubT[F]
|
||||
@ -35,6 +43,107 @@ final class RestAppImpl[F[_]: Async](
|
||||
|
||||
def subscriptions: Stream[F, Nothing] =
|
||||
Subscriptions[F](wsTopic, pubSub)
|
||||
|
||||
def routes(wsb: WebSocketBuilder2[F]): HttpRoutes[F] =
|
||||
createHttpApp(wsb)
|
||||
|
||||
val templates = TemplateRoutes[F](config, Templates[F])
|
||||
|
||||
def createHttpApp(
|
||||
wsB: WebSocketBuilder2[F]
|
||||
) =
|
||||
Router(
|
||||
"/api/info" -> InfoRoutes(),
|
||||
"/api/v1/open/" -> openRoutes(httpClient),
|
||||
"/api/v1/sec/" -> Authenticate(backend.login, config.auth) { token =>
|
||||
securedRoutes(wsB, token)
|
||||
},
|
||||
"/api/v1/admin" -> AdminAuth(config.adminEndpoint) {
|
||||
adminRoutes
|
||||
},
|
||||
"/api/v1/share" -> ShareAuth(backend.share, config.auth) { token =>
|
||||
shareRoutes(token)
|
||||
},
|
||||
"/api/doc" -> templates.doc,
|
||||
"/app/assets" -> EnvMiddleware(WebjarRoutes.appRoutes[F]),
|
||||
"/app" -> EnvMiddleware(templates.app),
|
||||
"/sw.js" -> EnvMiddleware(templates.serviceWorker)
|
||||
)
|
||||
|
||||
def adminRoutes: HttpRoutes[F] =
|
||||
Router(
|
||||
"fts" -> FullTextIndexRoutes.admin(config, backend),
|
||||
"user/otp" -> TotpRoutes.admin(backend),
|
||||
"user" -> UserRoutes.admin(backend),
|
||||
"info" -> InfoRoutes.admin(config),
|
||||
"attachments" -> AttachmentRoutes.admin(backend)
|
||||
)
|
||||
|
||||
def shareRoutes(
|
||||
token: ShareToken
|
||||
): HttpRoutes[F] =
|
||||
Router(
|
||||
"search" -> ShareSearchRoutes(backend, config, token),
|
||||
"attachment" -> ShareAttachmentRoutes(backend, token),
|
||||
"item" -> ShareItemRoutes(backend, token),
|
||||
"clientSettings" -> ClientSettingsRoutes.share(backend, token)
|
||||
)
|
||||
def openRoutes(
|
||||
client: Client[F]
|
||||
): HttpRoutes[F] =
|
||||
Router(
|
||||
"auth/openid" -> CodeFlowRoutes(
|
||||
config.openIdEnabled,
|
||||
OpenId.handle[F](backend, config),
|
||||
OpenId.codeFlowConfig(config),
|
||||
client
|
||||
),
|
||||
"auth" -> LoginRoutes.login(backend.login, config),
|
||||
"signup" -> RegisterRoutes(backend, config),
|
||||
"upload" -> UploadRoutes.open(backend, config),
|
||||
"checkfile" -> CheckFileRoutes.open(backend),
|
||||
"integration" -> IntegrationEndpointRoutes.open(backend, config),
|
||||
"share" -> ShareRoutes.verify(backend, config)
|
||||
)
|
||||
|
||||
def securedRoutes(
|
||||
wsB: WebSocketBuilder2[F],
|
||||
token: AuthToken
|
||||
): HttpRoutes[F] =
|
||||
Router(
|
||||
"ws" -> WebSocketRoutes(token, backend, wsTopic, wsB),
|
||||
"auth" -> LoginRoutes.session(backend.login, config, token),
|
||||
"tag" -> TagRoutes(backend, token),
|
||||
"equipment" -> EquipmentRoutes(backend, token),
|
||||
"organization" -> OrganizationRoutes(backend, token),
|
||||
"person" -> PersonRoutes(backend, token),
|
||||
"source" -> SourceRoutes(backend, token),
|
||||
"user/otp" -> TotpRoutes(backend, config, token),
|
||||
"user" -> UserRoutes(backend, token),
|
||||
"collective" -> CollectiveRoutes(backend, token),
|
||||
"queue" -> JobQueueRoutes(backend, token),
|
||||
"item" -> ItemRoutes(config, backend, token),
|
||||
"items" -> ItemMultiRoutes(config, backend, token),
|
||||
"attachment" -> AttachmentRoutes(backend, token),
|
||||
"attachments" -> AttachmentMultiRoutes(backend, token),
|
||||
"upload" -> UploadRoutes.secured(backend, config, token),
|
||||
"checkfile" -> CheckFileRoutes.secured(backend, token),
|
||||
"email/send" -> MailSendRoutes(backend, token),
|
||||
"email/settings" -> MailSettingsRoutes(backend, token),
|
||||
"email/sent" -> SentMailRoutes(backend, token),
|
||||
"share" -> ShareRoutes.manage(backend, token),
|
||||
"usertask/notifydueitems" -> NotifyDueItemsRoutes(config, backend, token),
|
||||
"usertask/scanmailbox" -> ScanMailboxRoutes(backend, token),
|
||||
"usertask/periodicquery" -> PeriodicQueryRoutes(config, backend, token),
|
||||
"calevent/check" -> CalEventCheckRoutes(),
|
||||
"fts" -> FullTextIndexRoutes.secured(config, backend, token),
|
||||
"folder" -> FolderRoutes(backend, token),
|
||||
"customfield" -> CustomFieldRoutes(backend, token),
|
||||
"clientSettings" -> ClientSettingsRoutes(backend, token),
|
||||
"notification" -> NotificationRoutes(config, backend, token),
|
||||
"querybookmark" -> BookmarkRoutes(backend, token)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
object RestAppImpl {
|
||||
@ -58,7 +167,14 @@ object RestAppImpl {
|
||||
backend <- BackendApp
|
||||
.create[F](store, javaEmil, ftsClient, pubSubT, notificationMod)
|
||||
|
||||
app = new RestAppImpl[F](cfg, backend, notificationMod, wsTopic, pubSubT)
|
||||
app = new RestAppImpl[F](
|
||||
cfg,
|
||||
backend,
|
||||
httpClient,
|
||||
notificationMod,
|
||||
wsTopic,
|
||||
pubSubT
|
||||
)
|
||||
} yield app
|
||||
}
|
||||
|
||||
|
@ -7,30 +7,21 @@
|
||||
package docspell.restserver
|
||||
|
||||
import scala.concurrent.duration._
|
||||
|
||||
import cats.effect._
|
||||
import cats.implicits._
|
||||
import fs2.Stream
|
||||
import fs2.concurrent.Topic
|
||||
|
||||
import docspell.backend.auth.{AuthToken, ShareToken}
|
||||
import docspell.backend.msg.Topics
|
||||
import docspell.common._
|
||||
import docspell.oidc.CodeFlowRoutes
|
||||
import docspell.pubsub.naive.NaivePubSub
|
||||
import docspell.restserver.auth.OpenId
|
||||
import docspell.restserver.http4s.{EnvMiddleware, InternalHeader}
|
||||
import docspell.restserver.routes._
|
||||
import docspell.restserver.webapp._
|
||||
import docspell.restserver.http4s.InternalHeader
|
||||
import docspell.restserver.ws.OutputEvent.KeepAlive
|
||||
import docspell.restserver.ws.{OutputEvent, WebSocketRoutes}
|
||||
import docspell.restserver.ws.OutputEvent
|
||||
import docspell.store.Store
|
||||
import docspell.store.records.RInternalSetting
|
||||
|
||||
import org.http4s._
|
||||
import org.http4s.blaze.client.BlazeClientBuilder
|
||||
import org.http4s.blaze.server.BlazeServerBuilder
|
||||
import org.http4s.client.Client
|
||||
import org.http4s.dsl.Http4sDsl
|
||||
import org.http4s.headers.Location
|
||||
import org.http4s.implicits._
|
||||
@ -51,7 +42,7 @@ object RestServer {
|
||||
server =
|
||||
Stream
|
||||
.resource(createApp(cfg, pools, wsTopic))
|
||||
.flatMap { case (restApp, pubSub, httpClient, setting) =>
|
||||
.flatMap { case (restApp, pubSub, setting) =>
|
||||
Stream(
|
||||
restApp.subscriptions,
|
||||
restApp.eventConsume(2),
|
||||
@ -59,7 +50,7 @@ object RestServer {
|
||||
.bindHttp(cfg.bind.port, cfg.bind.address)
|
||||
.withoutBanner
|
||||
.withHttpWebSocketApp(
|
||||
createHttpApp(cfg, setting, httpClient, pubSub, restApp, wsTopic)
|
||||
createHttpApp(setting, pubSub, restApp)
|
||||
)
|
||||
.serve
|
||||
.drain
|
||||
@ -76,7 +67,7 @@ object RestServer {
|
||||
wsTopic: Topic[F, OutputEvent]
|
||||
): Resource[
|
||||
F,
|
||||
(RestApp[F], NaivePubSub[F], Client[F], RInternalSetting)
|
||||
(RestApp[F], NaivePubSub[F], RInternalSetting)
|
||||
] =
|
||||
for {
|
||||
httpClient <- BlazeClientBuilder[F].resource
|
||||
@ -92,41 +83,22 @@ object RestServer {
|
||||
httpClient
|
||||
)(Topics.all.map(_.topic))
|
||||
restApp <- RestAppImpl.create[F](cfg, store, httpClient, pubSub, wsTopic)
|
||||
} yield (restApp, pubSub, httpClient, setting)
|
||||
} yield (restApp, pubSub, setting)
|
||||
|
||||
def createHttpApp[F[_]: Async](
|
||||
cfg: Config,
|
||||
internSettings: RInternalSetting,
|
||||
httpClient: Client[F],
|
||||
pubSub: NaivePubSub[F],
|
||||
restApp: RestApp[F],
|
||||
topic: Topic[F, OutputEvent]
|
||||
restApp: RestApp[F]
|
||||
)(
|
||||
wsB: WebSocketBuilder2[F]
|
||||
) = {
|
||||
val templates = TemplateRoutes[F](cfg, Templates[F])
|
||||
val httpApp = Router(
|
||||
val internal = Router(
|
||||
"/" -> redirectTo("/app"),
|
||||
"/internal" -> InternalHeader(internSettings.internalRouteKey) {
|
||||
internalRoutes(pubSub)
|
||||
},
|
||||
"/api/info" -> routes.InfoRoutes(),
|
||||
"/api/v1/open/" -> openRoutes(cfg, httpClient, restApp),
|
||||
"/api/v1/sec/" -> Authenticate(restApp.backend.login, cfg.auth) { token =>
|
||||
securedRoutes(cfg, restApp, wsB, topic, token)
|
||||
},
|
||||
"/api/v1/admin" -> AdminAuth(cfg.adminEndpoint) {
|
||||
adminRoutes(cfg, restApp)
|
||||
},
|
||||
"/api/v1/share" -> ShareAuth(restApp.backend.share, cfg.auth) { token =>
|
||||
shareRoutes(cfg, restApp, token)
|
||||
},
|
||||
"/api/doc" -> templates.doc,
|
||||
"/app/assets" -> EnvMiddleware(WebjarRoutes.appRoutes[F]),
|
||||
"/app" -> EnvMiddleware(templates.app),
|
||||
"/sw.js" -> EnvMiddleware(templates.serviceWorker),
|
||||
"/" -> redirectTo("/app")
|
||||
).orNotFound
|
||||
|
||||
}
|
||||
)
|
||||
val httpApp = (internal <+> restApp.routes(wsB)).orNotFound
|
||||
Logger.httpApp(logHeaders = false, logBody = false)(httpApp)
|
||||
}
|
||||
|
||||
@ -135,88 +107,6 @@ object RestServer {
|
||||
"pubsub" -> pubSub.receiveRoute
|
||||
)
|
||||
|
||||
def securedRoutes[F[_]: Async](
|
||||
cfg: Config,
|
||||
restApp: RestApp[F],
|
||||
wsB: WebSocketBuilder2[F],
|
||||
topic: Topic[F, OutputEvent],
|
||||
token: AuthToken
|
||||
): HttpRoutes[F] =
|
||||
Router(
|
||||
"ws" -> WebSocketRoutes(token, restApp.backend, topic, wsB),
|
||||
"auth" -> LoginRoutes.session(restApp.backend.login, cfg, token),
|
||||
"tag" -> TagRoutes(restApp.backend, token),
|
||||
"equipment" -> EquipmentRoutes(restApp.backend, token),
|
||||
"organization" -> OrganizationRoutes(restApp.backend, token),
|
||||
"person" -> PersonRoutes(restApp.backend, token),
|
||||
"source" -> SourceRoutes(restApp.backend, token),
|
||||
"user/otp" -> TotpRoutes(restApp.backend, cfg, token),
|
||||
"user" -> UserRoutes(restApp.backend, token),
|
||||
"collective" -> CollectiveRoutes(restApp.backend, token),
|
||||
"queue" -> JobQueueRoutes(restApp.backend, token),
|
||||
"item" -> ItemRoutes(cfg, restApp.backend, token),
|
||||
"items" -> ItemMultiRoutes(cfg, restApp.backend, token),
|
||||
"attachment" -> AttachmentRoutes(restApp.backend, token),
|
||||
"attachments" -> AttachmentMultiRoutes(restApp.backend, token),
|
||||
"upload" -> UploadRoutes.secured(restApp.backend, cfg, token),
|
||||
"checkfile" -> CheckFileRoutes.secured(restApp.backend, token),
|
||||
"email/send" -> MailSendRoutes(restApp.backend, token),
|
||||
"email/settings" -> MailSettingsRoutes(restApp.backend, token),
|
||||
"email/sent" -> SentMailRoutes(restApp.backend, token),
|
||||
"share" -> ShareRoutes.manage(restApp.backend, token),
|
||||
"usertask/notifydueitems" -> NotifyDueItemsRoutes(cfg, restApp.backend, token),
|
||||
"usertask/scanmailbox" -> ScanMailboxRoutes(restApp.backend, token),
|
||||
"usertask/periodicquery" -> PeriodicQueryRoutes(cfg, restApp.backend, token),
|
||||
"calevent/check" -> CalEventCheckRoutes(),
|
||||
"fts" -> FullTextIndexRoutes.secured(cfg, restApp.backend, token),
|
||||
"folder" -> FolderRoutes(restApp.backend, token),
|
||||
"customfield" -> CustomFieldRoutes(restApp.backend, token),
|
||||
"clientSettings" -> ClientSettingsRoutes(restApp.backend, token),
|
||||
"notification" -> NotificationRoutes(cfg, restApp.backend, token),
|
||||
"querybookmark" -> BookmarkRoutes(restApp.backend, token)
|
||||
)
|
||||
|
||||
def openRoutes[F[_]: Async](
|
||||
cfg: Config,
|
||||
client: Client[F],
|
||||
restApp: RestApp[F]
|
||||
): HttpRoutes[F] =
|
||||
Router(
|
||||
"auth/openid" -> CodeFlowRoutes(
|
||||
cfg.openIdEnabled,
|
||||
OpenId.handle[F](restApp.backend, cfg),
|
||||
OpenId.codeFlowConfig(cfg),
|
||||
client
|
||||
),
|
||||
"auth" -> LoginRoutes.login(restApp.backend.login, cfg),
|
||||
"signup" -> RegisterRoutes(restApp.backend, cfg),
|
||||
"upload" -> UploadRoutes.open(restApp.backend, cfg),
|
||||
"checkfile" -> CheckFileRoutes.open(restApp.backend),
|
||||
"integration" -> IntegrationEndpointRoutes.open(restApp.backend, cfg),
|
||||
"share" -> ShareRoutes.verify(restApp.backend, cfg)
|
||||
)
|
||||
|
||||
def adminRoutes[F[_]: Async](cfg: Config, restApp: RestApp[F]): HttpRoutes[F] =
|
||||
Router(
|
||||
"fts" -> FullTextIndexRoutes.admin(cfg, restApp.backend),
|
||||
"user/otp" -> TotpRoutes.admin(restApp.backend),
|
||||
"user" -> UserRoutes.admin(restApp.backend),
|
||||
"info" -> InfoRoutes.admin(cfg),
|
||||
"attachments" -> AttachmentRoutes.admin(restApp.backend)
|
||||
)
|
||||
|
||||
def shareRoutes[F[_]: Async](
|
||||
cfg: Config,
|
||||
restApp: RestApp[F],
|
||||
token: ShareToken
|
||||
): HttpRoutes[F] =
|
||||
Router(
|
||||
"search" -> ShareSearchRoutes(restApp.backend, cfg, token),
|
||||
"attachment" -> ShareAttachmentRoutes(restApp.backend, token),
|
||||
"item" -> ShareItemRoutes(restApp.backend, token),
|
||||
"clientSettings" -> ClientSettingsRoutes.share(restApp.backend, token)
|
||||
)
|
||||
|
||||
def redirectTo[F[_]: Async](path: String): HttpRoutes[F] = {
|
||||
val dsl = new Http4sDsl[F] {}
|
||||
import dsl._
|
||||
|
Loading…
x
Reference in New Issue
Block a user