about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--shell.nix1
-rw-r--r--src/App.hs24
-rw-r--r--src/Main.hs8
-rw-r--r--src/Types.hs12
5 files changed, 33 insertions, 13 deletions
diff --git a/.gitignore b/.gitignore
index ebea556fe5b6..d4d62d436b26 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+.envrc
 *.db
 *.sqlite3
 !populate.sqlite3
diff --git a/shell.nix b/shell.nix
index 8c948e9cb55d..bd31438b1957 100644
--- a/shell.nix
+++ b/shell.nix
@@ -10,6 +10,7 @@ in pkgs.mkShell {
       hpkgs.warp
       hpkgs.cryptonite
       hpkgs.uuid
+      hpkgs.envy
     ]))
   ];
 }
diff --git a/src/App.hs b/src/App.hs
index 708dd896fab2..7536e3c771e1 100644
--- a/src/App.hs
+++ b/src/App.hs
@@ -37,15 +37,15 @@ err429 = ServerError
   , errHeaders = []
   }
 
-server :: FilePath -> Server API
-server dbFile = createAccount
-           :<|> deleteAccount
-           :<|> listAccounts
-           :<|> createTrip
-           :<|> deleteTrip
-           :<|> listTrips
-           :<|> login
-           :<|> logout
+server :: T.Config -> Server API
+server T.Config{..} = createAccount
+                 :<|> deleteAccount
+                 :<|> listAccounts
+                 :<|> createTrip
+                 :<|> deleteTrip
+                 :<|> listTrips
+                 :<|> login
+                 :<|> logout
   where
     -- Admit Admins + whatever the predicate `p` passes.
     adminsAnd cookie p = Auth.assert dbFile cookie (\acct@T.Account{..} -> accountRole == T.Admin || p acct)
@@ -124,6 +124,6 @@ server dbFile = createAccount
           liftIO $ Sessions.delete dbFile uuid
           pure $ addHeader Auth.emptyCookie NoContent
 
-run :: FilePath -> IO ()
-run dbFile =
-  Warp.run 3000 (serve (Proxy @ API) $ server dbFile)
+run :: T.Config -> IO ()
+run config =
+  Warp.run 3000 (serve (Proxy @ API) $ server config)
diff --git a/src/Main.hs b/src/Main.hs
index de40b3225e4a..9df4232066bb 100644
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -1,7 +1,13 @@
+--------------------------------------------------------------------------------
 module Main where
 --------------------------------------------------------------------------------
 import qualified App
+import qualified System.Envy as Envy
 --------------------------------------------------------------------------------
 
 main :: IO ()
-main = App.run "../db.sqlite3"
+main = do
+  mEnv <- Envy.decodeEnv
+  case mEnv of
+    Left err -> putStrLn err
+    Right env -> App.run env
diff --git a/src/Types.hs b/src/Types.hs
index eed9bf8c1696..135c50f17f4a 100644
--- a/src/Types.hs
+++ b/src/Types.hs
@@ -16,6 +16,7 @@ import Database.SQLite.Simple.ToField
 import GHC.Generics
 import Web.Cookie
 import Servant.API
+import System.Envy (FromEnv, fromEnv, env)
 import Crypto.Random.Types (MonadRandom)
 
 import qualified Crypto.KDF.BCrypt as BC
@@ -26,6 +27,17 @@ import qualified Data.Text.Encoding as TE
 import qualified Data.UUID as UUID
 --------------------------------------------------------------------------------
 
+-- | Top-level application configuration.
+data Config = Config
+  { mailgunAPIKey :: Text
+  , dbFile :: FilePath
+  } deriving (Eq, Show)
+
+instance FromEnv Config where
+  fromEnv _ =
+    Config <$> env "MAILGUN_API_KEY"
+           <*> env "DB_FILE"
+
 -- TODO(wpcarro): Properly handle NULL for columns like profilePicture.
 forNewtype :: (Typeable b) => (Text -> b) -> FieldParser b
 forNewtype wrapper field =