87 lines
2.8 KiB
Haskell

module Core.Configuration ( adminEmail, appPort
, confLinkLength, dataPath, dbPath
, encKey, getRuntimeEnvironment
, keyFileInit, main) where
import qualified Data.ByteString as B
import Control.Monad (mapM)
import Core.Types
import Crypto.Saltine.Core.SecretBox (newKey)
import Crypto.Saltine.Class (encode)
import Configuration.Dotenv
import System.Directory (doesFileExist)
import System.Environment (getEnv, lookupEnv)
-- Load environment variables from dotenv file if required
main :: IO ()
main = do
reqEnvLookup <- getRequiredEnv
if (Nothing `elem` reqEnvLookup)
then checkEnvFile requiredEnvVars
else pure ()
where
getRequiredEnv :: IO [Maybe String]
getRequiredEnv = mapM (\s -> lookupEnv s) requiredEnvVars
checkEnvFile :: [String] -> IO ()
checkEnvFile requiredEnv = do
dotEnvExists <- doesFileExist "./.env"
if dotEnvExists
then do
loadFile defaultConfig
fromEnvFile <- getRequiredEnv
if (Nothing `elem` fromEnvFile)
then error $ missingEnvMsg requiredEnv
else pure ()
else error $ "Cannot find .env file in application directory.\n"
++ missingEnvMsg requiredEnv
missingEnvMsg :: [String] -> String
missingEnvMsg required =
"Missing required environment variable(s).\n"
++ "All required environment variables:\n"
++ unlines required
-- Check if an encryption key exists on the filesystem and create one if not
keyFileInit :: IO ()
keyFileInit = do
dataPathStr <- dataPath
keyExists <- doesFileExist $ dataPathStr ++ "data/encryptionKey"
case keyExists of
True -> putStrLn "Using existing key"
False -> do
key <- newKey
B.writeFile (dataPathStr ++ "data/encryptionKey") (encode key)
putStrLn "Creating new encryption key; any pre-existing DB entries will not decrypt"
-- Read and return the encryption key on the filesystem as a ByteString
encKey :: IO B.ByteString
encKey = do
dataPathStr <- dataPath
B.readFile (dataPathStr ++ "data/encryptionKey")
-- Helper functions for getting the value of environment variables
adminEmail :: IO String
adminEmail = getEnv "ADMINEMAIL"
getRuntimeEnvironment :: IO String
getRuntimeEnvironment = getEnv "ENVIRONMENT"
appPort :: IO String
appPort = getEnv "APPLICATIONPORT"
dataPath :: IO String
dataPath = getEnv "DATADIR"
dbPath :: String
dbPath = "data/Purr.sqlite"
confLinkLength :: IO String
confLinkLength = getEnv "LINKLENGTH"
requiredEnvVars :: [String]
requiredEnvVars = [ "ADMINEMAIL", "APPLICATIONHOST", "APPLICATIONPORT"
, "DATADIR", "ENVIRONMENT", "LINKLENGTH"
]