Is connecting using MongoDB over SSL possible?
chrissound opened this issue · 2 comments
This functionality seems to be supported with MongoDB using https://hackage.haskell.org/package/mongoDB-2.3.0.1/docs/Database-MongoDB-Transport-Tls.html#v:connect
I'm testing using the following:
let mongoConfig = MongoConf "test" "cluster0-shard-00-00-gv0qj.mongodb.net" (PortNumber 27017) (Just $ MongoAuth "*" "*") UnconfirmedWrites 1 1 2000 Nothing
withConnection mongoConfig $ \pool -> runMongoDBPool master actions pool
Which produces an error of:
*** Exception: Data.Binary.Get.runGet at position 0: not enough bytes
CallStack (from HasCallStack):
error, called at libraries/binary/src/Data/Binary/Get.hs:351:5 in binary-0.8.5.1:Data.Binary.Get
I've cloned down the repo and exported some constructors:
diff --git a/persistent-mongoDB/Database/Persist/MongoDB.hs b/persistent-mongoDB/Database/Persist/MongoDB.hs
index 0d337492..af3e15bf 100644
--- a/persistent-mongoDB/Database/Persist/MongoDB.hs
+++ b/persistent-mongoDB/Database/Persist/MongoDB.hs
@@ -74,8 +74,8 @@ module Database.Persist.MongoDB
, createMongoDBPool
, runMongoDBPool
, runMongoDBPoolDef
- , ConnectionPool
- , Connection
+ , ConnectionPool(..)
+ , Connection(..)
, MongoAuth (..)
-- * Connection configuration
And it seems I've managed to connect successfully, however the writes don't seem to be going through for some reason...
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS -Wno-unused-local-binds #-}
import Yesod
import Database.Persist.MongoDB
import qualified Database.MongoDB as DB
import MongoImport
import Network (PortID (PortNumber))
import Control.Monad.Reader
import qualified Data.Pool as Pool
import Database.MongoDB.Transport.Tls as DBTLS
share
[mkPersist mongoSettings, mkMigrate "migrateAll"]
[persistLowerCase|
User
name String
age Int Maybe
deriving Show
|]
actions :: ReaderT MongoContext IO ()
actions = do
i <- insert $ User "Chris" $ Just 123
lift $ print i
createPipe :: HostName -> PortID -> IO DB.Pipe
createPipe hostname port = DBTLS.connect hostname port
createConnection :: Database -> HostName -> PortID -> Maybe MongoAuth -> IO Connection
createConnection dbname hostname port mAuth = do
pipe <- createPipe hostname port
testAccess pipe dbname mAuth
return $ Connection pipe dbname
testAccess :: DB.Pipe -> Database -> Maybe MongoAuth -> IO ()
testAccess pipe dbname mAuth = do
_ <- case mAuth of
Just (MongoAuth user pass) -> DB.access pipe DB.UnconfirmedWrites dbname (DB.auth user pass)
Nothing -> return undefined
return ()
makeSslPool :: IO (ConnectionPool)
makeSslPool = Pool.createPool
(createConnection "test" "cluster0-shard-00-00-gv0qj.mongodb.net" (PortNumber 27017) (Just $ MongoAuth "" ""))
(\(Connection pipe _) -> DB.close pipe)
1
100
1
main :: IO ()
main = do
makeSslPool >>= runMongoDBPool master actions
It outputs:
UserKey {unUserKey = MongoKey {unMongoKey = 5a6209a32a0e1613e7000008}}
But using the mongo console I don't see this value?
Finally got this to work... The issue with my previous example is 1. It does not save any record 2. It produces no error. Potentially my code is actually doing something wrong.
I've managed to get this to work with the following:
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE EmptyDataDecls #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS -Wno-unused-local-binds #-}
import Yesod
import Database.Persist.MongoDB
import qualified Database.MongoDB as DB
import MongoImport
import Network (PortID (PortNumber))
import Control.Monad.Reader
import qualified Data.Pool as Pool
import Database.MongoDB.Transport.Tls as DBTLS
share
[mkPersist mongoSettings, mkMigrate "migrateAll"]
[persistLowerCase|
User
name String
age Int Maybe
deriving Show
|]
createConnection :: Database -> HostName -> PortID -> Maybe MongoAuth -> IO Connection
createConnection dbname _ _ mAuth = do
pipe <- DBTLS.connect "cluster0-shard-00-00-gv0qj.mongodb.net" (PortNumber 27017)
testAccess pipe mAuth
return $ Connection pipe dbname
actions :: ReaderT MongoContext IO ()
actions = do
i <- insert $ User "chrz" $ Just 1232
lift $ print i
testAccess :: DB.Pipe -> Maybe MongoAuth -> IO ()
testAccess pipe mAuth = do
x <- case mAuth of
Just (MongoAuth user pass) -> DB.access pipe DB.UnconfirmedWrites "admin" (DB.auth user pass)
Nothing -> error "no auth"
case x of
False -> error "second no auth"
True -> return ()
makeSslPool :: IO (ConnectionPool)
makeSslPool = Pool.createPool
(createConnection "test" "cluster0-shard-00-00-gv0qj.mongodb.net" (PortNumber 27017) (Just $ MongoAuth "" ""))
(\(Connection pipe _) -> DB.close pipe)
1
100
1
main :: IO ()
main = makeSslPool >>= runMongoDBPool master actions
Conclusion:
The above does need the exported Constructors - but this is just for hacking / debugging purposes. I'm not 100% sure on how this can actually be fixed in the library but I think the fix is we just need to create a new Connection
via so:
-- import Database.MongoDB.Transport.Tls as DBTLS
createTLSConnection :: Database -> HostName -> PortID -> Maybe MongoAuth -> IO Connection
createTLSConnection dbname host port mAuth = do
pipe <- DBTLS.connect host port
testAccess pipe mAuth
return $ Connection pipe dbname