mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-04-04 10:29:34 +00:00
Merge pull request #258 from eikek/base-url-confusion
Base url confusion
This commit is contained in:
commit
3b5a29b713
modules
common/src/main/scala/docspell/common
restserver/src/main/scala/docspell/restserver
webapp/src/main/elm/App
@ -83,6 +83,9 @@ case class LenientUri(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def isLocal: Boolean =
|
||||||
|
host.exists(_.equalsIgnoreCase("localhost"))
|
||||||
|
|
||||||
def asString: String = {
|
def asString: String = {
|
||||||
val schemePart = scheme.toList.mkString(":")
|
val schemePart = scheme.toList.mkString(":")
|
||||||
val authPart = authority.map(a => s"//$a").getOrElse("")
|
val authPart = authority.map(a => s"//$a").getOrElse("")
|
||||||
|
@ -11,8 +11,8 @@ case class CookieData(auth: AuthToken) {
|
|||||||
def accountId: AccountId = auth.account
|
def accountId: AccountId = auth.account
|
||||||
def asString: String = auth.asString
|
def asString: String = auth.asString
|
||||||
|
|
||||||
def asCookie(cfg: Config): ResponseCookie = {
|
def asCookie(cfg: Config, host: Option[String]): ResponseCookie = {
|
||||||
val domain = cfg.baseUrl.host
|
val domain = CookieData.getDomain(cfg, host)
|
||||||
val sec = cfg.baseUrl.scheme.exists(_.endsWith("s"))
|
val sec = cfg.baseUrl.scheme.exists(_.endsWith("s"))
|
||||||
val path = cfg.baseUrl.path / "api" / "v1" / "sec"
|
val path = cfg.baseUrl.path / "api" / "v1" / "sec"
|
||||||
ResponseCookie(
|
ResponseCookie(
|
||||||
@ -29,6 +29,10 @@ object CookieData {
|
|||||||
val cookieName = "docspell_auth"
|
val cookieName = "docspell_auth"
|
||||||
val headerName = "X-Docspell-Auth"
|
val headerName = "X-Docspell-Auth"
|
||||||
|
|
||||||
|
private def getDomain(cfg: Config, remote: Option[String]): Option[String] =
|
||||||
|
if (cfg.baseUrl.isLocal) remote.orElse(cfg.baseUrl.host)
|
||||||
|
else cfg.baseUrl.host
|
||||||
|
|
||||||
def authenticator[F[_]](r: Request[F]): Either[String, String] =
|
def authenticator[F[_]](r: Request[F]): Either[String, String] =
|
||||||
fromCookie(r).orElse(fromHeader(r))
|
fromCookie(r).orElse(fromHeader(r))
|
||||||
|
|
||||||
@ -47,11 +51,11 @@ object CookieData {
|
|||||||
.map(_.value)
|
.map(_.value)
|
||||||
.toRight("Couldn't find an authenticator")
|
.toRight("Couldn't find an authenticator")
|
||||||
|
|
||||||
def deleteCookie(cfg: Config): ResponseCookie =
|
def deleteCookie(cfg: Config, remoteHost: Option[String]): ResponseCookie =
|
||||||
ResponseCookie(
|
ResponseCookie(
|
||||||
cookieName,
|
cookieName,
|
||||||
"",
|
"",
|
||||||
domain = cfg.baseUrl.host,
|
domain = getDomain(cfg, remoteHost),
|
||||||
path = Some(cfg.baseUrl.path / "api" / "v1" / "sec").map(_.asString),
|
path = Some(cfg.baseUrl.path / "api" / "v1" / "sec").map(_.asString),
|
||||||
httpOnly = true,
|
httpOnly = true,
|
||||||
secure = cfg.baseUrl.scheme.exists(_.endsWith("s")),
|
secure = cfg.baseUrl.scheme.exists(_.endsWith("s")),
|
||||||
|
@ -21,9 +21,10 @@ object LoginRoutes {
|
|||||||
|
|
||||||
HttpRoutes.of[F] { case req @ POST -> Root / "login" =>
|
HttpRoutes.of[F] { case req @ POST -> Root / "login" =>
|
||||||
for {
|
for {
|
||||||
up <- req.as[UserPass]
|
up <- req.as[UserPass]
|
||||||
res <- S.loginUserPass(cfg.auth)(Login.UserPass(up.account, up.password))
|
res <- S.loginUserPass(cfg.auth)(Login.UserPass(up.account, up.password))
|
||||||
resp <- makeResponse(dsl, cfg, res, up.account)
|
remote = req.from.map(_.getHostName())
|
||||||
|
resp <- makeResponse(dsl, cfg, remote, res, up.account)
|
||||||
} yield resp
|
} yield resp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -36,16 +37,17 @@ object LoginRoutes {
|
|||||||
case req @ POST -> Root / "session" =>
|
case req @ POST -> Root / "session" =>
|
||||||
Authenticate
|
Authenticate
|
||||||
.authenticateRequest(S.loginSession(cfg.auth))(req)
|
.authenticateRequest(S.loginSession(cfg.auth))(req)
|
||||||
.flatMap(res => makeResponse(dsl, cfg, res, ""))
|
.flatMap(res => makeResponse(dsl, cfg, req.from.map(_.getHostName), res, ""))
|
||||||
|
|
||||||
case POST -> Root / "logout" =>
|
case req @ POST -> Root / "logout" =>
|
||||||
Ok().map(_.addCookie(CookieData.deleteCookie(cfg)))
|
Ok().map(_.addCookie(CookieData.deleteCookie(cfg, req.from.map(_.getHostName))))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def makeResponse[F[_]: Effect](
|
def makeResponse[F[_]: Effect](
|
||||||
dsl: Http4sDsl[F],
|
dsl: Http4sDsl[F],
|
||||||
cfg: Config,
|
cfg: Config,
|
||||||
|
remoteHost: Option[String],
|
||||||
res: Login.Result,
|
res: Login.Result,
|
||||||
account: String
|
account: String
|
||||||
): F[Response[F]] = {
|
): F[Response[F]] = {
|
||||||
@ -63,7 +65,7 @@ object LoginRoutes {
|
|||||||
Some(cd.asString),
|
Some(cd.asString),
|
||||||
cfg.auth.sessionValid.millis
|
cfg.auth.sessionValid.millis
|
||||||
)
|
)
|
||||||
).map(_.addCookie(cd.asCookie(cfg)))
|
).map(_.addCookie(cd.asCookie(cfg, remoteHost)))
|
||||||
} yield resp
|
} yield resp
|
||||||
case _ =>
|
case _ =>
|
||||||
Ok(AuthResult("", account, false, "Login failed.", None, 0L))
|
Ok(AuthResult("", account, false, "Login failed.", None, 0L))
|
||||||
|
@ -11,7 +11,7 @@ import yamusca.imports._
|
|||||||
|
|
||||||
case class Flags(
|
case class Flags(
|
||||||
appName: String,
|
appName: String,
|
||||||
baseUrl: LenientUri,
|
baseUrl: String,
|
||||||
signupMode: SignupConfig.Mode,
|
signupMode: SignupConfig.Mode,
|
||||||
docspellAssetPath: String,
|
docspellAssetPath: String,
|
||||||
integrationEnabled: Boolean,
|
integrationEnabled: Boolean,
|
||||||
@ -25,7 +25,7 @@ object Flags {
|
|||||||
def apply(cfg: Config): Flags =
|
def apply(cfg: Config): Flags =
|
||||||
Flags(
|
Flags(
|
||||||
cfg.appName,
|
cfg.appName,
|
||||||
cfg.baseUrl,
|
getBaseUrl(cfg),
|
||||||
cfg.backend.signup.mode,
|
cfg.backend.signup.mode,
|
||||||
s"/app/assets/docspell-webapp/${BuildInfo.version}",
|
s"/app/assets/docspell-webapp/${BuildInfo.version}",
|
||||||
cfg.integrationEndpoint.enabled,
|
cfg.integrationEndpoint.enabled,
|
||||||
@ -35,6 +35,10 @@ object Flags {
|
|||||||
cfg.showClassificationSettings
|
cfg.showClassificationSettings
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private def getBaseUrl(cfg: Config): String =
|
||||||
|
if (cfg.baseUrl.isLocal) cfg.baseUrl.path.asString
|
||||||
|
else cfg.baseUrl.asString
|
||||||
|
|
||||||
implicit val jsonEncoder: Encoder[Flags] =
|
implicit val jsonEncoder: Encoder[Flags] =
|
||||||
deriveEncoder[Flags]
|
deriveEncoder[Flags]
|
||||||
|
|
||||||
|
@ -49,8 +49,11 @@ type alias Model =
|
|||||||
|
|
||||||
|
|
||||||
init : Key -> Url -> Flags -> UiSettings -> ( Model, Cmd Msg )
|
init : Key -> Url -> Flags -> UiSettings -> ( Model, Cmd Msg )
|
||||||
init key url flags settings =
|
init key url flags_ settings =
|
||||||
let
|
let
|
||||||
|
flags =
|
||||||
|
initBaseUrl url flags_
|
||||||
|
|
||||||
page =
|
page =
|
||||||
Page.fromUrl url
|
Page.fromUrl url
|
||||||
|> Maybe.withDefault (defaultPage flags)
|
|> Maybe.withDefault (defaultPage flags)
|
||||||
@ -90,6 +93,30 @@ init key url flags settings =
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
initBaseUrl : Url -> Flags -> Flags
|
||||||
|
initBaseUrl url flags_ =
|
||||||
|
let
|
||||||
|
cfg =
|
||||||
|
flags_.config
|
||||||
|
|
||||||
|
baseUrl =
|
||||||
|
if cfg.baseUrl == "" then
|
||||||
|
Url.toString
|
||||||
|
{ url
|
||||||
|
| path = ""
|
||||||
|
, query = Nothing
|
||||||
|
, fragment = Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
cfg.baseUrl
|
||||||
|
|
||||||
|
cfgNew =
|
||||||
|
{ cfg | baseUrl = baseUrl }
|
||||||
|
in
|
||||||
|
{ flags_ | config = cfgNew }
|
||||||
|
|
||||||
|
|
||||||
type Msg
|
type Msg
|
||||||
= NavRequest UrlRequest
|
= NavRequest UrlRequest
|
||||||
| NavChange Url
|
| NavChange Url
|
||||||
|
Loading…
x
Reference in New Issue
Block a user