Files
registry/src/Settings.hs
Lucy C 35500cfc02 Feat/local packages (#133)
* enable packages to be marked as unavailable locally

* change isLocal column to hidden

* add option to deprecate a service version based on a min os version
2023-04-11 19:08:53 -06:00

144 lines
7.0 KiB
Haskell

{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE MultiParamTypeClasses #-}
-- | Settings are centralized, as much as possible, into this file. This
-- includes database connection settings, static file locations, etc.
-- In addition, you can configure a number of different aspects of Yesod
-- by overriding methods in the Yesod typeclass. That instance is
-- declared in the Foundation.hs file.
module Settings where
import Paths_start9_registry ( version )
import Startlude ( ($)
, (.)
, (<$>)
, Applicative(liftA2)
, Bool(..)
, ByteString
, ConvertText(toS)
, FilePath
, IsString(fromString)
, Monad(return)
, Monoid(mempty)
, Text
, Word16
, either
, id
, panic
)
import qualified Control.Exception as Exception
import Data.Aeson ( (.!=)
, (.:)
, (.:?)
, FromJSON(parseJSON)
, Result(Error, Success)
, Value(String)
, fromJSON
, withObject
)
import Data.Aeson.Types ( parseMaybe )
import Data.FileEmbed ( embedFile )
import Data.Maybe ( fromJust )
import Data.Version ( showVersion )
import Data.Yaml ( decodeEither' )
import Data.Yaml.Config ( applyEnvValue )
import Database.Persist.Postgresql ( PostgresConf )
import Network.Wai.Handler.Warp ( HostPreference )
import System.FilePath ( (</>)
, takeDirectory
)
import Yesod.Default.Config2 ( configSettingsYml )
import Control.Monad.Reader.Has ( Has(extract, update) )
import Lib.PkgRepository ( EosRepo(EosRepo, eosRepoFileRoot)
, PkgRepo(..)
)
import Lib.Types.Emver ( Version )
import Orphans.Emver ( )
-- | Runtime settings to configure this application. These settings can be
-- loaded from various sources: defaults, environment variables, config files,
-- theoretically even a database.
type AppPort = Word16
data AppSettings = AppSettings
{ appDatabaseConf :: !PostgresConf
, appDetailedRequestLogging :: !Bool
-- ^ Use detailed request logging system
, appHost :: !HostPreference
-- ^ Host/interface the server should bind to.
, appIpFromHeader :: !Bool
-- ^ Get the IP address from the header when logging. Useful when sitting
, appPort :: !AppPort
-- ^ Port to listen on
-- behind a reverse proxy.
, appShouldLogAll :: !Bool
-- ^ Should all log messages be displayed?
, errorLogRoot :: !FilePath
, marketplaceName :: !Text
, maxOsVersion :: !Version
, minOsVersion :: !Version
, registryHostname :: !Text
, registryVersion :: !Version
, resourcesDir :: !FilePath
, needsMigration :: !Bool
, sslAuto :: !Bool
, sslCertLocation :: !FilePath
, sslCsrLocation :: !FilePath
, sslKeyLocation :: !FilePath
, sslPath :: !FilePath
, staticBinDir :: !FilePath
, torPort :: !AppPort
}
instance Has PkgRepo AppSettings where
extract = liftA2 PkgRepo ((</> "apps") . resourcesDir) staticBinDir
update f r =
let repo = f $ extract r in r { resourcesDir = pkgRepoFileRoot repo, staticBinDir = pkgRepoAppMgrBin repo }
instance Has EosRepo AppSettings where
extract = EosRepo . (</> "eos") . resourcesDir
update f ctx =
let repo = f $ extract ctx
settings = ctx { resourcesDir = takeDirectory (eosRepoFileRoot repo) }
in settings
instance FromJSON AppSettings where
parseJSON = withObject "AppSettings" $ \o -> do
appDatabaseConf <- o .: "database"
appDetailedRequestLogging <- o .:? "detailed-logging" .!= True
appHost <- fromString <$> o .: "host"
appIpFromHeader <- o .: "ip-from-header"
appPort <- o .: "port"
appShouldLogAll <- o .:? "should-log-all" .!= False
errorLogRoot <- o .: "error-log-root"
marketplaceName <- o .: "marketplace-name"
maxOsVersion <- o .: "max-eos-version"
minOsVersion <- o .: "min-eos-version"
registryHostname <- o .: "registry-hostname"
resourcesDir <- o .: "resources-path"
needsMigration <- o .: "run-migration"
sslAuto <- o .: "ssl-auto"
sslPath <- o .: "ssl-path"
staticBinDir <- o .: "static-bin-dir"
torPort <- o .: "tor-port"
let sslKeyLocation = sslPath </> "key.pem"
let sslCsrLocation = sslPath </> "certificate.csr"
let sslCertLocation = sslPath </> "certificate.pem"
let registryVersion = fromJust . parseMaybe parseJSON . String . toS . showVersion $ version
return AppSettings { .. }
-- | Raw bytes at compile time of @config/settings.yml@
configSettingsYmlBS :: ByteString
configSettingsYmlBS = $(embedFile configSettingsYml)
-- | @config/settings.yml@, parsed to a @Value@.
configSettingsYmlValue :: Value
configSettingsYmlValue = either Exception.throw id $ decodeEither' configSettingsYmlBS
-- | A version of @AppSettings@ parsed at compile time from @config/settings.yml@.
compileTimeAppSettings :: AppSettings
compileTimeAppSettings = case fromJSON $ applyEnvValue False mempty configSettingsYmlValue of
Error e -> panic $ toS e
Success settings -> settings