From 731efa00aaacb06ec97480760b9d71becf133974 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Hamal=20Dvo=C5=99=C3=A1k?= <mordae@anilinux.org>
Date: Sun, 27 Sep 2020 16:57:56 +0200
Subject: [PATCH] Extend configuration file format
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Jan Hamal Dvořák <mordae@anilinux.org>
---
 lib/Hikaru/Config.hs | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)

diff --git a/lib/Hikaru/Config.hs b/lib/Hikaru/Config.hs
index fb297e6..a26da53 100644
--- a/lib/Hikaru/Config.hs
+++ b/lib/Hikaru/Config.hs
@@ -30,14 +30,14 @@ module Hikaru.Config
   , generateSecret
   )
 where
-  import Relude hiding (lines)
+  import Relude hiding (drop, lines, isPrefixOf, length)
 
   import qualified Data.Map as Map
 
   import Crypto.Random.Entropy
   import Data.ByteArray.Encoding
-  import Data.List (lines, span)
   import Data.String.Conversions
+  import Data.Text hiding (map)
   import System.Environment
 
 
@@ -68,11 +68,24 @@ where
   -- let cfg = env <> def
   -- @
   --
+  -- Configuration file format is approximately this:
+  --
+  -- @
+  -- # How many seconds before forms need to be reloaded?
+  -- CSRF_VALIDITY = 3600
+  --
+  -- # Secret key to protect against CSRF. Don't tell anyone!
+  -- CSRF_SECRET   = Ain9eec8aighoiri
+  -- @
+  --
   configFromFile :: (MonadIO m) => FilePath -> m Config
-  configFromFile path = Map.fromList <$> map parse <$> lines <$> readFile path
+  configFromFile path = Map.fromList <$> parseFile <$> readFileText path
     where
-      parse       = conv . span (/= '=')
-      conv (k, v) = (cs k, cs $ drop 1 v)
+      parseFile   = mapMaybe parseLine . lines
+      parseLine   = fmap tidy . fmap parseKV . reject . strip
+      parseKV     = fmap (drop 1) . span (/= '=')
+      reject      = guarded (not . isPrefixOf "#") <=< guarded ("" /=)
+      tidy (k, v) = (strip k, strip v)
 
 
   -- |
@@ -84,7 +97,6 @@ where
   configDefault :: (MonadIO m) => m Config
   configDefault = do
     secret <- generateSecret 16
-
     return $ Map.fromList [ ("CSRF_SECRET",   secret)
                           , ("CSRF_VALIDITY", "86400")
                           ]
-- 
GitLab