{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RecordWildCards #-}
module Aws.Iam.Core
( iamSignQuery
, iamResponseConsumer
, IamMetadata(..)
, IamConfiguration(..)
, IamError(..)
, parseDateTime
, AccessKeyStatus(..)
, User(..)
, parseUser
, Group(..)
, parseGroup
, MfaDevice(..)
, parseMfaDevice
) where
import Aws.Core
import qualified Blaze.ByteString.Builder as Blaze
import qualified Blaze.ByteString.Builder.Char8 as Blaze8
import Control.Exception (Exception)
import Control.Monad
import Control.Monad.Trans.Resource (MonadThrow, throwM)
import Data.ByteString (ByteString)
import Data.IORef
import Data.List (intersperse, sort)
import Data.Maybe
import Data.Monoid ()
import qualified Data.Semigroup as Sem
import Data.Text (Text)
import qualified Data.Text as Text
import Data.Time
import Data.Typeable
import qualified Network.HTTP.Conduit as HTTP
import qualified Network.HTTP.Types as HTTP
#if !MIN_VERSION_time(1,5,0)
import System.Locale
#endif
import Text.XML.Cursor (($//))
import qualified Text.XML.Cursor as Cu
data IamError
= IamError {
IamError -> Status
iamStatusCode :: HTTP.Status
, IamError -> Text
iamErrorCode :: Text
, IamError -> Text
iamErrorMessage :: Text
}
deriving (Int -> IamError -> ShowS
[IamError] -> ShowS
IamError -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IamError] -> ShowS
$cshowList :: [IamError] -> ShowS
show :: IamError -> String
$cshow :: IamError -> String
showsPrec :: Int -> IamError -> ShowS
$cshowsPrec :: Int -> IamError -> ShowS
Show, Typeable)
instance Exception IamError
data IamMetadata
= IamMetadata {
IamMetadata -> Maybe Text
requestId :: Maybe Text
}
deriving (Int -> IamMetadata -> ShowS
[IamMetadata] -> ShowS
IamMetadata -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IamMetadata] -> ShowS
$cshowList :: [IamMetadata] -> ShowS
show :: IamMetadata -> String
$cshow :: IamMetadata -> String
showsPrec :: Int -> IamMetadata -> ShowS
$cshowsPrec :: Int -> IamMetadata -> ShowS
Show, Typeable)
instance Loggable IamMetadata where
toLogText :: IamMetadata -> Text
toLogText (IamMetadata Maybe Text
r) = Text
"IAM: request ID=" forall a. Semigroup a => a -> a -> a
Sem.<> forall a. a -> Maybe a -> a
fromMaybe Text
"<none>" Maybe Text
r
instance Sem.Semigroup IamMetadata where
IamMetadata Maybe Text
r1 <> :: IamMetadata -> IamMetadata -> IamMetadata
<> IamMetadata Maybe Text
r2 = Maybe Text -> IamMetadata
IamMetadata (Maybe Text
r1 forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
`mplus` Maybe Text
r2)
instance Monoid IamMetadata where
mempty :: IamMetadata
mempty = Maybe Text -> IamMetadata
IamMetadata forall a. Maybe a
Nothing
mappend :: IamMetadata -> IamMetadata -> IamMetadata
mappend = forall a. Semigroup a => a -> a -> a
(Sem.<>)
data IamConfiguration qt
= IamConfiguration {
forall qt. IamConfiguration qt -> ByteString
iamEndpoint :: ByteString
, forall qt. IamConfiguration qt -> Int
iamPort :: Int
, forall qt. IamConfiguration qt -> Protocol
iamProtocol :: Protocol
, forall qt. IamConfiguration qt -> Method
iamHttpMethod :: Method
}
deriving (Int -> IamConfiguration qt -> ShowS
forall qt. Int -> IamConfiguration qt -> ShowS
forall qt. [IamConfiguration qt] -> ShowS
forall qt. IamConfiguration qt -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [IamConfiguration qt] -> ShowS
$cshowList :: forall qt. [IamConfiguration qt] -> ShowS
show :: IamConfiguration qt -> String
$cshow :: forall qt. IamConfiguration qt -> String
showsPrec :: Int -> IamConfiguration qt -> ShowS
$cshowsPrec :: forall qt. Int -> IamConfiguration qt -> ShowS
Show)
instance DefaultServiceConfiguration (IamConfiguration NormalQuery) where
defServiceConfig :: IamConfiguration NormalQuery
defServiceConfig = forall qt. Method -> Protocol -> ByteString -> IamConfiguration qt
iam Method
PostQuery Protocol
HTTPS ByteString
iamEndpointDefault
debugServiceConfig :: IamConfiguration NormalQuery
debugServiceConfig = forall qt. Method -> Protocol -> ByteString -> IamConfiguration qt
iam Method
PostQuery Protocol
HTTP ByteString
iamEndpointDefault
instance DefaultServiceConfiguration (IamConfiguration UriOnlyQuery) where
defServiceConfig :: IamConfiguration UriOnlyQuery
defServiceConfig = forall qt. Method -> Protocol -> ByteString -> IamConfiguration qt
iam Method
Get Protocol
HTTPS ByteString
iamEndpointDefault
debugServiceConfig :: IamConfiguration UriOnlyQuery
debugServiceConfig = forall qt. Method -> Protocol -> ByteString -> IamConfiguration qt
iam Method
Get Protocol
HTTP ByteString
iamEndpointDefault
iamEndpointDefault :: ByteString
iamEndpointDefault :: ByteString
iamEndpointDefault = ByteString
"iam.amazonaws.com"
iam :: Method -> Protocol -> ByteString -> IamConfiguration qt
iam :: forall qt. Method -> Protocol -> ByteString -> IamConfiguration qt
iam Method
method Protocol
protocol ByteString
endpoint
= IamConfiguration {
iamEndpoint :: ByteString
iamEndpoint = ByteString
endpoint
, iamProtocol :: Protocol
iamProtocol = Protocol
protocol
, iamPort :: Int
iamPort = Protocol -> Int
defaultPort Protocol
protocol
, iamHttpMethod :: Method
iamHttpMethod = Method
method
}
iamSignQuery
:: [(ByteString, ByteString)]
-> IamConfiguration qt
-> SignatureData
-> SignedQuery
iamSignQuery :: forall qt.
[(ByteString, ByteString)]
-> IamConfiguration qt -> SignatureData -> SignedQuery
iamSignQuery [(ByteString, ByteString)]
q IamConfiguration{Int
ByteString
Method
Protocol
iamHttpMethod :: Method
iamProtocol :: Protocol
iamPort :: Int
iamEndpoint :: ByteString
iamHttpMethod :: forall qt. IamConfiguration qt -> Method
iamProtocol :: forall qt. IamConfiguration qt -> Protocol
iamPort :: forall qt. IamConfiguration qt -> Int
iamEndpoint :: forall qt. IamConfiguration qt -> ByteString
..} SignatureData{UTCTime
AbsoluteTimeInfo
Credentials
signatureCredentials :: SignatureData -> Credentials
signatureTime :: SignatureData -> UTCTime
signatureTimeInfo :: SignatureData -> AbsoluteTimeInfo
signatureCredentials :: Credentials
signatureTime :: UTCTime
signatureTimeInfo :: AbsoluteTimeInfo
..}
= SignedQuery {
sqMethod :: Method
sqMethod = Method
iamHttpMethod
, sqProtocol :: Protocol
sqProtocol = Protocol
iamProtocol
, sqHost :: ByteString
sqHost = ByteString
iamEndpoint
, sqPort :: Int
sqPort = Int
iamPort
, sqPath :: ByteString
sqPath = ByteString
"/"
, sqQuery :: [(ByteString, Maybe ByteString)]
sqQuery = [(ByteString, Maybe ByteString)]
signedQuery
, sqDate :: Maybe UTCTime
sqDate = forall a. a -> Maybe a
Just UTCTime
signatureTime
, sqAuthorization :: Maybe (IO ByteString)
sqAuthorization = forall a. Maybe a
Nothing
, sqContentType :: Maybe ByteString
sqContentType = forall a. Maybe a
Nothing
, sqContentMd5 :: Maybe (Digest MD5)
sqContentMd5 = forall a. Maybe a
Nothing
, sqAmzHeaders :: RequestHeaders
sqAmzHeaders = []
, sqOtherHeaders :: RequestHeaders
sqOtherHeaders = []
, sqBody :: Maybe RequestBody
sqBody = forall a. Maybe a
Nothing
, sqStringToSign :: ByteString
sqStringToSign = ByteString
stringToSign
}
where
sig :: ByteString
sig = Credentials -> AuthorizationHash -> ByteString -> ByteString
signature Credentials
signatureCredentials AuthorizationHash
HmacSHA256 ByteString
stringToSign
signedQuery :: [(ByteString, Maybe ByteString)]
signedQuery = (ByteString
"Signature", forall a. a -> Maybe a
Just ByteString
sig)forall a. a -> [a] -> [a]
:[(ByteString, Maybe ByteString)]
expandedQuery
accessKey :: ByteString
accessKey = Credentials -> ByteString
accessKeyID Credentials
signatureCredentials
timestampHeader :: (ByteString, Maybe ByteString)
timestampHeader =
case AbsoluteTimeInfo
signatureTimeInfo of
AbsoluteTimestamp UTCTime
time -> (ByteString
"Timestamp", forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ UTCTime -> ByteString
fmtAmzTime UTCTime
time)
AbsoluteExpires UTCTime
time -> (ByteString
"Expires" , forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ UTCTime -> ByteString
fmtAmzTime UTCTime
time)
newline :: Builder
newline = Char -> Builder
Blaze8.fromChar Char
'\n'
stringToSign :: ByteString
stringToSign = Builder -> ByteString
Blaze.toByteString forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Monoid a => [a] -> a
mconcat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> [a] -> [a]
intersperse Builder
newline forall a b. (a -> b) -> a -> b
$
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> Builder
Blaze.copyByteString
[Method -> ByteString
httpMethod Method
iamHttpMethod, ByteString
iamEndpoint, ByteString
"/"]
forall a. [a] -> [a] -> [a]
++ [Bool -> [(ByteString, Maybe ByteString)] -> Builder
HTTP.renderQueryBuilder Bool
False [(ByteString, Maybe ByteString)]
expandedQuery]
expandedQuery :: [(ByteString, Maybe ByteString)]
expandedQuery = forall a. QueryLike a => a -> [(ByteString, Maybe ByteString)]
HTTP.toQuery forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Ord a => [a] -> [a]
sort forall a b. (a -> b) -> a -> b
$ (forall a b. (a -> b) -> [a] -> [b]
map (\(ByteString
a,ByteString
b) -> (ByteString
a, forall a. a -> Maybe a
Just ByteString
b)) [(ByteString, ByteString)]
q forall a. [a] -> [a] -> [a]
++) [
(ByteString
"AWSAccessKeyId" , forall a. a -> Maybe a
Just ByteString
accessKey)
, (ByteString
"SignatureMethod" , forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ AuthorizationHash -> ByteString
amzHash AuthorizationHash
HmacSHA256)
, (ByteString
"SignatureVersion", forall a. a -> Maybe a
Just ByteString
"2")
, (ByteString
"Version" , forall a. a -> Maybe a
Just ByteString
"2010-05-08")
, (ByteString, Maybe ByteString)
timestampHeader] forall a. [a] -> [a] -> [a]
++
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (\ByteString
tok -> [ (ByteString
"SecurityToken", forall a. a -> Maybe a
Just ByteString
tok)]) (Credentials -> Maybe ByteString
iamToken Credentials
signatureCredentials)
iamResponseConsumer :: (Cu.Cursor -> Response IamMetadata a)
-> IORef IamMetadata
-> HTTPResponseConsumer a
iamResponseConsumer :: forall a.
(Cursor -> Response IamMetadata a)
-> IORef IamMetadata -> HTTPResponseConsumer a
iamResponseConsumer Cursor -> Response IamMetadata a
inner IORef IamMetadata
md Response (ConduitM () ByteString (ResourceT IO) ())
resp = forall m a.
Monoid m =>
(Cursor -> Response m a) -> IORef m -> HTTPResponseConsumer a
xmlCursorConsumer Cursor -> Response IamMetadata a
parse IORef IamMetadata
md Response (ConduitM () ByteString (ResourceT IO) ())
resp
where
parse :: Cursor -> Response IamMetadata a
parse Cursor
cursor = do
let rid :: Maybe Text
rid = forall a. [a] -> Maybe a
listToMaybe forall a b. (a -> b) -> a -> b
$ Cursor
cursor forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
"RequestID"
forall m. m -> Response m ()
tellMetadata forall a b. (a -> b) -> a -> b
$ Maybe Text -> IamMetadata
IamMetadata Maybe Text
rid
case Cursor
cursor forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Axis
Cu.laxElement Text
"Error" of
[] -> Cursor -> Response IamMetadata a
inner Cursor
cursor
(Cursor
err:[Cursor]
_) -> Cursor -> Response IamMetadata a
fromError Cursor
err
fromError :: Cursor -> Response IamMetadata a
fromError Cursor
cursor = do
Text
errCode <- forall (m :: * -> *) a. MonadThrow m => String -> [a] -> m a
force String
"Missing Error Code" forall a b. (a -> b) -> a -> b
$ Cursor
cursor forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
"Code"
Text
errMsg <- forall (m :: * -> *) a. MonadThrow m => String -> [a] -> m a
force String
"Missing Error Message" forall a b. (a -> b) -> a -> b
$ Cursor
cursor forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
"Message"
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM forall a b. (a -> b) -> a -> b
$ Status -> Text -> Text -> IamError
IamError (forall body. Response body -> Status
HTTP.responseStatus Response (ConduitM () ByteString (ResourceT IO) ())
resp) Text
errCode Text
errMsg
parseDateTime :: MonadThrow m => String -> m UTCTime
parseDateTime :: forall (m :: * -> *). MonadThrow m => String -> m UTCTime
parseDateTime String
x
= case forall (m :: * -> *) t.
(MonadFail m, ParseTime t) =>
Bool -> TimeLocale -> String -> String -> m t
parseTimeM Bool
True TimeLocale
defaultTimeLocale String
iso8601UtcDate String
x of
Maybe UTCTime
Nothing -> forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM forall a b. (a -> b) -> a -> b
$ String -> XmlException
XmlException forall a b. (a -> b) -> a -> b
$ String
"Invalid DateTime: " forall a. [a] -> [a] -> [a]
++ String
x
Just UTCTime
dt -> forall (m :: * -> *) a. Monad m => a -> m a
return UTCTime
dt
data User
= User {
User -> Text
userArn :: Text
, User -> UTCTime
userCreateDate :: UTCTime
, User -> Text
userPath :: Text
, User -> Text
userUserId :: Text
, User -> Text
userUserName :: Text
}
deriving (User -> User -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: User -> User -> Bool
$c/= :: User -> User -> Bool
== :: User -> User -> Bool
$c== :: User -> User -> Bool
Eq, Eq User
User -> User -> Bool
User -> User -> Ordering
User -> User -> User
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: User -> User -> User
$cmin :: User -> User -> User
max :: User -> User -> User
$cmax :: User -> User -> User
>= :: User -> User -> Bool
$c>= :: User -> User -> Bool
> :: User -> User -> Bool
$c> :: User -> User -> Bool
<= :: User -> User -> Bool
$c<= :: User -> User -> Bool
< :: User -> User -> Bool
$c< :: User -> User -> Bool
compare :: User -> User -> Ordering
$ccompare :: User -> User -> Ordering
Ord, Int -> User -> ShowS
[User] -> ShowS
User -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [User] -> ShowS
$cshowList :: [User] -> ShowS
show :: User -> String
$cshow :: User -> String
showsPrec :: Int -> User -> ShowS
$cshowsPrec :: Int -> User -> ShowS
Show, Typeable)
parseUser :: MonadThrow m => Cu.Cursor -> m User
parseUser :: forall (m :: * -> *). MonadThrow m => Cursor -> m User
parseUser Cursor
cursor = do
Text
userArn <- Text -> m Text
attr Text
"Arn"
UTCTime
userCreateDate <- Text -> m Text
attr Text
"CreateDate" forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *). MonadThrow m => String -> m UTCTime
parseDateTime forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
Text.unpack
Text
userPath <- Text -> m Text
attr Text
"Path"
Text
userUserId <- Text -> m Text
attr Text
"UserId"
Text
userUserName <- Text -> m Text
attr Text
"UserName"
forall (m :: * -> *) a. Monad m => a -> m a
return User{UTCTime
Text
userUserName :: Text
userUserId :: Text
userPath :: Text
userCreateDate :: UTCTime
userArn :: Text
userUserName :: Text
userUserId :: Text
userPath :: Text
userCreateDate :: UTCTime
userArn :: Text
..}
where
attr :: Text -> m Text
attr Text
name = forall (m :: * -> *) a. MonadThrow m => String -> [a] -> m a
force (String
"Missing " forall a. [a] -> [a] -> [a]
++ Text -> String
Text.unpack Text
name) forall a b. (a -> b) -> a -> b
$
Cursor
cursor forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
name
data Group
= Group {
Group -> Text
groupArn :: Text
, Group -> UTCTime
groupCreateDate :: UTCTime
, Group -> Text
groupPath :: Text
, Group -> Text
groupGroupId :: Text
, Group -> Text
groupGroupName :: Text
}
deriving (Group -> Group -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Group -> Group -> Bool
$c/= :: Group -> Group -> Bool
== :: Group -> Group -> Bool
$c== :: Group -> Group -> Bool
Eq, Eq Group
Group -> Group -> Bool
Group -> Group -> Ordering
Group -> Group -> Group
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Group -> Group -> Group
$cmin :: Group -> Group -> Group
max :: Group -> Group -> Group
$cmax :: Group -> Group -> Group
>= :: Group -> Group -> Bool
$c>= :: Group -> Group -> Bool
> :: Group -> Group -> Bool
$c> :: Group -> Group -> Bool
<= :: Group -> Group -> Bool
$c<= :: Group -> Group -> Bool
< :: Group -> Group -> Bool
$c< :: Group -> Group -> Bool
compare :: Group -> Group -> Ordering
$ccompare :: Group -> Group -> Ordering
Ord, Int -> Group -> ShowS
[Group] -> ShowS
Group -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Group] -> ShowS
$cshowList :: [Group] -> ShowS
show :: Group -> String
$cshow :: Group -> String
showsPrec :: Int -> Group -> ShowS
$cshowsPrec :: Int -> Group -> ShowS
Show, Typeable)
parseGroup :: MonadThrow m => Cu.Cursor -> m Group
parseGroup :: forall (m :: * -> *). MonadThrow m => Cursor -> m Group
parseGroup Cursor
cursor = do
Text
groupArn <- Text -> m Text
attr Text
"Arn"
UTCTime
groupCreateDate <- Text -> m Text
attr Text
"CreateDate" forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *). MonadThrow m => String -> m UTCTime
parseDateTime forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
Text.unpack
Text
groupPath <- Text -> m Text
attr Text
"Path"
Text
groupGroupId <- Text -> m Text
attr Text
"GroupId"
Text
groupGroupName <- Text -> m Text
attr Text
"GroupName"
forall (m :: * -> *) a. Monad m => a -> m a
return Group{UTCTime
Text
groupGroupName :: Text
groupGroupId :: Text
groupPath :: Text
groupCreateDate :: UTCTime
groupArn :: Text
groupGroupName :: Text
groupGroupId :: Text
groupPath :: Text
groupCreateDate :: UTCTime
groupArn :: Text
..}
where
attr :: Text -> m Text
attr Text
name = forall (m :: * -> *) a. MonadThrow m => String -> [a] -> m a
force (String
"Missing " forall a. [a] -> [a] -> [a]
++ Text -> String
Text.unpack Text
name) forall a b. (a -> b) -> a -> b
$
Cursor
cursor forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
name
data AccessKeyStatus = AccessKeyActive | AccessKeyInactive
deriving (AccessKeyStatus -> AccessKeyStatus -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AccessKeyStatus -> AccessKeyStatus -> Bool
$c/= :: AccessKeyStatus -> AccessKeyStatus -> Bool
== :: AccessKeyStatus -> AccessKeyStatus -> Bool
$c== :: AccessKeyStatus -> AccessKeyStatus -> Bool
Eq, Eq AccessKeyStatus
AccessKeyStatus -> AccessKeyStatus -> Bool
AccessKeyStatus -> AccessKeyStatus -> Ordering
AccessKeyStatus -> AccessKeyStatus -> AccessKeyStatus
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: AccessKeyStatus -> AccessKeyStatus -> AccessKeyStatus
$cmin :: AccessKeyStatus -> AccessKeyStatus -> AccessKeyStatus
max :: AccessKeyStatus -> AccessKeyStatus -> AccessKeyStatus
$cmax :: AccessKeyStatus -> AccessKeyStatus -> AccessKeyStatus
>= :: AccessKeyStatus -> AccessKeyStatus -> Bool
$c>= :: AccessKeyStatus -> AccessKeyStatus -> Bool
> :: AccessKeyStatus -> AccessKeyStatus -> Bool
$c> :: AccessKeyStatus -> AccessKeyStatus -> Bool
<= :: AccessKeyStatus -> AccessKeyStatus -> Bool
$c<= :: AccessKeyStatus -> AccessKeyStatus -> Bool
< :: AccessKeyStatus -> AccessKeyStatus -> Bool
$c< :: AccessKeyStatus -> AccessKeyStatus -> Bool
compare :: AccessKeyStatus -> AccessKeyStatus -> Ordering
$ccompare :: AccessKeyStatus -> AccessKeyStatus -> Ordering
Ord, Int -> AccessKeyStatus -> ShowS
[AccessKeyStatus] -> ShowS
AccessKeyStatus -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AccessKeyStatus] -> ShowS
$cshowList :: [AccessKeyStatus] -> ShowS
show :: AccessKeyStatus -> String
$cshow :: AccessKeyStatus -> String
showsPrec :: Int -> AccessKeyStatus -> ShowS
$cshowsPrec :: Int -> AccessKeyStatus -> ShowS
Show, Typeable)
data MfaDevice = MfaDevice
{ MfaDevice -> UTCTime
mfaEnableDate :: UTCTime
, MfaDevice -> Text
mfaSerialNumber :: Text
, MfaDevice -> Text
mfaUserName :: Text
} deriving (MfaDevice -> MfaDevice -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MfaDevice -> MfaDevice -> Bool
$c/= :: MfaDevice -> MfaDevice -> Bool
== :: MfaDevice -> MfaDevice -> Bool
$c== :: MfaDevice -> MfaDevice -> Bool
Eq, Eq MfaDevice
MfaDevice -> MfaDevice -> Bool
MfaDevice -> MfaDevice -> Ordering
MfaDevice -> MfaDevice -> MfaDevice
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MfaDevice -> MfaDevice -> MfaDevice
$cmin :: MfaDevice -> MfaDevice -> MfaDevice
max :: MfaDevice -> MfaDevice -> MfaDevice
$cmax :: MfaDevice -> MfaDevice -> MfaDevice
>= :: MfaDevice -> MfaDevice -> Bool
$c>= :: MfaDevice -> MfaDevice -> Bool
> :: MfaDevice -> MfaDevice -> Bool
$c> :: MfaDevice -> MfaDevice -> Bool
<= :: MfaDevice -> MfaDevice -> Bool
$c<= :: MfaDevice -> MfaDevice -> Bool
< :: MfaDevice -> MfaDevice -> Bool
$c< :: MfaDevice -> MfaDevice -> Bool
compare :: MfaDevice -> MfaDevice -> Ordering
$ccompare :: MfaDevice -> MfaDevice -> Ordering
Ord, Int -> MfaDevice -> ShowS
[MfaDevice] -> ShowS
MfaDevice -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MfaDevice] -> ShowS
$cshowList :: [MfaDevice] -> ShowS
show :: MfaDevice -> String
$cshow :: MfaDevice -> String
showsPrec :: Int -> MfaDevice -> ShowS
$cshowsPrec :: Int -> MfaDevice -> ShowS
Show, Typeable)
parseMfaDevice :: MonadThrow m => Cu.Cursor -> m MfaDevice
parseMfaDevice :: forall (m :: * -> *). MonadThrow m => Cursor -> m MfaDevice
parseMfaDevice Cursor
cursor = do
UTCTime
mfaEnableDate <- Text -> m Text
attr Text
"EnableDate" forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *). MonadThrow m => String -> m UTCTime
parseDateTime forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
Text.unpack
Text
mfaSerialNumber <- Text -> m Text
attr Text
"SerialNumber"
Text
mfaUserName <- Text -> m Text
attr Text
"UserName"
forall (m :: * -> *) a. Monad m => a -> m a
return MfaDevice{UTCTime
Text
mfaUserName :: Text
mfaSerialNumber :: Text
mfaEnableDate :: UTCTime
mfaUserName :: Text
mfaSerialNumber :: Text
mfaEnableDate :: UTCTime
..}
where attr :: Text -> m Text
attr Text
name = forall (m :: * -> *) a. MonadThrow m => String -> [a] -> m a
force (String
"Missing " forall a. [a] -> [a] -> [a]
++ Text -> String
Text.unpack Text
name) forall a b. (a -> b) -> a -> b
$
Cursor
cursor forall node a. Cursor node -> (Cursor node -> [a]) -> [a]
$// Text -> Cursor -> [Text]
elContent Text
name