module Network.Gitit.Rpxnow
( Identifier (..)
, authenticate
) where
import Text.JSON
import Data.Maybe (isJust, fromJust)
import System.Process
import System.Exit
import System.IO
import Network.HTTP (urlEncodeVars)
curl :: Monad m
=> String
-> [(String, String)]
-> IO (m String)
curl url params = do
(Nothing, Just hout, Just herr, phandle) <- createProcess $ (proc "curl"
[url, "-d", urlEncodeVars params]
) { std_out = CreatePipe, std_err = CreatePipe }
exitCode <- waitForProcess phandle
case exitCode of
ExitSuccess -> hGetContents hout >>= return . return
_ -> hGetContents herr >>= return . fail
data Identifier = Identifier
{ userIdentifier :: String
, userData :: [(String, String)]
}
deriving Show
authenticate :: Monad m
=> String
-> String
-> IO (m Identifier)
authenticate apiKey token = do
body <- curl
"https://rpxnow.com/api/v2/auth_info"
[ ("apiKey", apiKey)
, ("token", token)
]
case body of
Left s -> return $ fail $ "Unable to connect to rpxnow: " ++ s
Right b ->
case decode b >>= getObject of
Error s -> return $ fail $ "Not a valid JSON response: " ++ s
Ok o ->
case valFromObj "stat" o of
Error _ -> return $ fail "Missing 'stat' field"
Ok "ok" -> return $ parseProfile o
Ok stat -> return $ fail $ "Login not accepted: " ++ stat
parseProfile :: Monad m => JSObject JSValue -> m Identifier
parseProfile v = do
profile <- resultToMonad $ valFromObj "profile" v >>= getObject
ident <- resultToMonad $ valFromObj "identifier" profile
let pairs = fromJSObject profile
pairs' = filter (\(k, _) -> k /= "identifier") pairs
pairs'' = map fromJust . filter isJust . map takeString $ pairs'
return $ Identifier ident pairs''
takeString :: (String, JSValue) -> Maybe (String, String)
takeString (k, JSString v) = Just (k, fromJSString v)
takeString _ = Nothing
getObject :: Monad m => JSValue -> m (JSObject JSValue)
getObject (JSObject o) = return o
getObject _ = fail "Not an object"
resultToMonad :: Monad m => Result a -> m a
resultToMonad (Ok x) = return x
resultToMonad (Error s) = fail s