2022-08-10 15:17:47 +00:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
|
|
|
|
module Xero where
|
|
|
|
|
|
|
|
import Data.Aeson
|
|
|
|
import qualified Data.Bson as B
|
2022-08-11 22:30:24 +00:00
|
|
|
import Data.Maybe
|
2022-08-10 15:17:47 +00:00
|
|
|
import qualified Data.Text as T
|
2022-08-11 22:30:24 +00:00
|
|
|
import Data.Time.Clock
|
2022-08-10 15:17:47 +00:00
|
|
|
import Database.MongoDB
|
|
|
|
import GHC.Generics
|
|
|
|
|
|
|
|
-- | Type to represent a Xero app configuration
|
|
|
|
data Xero =
|
|
|
|
Xero
|
|
|
|
{ x_id :: ObjectId
|
|
|
|
, x_clientId :: T.Text
|
|
|
|
, x_clientSecret :: T.Text
|
|
|
|
}
|
|
|
|
deriving (Eq, Show)
|
|
|
|
|
|
|
|
instance ToJSON Xero where
|
|
|
|
toJSON (Xero i cI s) =
|
|
|
|
object ["_id" .= show i, "clientId" .= cI, "clientSecret" .= s]
|
|
|
|
|
|
|
|
instance Val Xero where
|
|
|
|
val (Xero i cI s) = Doc ["_id" =: i, "clientId" =: cI, "clientSecret" =: s]
|
|
|
|
cast' (Doc d) = do
|
|
|
|
i <- B.lookup "_id" d
|
|
|
|
cI <- B.lookup "clientId" d
|
|
|
|
s <- B.lookup "clientSecret" d
|
|
|
|
Just (Xero i cI s)
|
|
|
|
cast' _ = Nothing
|
|
|
|
|
2022-08-11 22:30:24 +00:00
|
|
|
-- | Type to represent a Xero access token
|
|
|
|
data XeroToken =
|
|
|
|
XeroToken
|
|
|
|
{ t_id :: Maybe ObjectId
|
|
|
|
, t_address :: T.Text
|
|
|
|
, t_access :: T.Text
|
|
|
|
, t_expires :: UTCTime
|
|
|
|
, t_refresh :: T.Text
|
|
|
|
}
|
|
|
|
deriving (Eq, Show)
|
|
|
|
|
|
|
|
instance ToJSON XeroToken where
|
|
|
|
toJSON (XeroToken i a t e r) =
|
|
|
|
case i of
|
|
|
|
Just oid ->
|
|
|
|
object
|
|
|
|
[ "_id" .= show oid
|
|
|
|
, "address" .= a
|
|
|
|
, "accessToken" .= t
|
|
|
|
, "expires" .= e
|
|
|
|
, "refreshToken" .= r
|
|
|
|
]
|
|
|
|
Nothing ->
|
|
|
|
object
|
|
|
|
[ "_id" .= ("" :: String)
|
|
|
|
, "address" .= a
|
|
|
|
, "accessToken" .= t
|
|
|
|
, "expires" .= e
|
|
|
|
, "refreshToken" .= r
|
|
|
|
]
|
|
|
|
|
|
|
|
instance FromJSON XeroToken where
|
|
|
|
parseJSON =
|
|
|
|
withObject "XeroToken" $ \obj -> do
|
|
|
|
i <- obj .: "_id"
|
|
|
|
a <- obj .: "address"
|
|
|
|
t <- obj .: "accessToken"
|
|
|
|
e <- obj .: "expires"
|
|
|
|
r <- obj .: "refreshToken"
|
|
|
|
pure $
|
|
|
|
XeroToken
|
|
|
|
(if not (null i)
|
|
|
|
then Just (read i)
|
|
|
|
else Nothing)
|
|
|
|
a
|
|
|
|
t
|
|
|
|
e
|
|
|
|
r
|
|
|
|
|
|
|
|
instance Val XeroToken where
|
|
|
|
val (XeroToken i a t e r) =
|
|
|
|
if isJust i
|
|
|
|
then Doc
|
|
|
|
[ "_id" =: i
|
|
|
|
, "address" =: a
|
|
|
|
, "accessToken" =: t
|
|
|
|
, "expires" =: e
|
|
|
|
, "refreshToken" =: r
|
|
|
|
]
|
|
|
|
else Doc
|
|
|
|
[ "address" =: a
|
|
|
|
, "accessToken" =: t
|
|
|
|
, "expires" =: e
|
|
|
|
, "refreshToken" =: r
|
|
|
|
]
|
|
|
|
cast' (Doc d) = do
|
|
|
|
i <- B.lookup "_id" d
|
|
|
|
a <- B.lookup "address" d
|
|
|
|
t <- B.lookup "accessToken" d
|
|
|
|
e <- B.lookup "expires" d
|
|
|
|
r <- B.lookup "refreshToken" d
|
|
|
|
Just (XeroToken i a t e r)
|
|
|
|
cast' _ = Nothing
|
|
|
|
|
2022-08-10 15:17:47 +00:00
|
|
|
-- Database actions
|
|
|
|
findXero :: Action IO (Maybe Document)
|
|
|
|
findXero = findOne (select [] "xero")
|
2022-08-11 22:30:24 +00:00
|
|
|
|
|
|
|
upsertToken :: XeroToken -> Action IO ()
|
|
|
|
upsertToken t = do
|
|
|
|
let token = val t
|
|
|
|
case token of
|
|
|
|
Doc d -> upsert (select ["address" =: t_address t] "xerotokens") d
|
|
|
|
_ -> return ()
|
|
|
|
|
|
|
|
findToken :: T.Text -> Action IO (Maybe Document)
|
|
|
|
findToken a = findOne (select ["address" =: a] "xerotokens")
|