git.iko.soy/typeable/swagger2
on master help sign in
.gitignore+1−1
since splitsnapshots
unifiedsplit
@@ -16,4 +16,4 @@ cabal.sandbox.config
16*.prof
16*.prof
17*.aux
17*.aux
18*.hp
18*.hp
19−.stack-work/
19+.stack-work/
src/Data/Swagger.hs+2−1
@@ -89,6 +89,7 @@ module Data.Swagger (
89 SecurityScheme(..),
89 SecurityScheme(..),
90 SecuritySchemeType(..),
90 SecuritySchemeType(..),
91 SecurityRequirement(..),
91 SecurityRequirement(..),
92+ SecurityDefinitions(..),
92
93
93 -- *** API key
94 -- *** API key
94 ApiKeyParams(..),
95 ApiKeyParams(..),
@@ -279,7 +280,7 @@ import Data.Swagger.Internal
279-- >>> encode $ toSchema (Proxy :: Proxy Person)
280-- >>> encode $ toSchema (Proxy :: Proxy Person)
280-- "{\"required\":[\"name\",\"age\"],\"properties\":{\"name\":{\"type\":\"string\"},\"age\":{\"type\":\"integer\"}},\"type\":\"object\"}"
281-- "{\"required\":[\"name\",\"age\"],\"properties\":{\"name\":{\"type\":\"string\"},\"age\":{\"type\":\"integer\"}},\"type\":\"object\"}"
281--
282--
282−-- Please note that not all valid Haskell data types will have a proper swagger schema. For example while we can derive a
283+-- Please note that not all valid Haskell data types will have a proper swagger schema. For example while we can derive a
283-- schema for basic enums like
284-- schema for basic enums like
284--
285--
285-- >>> data SampleEnum = ChoiceOne | ChoiceTwo deriving Generic
286-- >>> data SampleEnum = ChoiceOne | ChoiceTwo deriving Generic
src/Data/Swagger/Internal.hs+36−13
@@ -117,7 +117,7 @@ data Swagger = Swagger
117 , _swaggerResponses :: Definitions Response
117 , _swaggerResponses :: Definitions Response
118
118
119 -- | Security scheme definitions that can be used across the specification.
119 -- | Security scheme definitions that can be used across the specification.
120− , _swaggerSecurityDefinitions :: Definitions SecurityScheme
120+ , _swaggerSecurityDefinitions :: SecurityDefinitions
121
121
122 -- | A declaration of which security schemes are applied for the API as a whole.
122 -- | A declaration of which security schemes are applied for the API as a whole.
123 -- The list of values describes alternative security schemes that can be used
123 -- The list of values describes alternative security schemes that can be used
@@ -755,6 +755,22 @@ data SecurityScheme = SecurityScheme
755 , _securitySchemeDescription :: Maybe Text
755 , _securitySchemeDescription :: Maybe Text
756 } deriving (Eq, Show, Generic, Data, Typeable)
756 } deriving (Eq, Show, Generic, Data, Typeable)
757
757
758+
759+-- | merge scopes of two OAuth2 security schemes when their flows are identical.
760+-- In other case returns first security scheme
761+mergeSecurityScheme :: SecurityScheme -> SecurityScheme -> SecurityScheme
762+mergeSecurityScheme s1@(SecurityScheme (SecuritySchemeOAuth2 (OAuth2Params flow1 scopes1)) desc)
763+ s2@(SecurityScheme (SecuritySchemeOAuth2 (OAuth2Params flow2 scopes2)) _)
764+ = if flow1 == flow2 then
765+ SecurityScheme (SecuritySchemeOAuth2 (OAuth2Params flow1 (scopes1 <> scopes2))) desc
766+ else
767+ s1
768+mergeSecurityScheme s1 _ = s1
769+
770+newtype SecurityDefinitions
771+ = SecurityDefinitions (Definitions SecurityScheme)
772+ deriving (Eq, Show, Generic, Data, Typeable)
773+
758-- | Lists the required security schemes to execute this operation.
774-- | Lists the required security schemes to execute this operation.
759-- The object can have multiple security schemes declared in it which are all required
775-- The object can have multiple security schemes declared in it which are all required
760-- (that is, there is a logical AND between the schemes).
776-- (that is, there is a logical AND between the schemes).
@@ -904,6 +920,17 @@ instance Monoid Example where
904 mempty = genericMempty
920 mempty = genericMempty
905 mappend = (<>)
921 mappend = (<>)
906
922
923+instance Semigroup SecurityScheme where
924+ (<>) = mergeSecurityScheme
925+
926+instance Semigroup SecurityDefinitions where
927+ (SecurityDefinitions sd1) <> (SecurityDefinitions sd2) =
928+ SecurityDefinitions $ InsOrdHashMap.unionWith (<>) sd1 sd2
929+
930+instance Monoid SecurityDefinitions where
931+ mempty = SecurityDefinitions $ InsOrdHashMap.empty
932+ mappend = (<>)
933+
907-- =======================================================================
934-- =======================================================================
908-- SwaggerMonoid helper instances
935-- SwaggerMonoid helper instances
909-- =======================================================================
936-- =======================================================================
@@ -918,6 +945,7 @@ instance SwaggerMonoid Responses
918instance SwaggerMonoid Response
945instance SwaggerMonoid Response
919instance SwaggerMonoid ExternalDocs
946instance SwaggerMonoid ExternalDocs
920instance SwaggerMonoid Operation
947instance SwaggerMonoid Operation
948+instance SwaggerMonoid SecurityDefinitions
921instance (Eq a, Hashable a) => SwaggerMonoid (InsOrdHashSet a)
949instance (Eq a, Hashable a) => SwaggerMonoid (InsOrdHashSet a)
922
950
923instance SwaggerMonoid MimeList
951instance SwaggerMonoid MimeList
@@ -935,18 +963,6 @@ instance OVERLAPPING_ SwaggerMonoid (InsOrdHashMap FilePath PathItem) where
935 swaggerMempty = InsOrdHashMap.empty
963 swaggerMempty = InsOrdHashMap.empty
936 swaggerMappend = InsOrdHashMap.unionWith mappend
964 swaggerMappend = InsOrdHashMap.unionWith mappend
937
965
938−instance OVERLAPPING_ SwaggerMonoid (InsOrdHashMap Text SecurityScheme) where
939− swaggerMempty = InsOrdHashMap.empty
940− swaggerMappend = InsOrdHashMap.unionWith mergeFun
941− where
942− mergeFun s1@(SecurityScheme (SecuritySchemeOAuth2 (OAuth2Params flow1 scopes1)) desc)
943− s2@(SecurityScheme (SecuritySchemeOAuth2 (OAuth2Params flow2 scopes2)) _)
944− = if flow1 == flow2 then
945− SecurityScheme (SecuritySchemeOAuth2 (OAuth2Params flow1 (scopes1 <> scopes2))) desc
946− else
947− s2
948− mergeFun _ ss = ss
949−
950instance Monoid a => SwaggerMonoid (Referenced a) where
966instance Monoid a => SwaggerMonoid (Referenced a) where
951 swaggerMempty = Inline mempty
967 swaggerMempty = Inline mempty
952 swaggerMappend (Inline x) (Inline y) = Inline (mappend x y)
968 swaggerMappend (Inline x) (Inline y) = Inline (mappend x y)
@@ -1130,6 +1146,9 @@ instance ToJSON PathItem where
1130instance ToJSON Example where
1146instance ToJSON Example where
1131 toJSON = toJSON . Map.mapKeys show . getExample
1147 toJSON = toJSON . Map.mapKeys show . getExample
1132
1148
1149+instance ToJSON SecurityDefinitions where
1150+ toJSON (SecurityDefinitions sd) = toJSON sd
1151+
1133instance ToJSON Reference where
1152instance ToJSON Reference where
1134 toJSON (Reference ref) = object [ "$ref" .= ref ]
1153 toJSON (Reference ref) = object [ "$ref" .= ref ]
1135
1154
@@ -1291,6 +1310,9 @@ instance FromJSON Operation where
1291instance FromJSON PathItem where
1310instance FromJSON PathItem where
1292 parseJSON = sopSwaggerGenericParseJSON
1311 parseJSON = sopSwaggerGenericParseJSON
1293
1312
1313+instance FromJSON SecurityDefinitions where
1314+ parseJSON js = SecurityDefinitions <$> parseJSON js
1315+
1294instance FromJSON Reference where
1316instance FromJSON Reference where
1295 parseJSON (Object o) = Reference <$> o .: "$ref"
1317 parseJSON (Object o) = Reference <$> o .: "$ref"
1296 parseJSON _ = empty
1318 parseJSON _ = empty
@@ -1402,3 +1424,4 @@ instance AesonDefaultValue (SwaggerType a)
1402instance AesonDefaultValue MimeList where defaultValue = Just mempty
1424instance AesonDefaultValue MimeList where defaultValue = Just mempty
1403instance AesonDefaultValue Info
1425instance AesonDefaultValue Info
1404instance AesonDefaultValue ParamLocation
1426instance AesonDefaultValue ParamLocation
1427+instance AesonDefaultValue SecurityDefinitions where defaultValue = Just $ SecurityDefinitions mempty
src/Data/Swagger/Lens.hs+6
@@ -96,6 +96,12 @@ instance At Responses where at n = responses . at n
96instance Ixed Operation where ix n = responses . ix n
96instance Ixed Operation where ix n = responses . ix n
97instance At Operation where at n = responses . at n
97instance At Operation where at n = responses . at n
98
98
99+type instance Index SecurityDefinitions = Text
100+type instance IxValue SecurityDefinitions = SecurityScheme
101+
102+instance Ixed SecurityDefinitions where ix n = (coerced :: Lens' SecurityDefinitions (Definitions SecurityScheme)). ix n
103+instance At SecurityDefinitions where at n = (coerced :: Lens' SecurityDefinitions (Definitions SecurityScheme)). at n
104+
99instance HasParamSchema NamedSchema (ParamSchema 'SwaggerKindSchema) where paramSchema = schema.paramSchema
105instance HasParamSchema NamedSchema (ParamSchema 'SwaggerKindSchema) where paramSchema = schema.paramSchema
100
106
101-- HasType instances
107-- HasType instances
test/Data/SwaggerSpec.hs+43−2
@@ -43,6 +43,7 @@ spec = do
43 describe "Parameters Definition Object" $ paramsDefinitionExample <=> paramsDefinitionExampleJSON
43 describe "Parameters Definition Object" $ paramsDefinitionExample <=> paramsDefinitionExampleJSON
44 describe "Responses Definition Object" $ responsesDefinitionExample <=> responsesDefinitionExampleJSON
44 describe "Responses Definition Object" $ responsesDefinitionExample <=> responsesDefinitionExampleJSON
45 describe "Security Definitions Object" $ securityDefinitionsExample <=> securityDefinitionsExampleJSON
45 describe "Security Definitions Object" $ securityDefinitionsExample <=> securityDefinitionsExampleJSON
46+ describe "OAuth2 Security Definitions with merged Scope" $ oAuth2SecurityDefinitionsExample <=> oAuth2SecurityDefinitionsExampleJSON
46 describe "Composition Schema Example" $ compositionSchemaExample <=> compositionSchemaExampleJSON
47 describe "Composition Schema Example" $ compositionSchemaExample <=> compositionSchemaExampleJSON
47 describe "Swagger Object" $ do
48 describe "Swagger Object" $ do
48 context "Todo Example" $ swaggerExample <=> swaggerExampleJSON
49 context "Todo Example" $ swaggerExample <=> swaggerExampleJSON
@@ -459,8 +460,8 @@ responsesDefinitionExampleJSON = [aesonQQ|
459-- Responses Definition object
460-- Responses Definition object
460-- =======================================================================
461-- =======================================================================
461
462
462−securityDefinitionsExample :: HashMap Text SecurityScheme
463+securityDefinitionsExample :: SecurityDefinitions
463−securityDefinitionsExample =
464+securityDefinitionsExample = SecurityDefinitions
464 [ ("api_key", SecurityScheme
465 [ ("api_key", SecurityScheme
465 { _securitySchemeType = SecuritySchemeApiKey (ApiKeyParams "api_key" ApiKeyHeader)
466 { _securitySchemeType = SecuritySchemeApiKey (ApiKeyParams "api_key" ApiKeyHeader)
466 , _securitySchemeDescription = Nothing })
467 , _securitySchemeDescription = Nothing })
@@ -492,6 +493,46 @@ securityDefinitionsExampleJSON = [aesonQQ|
492}
493}
493|]
494|]
494
495
496+oAuth2SecurityDefinitionsReadExample :: SecurityDefinitions
497+oAuth2SecurityDefinitionsReadExample = SecurityDefinitions
498+ [ ("petstore_auth", SecurityScheme
499+ { _securitySchemeType = SecuritySchemeOAuth2 (OAuth2Params
500+ { _oauth2Flow = OAuth2Implicit "http://swagger.io/api/oauth/dialog"
501+ , _oauth2Scopes =
502+ [ ("read:pets", "read your pets") ] } )
503+ , _securitySchemeDescription = Nothing })
504+ ]
505+
506+oAuth2SecurityDefinitionsWriteExample :: SecurityDefinitions
507+oAuth2SecurityDefinitionsWriteExample = SecurityDefinitions
508+ [ ("petstore_auth", SecurityScheme
509+ { _securitySchemeType = SecuritySchemeOAuth2 (OAuth2Params
510+ { _oauth2Flow = OAuth2Implicit "http://swagger.io/api/oauth/dialog"
511+ , _oauth2Scopes =
512+ [ ("write:pets", "modify pets in your account") ] } )
513+ , _securitySchemeDescription = Nothing })
514+ ]
515+
516+oAuth2SecurityDefinitionsExample :: SecurityDefinitions
517+oAuth2SecurityDefinitionsExample =
518+ oAuth2SecurityDefinitionsWriteExample <>
519+ oAuth2SecurityDefinitionsReadExample
520+
521+oAuth2SecurityDefinitionsExampleJSON :: Value
522+oAuth2SecurityDefinitionsExampleJSON = [aesonQQ|
523+{
524+ "petstore_auth": {
525+ "type": "oauth2",
526+ "authorizationUrl": "http://swagger.io/api/oauth/dialog",
527+ "flow": "implicit",
528+ "scopes": {
529+ "write:pets": "modify pets in your account",
530+ "read:pets": "read your pets"
531+ }
532+ }
533+}
534+|]
535+
495-- =======================================================================
536-- =======================================================================
496-- Swagger object
537-- Swagger object
497-- =======================================================================
538-- =======================================================================