amazonka-iam-policy 0.0.2 → 0.0.3
raw patch · 2 files changed
+160/−19 lines, 2 filesdep +hashablePVP ok
version bump matches the API change (PVP)
Dependencies added: hashable
API changes (from Hackage documentation)
+ Amazonka.IAM.Policy: [fromAction] :: Action -> Text
+ Amazonka.IAM.Policy: [fromResource] :: Resource -> Text
+ Amazonka.IAM.Policy: instance Data.Foldable.Foldable Amazonka.IAM.Policy.OneOrMany
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable Amazonka.IAM.Policy.Action
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable Amazonka.IAM.Policy.Condition
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable Amazonka.IAM.Policy.Effect
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable Amazonka.IAM.Policy.Id
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable Amazonka.IAM.Policy.Key
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable Amazonka.IAM.Policy.Principal
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable Amazonka.IAM.Policy.Resource
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable Amazonka.IAM.Policy.Sid
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable Amazonka.IAM.Policy.Statement
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable Amazonka.IAM.Policy.Version
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable a => Data.Hashable.Class.Hashable (Amazonka.IAM.Policy.Block a)
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable a => Data.Hashable.Class.Hashable (Amazonka.IAM.Policy.Match a)
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable a => Data.Hashable.Class.Hashable (Amazonka.IAM.Policy.OneOrMany a)
+ Amazonka.IAM.Policy: instance Data.Hashable.Class.Hashable a => Data.Hashable.Class.Hashable (Amazonka.IAM.Policy.Policy a)
+ Amazonka.IAM.Policy: instance Data.Traversable.Traversable Amazonka.IAM.Policy.OneOrMany
+ Amazonka.IAM.Policy: instance GHC.Base.Functor Amazonka.IAM.Policy.OneOrMany
+ Amazonka.IAM.Policy: instance GHC.Classes.Ord Amazonka.IAM.Policy.Action
+ Amazonka.IAM.Policy: instance GHC.Classes.Ord Amazonka.IAM.Policy.Condition
+ Amazonka.IAM.Policy: instance GHC.Classes.Ord Amazonka.IAM.Policy.Key
+ Amazonka.IAM.Policy: instance GHC.Classes.Ord Amazonka.IAM.Policy.Principal
+ Amazonka.IAM.Policy: instance GHC.Classes.Ord Amazonka.IAM.Policy.Resource
+ Amazonka.IAM.Policy: instance GHC.Classes.Ord Amazonka.IAM.Policy.Statement
+ Amazonka.IAM.Policy: instance GHC.Classes.Ord a => GHC.Classes.Ord (Amazonka.IAM.Policy.Block a)
+ Amazonka.IAM.Policy: instance GHC.Classes.Ord a => GHC.Classes.Ord (Amazonka.IAM.Policy.Match a)
+ Amazonka.IAM.Policy: instance GHC.Classes.Ord a => GHC.Classes.Ord (Amazonka.IAM.Policy.OneOrMany a)
+ Amazonka.IAM.Policy: instance GHC.Classes.Ord a => GHC.Classes.Ord (Amazonka.IAM.Policy.Policy a)
+ Amazonka.IAM.Policy: instance GHC.Generics.Generic (Amazonka.IAM.Policy.Block a)
+ Amazonka.IAM.Policy: instance GHC.Generics.Generic (Amazonka.IAM.Policy.Match a)
+ Amazonka.IAM.Policy: instance GHC.Generics.Generic (Amazonka.IAM.Policy.OneOrMany a)
+ Amazonka.IAM.Policy: instance GHC.Generics.Generic (Amazonka.IAM.Policy.Policy a)
+ Amazonka.IAM.Policy: instance GHC.Generics.Generic Amazonka.IAM.Policy.Condition
+ Amazonka.IAM.Policy: instance GHC.Generics.Generic Amazonka.IAM.Policy.Effect
+ Amazonka.IAM.Policy: instance GHC.Generics.Generic Amazonka.IAM.Policy.Principal
+ Amazonka.IAM.Policy: instance GHC.Generics.Generic Amazonka.IAM.Policy.Statement
+ Amazonka.IAM.Policy: instance GHC.Generics.Generic Amazonka.IAM.Policy.Version
Files
- amazonka-iam-policy.cabal +2/−1
- src/Amazonka/IAM/Policy.hs +158/−18
amazonka-iam-policy.cabal view
@@ -1,5 +1,5 @@ name: amazonka-iam-policy-version: 0.0.2+version: 0.0.3 synopsis: Amazon IAM Policy Document DSL and Combinators. homepage: https://github.com/brendanhay/amazonka-iam-policy bug-reports: https://github.com/brendanhay/amazonka-iam-policy/issues@@ -55,6 +55,7 @@ , base >= 4.7 && < 5 , base64-bytestring , bytestring+ , hashable , profunctors , scientific , text
src/Amazonka/IAM/Policy.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}@@ -91,6 +92,7 @@ import Data.Bifunctor (second) import Data.ByteString (ByteString) import Data.Function (on)+import Data.Hashable (Hashable (hashWithSalt)) import Data.List.NonEmpty (NonEmpty) import Data.Maybe (catMaybes) import Data.Scientific (Scientific, scientificP)@@ -99,7 +101,8 @@ import Data.Text (Text) import Data.Time (UTCTime) -import GHC.Exts (IsList (..))+import GHC.Exts (IsList (..))+import GHC.Generics (Generic) import qualified Data.Aeson as JSON import qualified Data.Aeson.Types as JSON@@ -107,8 +110,8 @@ import qualified Data.ByteString.Lazy as LBS import qualified Data.List.NonEmpty as NE import qualified Data.Text.Encoding as Text+import qualified Data.Time as Time import qualified Data.Time.Clock.POSIX as POSIX-import qualified Data.Time.Format as Time import qualified Text.ParserCombinators.ReadP as Read {- $setup@@ -317,8 +320,10 @@ data Block a = Match !(Match a) | Not !(Match a)- deriving (Show, Eq, Functor, Foldable, Traversable)+ deriving (Show, Eq, Ord, Generic, Functor, Foldable, Traversable) +instance Hashable a => Hashable (Block a)+ blockToJSON :: ToJSON a => Text -> Block a -> JSON.Pair blockToJSON k = \case Match v -> k .= v@@ -368,8 +373,10 @@ data Match a = Some !a | Wildcard- deriving (Show, Eq, Functor, Foldable, Traversable)+ deriving (Show, Eq, Ord, Generic, Functor, Foldable, Traversable) +instance Hashable a => Hashable (Match a)+ instance Semigroup a => Semigroup (Match a) where (<>) a b = case (a, b) of@@ -403,8 +410,10 @@ data OneOrMany a = One !a | Many ![a]- deriving (Show, Eq)+ deriving (Show, Eq, Ord, Generic, Functor, Foldable, Traversable) +instance Hashable a => Hashable (OneOrMany a)+ instance ToJSON a => ToJSON (OneOrMany a) where toJSON = \case One x -> toJSON x@@ -450,8 +459,10 @@ { version :: !(Maybe Version) , id :: !(Maybe Id) , statement :: !(NonEmpty a)- } deriving (Show, Eq, Functor, Foldable, Traversable)+ } deriving (Show, Eq, Ord, Generic, Functor, Foldable, Traversable) +instance Hashable a => Hashable (Policy a)+ -- FIXME: Note about pointwise 'First' behaviour of version/id. instance Semigroup (Policy a) where (<>) a b = Policy@@ -561,8 +572,10 @@ data Version = Version_2008_10_17 | Version_2012_10_17- deriving (Show, Eq, Ord)+ deriving (Show, Eq, Ord, Generic) +instance Hashable Version+ -- | '(<>)' always chooses the newest version. instance Semigroup Version where (<>) = max@@ -609,7 +622,7 @@ -} newtype Id = Id { fromId :: Text }- deriving (Show, Eq, Ord, ToJSON, FromJSON, IsString)+ deriving (Show, Eq, Ord, Hashable, ToJSON, FromJSON, IsString) {- | The 'Statement' element is the main element for a policy. This element is required. It can include multiple elements (see the subsequent sections in this@@ -636,8 +649,10 @@ , action :: !(Block [Action]) , resource :: !(Block [Resource]) , condition :: !(Maybe Condition)- } deriving (Show, Eq)+ } deriving (Show, Eq, Ord, Generic) +instance Hashable Statement+ instance ToJSON Statement where toJSON Statement{..} = let oneOrMany = fmap (fromList :: [a] -> OneOrMany a)@@ -718,7 +733,7 @@ -} newtype Sid = Sid { fromSid :: Text }- deriving (Show, Eq, Ord, ToJSON, FromJSON, IsString)+ deriving (Show, Eq, Ord, Hashable, ToJSON, FromJSON, IsString) {- | The 'Effect' element is required and specifies whether the statement results in an allow or an explicit deny.@@ -736,8 +751,10 @@ > <effect_block> = "Effect" : ("Allow" | "Deny") -} data Effect = Allow | Deny- deriving (Show, Eq, Ord, Enum)+ deriving (Show, Eq, Ord, Generic, Enum) +instance Hashable Effect+ instance ToJSON Effect where toJSON = \case Allow -> "Allow"@@ -822,8 +839,10 @@ | Federated !Text | Service !(NonEmpty Text) | CanonicalUser !Text- deriving (Show, Eq)+ deriving (Show, Eq, Ord, Generic) +instance Hashable Principal+ instance ToJSON Principal where toJSON = \case Everyone -> JSON.String "*"@@ -862,8 +881,8 @@ > ("*" | [<action_string>, <action_string>, ...]) -}-newtype Action = Action Text- deriving (Show, Eq, ToJSON, FromJSON, IsString)+newtype Action = Action { fromAction :: Text }+ deriving (Show, Eq, Ord, Hashable, ToJSON, FromJSON, IsString) {- | The 'Resource' element specifies the object or objects that the statement covers. Statements must include either a Resource or a NotResource element.@@ -887,12 +906,12 @@ > ("*" | [<resource_string>, <resource_string>, ...]) -}-newtype Resource = Resource Text- deriving (Show, Eq, ToJSON, FromJSON, IsString)+newtype Resource = Resource { fromResource :: Text }+ deriving (Show, Eq, Ord, Hashable, ToJSON, FromJSON, IsString) -- | A key that will be tested as the target of a 'Condition'. newtype Key = Key { fromKey :: Text }- deriving (Show, Eq, FromJSON, ToJSON, IsString)+ deriving (Show, Eq, Ord, Hashable, FromJSON, ToJSON, IsString) {- | The 'Condition' element (or Condition block) lets you specify conditions for when a policy is in effect. The Condition element is optional. In the@@ -1076,8 +1095,122 @@ -- ^ Negated matching for ARN. These behave identically. | ArnNotLike !Key !Text -- ^ Negated matching for ARN. These behave identically.- deriving (Show, Eq)+ deriving (Show, Eq, Ord, Generic) +instance Hashable Condition where+ hashWithSalt s = \case+ StringEquals k v ->+ s `hashWithSalt` (0 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ StringNotEquals k v ->+ s `hashWithSalt` (1 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ StringEqualsIgnoreCase k v ->+ s `hashWithSalt` (2 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ StringNotEqualsIgnoreCase k v ->+ s `hashWithSalt` (3 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ StringLike k vs ->+ s `hashWithSalt` (4 :: Int)+ `hashWithSalt` k+ `hashWithSalt` vs+ StringNotLike k vs ->+ s `hashWithSalt` (5 :: Int)+ `hashWithSalt` k+ `hashWithSalt` vs++ NumericEquals k v ->+ s `hashWithSalt` (6 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ NumericNotEquals k v ->+ s `hashWithSalt` (7 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ NumericLessThan k v ->+ s `hashWithSalt` (8 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ NumericLessThanEquals k v ->+ s `hashWithSalt` (9 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ NumericGreaterThan k v ->+ s `hashWithSalt` (10 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ NumericGreaterThanEquals k v ->+ s `hashWithSalt` (11 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v++ DateEquals k v ->+ s `hashWithSalt` (12 :: Int)+ `hashWithSalt` k+ `hashUTCTime` v+ DateNotEquals k v ->+ s `hashWithSalt` (13 :: Int)+ `hashWithSalt` k+ `hashUTCTime` v+ DateLessThan k v ->+ s `hashWithSalt` (14 :: Int)+ `hashWithSalt` k+ `hashUTCTime` v+ DateLessThanEquals k v ->+ s `hashWithSalt` (15 :: Int)+ `hashWithSalt` k+ `hashUTCTime` v+ DateGreaterThan k v ->+ s `hashWithSalt` (16 :: Int)+ `hashWithSalt` k+ `hashUTCTime` v+ DateGreaterThanEquals k v ->+ s `hashWithSalt` (17 :: Int)+ `hashWithSalt` k+ `hashUTCTime` v++ Bool k v ->+ s `hashWithSalt` (18 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v++ BinaryEquals k v ->+ s `hashWithSalt` (19 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v++ IpAddress k v ->+ s `hashWithSalt` (20 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ NotIpAddress k v ->+ s `hashWithSalt` (21 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v++ ArnEquals k v ->+ s `hashWithSalt` (22 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ ArnLike k v ->+ s `hashWithSalt` (23 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ ArnNotEquals k v ->+ s `hashWithSalt` (24 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ ArnNotLike k v ->+ s `hashWithSalt` (25 :: Int)+ `hashWithSalt` k+ `hashWithSalt` v+ {-# INLINEABLE hashWithSalt #-}+ instance ToJSON Condition where toJSON x = JSON.object [op .= JSON.object [key .= val]] where@@ -1256,3 +1389,10 @@ <|> fail ("Unrecognized Condition: " ++ show o) {-# INLINEABLE parseJSON #-}++infixl 0 `hashUTCTime`++hashUTCTime :: Int -> UTCTime -> Int+hashUTCTime s (Time.UTCTime (Time.ModifiedJulianDay day) diff) =+ s `hashWithSalt` day+ `hashWithSalt` (Time.diffTimeToPicoseconds diff)