module Signet.UnstableTest where

import qualified Data.ByteString.Char8 as Ascii
import qualified Data.Time as Time
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.Extra.Tasty as Tasty
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
import Test.Tasty.HUnit ((@?=))

spec :: Tasty.Spec
spec :: Spec
spec = TestName -> Spec -> Spec
Tasty.describe TestName
"Signet.Unstable" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
  TestName -> Spec -> Spec
Tasty.describe TestName
"verifyWebhookText" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    () -> Spec
forall a. a -> WriterT [TestTree] Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

  TestName -> Spec -> Spec
Tasty.describe TestName
"verifyWebhookByteString" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    () -> Spec
forall a. a -> WriterT [TestTree] Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

  TestName -> Spec -> Spec
Tasty.describe TestName
"verifyWebhook" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    () -> Spec
forall a. a -> WriterT [TestTree] Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

  TestName -> Spec -> Spec
Tasty.describe TestName
"verifyWebhookWith" (Spec -> Spec) -> Spec -> Spec
forall a b. (a -> b) -> a -> b
$ do
    TestName -> Assertion -> Spec
Tasty.it TestName
"succeeds with a valid symmetric signature" (Assertion -> Spec) -> Assertion -> Spec
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
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
$ TestName -> ByteString
Ascii.pack TestName
"whsec_bXlzZWNyZXRrZXkxMjM0NQ=="
      Message
message <- Either InvalidMessage Message -> IO Message
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidMessage Message -> IO Message)
-> (ByteString -> Either InvalidMessage Message)
-> ByteString
-> IO Message
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either InvalidMessage Message
Message.parse (ByteString -> IO Message) -> ByteString -> IO Message
forall a b. (a -> b) -> a -> b
$ TestName -> ByteString
Ascii.pack TestName
"i.0.Hello, world!"
      let byteString :: ByteString
byteString = TestName -> ByteString
Ascii.pack TestName
"v1,IywpE5NXy+JdAScgR7j5Pt59GjmazD7iJuVsQoRZFyw="
      ([UnknownSignature]
_, Signatures
signatures) <- Either InvalidSignature ([UnknownSignature], Signatures)
-> IO ([UnknownSignature], Signatures)
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidSignature ([UnknownSignature], Signatures)
 -> IO ([UnknownSignature], Signatures))
-> Either InvalidSignature ([UnknownSignature], Signatures)
-> IO ([UnknownSignature], Signatures)
forall a b. (a -> b) -> a -> b
$ ByteString
-> Either InvalidSignature ([UnknownSignature], Signatures)
Signatures.parse ByteString
byteString
      let result :: Either SignetException Signature
result = Tolerance
-> UTCTime
-> Verifier
-> Message
-> Signatures
-> Either SignetException Signature
Signet.verifyWebhookWith Tolerance
tolerance UTCTime
now Verifier
verifier Message
message Signatures
signatures
      Right Signature
signature <- Either InvalidSignature (Either UnknownSignature Signature)
-> IO (Either UnknownSignature Signature)
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidSignature (Either UnknownSignature Signature)
 -> IO (Either UnknownSignature Signature))
-> Either InvalidSignature (Either UnknownSignature Signature)
-> IO (Either UnknownSignature Signature)
forall a b. (a -> b) -> a -> b
$ ByteString
-> Either InvalidSignature (Either UnknownSignature Signature)
Signature.parse ByteString
byteString
      Either SignetException Signature
result Either SignetException Signature
-> Either SignetException Signature -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= Signature -> Either SignetException Signature
forall a b. b -> Either a b
Right Signature
signature

    TestName -> Assertion -> Spec
Tasty.it TestName
"fails with an invalid timestamp" (Assertion -> Spec) -> Assertion -> Spec
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
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
$ TestName -> ByteString
Ascii.pack TestName
"whsec_bXlzZWNyZXRrZXkxMjM0NQ=="
      Message
message <- Either InvalidMessage Message -> IO Message
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidMessage Message -> IO Message)
-> (ByteString -> Either InvalidMessage Message)
-> ByteString
-> IO Message
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either InvalidMessage Message
Message.parse (ByteString -> IO Message) -> ByteString -> IO Message
forall a b. (a -> b) -> a -> b
$ TestName -> ByteString
Ascii.pack TestName
"i.301.Hello, world!"
      ([UnknownSignature]
_, Signatures
signatures) <- Either InvalidSignature ([UnknownSignature], Signatures)
-> IO ([UnknownSignature], Signatures)
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidSignature ([UnknownSignature], Signatures)
 -> IO ([UnknownSignature], Signatures))
-> (ByteString
    -> Either InvalidSignature ([UnknownSignature], Signatures))
-> ByteString
-> IO ([UnknownSignature], Signatures)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString
-> Either InvalidSignature ([UnknownSignature], Signatures)
Signatures.parse (ByteString -> IO ([UnknownSignature], Signatures))
-> ByteString -> IO ([UnknownSignature], Signatures)
forall a b. (a -> b) -> a -> b
$ TestName -> ByteString
Ascii.pack TestName
"v1,IywpE5NXy+JdAScgR7j5Pt59GjmazD7iJuVsQoRZFyw="
      let result :: Either SignetException Signature
result = Tolerance
-> UTCTime
-> Verifier
-> Message
-> Signatures
-> Either SignetException Signature
Signet.verifyWebhookWith Tolerance
tolerance UTCTime
now Verifier
verifier Message
message Signatures
signatures
      Either SignetException Signature
result Either SignetException Signature
-> Either SignetException Signature -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= SignetException -> Either SignetException Signature
forall a b. a -> Either a b
Left (ToleranceException -> SignetException
SignetException.ToleranceException (ToleranceException -> SignetException)
-> (Timestamp -> ToleranceException)
-> Timestamp
-> SignetException
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Timestamp -> ToleranceException
ToleranceException.MkToleranceException (Timestamp -> SignetException) -> Timestamp -> SignetException
forall a b. (a -> b) -> a -> b
$ Message -> Timestamp
Message.timestamp Message
message)

    TestName -> Assertion -> Spec
Tasty.it TestName
"fails with an invalid symmetric signature" (Assertion -> Spec) -> Assertion -> Spec
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
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
$ TestName -> ByteString
Ascii.pack TestName
"whsec_bXlzZWNyZXRrZXkxMjM0NQ=="
      Message
message <- Either InvalidMessage Message -> IO Message
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidMessage Message -> IO Message)
-> (ByteString -> Either InvalidMessage Message)
-> ByteString
-> IO Message
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Either InvalidMessage Message
Message.parse (ByteString -> IO Message) -> ByteString -> IO Message
forall a b. (a -> b) -> a -> b
$ TestName -> ByteString
Ascii.pack TestName
"i.0.Hello, world!"
      ([UnknownSignature]
_, Signatures
signatures) <- Either InvalidSignature ([UnknownSignature], Signatures)
-> IO ([UnknownSignature], Signatures)
forall e (m :: * -> *) a.
(Exception e, MonadThrow m) =>
Either e a -> m a
Either.throw (Either InvalidSignature ([UnknownSignature], Signatures)
 -> IO ([UnknownSignature], Signatures))
-> (ByteString
    -> Either InvalidSignature ([UnknownSignature], Signatures))
-> ByteString
-> IO ([UnknownSignature], Signatures)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString
-> Either InvalidSignature ([UnknownSignature], Signatures)
Signatures.parse (ByteString -> IO ([UnknownSignature], Signatures))
-> ByteString -> IO ([UnknownSignature], Signatures)
forall a b. (a -> b) -> a -> b
$ TestName -> ByteString
Ascii.pack TestName
"v1,0000000000000000000000000000000000000000000="
      let result :: Either SignetException Signature
result = Tolerance
-> UTCTime
-> Verifier
-> Message
-> Signatures
-> Either SignetException Signature
Signet.verifyWebhookWith Tolerance
tolerance UTCTime
now Verifier
verifier Message
message Signatures
signatures
      Either SignetException Signature
result Either SignetException Signature
-> Either SignetException Signature -> Assertion
forall a. (Eq a, Show a, HasCallStack) => a -> a -> Assertion
@?= SignetException -> Either SignetException Signature
forall a b. a -> Either a b
Left (VerificationException -> SignetException
SignetException.VerificationException (VerificationException -> SignetException)
-> (Id -> VerificationException) -> Id -> SignetException
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Id -> VerificationException
VerificationException.MkVerificationException (Id -> SignetException) -> Id -> SignetException
forall a b. (a -> b) -> a -> b
$ Message -> Id
Message.id_ Message
message)