/src/DB.hs

http://github.com/biilmann/eventsource-broker · Haskell · 110 lines · 72 code · 31 blank · 7 comment · 2 complexity · 9fca07ac67f9a21d7a2d41ad39a65730 MD5 · raw file

  1. {-# LANGUAGE OverloadedStrings #-}
  2. module DB
  3. (
  4. DB,
  5. Document,
  6. Failure,
  7. withDB,
  8. openDB,
  9. closeDB,
  10. returnModel,
  11. run,
  12. repsert,
  13. modify,
  14. delete,
  15. select,
  16. findOne,
  17. count,
  18. lookup,
  19. at,
  20. (=:)
  21. ) where
  22. import Prelude hiding (lookup)
  23. import Control.Exception (bracket)
  24. import System.Posix.Env(getEnvDefault)
  25. import Data.String.Utils(split)
  26. import Text.URI(URI(..), parseURI)
  27. import Data.UString (UString, u)
  28. import Data.Maybe (fromJust)
  29. import Database.MongoDB (
  30. Action, Pipe, Database, Document, Failure, runIOE, connect, auth, access, master,
  31. readHostPort, close, repsert, modify, delete, (=:), select,
  32. findOne, count, lookup, at
  33. )
  34. -- |A connection to a mongoDB
  35. data DB = DB { mongoPipe :: Pipe, mongoDB :: Database }
  36. -- |Credentials for authenticating with a mongoDB
  37. data Credentials = NoAuth
  38. | Credentials { crUser :: UString, crPass :: UString }
  39. -- |Opens a connection to the database speficied in the MONGO_URL
  40. -- environment variable
  41. openDB :: IO DB
  42. openDB = do
  43. mongoURI <- getEnvDefault "MONGO_URL" "mongodb://127.0.0.1:27017/eventsourcehq"
  44. openConn mongoURI
  45. -- |Close the connection to the database
  46. closeDB :: DB -> IO ()
  47. closeDB = do
  48. closeConn
  49. -- |Bracket around opening and closing the DB connection
  50. withDB :: (DB -> IO ()) -> IO ()
  51. withDB f = do
  52. mongoURI <- getEnvDefault "MONGO_URL" "mongodb://127.0.0.1:27017/eventsourcehq"
  53. bracket (openConn mongoURI) closeConn f
  54. returnModel :: (Document -> a) -> Either Failure (Maybe Document) -> Either Failure (Maybe a)
  55. returnModel constructor (Right result) = return (fmap constructor result)
  56. returnModel _ (Left failure) = Left failure
  57. openConn :: String -> IO DB
  58. openConn mongoURI = do
  59. let uri = fromJust $ parseURI mongoURI
  60. let creds = case fmap (split ":") (uriUserInfo uri) of
  61. Nothing -> NoAuth
  62. Just [us, pw] -> Credentials (u us) (u pw)
  63. let hostname = fromJust $ uriRegName uri
  64. let port = case uriPort uri of
  65. Just p -> show p
  66. Nothing -> "27017"
  67. let dbName = u $ drop 1 (uriPath uri)
  68. pipe <- runIOE $ connect (readHostPort (hostname ++ ":" ++ port))
  69. let db = DB pipe dbName
  70. authenticate db creds
  71. return db
  72. authenticate :: DB -> Credentials -> IO (Either Failure Bool)
  73. authenticate db NoAuth = return (Right True)
  74. authenticate db (Credentials user pass) = run db (auth user pass)
  75. run :: DB -> Action IO a -> IO (Either Failure a)
  76. run (DB pipe db) action =
  77. access pipe master db action
  78. closeConn :: DB -> IO ()
  79. closeConn db = close (mongoPipe db)