/
swagger.clj
130 lines (121 loc) · 6.35 KB
/
swagger.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
(ns kaleidoscope.clj.http-api.swagger
(:require [compojure.api.middleware :as mw]
[compojure.api.swagger :as swag]
[compojure.api.sweet :refer [GET routes undocumented]]
[ring.swagger.common :as rsc]
[ring.swagger.middleware :as rsm]
[ring.swagger.swagger-ui :as swagger-ui]
[ring.swagger.swagger2 :as swagger2]
[ring.util.http-response :refer [ok]]
[spec-tools.core :as st-core]
[spec-tools.swagger.core :as st]))
(def example-data-2
{:kaleidoscope.article/article {:summary "An example article"
:value {:id 10
:article_tags "thoughts"
:article_url "my-test-article"
:author "Andrew Lai"
:content "<h1>Hello world!</h1>"
:timestamp "2020-10-28T00:00:00"
:title "My test article"}}})
(defn extract-specs [swagger]
(reduce (fn [acc [_ {{schemas :schemas} :components :as x}]]
(if schemas
(conj acc schemas)
acc))
{}
(mapcat second (:paths swagger))))
(defn specs->components [swagger-specs]
(reduce-kv (fn [acc k v]
(assoc acc
k (-> v st-core/create-spec st/transform)))
{}
swagger-specs))
(def security-schemes
"This works in conjunction with the `/resources/swagger-ui/index.html` to
initialize the basic security scheme for PKCE. In addition to doing this, we
also need to do some initialization in order to use PKCE.
See https://swagger.io/docs/open-source-tools/swagger-ui/usage/oauth2/"
{:andrewslai-pkce
{:type "oauth2"
:flows {:authorizationCode {:authorizationUrl "https://keycloak.andrewslai.com/auth/realms/andrewslai/protocol/openid-connect/auth"
:tokenUrl "https://keycloak.andrewslai.com/auth/realms/andrewslai/protocol/openid-connect/token"
:scopes {"profile" "A users profile"
"roles" "View users roles"}}}}})
#_{:type "openIdConnect"
:openIdConnectUrl "https://keycloak.andrewslai.com/auth/realms/andrewslai/.well-known/openid-configuration"}
(def swagger-ui-routes
(routes
(undocumented
(swagger-ui/swagger-ui {:path "/swagger"
:swagger-docs "/swagger.json"}))
(GET "/swagger.json" req
{:summary "Return a swagger 3.0.2 spec"
:produces #{"application/json"}}
(let [runtime-info1 (mw/get-swagger-data req)
runtime-info2 (rsm/get-swagger-data req)
base-path {:basePath (swag/base-path req)}
options (:compojure.api.request/ring-swagger req)
paths (:compojure.api.request/paths req)
swagger (apply rsc/deep-merge
(keep identity [base-path
paths
runtime-info1
runtime-info2]))
spec (st/swagger-spec
(swagger2/swagger-json swagger options))]
(-> spec
(merge {:openapi "3.0.2"
:info {:title "andrewslai"
:description "The backend HTTP API for a blog"}
:tags [{:name "articles"
:description "Articles (published and non-published)"}]
:components {:schemas (-> swagger
extract-specs
specs->components)
:securitySchemes security-schemes
:examples (reduce-kv (fn [acc k v]
(assoc acc (name k) v))
{}
example-data-2)}})
(dissoc :swagger)
ok)))))
(def example-wedding-data
{:kaleidoscope.albums/album {:summary "An example album"
:value {:id 1
:album-name "my album"
:created-at "2022-10-01T02:55:27Z"
:modified-at "2022-10-01T02:55:27Z"}}})
(def swagger-wedding-routes
(routes
(undocumented
(swagger-ui/swagger-ui {:path "/swagger"
:swagger-docs "/swagger.json"}))
(GET "/swagger.json" req
{:summary "Return a swagger 3.0.2 spec"
:produces #{"application/json"}}
(let [runtime-info1 (mw/get-swagger-data req)
runtime-info2 (rsm/get-swagger-data req)
base-path {:basePath (swag/base-path req)}
options (:compojure.api.request/ring-swagger req)
paths (:compojure.api.request/paths req)
swagger (apply rsc/deep-merge
(keep identity [base-path
paths
runtime-info1
runtime-info2]))
spec (st/swagger-spec
(swagger2/swagger-json swagger options))]
(-> spec
(assoc :openapi "3.0.2"
:info {:title "caheriaguilar.and.andrewslai"
:description "The backend HTTP API for a photo sharing web-app"}
:components {:schemas (-> swagger
extract-specs
specs->components)
:examples (reduce-kv (fn [acc k v]
(assoc acc (name k) v))
{}
example-wedding-data)})
(dissoc :swagger)
ok)))))