packages feed

breve-0.5.0.0: src/Breve/Settings.hs

{-|
This module defines the Breve configuration
parser and application settings.
-}
module Breve.Settings
( AppSettings(..)
, createEmptyIfMissing
, settings
) where

import Control.Monad                  (when)
import System.Environment             (lookupEnv)
import System.Directory               (doesFileExist, getXdgDirectory, XdgDirectory(..))
import Data.Text                      (Text, pack)
import Data.Configurator
import Data.Monoid

import Network.Wai.Handler.WarpTLS    (TLSSettings (..), tlsSettingsChain)
import Network.TLS                    (Version (..))
import Network.TLS.Extra              (ciphersuite_strong)

-- | Breve settings
data AppSettings = AppSettings
  { bindHost    :: Text         -- ^ the host to bind to
  , bindPort    :: Int          -- ^ the port to bind to
  , bindUrl     :: Text         -- ^ the url used to reach breve
  , urlTable    :: FilePath     -- ^ path where to save the url table
  , tlsSettings :: TLSSettings  -- ^ warp TLS settings
  }

-- | Initialises a file if it doesn't exist
createEmptyIfMissing :: FilePath -> IO ()
createEmptyIfMissing file = do
  exists <- doesFileExist file
  when (not exists) (writeFile file "")

-- | Configuration file parser
settings :: Maybe FilePath -> IO AppSettings
settings path = do
  configPath <- case path of
    Just path -> return path
    Nothing   -> getXdgDirectory XdgConfig "breve"

  urlsPath  <- getXdgDirectory XdgData "breve"

  config  <- load [Required configPath]
  host    <- lookupDefault "localhost"                config "hostname"
  portnum <- lookupDefault 3000                       config "port"
  urls    <- lookupDefault urlsPath                   config "urltable"
  cert    <- lookupDefault "/usr/share/tls/breve.crt" config "tls.cert"
  key     <- lookupDefault "/usr/share/tls/breve.key" config "tls.key"
  chain   <- lookupDefault []                         config "tls.chain"

  let
    port = if portnum == 443 then "" else ":" <> pack (show portnum)
    url  = "https://" <> host <> port <> "/"

  baseURL <- lookupDefault url config "baseurl"

  createEmptyIfMissing urls

  return AppSettings
    { bindHost = host
    , bindPort = portnum
    , bindUrl  = baseURL
    , urlTable = urls
    , tlsSettings = (tlsSettingsChain cert chain key)
      { tlsAllowedVersions = [TLS12, TLS11]
      , tlsCiphers = ciphersuite_strong
      }
    }