module Signet.UnstableTest where

import qualified Control.Monad.Catch as Exception
import qualified Data.ByteString.Char8 as Ascii
import qualified Data.Time as Time
import qualified Heck as Test
import qualified Signet.Unstable as Signet
import qualified Signet.Unstable.Exception.SignetException as SignetException
import qualified Signet.Unstable.Exception.ToleranceException as ToleranceException
import qualified Signet.Unstable.Exception.VerificationException as VerificationException
import qualified Signet.Unstable.Extra.Either as Either
import qualified Signet.Unstable.Type.Message as Message
import qualified Signet.Unstable.Type.Signature as Signature
import qualified Signet.Unstable.Type.Signatures as Signatures
import qualified Signet.Unstable.Type.Tolerance as Tolerance
import qualified Signet.Unstable.Type.Verifier as Verifier

spec :: (Exception.MonadThrow io, Monad tree) => Test.Test io tree -> tree ()
spec :: forall (io :: * -> *) (tree :: * -> *).
(MonadThrow io, Monad tree) =>
Test io tree -> tree ()
spec Test io tree
test = Test io tree -> String -> tree () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> n () -> n ()
Test.describe Test io tree
test String
"Signet.Unstable" (tree () -> tree ()) -> tree () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
  Test io tree -> String -> tree () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> n () -> n ()
Test.describe Test io tree
test String
"verifyWebhookText" (tree () -> tree ()) -> tree () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
    () -> tree ()
forall a. a -> tree a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

  Test io tree -> String -> tree () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> n () -> n ()
Test.describe Test io tree
test String
"verifyWebhookByteString" (tree () -> tree ()) -> tree () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
    () -> tree ()
forall a. a -> tree a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

  Test io tree -> String -> tree () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> n () -> n ()
Test.describe Test io tree
test String
"verifyWebhook" (tree () -> tree ()) -> tree () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
    () -> tree ()
forall a. a -> tree a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

  Test io tree -> String -> tree () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> n () -> n ()
Test.describe Test io tree
test String
"verifyWebhookWith" (tree () -> tree ()) -> tree () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
    Test io tree -> String -> io () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> m () -> n ()
Test.it Test io tree
test String
"succeeds with a valid symmetric signature" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let tolerance :: Tolerance
tolerance = Tolerance
Tolerance.typical
      let now :: UTCTime
now = Day -> DiffTime -> UTCTime
Time.UTCTime (Year -> MonthOfYear -> MonthOfYear -> Day
Time.fromGregorian Year
1970 MonthOfYear
1 MonthOfYear
1) DiffTime
0
      verifier <- Either InvalidVerifier Verifier -> io Verifier
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidVerifier Verifier -> io Verifier)
-> (ByteString -> Either InvalidVerifier Verifier)
-> ByteString
-> io Verifier
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either InvalidVerifier Verifier
Verifier.parse (ByteString -> io Verifier) -> ByteString -> io Verifier
forall a b. (a -> b) -> a -> b
$ String -> ByteString
Ascii.pack String
"whsec_bXlzZWNyZXRrZXkxMjM0NQ=="
      message <- Either.throw . Message.parse $ Ascii.pack "i.0.Hello, world!"
      let byteString = String -> ByteString
Ascii.pack String
"v1,IywpE5NXy+JdAScgR7j5Pt59GjmazD7iJuVsQoRZFyw="
      (_, signatures) <- Either.throw $ Signatures.parse byteString
      let result = Tolerance
-> UTCTime
-> Verifier
-> Message
-> Signatures
-> Either SignetException Signature
Signet.verifyWebhookWith Tolerance
tolerance UTCTime
now Verifier
verifier Message
message Signatures
signatures
      signature <- Either.throw =<< Either.throw (Signature.parse byteString)
      Test.assertEq test result (Right signature)

    Test io tree -> String -> io () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> m () -> n ()
Test.it Test io tree
test String
"fails with an invalid timestamp" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let tolerance :: Tolerance
tolerance = Tolerance
Tolerance.typical
      let now :: UTCTime
now = Day -> DiffTime -> UTCTime
Time.UTCTime (Year -> MonthOfYear -> MonthOfYear -> Day
Time.fromGregorian Year
1970 MonthOfYear
1 MonthOfYear
1) DiffTime
0
      verifier <- Either InvalidVerifier Verifier -> io Verifier
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidVerifier Verifier -> io Verifier)
-> (ByteString -> Either InvalidVerifier Verifier)
-> ByteString
-> io Verifier
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either InvalidVerifier Verifier
Verifier.parse (ByteString -> io Verifier) -> ByteString -> io Verifier
forall a b. (a -> b) -> a -> b
$ String -> ByteString
Ascii.pack String
"whsec_bXlzZWNyZXRrZXkxMjM0NQ=="
      message <- Either.throw . Message.parse $ Ascii.pack "i.301.Hello, world!"
      (_, signatures) <- Either.throw . Signatures.parse $ Ascii.pack "v1,IywpE5NXy+JdAScgR7j5Pt59GjmazD7iJuVsQoRZFyw="
      let result = Tolerance
-> UTCTime
-> Verifier
-> Message
-> Signatures
-> Either SignetException Signature
Signet.verifyWebhookWith Tolerance
tolerance UTCTime
now Verifier
verifier Message
message Signatures
signatures
      Test.assertEq test result (Left (SignetException.ToleranceException . ToleranceException.MkToleranceException $ Message.timestamp message))

    Test io tree -> String -> io () -> tree ()
forall (m :: * -> *) (n :: * -> *).
Test m n -> String -> m () -> n ()
Test.it Test io tree
test String
"fails with an invalid symmetric signature" (io () -> tree ()) -> io () -> tree ()
forall a b. (a -> b) -> a -> b
$ do
      let tolerance :: Tolerance
tolerance = Tolerance
Tolerance.typical
      let now :: UTCTime
now = Day -> DiffTime -> UTCTime
Time.UTCTime (Year -> MonthOfYear -> MonthOfYear -> Day
Time.fromGregorian Year
1970 MonthOfYear
1 MonthOfYear
1) DiffTime
0
      verifier <- Either InvalidVerifier Verifier -> io Verifier
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidVerifier Verifier -> io Verifier)
-> (ByteString -> Either InvalidVerifier Verifier)
-> ByteString
-> io Verifier
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either InvalidVerifier Verifier
Verifier.parse (ByteString -> io Verifier) -> ByteString -> io Verifier
forall a b. (a -> b) -> a -> b
$ String -> ByteString
Ascii.pack String
"whsec_bXlzZWNyZXRrZXkxMjM0NQ=="
      message <- Either.throw . Message.parse $ Ascii.pack "i.0.Hello, world!"
      (_, signatures) <- Either.throw . Signatures.parse $ Ascii.pack "v1,0000000000000000000000000000000000000000000="
      let result = Tolerance
-> UTCTime
-> Verifier
-> Message
-> Signatures
-> Either SignetException Signature
Signet.verifyWebhookWith Tolerance
tolerance UTCTime
now Verifier
verifier Message
message Signatures
signatures
      Test.assertEq test result (Left (SignetException.VerificationException . VerificationException.MkVerificationException $ Message.id_ message))