Implement WooCommerce authentication

This commit is contained in:
Rene Vergara 2022-11-14 15:56:30 -06:00
parent 0eae258dee
commit daa4f59faa
Signed by: pitmutt
GPG key ID: 65122AD495A7F5B2
5 changed files with 145 additions and 2 deletions

View file

@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- New utility to refresh Xero tokens periodically. - New utility to refresh Xero tokens periodically.
- New module for WooCommerce interaction.
- New `/api/auth` endpoint to authenticate with the WooCommerce plugin
### Changed ### Changed

40
src/WooCommerce.hs Normal file
View file

@ -0,0 +1,40 @@
{-# LANGUAGE OverloadedStrings #-}
module WooCommerce where
import Data.Aeson
import qualified Data.Bson as B
import Data.Maybe
import qualified Data.Text as T
import Database.MongoDB
-- | Type to represent the WooCommerce token
data WooToken =
WooToken
{ w_id :: Maybe ObjectId
, w_owner :: ObjectId
, w_token :: T.Text
, w_url :: Maybe T.Text
}
deriving (Eq, Show)
instance Val WooToken where
val (WooToken i o t u) =
if isJust i
then Doc ["_id" =: i, "owner" =: o, "token" =: t, "url" =: u]
else Doc ["owner" =: o, "token" =: t, "url" =: u]
cast' (Doc d) = do
i <- B.lookup "_id" d
o <- B.lookup "owner" d
t <- B.lookup "token" d
u <- B.lookup "url" d
Just (WooToken i o t u)
cast' _ = Nothing
-- Database actions
findWooToken :: ObjectId -> Action IO (Maybe Document)
findWooToken oid = findOne (select ["owner" =: oid] "wootokens")
addUrl :: WooToken -> T.Text -> Action IO ()
addUrl t u =
modify (select ["_id" =: w_id t] "wootokens") ["$set" =: ["url" =: u]]

View file

@ -52,6 +52,7 @@ import Text.Regex
import Text.Regex.Base import Text.Regex.Base
import User import User
import Web.Scotty import Web.Scotty
import WooCommerce
import Xero import Xero
import ZGoTx import ZGoTx
@ -604,6 +605,46 @@ routes pipe config = do
c <- param "code" c <- param "code"
liftAndCatchIO $ run (addAccCode oAdd c) liftAndCatchIO $ run (addAccCode oAdd c)
status accepted202 status accepted202
-- Authenticate the WooCommerce plugin
get "/api/auth" $ do
oid <- param "ownerid"
t <- param "token"
siteurl <- param "siteurl"
res <- liftAndCatchIO $ run (findWooToken (read oid))
let c = cast' . Doc =<< res
case c of
Nothing -> do
status accepted202
Web.Scotty.json
(object
["authorized" .= False, "message" .= ("Owner not found" :: String)])
Just c ->
if t == w_token c
then if isNothing (w_url c)
then do
liftAndCatchIO $ run (addUrl c siteurl)
status ok200
Web.Scotty.json
(object
[ "authorized" .= True
, "message" .= ("Authorized!" :: String)
])
else do
status accepted202
Web.Scotty.json
(object
[ "authorized" .= False
, "message" .=
("ZGo shop already linked to" <>
fromMaybe "" (w_url c))
])
else do
status accepted202
Web.Scotty.json
(object
[ "authorized" .= False
, "message" .= ("Token mismatch" :: String)
])
--Get user associated with session --Get user associated with session
get "/api/user" $ do get "/api/user" $ do
sess <- param "session" sess <- param "session"

View file

@ -33,6 +33,7 @@ import Test.QuickCheck.Gen
import Test.QuickCheck.Monadic import Test.QuickCheck.Monadic
import User import User
import Web.Scotty import Web.Scotty
import WooCommerce
import Xero import Xero
import ZGoBackend import ZGoBackend
import ZGoTx import ZGoTx
@ -156,7 +157,7 @@ main = do
res <- httpJSON req res <- httpJSON req
getResponseStatus (res :: Response A.Value) `shouldBe` ok200 getResponseStatus (res :: Response A.Value) `shouldBe` ok200
describe "blockheight endpoint" $ do describe "blockheight endpoint" $ do
xit "returns a block number" $ do it "returns a block number" $ do
req <- testGet "/api/blockheight" [] req <- testGet "/api/blockheight" []
res <- httpJSON req res <- httpJSON req
height (getResponseBody (res :: Response Block)) `shouldSatisfy` \x -> height (getResponseBody (res :: Response Block)) `shouldSatisfy` \x ->
@ -250,6 +251,48 @@ main = do
req <- testDelete "/api/item/" "627d7ba92b05a76be3000003" req <- testDelete "/api/item/" "627d7ba92b05a76be3000003"
res <- httpLBS req res <- httpLBS req
getResponseStatus res `shouldBe` ok200 getResponseStatus res `shouldBe` ok200
describe "WooCommerce endpoints" $ do
it "generate token" pending
it "authenticate with incorrect owner" $ do
req <-
testGet
"/api/auth/"
[ ("ownerid", Just "62cca13f5530331e2a900001")
, ("token", Just "89bd9d8d69a674e0f467cc8796ed151a")
, ("siteurl", Just "testyMcTest")
]
res <- httpJSON req
getResponseStatus (res :: Response A.Value) `shouldBe` accepted202
it "authenticate with incorrect token" $ do
req <-
testGet
"/api/auth/"
[ ("ownerid", Just "62cca13f5530331e2a97c78e")
, ("token", Just "89bd9d8d69a674e0f467cc8796000000")
, ("siteurl", Just "testyMcTest")
]
res <- httpJSON req
getResponseStatus (res :: Response A.Value) `shouldBe` accepted202
it "authenticate with correct token" $ do
req <-
testGet
"/api/auth/"
[ ("ownerid", Just "62cca13f5530331e2a97c78e")
, ("token", Just "89bd9d8d69a674e0f467cc8796ed151a")
, ("siteurl", Just "testyMcTest")
]
res <- httpJSON req
getResponseStatus (res :: Response A.Value) `shouldBe` ok200
it "authenticate with correct token on existing shop" $ do
req <-
testGet
"/api/auth/"
[ ("ownerid", Just "62cca13f5530331e2a97c78e")
, ("token", Just "89bd9d8d69a674e0f467cc8796ed151a")
, ("siteurl", Just "testyMcTest")
]
res <- httpJSON req
getResponseStatus (res :: Response A.Value) `shouldBe` accepted202
around handleDb $ around handleDb $
describe "Database actions" $ do describe "Database actions" $ do
describe "authentication" $ do describe "authentication" $ do
@ -304,7 +347,7 @@ main = do
it "deleted" $ \p -> do it "deleted" $ \p -> do
t <- access p master "test" $ findOne (select [] "users") t <- access p master "test" $ findOne (select [] "users")
let s = parseUserBson =<< t let s = parseUserBson =<< t
let userId = maybe Nothing u_id s let userId = u_id =<< s
let idString = maybe "" show userId let idString = maybe "" show userId
_ <- access p master "test" $ deleteUser idString _ <- access p master "test" $ deleteUser idString
q <- q <-
@ -332,6 +375,7 @@ main = do
let ordTest = val myOrder let ordTest = val myOrder
case ordTest of case ordTest of
Doc oT -> access p master "test" (insert_ "orders" oT) Doc oT -> access p master "test" (insert_ "orders" oT)
_ -> fail "Couldn't save Order in DB"
_ <- _ <-
access p master "test" $ access p master "test" $
markOrderPaid ("627ab3ea2b05a76be3000001", 0) markOrderPaid ("627ab3ea2b05a76be3000001", 0)
@ -576,6 +620,8 @@ startAPI config = do
c <- access pipe master "zgo" (auth "zgo" "zcashrules") c <- access pipe master "zgo" (auth "zgo" "zcashrules")
let appRoutes = routes pipe config let appRoutes = routes pipe config
_ <- forkIO (scotty 3000 appRoutes) _ <- forkIO (scotty 3000 appRoutes)
_ <-
access pipe master "test" (Database.MongoDB.delete (select [] "wootokens"))
let myUser = let myUser =
User User
(Just (read "6272a90f2b05a74cf1000001" :: ObjectId)) (Just (read "6272a90f2b05a74cf1000001" :: ObjectId))
@ -629,6 +675,7 @@ startAPI config = do
let o = val myOwner let o = val myOwner
case o of case o of
Doc d -> access pipe master "test" (insert_ "owners" d) Doc d -> access pipe master "test" (insert_ "owners" d)
_ -> fail "Couldn't save Owner in DB"
_ <- access pipe master "test" (Database.MongoDB.delete (select [] "orders")) _ <- access pipe master "test" (Database.MongoDB.delete (select [] "orders"))
myTs <- liftIO getCurrentTime myTs <- liftIO getCurrentTime
let myOrder = let myOrder =
@ -649,6 +696,7 @@ startAPI config = do
let ordTest = val myOrder let ordTest = val myOrder
case ordTest of case ordTest of
Doc oT -> access pipe master "test" (insert_ "orders" oT) Doc oT -> access pipe master "test" (insert_ "orders" oT)
_ -> fail "Couldn't save Order in DB"
let myItem1 = let myItem1 =
Item Item
(Just (read "627d7ba92b05a76be3000003")) (Just (read "627d7ba92b05a76be3000003"))
@ -659,6 +707,17 @@ startAPI config = do
let itemTest = val myItem1 let itemTest = val myItem1
case itemTest of case itemTest of
Doc iT -> access pipe master "test" (insert_ "items" iT) Doc iT -> access pipe master "test" (insert_ "items" iT)
_ -> fail "Couldn't save test Item in DB"
let myWooToken =
WooToken
Nothing
(read "62cca13f5530331e2a97c78e")
"89bd9d8d69a674e0f467cc8796ed151a"
Nothing
let wooTest = val myWooToken
case wooTest of
Doc wT -> access pipe master "test" (insert_ "wootokens" wT)
_ -> fail "Couldn't save test WooToken in DB"
threadDelay 1000000 threadDelay 1000000
putStrLn "Test server is up!" putStrLn "Test server is up!"

View file

@ -32,6 +32,7 @@ library
Owner Owner
Payment Payment
User User
WooCommerce
Xero Xero
ZGoBackend ZGoBackend
ZGoTx ZGoTx