Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix most warnings, add several TODO comments #142

Merged
merged 1 commit into from
Nov 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions PaymentServer.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,21 @@ library
, servant-prometheus
, mtl
default-language: Haskell2010
ghc-options: -Wmissing-import-lists -Wunused-imports
ghc-options: -Werror -Wall -Wno-name-shadowing -Wno-orphans -Wno-error=unused-do-bind
pkgconfig-depends: libchallenge_bypass_ristretto_ffi

executable PaymentServer-exe
hs-source-dirs: app
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wmissing-import-lists -Wunused-imports
ghc-options: -Werror -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, PaymentServer
default-language: Haskell2010

executable PaymentServer-generate-key
hs-source-dirs: generate-key
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wmissing-import-lists -Wunused-imports
ghc-options: -Werror -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, text
, PaymentServer
Expand All @@ -75,7 +75,7 @@ executable PaymentServer-generate-key
executable PaymentServer-get-public-key
hs-source-dirs: get-public-key
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wmissing-import-lists -Wunused-imports
ghc-options: -Werror -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, text
, optparse-applicative
Expand All @@ -85,7 +85,7 @@ executable PaymentServer-get-public-key
executable PaymentServer-complete-payment
hs-source-dirs: complete-payment
main-is: Main.hs
ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wmissing-import-lists -Wunused-imports
ghc-options: -Werror -threaded -rtsopts -with-rtsopts=-N
build-depends: base
, time
, text
Expand Down Expand Up @@ -132,6 +132,7 @@ test-suite PaymentServer-tests
, stripe-core
, PaymentServer
default-language: Haskell2010
ghc-options: -Wall -Wno-name-shadowing

source-repository head
type: git
Expand Down
2 changes: 0 additions & 2 deletions complete-payment/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ import Options.Applicative
( Parser
, ParserInfo
, strOption
, option
, auto
, long
, help
, showDefault
Expand Down
10 changes: 2 additions & 8 deletions generate-key/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,11 @@ module Main
( main
) where

import Prelude hiding
( putStrLn
)

import Data.Text.IO
( putStrLn
)
import qualified Data.Text.IO as TIO

import PaymentServer.Ristretto
( randomSigningKey
)

main :: IO ()
main = randomSigningKey >>= putStrLn
main = randomSigningKey >>= TIO.putStrLn
12 changes: 2 additions & 10 deletions get-public-key/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,7 @@ module Main
( main
) where

import Prelude hiding
( putStrLn
, getLine
)

import Data.Text.IO
( putStrLn
, getLine
)
import qualified Data.Text.IO as TIO

import Options.Applicative
( ParserInfo
Expand All @@ -37,4 +29,4 @@ opts = info (pure () <**> helper)

main :: IO ()
main =
execParser opts >> getLine >>= getPublicKey >>= putStrLn
execParser opts >> TIO.getLine >>= getPublicKey >>= TIO.putStrLn
10 changes: 5 additions & 5 deletions src/PaymentServer/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,6 @@ import Options.Applicative
import System.Exit
( exitFailure
)
import Data.Semigroup ((<>))
import qualified Data.Text.IO as TIO
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as Char8
Expand Down Expand Up @@ -264,6 +263,7 @@ main = do
logEndpoint (endpoint config)
run app

getPortNumber :: Endpoint -> Port
getPortNumber (TCPEndpoint portNumber) = portNumber
getPortNumber (TLSEndpoint portNumber _ _ _) = portNumber

Expand All @@ -272,7 +272,7 @@ getRunner endpoint =
let
onException :: Maybe Request -> SomeException -> IO ()
onException _ exc = do
print "onException"
print ("onException" :: Text)
print exc
return ()
onExceptionResponse :: SomeException -> Response
Expand Down Expand Up @@ -310,12 +310,12 @@ getApp config =
(Ristretto, Just keyPath) -> do
key <- TIO.readFile keyPath
return $ Right $ ristrettoIssue key
_ -> return $ Left "invalid options"
_ -> return $ Left ("invalid options" :: Text)
getDatabase ServerConfig{ database, databasePath } =
case (database, databasePath) of
(Memory, Nothing) -> Right memory
(SQLite3, Just path) -> Right (sqlite path)
_ -> Left "invalid options"
_ -> Left ("invalid options" :: Text)

stripeConfig ServerConfig
{ stripeKeyPath
Expand All @@ -339,7 +339,7 @@ getApp config =
in do
issuer <- getIssuer config
case issuer of
Left err -> do
Left err -> do -- XXX shae turn this into a monad instead of a stairstep
print err
exitFailure
Right issuer ->
Expand Down
11 changes: 7 additions & 4 deletions src/PaymentServer/Persistence.hs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ instance Exception PaymentError
instance Eq PaymentError where
AlreadyPaid == AlreadyPaid = True
PaymentFailed self == PaymentFailed other = show self == show other
self == other = False
_self == _other = False

-- | Reasons that a voucher cannot be redeemed.
data RedeemError =
Expand Down Expand Up @@ -181,7 +181,7 @@ data VoucherDatabaseState =
| SQLiteDB { connect :: IO Sqlite.Connection }

instance VoucherDatabase VoucherDatabaseState where
payForVoucher MemoryDB{ paid = paidRef, redeemed = redeemed } voucher pay = do
payForVoucher MemoryDB{ paid = paidRef } voucher pay = do
-- Surely far from ideal...
paid <- readIORef paidRef
if Set.member voucher paid
Expand Down Expand Up @@ -237,6 +237,8 @@ instance VoucherDatabase VoucherDatabaseState where

transformBusy (Sqlite.SQLError Sqlite.ErrorBusy _ _) =
return . Left $ DatabaseUnavailable
-- XXX things went poorly, should we handle with more detail?
transformBusy panic = error $ "redeemVoucherHelper got bad input " <> show panic


-- | Look up the voucher, counter tuple which previously performed a
Expand Down Expand Up @@ -369,7 +371,7 @@ insertVoucher dbConn voucher pay =
Right _ -> do
Sqlite.execute dbConn "INSERT INTO vouchers (name, charge_id) VALUES (?, ?)" (voucher, Nothing :: Maybe Text)
return result
Left err ->
Left _err ->
return result

-- | Mark the given voucher as having been redeemed (with the given
Expand All @@ -392,6 +394,7 @@ sqlite path =
let exec = Sqlite.execute_ dbConn
exec "PRAGMA busy_timeout = 60000"
exec "PRAGMA foreign_keys = ON"
-- XXX handle any upgrade failures here!
Sqlite.withExclusiveTransaction dbConn (upgradeSchema latestVersion dbConn)
return dbConn

Expand Down Expand Up @@ -494,7 +497,7 @@ upgradeSchema targetVersion conn = do
oneStep :: [Sqlite.Query] -> IO [()]
oneStep = mapM $ Sqlite.execute_ conn
in do
mapM oneStep upgrades
mapM_ oneStep upgrades
return $ Right ()


Expand Down
21 changes: 8 additions & 13 deletions src/PaymentServer/Processors/Stripe.hs
Original file line number Diff line number Diff line change
Expand Up @@ -76,17 +76,14 @@ import Servant.API
( Header
, ReqBody
, JSON
, OctetStream
, PlainText
, Post
, Accept(contentType)
, MimeUnrender(mimeUnrender)
, (:>)
)
import Web.Stripe.Event
( Event(Event, eventId, eventType, eventData)
, EventId(EventId)
, EventType(ChargeSucceededEvent, CheckoutSessionCompleted, PaymentIntentCreated)
( Event(Event, eventType, eventData)
, EventType(CheckoutSessionCompleted)
, EventData(ChargeEvent, CheckoutSessionEvent)
)

Expand All @@ -109,8 +106,7 @@ import Web.Stripe.Charge
, TokenId(TokenId)
)
import Web.Stripe.Client
( StripeConfig(StripeConfig, secretKey)
, StripeKey(StripeKey)
( StripeConfig
)
import Web.Stripe
( stripe
Expand All @@ -130,7 +126,6 @@ import PaymentServer.Persistence
, ProcessorResult
)
import Data.Data (Typeable)
import Servant.API.ContentTypes (AcceptHeader(AcceptHeader))

data Acknowledgement = Ok deriving (Eq, Show)

Expand Down Expand Up @@ -164,8 +159,8 @@ getVoucher Event{eventData=(ChargeEvent charge)} =
voucherFromMetadata . chargeMetaData $ charge
where
voucherFromMetadata (MetaData []) = Nothing
voucherFromMetadata (MetaData (("Voucher", value):xs)) = Just value
voucherFromMetadata (MetaData (x:xs)) = voucherFromMetadata (MetaData xs)
voucherFromMetadata (MetaData (("Voucher", value):_)) = Just value
voucherFromMetadata (MetaData (_:xs)) = voucherFromMetadata (MetaData xs)
getVoucher _ = Nothing

chargeServer :: VoucherDatabase d => StripeConfig -> d -> Server ChargesAPI
Expand Down Expand Up @@ -215,7 +210,7 @@ webhookServer WebhookConfig { webhookConfigKey } d (Just signatureText) payload
-- should be able to indicate error I guess.
_ <- liftIO . payForVoucher d v . return . Right $ ()
return Ok
Right event@Event { eventType } ->
Right Event { eventType } ->
throwError . jsonErr status400 . pack $ "unsupported event type " ++ show eventType

-- | Browser facing API that takes token, voucher and a few other information
Expand Down Expand Up @@ -280,8 +275,7 @@ charge stripeConfig d (Charges token voucher 650 USD) = do
throwError $ voucherAlreadyPaid "Payment for voucher already supplied"

Left (PaymentFailed (StripeError { errorType = errorType, errorMsg = msg })) -> do
liftIO $ print "Stripe createCharge failed:"
liftIO $ print msg
liftIO $ print $ "Stripe createCharge failed: " <> msg
let err = errorForStripe errorType ( Data.Text.concat [ "Stripe charge didn't succeed: ", msg ])
throwError err

Expand Down Expand Up @@ -336,6 +330,7 @@ charge stripeConfig d (Charges token voucher 650 USD) = do
charge _ _ (Charges _ _ 650 _) = throwError (jsonErr status400 "Unsupported currency")
-- The wrong amount
charge _ _ (Charges _ _ _ USD) = throwError (jsonErr status400 "Incorrect charge amount")
charge badInput1 _badInput2 badInput3 = error $ mconcat ["charge got unexpected input : ", show badInput1, " ", "some VoucherDatabase value", " ", show badInput3]

jsonErr :: Status -> Text -> ServerError
jsonErr (Status statusCode statusMessage) detail = ServerError
Expand Down
11 changes: 4 additions & 7 deletions src/PaymentServer/Redemption.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ module PaymentServer.Redemption
, redemptionServer
) where

import Prelude hiding
( concat
)

import GHC.Generics
( Generic
)
Expand All @@ -39,8 +35,8 @@ import Control.Monad.IO.Class
import Data.Text
( Text
, pack
, concat
)
import qualified Data.Text as Text
import Data.Text.Encoding
( encodeUtf8
)
Expand Down Expand Up @@ -176,6 +172,7 @@ instance FromJSON Result where

type RedemptionAPI = ReqBody '[JSON] Redeem :> Post '[JSON] Result

jsonErr :: ToJSON a => ServerError -> a -> ServerError
jsonErr err reason = err
{ errBody = encode reason
, errHeaders = [ ("Content-Type", "application/json;charset=utf-8") ]
Expand All @@ -198,7 +195,7 @@ retry op =
numRetries = totalRetryDuration `div` perRetryDelay

policy = constantDelay (perRetryDelay * 1000) <> limitRetries numRetries
shouldRetry status value =
shouldRetry _status value =
case value of
Left NotPaid -> return True
_ -> return False
Expand Down Expand Up @@ -290,4 +287,4 @@ signaturesIssued
-- be used as an identifier for this exact sequence of tokens.
fingerprintFromTokens :: [BlindedToken] -> Fingerprint
fingerprintFromTokens =
pack . show . hashWith SHA3_512 . encodeUtf8 . concat
pack . show . hashWith SHA3_512 . encodeUtf8 . Text.concat
3 changes: 0 additions & 3 deletions src/PaymentServer/Server.hs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ import PaymentServer.Metrics
( MetricsAPI
, metricsServer
)
import PaymentServer.Issuer
( Issuer
)
import PaymentServer.Persistence
( VoucherDatabase
)
Expand Down
13 changes: 2 additions & 11 deletions test/FakeStripe.hs
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@ import Data.ByteString.Lazy
( ByteString
)

import Data.Time.Clock
( UTCTime(UTCTime)
, secondsToDiffTime
)

import Data.Time.Calendar
( Day(ModifiedJulianDay)
)

import Network.HTTP.Types
( status200
, status400
Expand Down Expand Up @@ -183,11 +174,11 @@ aCharge = [r|

-- Accept a charge creation and respond in the affirmative.
chargeOkay :: Application
chargeOkay req respond =
chargeOkay _req respond =
respond . responseLBS status200 [] $ aCharge

chargeFailed :: ByteString -> Application
chargeFailed stripeResponse req respond =
chargeFailed stripeResponse _req respond =
respond . responseLBS status400 [] $ stripeResponse

-- Pass a Stripe-flavored configuration for a running Wai application to a
Expand Down
10 changes: 5 additions & 5 deletions test/Metrics.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ import Test.Tasty
)

import Test.Tasty.HUnit
( testCase
, assertEqual
)
( testCase )

import Network.HTTP.Types
( methodGet
Expand Down Expand Up @@ -48,6 +46,7 @@ import Prometheus
, unsafeRegister
, counter
, incCounter
, Counter
)

import PaymentServer.Metrics
Expand All @@ -73,12 +72,13 @@ readMetrics = request $ setPath defaultRequest { requestMethod = methodGet } "/m
-- Register a counter at the top-level because the registry is global and this
-- lets us avoid thinking about collisions or unregistration. unsafeRegister
-- is (only) safe for defining a top-level symbol.
aCounter :: Counter
aCounter = unsafeRegister $ counter (Info "a_counter" "A test counter.")

-- | A ``GET /metrics`` request receives a text/plain OK response containing
-- current Prometheus-formatted metrics information.
metricsTests :: TestTree
metricsTests =
-- | A ``GET /metrics`` request receives a text/plain OK response containing
-- current Prometheus-formatted metrics information.
testCase "plaintext metrics response" $
let
app :: Application
Expand Down
Loading