Skip to content

Commit f0842c1

Browse files
authored
Defendpoint 2.0 (metabase#51559)
* Split Kondo lint fixes off into metabase#51747 * Merge changes from metabase#51660 * Reworked API documentation generation code * Oops Markdown not YAML * BIG documentation generation improvements * Don't try to style tables ourselves * Fix lint errors * Fix tests 🔧 * Fix Kondo warnings * Update OpenAPI dox generator to handle Defendpoint v2 * Update OpenAPI dox generator to handle Defendpoint v2 * Test fixes 🔧 * Fix uberjar compilation * PR feedback from @escherize * Deprecate the old `defendpoint` * Nuke the old version of the API documentation code (new version will be merged in metabase#51872) * Remove empty file * Disable output validation in prod * Fix the way we define defendpoint 2 handlers
1 parent 9c9dc1f commit f0842c1

85 files changed

Lines changed: 1574 additions & 557 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.clj-kondo/config.edn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@
326326
metabase.analyze #{metabase.analyze}
327327
metabase.api #{metabase.api.common
328328
metabase.api.dataset
329+
metabase.api.macros
329330
metabase.api.permission-graph
330331
metabase.api.routes} ; TODO -- consolidate these into a real API namespace. I think the `*current-user*` type stuff might need to be moved into a separate module.
331332
metabase.async #{metabase.async.streaming-response
@@ -888,6 +889,7 @@
888889
metabase.api.embed-test/with-chain-filter-fixtures! hooks.common/let-one-with-optional-value
889890
metabase.api.embed-test/with-temp-card hooks.common/let-one-with-optional-value
890891
metabase.api.embed-test/with-temp-dashcard hooks.common/let-one-with-optional-value
892+
metabase.api.macros/defendpoint hooks.metabase.api.macros/defendpoint
891893
metabase.api.persist-test/with-setup! hooks.common/with-one-top-level-binding
892894
metabase.api.public-test/with-required-param-card! hooks.common/with-one-binding
893895
metabase.api.public-test/with-temp-public-card hooks.common/let-one-with-optional-value
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
(ns hooks.metabase.api.macros
2+
(:require
3+
[clj-kondo.hooks-api :as api]))
4+
5+
(defn defendpoint
6+
[arg]
7+
(letfn [(update-defendpoint [node]
8+
(let [[defendpoint method route & more] (:children node)
9+
[result-schema & more] (if (= (api/sexpr (first more)) :-)
10+
(drop 1 more)
11+
(cons nil more))
12+
[_docstring & more] (if (api/string-node? (first more))
13+
more
14+
(cons nil more))
15+
[metadata & more] (if (api/map-node? (first more))
16+
more
17+
(cons nil more))
18+
[params & body] more
19+
[bindings schemas] (when (api/vector-node? params)
20+
(loop [bindings [], schemas [], [x y & more] (:children params)]
21+
(cond
22+
(not x)
23+
[bindings schemas]
24+
25+
(= (api/sexpr x) :-)
26+
(recur bindings (conj schemas y) more)
27+
28+
:else
29+
(recur (conj bindings x) schemas (cons y more)))))]
30+
(-> (api/list-node
31+
(list
32+
(api/token-node 'do)
33+
defendpoint
34+
method
35+
route
36+
(api/list-node
37+
(list*
38+
(api/token-node 'do)
39+
(filter some? (list* metadata result-schema schemas))))
40+
(api/list-node
41+
(list*
42+
(api/token-node `let)
43+
(api/vector-node (into []
44+
(mapcat (fn [a-binding]
45+
[a-binding (api/token-node nil)]))
46+
bindings))
47+
body))))
48+
(with-meta (meta node)))))]
49+
(update arg :node update-defendpoint)))
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
(ns hooks.metabase.api.macros-test
2+
(:require
3+
[clj-kondo.hooks-api :as api]
4+
[clojure.test :refer :all]
5+
[hooks.metabase.api.macros]))
6+
7+
(deftest ^:parallel defendpoint-test
8+
(let [form '(api.macros/defendpoint :post "/" :- [:map [:collection_id :int]]
9+
"Create a new [[Timeline]]."
10+
[_route-params
11+
_query-params
12+
{:keys [icon], collection-id :collection_id, :as body} :- [:map
13+
[:name ms/NonBlankString]
14+
[:default {:optional true} [:maybe :boolean]]]]
15+
(body icon)
16+
(body collection-id))
17+
node (-> form pr-str api/parse-string)]
18+
(is (= '(do
19+
api.macros/defendpoint
20+
:post
21+
"/"
22+
(do
23+
[:map [:collection_id :int]]
24+
[:map
25+
[:name ms/NonBlankString]
26+
[:default {:optional true} [:maybe :boolean]]])
27+
(clojure.core/let [_route-params nil
28+
_query-params nil
29+
{:keys [icon], collection-id :collection_id, :as body} nil]
30+
(body icon)
31+
(body collection-id)))
32+
(-> {:node node}
33+
hooks.metabase.api.macros/defendpoint
34+
:node
35+
api/sexpr)))))

.github/file-paths.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ backend_specs: &backend_specs
7979
- "test_modules/**"
8080
- "modules/drivers/*/test/**"
8181
- "test_config/**"
82-
- "dev/**"
8382
- "test_resources/**"
8483

8584
backend_all: &backend_all

enterprise/backend/src/metabase_enterprise/advanced_config/api/logs.clj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
(date-part :month month)]})]
3333
results))
3434

35+
#_{:clj-kondo/ignore [:deprecated-var]}
3536
(api/defendpoint GET "/query_execution/:yyyy-mm"
3637
"Fetch rows for the month specified by `:yyyy-mm` from the query_execution logs table.
3738
Must be a superuser."

enterprise/backend/src/metabase_enterprise/advanced_permissions/api/application.clj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
(set! *warn-on-reflection* true)
1313

14+
#_{:clj-kondo/ignore [:deprecated-var]}
1415
(api/defendpoint GET "/graph"
1516
"Fetch a graph of Application Permissions."
1617
[]
@@ -34,6 +35,7 @@
3435
[graph]
3536
(update graph :groups dejsonify-groups))
3637

38+
#_{:clj-kondo/ignore [:deprecated-var]}
3739
(api/defendpoint PUT "/graph"
3840
"Do a batch update of Application Permissions by passing a modified graph."
3941
[:as {body :body

enterprise/backend/src/metabase_enterprise/advanced_permissions/api/impersonation.clj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
[metabase.util.malli.schema :as ms]
66
[toucan2.core :as t2]))
77

8+
#_{:clj-kondo/ignore [:deprecated-var]}
89
(api/defendpoint GET "/"
910
"Fetch a list of all Impersonation policies currently in effect, or a single policy if both `group_id` and `db_id`
1011
are provided."
@@ -16,6 +17,7 @@
1617
(t2/select-one :model/ConnectionImpersonation :group_id group_id :db_id db_id)
1718
(t2/select :model/ConnectionImpersonation {:order-by [[:id :asc]]})))
1819

20+
#_{:clj-kondo/ignore [:deprecated-var]}
1921
(api/defendpoint DELETE "/:id"
2022
"Delete a Connection Impersonation entry."
2123
[id]

enterprise/backend/src/metabase_enterprise/audit_app/api/user.clj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
[metabase.util.malli.schema :as ms]
1212
[toucan2.core :as t2]))
1313

14+
#_{:clj-kondo/ignore [:deprecated-var]}
1415
(api/defendpoint GET "/audit-info"
1516
"Gets audit info for the current user if he has permissions to access the audit collection.
1617
Otherwise return an empty map."
@@ -26,6 +27,7 @@
2627
{(u/slugify (:name question-overview)) (:id question-overview)
2728
(u/slugify (:name dashboard-overview)) (:id dashboard-overview)}))))
2829

30+
#_{:clj-kondo/ignore [:deprecated-var]}
2931
(api/defendpoint DELETE "/:id/subscriptions"
3032
"Delete all Alert and DashboardSubscription subscriptions for a User (i.e., so they will no longer receive them).
3133
Archive all Alerts and DashboardSubscriptions created by the User. Only allowed for admins or for the current user."

enterprise/backend/src/metabase_enterprise/billing/billing.clj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
{:name "Token expiration date" :value (valid-thru) :format "string" :display "value"}
5454
{:name "Plan" :value "Enterprise Airgap" :format "string" :display "value"}]}))
5555

56+
#_{:clj-kondo/ignore [:deprecated-var]}
5657
(api/defendpoint GET "/"
5758
"Get billing information. This acts as a proxy between `metabase-billing-info-url` and the client,
5859
using the embedding token and signed in user's email to fetch the billing information."

enterprise/backend/src/metabase_enterprise/content_verification/api/review.clj renamed to enterprise/backend/src/metabase_enterprise/content_verification/api/moderation_review.clj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
(ns metabase-enterprise.content-verification.api.review
1+
(ns metabase-enterprise.content-verification.api.moderation-review
2+
"`api/ee/moderation-review` routes."
23
(:require
34
[compojure.core :refer [POST]]
45
[metabase.api.common :as api]
@@ -7,6 +8,7 @@
78
[metabase.util.malli.schema :as ms]
89
[toucan2.core :as t2]))
910

11+
#_{:clj-kondo/ignore [:deprecated-var]}
1012
(api/defendpoint POST "/"
1113
"Create a new `ModerationReview`."
1214
[:as {{:keys [text moderated_item_id moderated_item_type status]} :body}]

0 commit comments

Comments
 (0)