-- | Stability: experimental
-- This module provides functions for encoding and decoding WebAuthn enum types
-- between their Haskell types defined in "Crypto.WebAuthn.Model.Types" and
-- their string forms.
module Crypto.WebAuthn.Encoding.Strings
  ( encodeCredentialType,
    decodeCredentialType,
    encodeUserVerificationRequirement,
    decodeUserVerificationRequirement,
    encodeAuthenticatorAttachment,
    decodeAuthenticatorAttachment,
    encodeResidentKeyRequirement,
    decodeResidentKeyRequirement,
    encodeAttestationConveyancePreference,
    decodeAttestationConveyancePreference,
    encodeAuthenticatorTransport,
    decodeAuthenticatorTransport,
  )
where

import qualified Crypto.WebAuthn.Model.Types as T
import Data.Text (Text)

-- | [(spec)](https://www.w3.org/TR/webauthn-2/#enumdef-publickeycredentialtype)
-- Encodes a 'T.CredentialType' to a string.
encodeCredentialType :: T.CredentialType -> Text
encodeCredentialType :: CredentialType -> Text
encodeCredentialType CredentialType
T.CredentialTypePublicKey = Text
"public-key"

-- | [(spec)](https://www.w3.org/TR/webauthn-2/#enumdef-publickeycredentialtype)
-- Decodes a string into a 'T.CredentialType', returning 'Left' when the string
-- isn't known to be an enum value.
decodeCredentialType :: Text -> Either Text T.CredentialType
decodeCredentialType :: Text -> Either Text CredentialType
decodeCredentialType Text
"public-key" = forall (f :: * -> *) a. Applicative f => a -> f a
pure CredentialType
T.CredentialTypePublicKey
decodeCredentialType Text
str = forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Text
"Unknown PublicKeyCredentialType string: " forall a. Semigroup a => a -> a -> a
<> Text
str

-- | [(spec)](https://www.w3.org/TR/webauthn-2/#enum-userVerificationRequirement)
-- Encodes a 'T.UserVerificationRequirement' to a string.
encodeUserVerificationRequirement :: T.UserVerificationRequirement -> Text
encodeUserVerificationRequirement :: UserVerificationRequirement -> Text
encodeUserVerificationRequirement UserVerificationRequirement
T.UserVerificationRequirementRequired = Text
"required"
encodeUserVerificationRequirement UserVerificationRequirement
T.UserVerificationRequirementPreferred = Text
"preferred"
encodeUserVerificationRequirement UserVerificationRequirement
T.UserVerificationRequirementDiscouraged = Text
"discouraged"

-- | [(spec)](https://www.w3.org/TR/webauthn-2/#enum-userVerificationRequirement)
-- Decodes a string into a 'T.UserVerificationRequirement', returning 'Left' when
-- the string isn't known to be an enum value.
decodeUserVerificationRequirement :: Text -> Either Text T.UserVerificationRequirement
decodeUserVerificationRequirement :: Text -> Either Text UserVerificationRequirement
decodeUserVerificationRequirement Text
"discouraged" = forall (f :: * -> *) a. Applicative f => a -> f a
pure UserVerificationRequirement
T.UserVerificationRequirementDiscouraged
decodeUserVerificationRequirement Text
"preferred" = forall (f :: * -> *) a. Applicative f => a -> f a
pure UserVerificationRequirement
T.UserVerificationRequirementPreferred
decodeUserVerificationRequirement Text
"required" = forall (f :: * -> *) a. Applicative f => a -> f a
pure UserVerificationRequirement
T.UserVerificationRequirementRequired
decodeUserVerificationRequirement Text
str = forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Text
"Unknown UserVerificationRequirement string: " forall a. Semigroup a => a -> a -> a
<> Text
str

-- | [(spec)](https://www.w3.org/TR/webauthn-2/#enumdef-authenticatorattachment)
-- Encodes a 'T.AuthenticatorAttachment' to a string.
encodeAuthenticatorAttachment :: T.AuthenticatorAttachment -> Text
encodeAuthenticatorAttachment :: AuthenticatorAttachment -> Text
encodeAuthenticatorAttachment AuthenticatorAttachment
T.AuthenticatorAttachmentPlatform = Text
"platform"
encodeAuthenticatorAttachment AuthenticatorAttachment
T.AuthenticatorAttachmentCrossPlatform = Text
"cross-platform"

-- | [(spec)](https://www.w3.org/TR/webauthn-2/#enumdef-authenticatorattachment)
-- Decodes a string into a 'T.AuthenticatorAttachment', returning 'Left' when
-- the string isn't known to be an enum value.
decodeAuthenticatorAttachment :: Text -> Either Text T.AuthenticatorAttachment
decodeAuthenticatorAttachment :: Text -> Either Text AuthenticatorAttachment
decodeAuthenticatorAttachment Text
"platform" = forall (f :: * -> *) a. Applicative f => a -> f a
pure AuthenticatorAttachment
T.AuthenticatorAttachmentPlatform
decodeAuthenticatorAttachment Text
"cross-platform" = forall (f :: * -> *) a. Applicative f => a -> f a
pure AuthenticatorAttachment
T.AuthenticatorAttachmentCrossPlatform
decodeAuthenticatorAttachment Text
str = forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Text
"Unknown AuthenticatorAttachment string: " forall a. Semigroup a => a -> a -> a
<> Text
str

-- | [(spec)](https://www.w3.org/TR/webauthn-2/#enum-residentKeyRequirement)
-- Encodes a 'T.ResidentKeyRequirement' to a string.
encodeResidentKeyRequirement :: T.ResidentKeyRequirement -> Text
encodeResidentKeyRequirement :: ResidentKeyRequirement -> Text
encodeResidentKeyRequirement ResidentKeyRequirement
T.ResidentKeyRequirementDiscouraged = Text
"discouraged"
encodeResidentKeyRequirement ResidentKeyRequirement
T.ResidentKeyRequirementPreferred = Text
"preferred"
encodeResidentKeyRequirement ResidentKeyRequirement
T.ResidentKeyRequirementRequired = Text
"required"

-- | [(spec)](https://www.w3.org/TR/webauthn-2/#enum-residentKeyRequirement)
-- Decodes a string into a 'T.ResidentKeyRequirement', returning 'Left' when
-- the string isn't known to be an enum value.
decodeResidentKeyRequirement :: Text -> Either Text T.ResidentKeyRequirement
decodeResidentKeyRequirement :: Text -> Either Text ResidentKeyRequirement
decodeResidentKeyRequirement Text
"discouraged" = forall (f :: * -> *) a. Applicative f => a -> f a
pure ResidentKeyRequirement
T.ResidentKeyRequirementDiscouraged
decodeResidentKeyRequirement Text
"preferred" = forall (f :: * -> *) a. Applicative f => a -> f a
pure ResidentKeyRequirement
T.ResidentKeyRequirementPreferred
decodeResidentKeyRequirement Text
"required" = forall (f :: * -> *) a. Applicative f => a -> f a
pure ResidentKeyRequirement
T.ResidentKeyRequirementRequired
decodeResidentKeyRequirement Text
str = forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Text
"Unknown ResidentKeyRequirement string: " forall a. Semigroup a => a -> a -> a
<> Text
str

-- | [(spec)](https://www.w3.org/TR/webauthn-2/#enum-attestation-convey)
-- Encodes a 'T.AttestationConveyancePreference' to a string.
encodeAttestationConveyancePreference :: T.AttestationConveyancePreference -> Text
encodeAttestationConveyancePreference :: AttestationConveyancePreference -> Text
encodeAttestationConveyancePreference AttestationConveyancePreference
T.AttestationConveyancePreferenceNone = Text
"none"
encodeAttestationConveyancePreference AttestationConveyancePreference
T.AttestationConveyancePreferenceIndirect = Text
"indirect"
encodeAttestationConveyancePreference AttestationConveyancePreference
T.AttestationConveyancePreferenceDirect = Text
"direct"
encodeAttestationConveyancePreference AttestationConveyancePreference
T.AttestationConveyancePreferenceEnterprise = Text
"enterprise"

-- | [(spec)](https://www.w3.org/TR/webauthn-2/#enum-attestation-convey)
-- Decodes a string into a 'T.AttestationConveyancePreference', returning 'Left' when
-- the string isn't known to be an enum value.
decodeAttestationConveyancePreference :: Text -> Either Text T.AttestationConveyancePreference
decodeAttestationConveyancePreference :: Text -> Either Text AttestationConveyancePreference
decodeAttestationConveyancePreference Text
"none" = forall (f :: * -> *) a. Applicative f => a -> f a
pure AttestationConveyancePreference
T.AttestationConveyancePreferenceNone
decodeAttestationConveyancePreference Text
"indirect" = forall (f :: * -> *) a. Applicative f => a -> f a
pure AttestationConveyancePreference
T.AttestationConveyancePreferenceIndirect
decodeAttestationConveyancePreference Text
"direct" = forall (f :: * -> *) a. Applicative f => a -> f a
pure AttestationConveyancePreference
T.AttestationConveyancePreferenceDirect
decodeAttestationConveyancePreference Text
"enterprise" = forall (f :: * -> *) a. Applicative f => a -> f a
pure AttestationConveyancePreference
T.AttestationConveyancePreferenceEnterprise
decodeAttestationConveyancePreference Text
str = forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ Text
"Unknown AttestationConveyancePreference string: " forall a. Semigroup a => a -> a -> a
<> Text
str

-- | [(spec)](https://www.w3.org/TR/webauthn-2/#enumdef-authenticatortransport)
-- Encodes a 'T.AuthenticatorTransport' to a string.
encodeAuthenticatorTransport :: T.AuthenticatorTransport -> Text
encodeAuthenticatorTransport :: AuthenticatorTransport -> Text
encodeAuthenticatorTransport AuthenticatorTransport
T.AuthenticatorTransportUSB = Text
"usb"
encodeAuthenticatorTransport AuthenticatorTransport
T.AuthenticatorTransportNFC = Text
"nfc"
encodeAuthenticatorTransport AuthenticatorTransport
T.AuthenticatorTransportBLE = Text
"ble"
encodeAuthenticatorTransport AuthenticatorTransport
T.AuthenticatorTransportInternal = Text
"internal"
encodeAuthenticatorTransport (T.AuthenticatorTransportUnknown Text
str) = Text
str

-- | [(spec)](https://www.w3.org/TR/webauthn-2/#enumdef-authenticatortransport)
-- Decodes a string into a 'T.AuthenticatorTransport', returning
-- 'T.AuthenticatorTransportUnknown' when the string isn't known to be an enum
-- value. This is required so that relying parties can still store unknown
-- values, see
-- [transports](https://www.w3.org/TR/webauthn-2/#dom-authenticatorattestationresponse-transports-slot)
-- and the clarification to that section
-- [here](https://github.com/w3c/webauthn/pull/1654)
decodeAuthenticatorTransport :: Text -> T.AuthenticatorTransport
decodeAuthenticatorTransport :: Text -> AuthenticatorTransport
decodeAuthenticatorTransport Text
"usb" = AuthenticatorTransport
T.AuthenticatorTransportUSB
decodeAuthenticatorTransport Text
"nfc" = AuthenticatorTransport
T.AuthenticatorTransportNFC
decodeAuthenticatorTransport Text
"ble" = AuthenticatorTransport
T.AuthenticatorTransportBLE
decodeAuthenticatorTransport Text
"internal" = AuthenticatorTransport
T.AuthenticatorTransportInternal
-- <https://www.w3.org/TR/webauthn-2/#dom-authenticatorattestationresponse-transports-slot>
-- mentions:
--
-- > The values SHOULD be members of AuthenticatorTransport but Relying Parties
-- > MUST ignore unknown values.
--
-- This is a small bug in the standard however, see
-- https://github.com/w3c/webauthn/pull/1654 which changes it to
--
-- > The values SHOULD be members of AuthenticatorTransport but Relying
-- > Parties SHOULD accept and store unknown values.
decodeAuthenticatorTransport Text
str = Text -> AuthenticatorTransport
T.AuthenticatorTransportUnknown Text
str