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