purr

password generation and secret sharing
Log | Files | Refs | README | LICENSE

Configuration.hs (2932B)


      1 module Core.Configuration ( adminEmail, appPort 
      2                           , confLinkLength, dataPath, dbPath
      3                           , encKey, getRuntimeEnvironment 
      4                           , keyFileInit, init) where 
      5 
      6 import qualified Data.ByteString               as B
      7 
      8 import           Control.Monad                 (mapM)
      9 import           Configuration.Dotenv
     10 import           Core.Types
     11 import           Crypto.Saltine.Core.SecretBox (newKey)
     12 import           Crypto.Saltine.Class          (encode)
     13 import           Prelude                hiding (init)
     14 import           System.Directory              (doesFileExist)
     15 import           System.Environment            (getEnv, lookupEnv)
     16 
     17 -- Load environment variables from dotenv file if required
     18 init :: IO ()
     19 init = do
     20   reqEnvLookup <- getRequiredEnv
     21   if (Nothing `elem` reqEnvLookup)
     22     then checkEnvFile requiredEnvVars
     23     else pure ()
     24   where
     25     getRequiredEnv :: IO [Maybe String]
     26     getRequiredEnv = mapM (\s -> lookupEnv s) requiredEnvVars
     27 
     28     checkEnvFile :: [String] -> IO ()
     29     checkEnvFile requiredEnv = do
     30       dotEnvExists <- doesFileExist "./.env"
     31       if dotEnvExists
     32         then do
     33           loadFile defaultConfig
     34           fromEnvFile <- getRequiredEnv
     35           if (Nothing `elem` fromEnvFile)
     36              then error $ missingEnvMsg requiredEnv
     37              else pure ()
     38         else error $ "Cannot find .env file in application directory.\n"
     39           ++ missingEnvMsg requiredEnv
     40 
     41     missingEnvMsg :: [String] -> String
     42     missingEnvMsg required = 
     43       "Missing required environment variable(s).\n"
     44       ++ "All required environment variables:\n" 
     45       ++  unlines required
     46 
     47 -- Check if an encryption key exists on the filesystem and create one if not
     48 keyFileInit :: IO ()
     49 keyFileInit = do
     50   dataPathStr <- dataPath
     51   keyExists <- doesFileExist $ dataPathStr ++ "data/encryptionKey"
     52   case keyExists of
     53     True -> putStrLn "Using existing key"
     54     False -> do
     55       key <- newKey
     56       B.writeFile (dataPathStr ++ "data/encryptionKey") (encode key)
     57       putStrLn "Creating new encryption key; any pre-existing DB entries will not decrypt"
     58 
     59 -- Read and return the encryption key on the filesystem as a ByteString
     60 encKey :: IO B.ByteString
     61 encKey = do
     62   dataPathStr <- dataPath 
     63   B.readFile (dataPathStr ++ "data/encryptionKey")
     64 
     65 -- Helper functions for getting the value of environment variables
     66 adminEmail :: IO String
     67 adminEmail = getEnv "ADMINEMAIL"
     68 
     69 getRuntimeEnvironment :: IO String
     70 getRuntimeEnvironment = getEnv "ENVIRONMENT"
     71 
     72 appPort :: IO String
     73 appPort = getEnv "APPLICATIONPORT"
     74 
     75 dataPath :: IO String
     76 dataPath = getEnv "DATADIR"
     77 
     78 dbPath :: String
     79 dbPath = "data/Purr.sqlite"
     80 
     81 confLinkLength :: IO String
     82 confLinkLength = getEnv "LINKLENGTH"
     83 
     84 requiredEnvVars :: [String]
     85 requiredEnvVars = [ "ADMINEMAIL", "APPLICATIONHOST", "APPLICATIONPORT"
     86                   , "DATADIR", "ENVIRONMENT", "LINKLENGTH"
     87                   ]