Skip to content
Snippets Groups Projects
Unverified Commit be67302b authored by Cam Saul's avatar Cam Saul Committed by GitHub
Browse files

Include EE endpoints in API documentation. (#22688)

parent fe158d74
No related branches found
No related tags found
No related merge requests found
......@@ -113,6 +113,28 @@ Update a `Alert` with ID.
* **`alert-updates`**
## Application
`/advanced-permisisons/application` Routes.
Implements the Permissions routes needed for application permission - a class of permissions that control access to features
like access Setting pages, access monitoring tools ... etc.
- [GET /api/ee/advanced-permissions/application/graph](#get-apieeadvanced-permissionsapplicationgraph)
- [PUT /api/ee/advanced-permissions/application/graph](#put-apieeadvanced-permissionsapplicationgraph)
### `GET /api/ee/advanced-permissions/application/graph`
Fetch a graph of Application Permissions.
You must be a superuser to do this.
### `PUT /api/ee/advanced-permissions/application/graph`
Do a batch update of Application Permissions by passing a modified graph.
You must be a superuser to do this.
## Automagic dashboards
- [GET /api/automagic-dashboards/:entity/:entity-id-or-query](#get-apiautomagic-dashboardsentityentity-id-or-query)
......@@ -338,9 +360,12 @@ Sets the order of bookmarks for user.
- [GET /api/card/embeddable](#get-apicardembeddable)
- [GET /api/card/public](#get-apicardpublic)
- [POST /api/card/](#post-apicard)
- [POST /api/card/:card-id/persist](#post-apicardcard-idpersist)
- [POST /api/card/:card-id/public_link](#post-apicardcard-idpublic_link)
- [POST /api/card/:card-id/query](#post-apicardcard-idquery)
- [POST /api/card/:card-id/query/:export-format](#post-apicardcard-idqueryexport-format)
- [POST /api/card/:card-id/refresh](#post-apicardcard-idrefresh)
- [POST /api/card/:card-id/unpersist](#post-apicardcard-idunpersist)
- [POST /api/card/:id/copy](#post-apicardidcopy)
- [POST /api/card/collections](#post-apicardcollections)
- [POST /api/card/pivot/:card-id/query](#post-apicardpivotcard-idquery)
......@@ -438,6 +463,17 @@ Create a new `Card`.
* **`display`** value must be a non-blank string.
### `POST /api/card/:card-id/persist`
Mark the model (card) as persisted. Runs the query and saves it to the database backing the card and hot swaps this
query in place of the model's query.
You must be a superuser to do this.
##### PARAMS:
* **`card-id`** value must be an integer greater than zero.
### `POST /api/card/:card-id/public_link`
Generate publicly-accessible links for this Card. Returns UUID to be used in public links. (If this Card has
......@@ -479,6 +515,27 @@ Run the query associated with a Card, and return its results as a file in the sp
* **`parameters`** value may be nil, or if non-nil, value must be a valid JSON string.
### `POST /api/card/:card-id/refresh`
Refresh the persisted model caching `card-id`.
You must be a superuser to do this.
##### PARAMS:
* **`card-id`** value must be an integer greater than zero.
### `POST /api/card/:card-id/unpersist`
Unpersist this model. Deletes the persisted table backing the model and all queries after this will use the card's
query rather than the saved version of the query.
You must be a superuser to do this.
##### PARAMS:
* **`card-id`** value must be an integer greater than zero.
### `POST /api/card/:id/copy`
Copy a `Card`, with the new name 'Copy of _name_'.
......@@ -696,19 +753,21 @@ Fetch the root Collection's timelines.
Similar to `GET /`, but returns Collections in a tree structure, e.g.
```
[{:name "A"
:below #{:card :dataset}
:children [{:name "B"}
{:name "C"
:here #{:dataset :card}
:below #{:dataset :card}
:children [{:name "D"
:here #{:dataset}
:children [{:name "E"}]}
{:name "F"
:here #{:card}
:children [{:name "G"}]}]}]}
{:name "C"
:here #{:dataset :card}
:below #{:dataset :card}
:children [{:name "D"
:here #{:dataset}
:children [{:name "E"}]}
{:name "F"
:here #{:card}
:children [{:name "G"}]}]}]}
{:name "H"}]
```
The here and below keys indicate the types of items at this particular level of the tree (here) and in its
subtree (below).
......@@ -1166,9 +1225,11 @@ Update `Cards` on a Dashboard. Request body should have the form:
- [GET /api/database/db-ids-with-deprecated-drivers](#get-apidatabasedb-ids-with-deprecated-drivers)
- [POST /api/database/](#post-apidatabase)
- [POST /api/database/:id/discard_values](#post-apidatabaseiddiscard_values)
- [POST /api/database/:id/persist](#post-apidatabaseidpersist)
- [POST /api/database/:id/rescan_values](#post-apidatabaseidrescan_values)
- [POST /api/database/:id/sync](#post-apidatabaseidsync)
- [POST /api/database/:id/sync_schema](#post-apidatabaseidsync_schema)
- [POST /api/database/:id/unpersist](#post-apidatabaseidunpersist)
- [POST /api/database/sample_database](#post-apidatabasesample_database)
- [POST /api/database/validate](#post-apidatabasevalidate)
- [PUT /api/database/:id](#put-apidatabaseid)
......@@ -1383,6 +1444,16 @@ Discards all saved field values for this `Database`.
* **`id`**
### `POST /api/database/:id/persist`
Attempt to enable model persistence for a database. If already enabled returns a generic 204.
You must be a superuser to do this.
##### PARAMS:
* **`id`**
### `POST /api/database/:id/rescan_values`
Trigger a manual scan of the field values for this `Database`.
......@@ -1407,6 +1478,16 @@ Trigger a manual update of the schema metadata for this `Database`.
* **`id`**
### `POST /api/database/:id/unpersist`
Attempt to disable model persistence for a database. If already not enabled, just returns a generic 204.
You must be a superuser to do this.
##### PARAMS:
* **`id`**
### `POST /api/database/sample_database`
Add the sample database as a new `Database`.
......@@ -2007,6 +2088,63 @@ Fetch a custom GeoJSON file as defined in the `custom-geojson` setting. (This ju
* **`raise`**
## Gtap
`/api/mt/gtap` endpoints, for CRUD operations and the like on GTAPs (Group Table Access Policies).
- [DELETE /api/ee/sandbox/gtap/:id](#delete-apieesandboxgtapid)
- [GET /api/ee/sandbox/gtap/](#get-apieesandboxgtap)
- [GET /api/ee/sandbox/gtap/:id](#get-apieesandboxgtapid)
- [POST /api/ee/sandbox/gtap/](#post-apieesandboxgtap)
- [PUT /api/ee/sandbox/gtap/:id](#put-apieesandboxgtapid)
### `DELETE /api/ee/sandbox/gtap/:id`
Delete a GTAP entry.
##### PARAMS:
* **`id`**
### `GET /api/ee/sandbox/gtap/`
Fetch a list of all the GTAPs currently in use.
### `GET /api/ee/sandbox/gtap/:id`
Fetch GTAP by `id`.
##### PARAMS:
* **`id`**
### `POST /api/ee/sandbox/gtap/`
Create a new GTAP.
##### PARAMS:
* **`table_id`** value must be an integer greater than zero.
* **`card_id`** value may be nil, or if non-nil, value must be an integer greater than zero.
* **`group_id`** value must be an integer greater than zero.
* **`attribute_remappings`**
### `PUT /api/ee/sandbox/gtap/:id`
Update a GTAP entry. The only things you're allowed to update for a GTAP are the Card being used (`card_id`) or the
paramter mappings; changing `table_id` or `group_id` would effectively be deleting this entry and creating a new
one. If that's what you want to do, do so explicity with appropriate calls to the `DELETE` and `POST` endpoints.
##### PARAMS:
* **`id`**
* **`card_id`** value may be nil, or if non-nil, value must be an integer greater than zero.
## Ldap
/api/ldap endpoints.
......@@ -2353,6 +2491,67 @@ Update a Permission Group membership. Returns the updated record.
* **`is_group_manager`** value must be a boolean.
## Persist
- [GET /api/persist/](#get-apipersist)
- [GET /api/persist/:persisted-info-id](#get-apipersistpersisted-info-id)
- [GET /api/persist/card/:card-id](#get-apipersistcardcard-id)
- [POST /api/persist/disable](#post-apipersistdisable)
- [POST /api/persist/enable](#post-apipersistenable)
- [POST /api/persist/set-interval](#post-apipersistset-interval)
### `GET /api/persist/`
List the entries of [[PersistedInfo]] in order to show a status page.
You must be a superuser to do this.
### `GET /api/persist/:persisted-info-id`
Fetch a particular [[PersistedInfo]] by id.
You must be a superuser to do this.
##### PARAMS:
* **`persisted-info-id`** value may be nil, or if non-nil, value must be an integer greater than zero.
### `GET /api/persist/card/:card-id`
Fetch a particular [[PersistedInfo]] by card-id.
You must be a superuser to do this.
##### PARAMS:
* **`card-id`** value may be nil, or if non-nil, value must be an integer greater than zero.
### `POST /api/persist/disable`
Disable global setting to allow databases to persist models. This will remove all tasks to refresh tables, remove
that option from databases which might have it enabled, and delete all cached tables.
You must be a superuser to do this.
### `POST /api/persist/enable`
Enable global setting to allow databases to persist models.
You must be a superuser to do this.
### `POST /api/persist/set-interval`
Set the interval (in hours) to refresh persisted models. Shape should be JSON like {hours: 4}.
You must be a superuser to do this.
##### PARAMS:
* **`hours`** Value must be an integer representing hours greater than or equal to one and less than or equal to twenty-four
* **`_body`**
## Premium features
- [GET /api/premium-features/token/status](#get-apipremium-featurestokenstatus)
......@@ -2821,6 +3020,27 @@ Update a Pulse with `id`.
* **`pulse-updates`**
## Review
- [POST /api/ee/content-management/review/](#post-apieecontent-managementreview)
### `POST /api/ee/content-management/review/`
Create a new `ModerationReview`.
You must be a superuser to do this.
##### PARAMS:
* **`text`** value may be nil, or if non-nil, value must be a string.
* **`moderated_item_id`** value must be an integer greater than zero.
* **`moderated_item_type`** value must be one of: `:card`, `:dashboard`, `card`, `dashboard`.
* **`status`** value must be one of: ``, `verified`.
## Revision
- [GET /api/revision/](#get-apirevision)
......@@ -3211,10 +3431,36 @@ Update Slack related settings. You must be a superuser to do this. Also updates
* **`slack-files-channel`** value may be nil, or if non-nil, value must be a non-blank string.
## Table
## Sso
`/auth/sso` Routes.
Implements the SSO routes needed for SAML and JWT. This namespace primarily provides hooks for those two backends so
we can have a uniform interface both via the API and code.
- [GET /api/ee/sso/sso/](#get-apieessosso)
- [POST /api/ee/sso/sso/](#post-apieessosso)
### `GET /api/ee/sso/sso/`
SSO entry-point for an SSO user that has not logged in yet.
##### PARAMS:
* **`req`**
/api/table endpoints.
### `POST /api/ee/sso/sso/`
Route the SSO backends call with successful login details.
##### PARAMS:
* **`req`**
## Table
- [GET /api/ee/sandbox/table/:id/query_metadata](#get-apieesandboxtableidquery_metadata)
- [GET /api/table/](#get-apitable)
- [GET /api/table/:id](#get-apitableid)
- [GET /api/table/:id/fks](#get-apitableidfks)
......@@ -3228,6 +3474,22 @@ Update Slack related settings. You must be a superuser to do this. Also updates
- [PUT /api/table/:id](#put-apitableid)
- [PUT /api/table/:id/fields/order](#put-apitableidfieldsorder)
### `GET /api/ee/sandbox/table/:id/query_metadata`
This endpoint essentially acts as a wrapper for the OSS version of this route. When a user has segmented permissions
that only gives them access to a subset of columns for a given table, those inaccessable columns should also be
excluded from what is show in the query builder. When the user has full permissions (or no permissions) this route
doesn't add/change anything from the OSS version. See the docs on the OSS version of the endpoint for more
information.
##### PARAMS:
* **`id`**
* **`include_sensitive_fields`** value may be nil, or if non-nil, value must be a valid boolean string ('true' or 'false').
* **`include_hidden_fields`** value may be nil, or if non-nil, value must be a valid boolean string ('true' or 'false').
### `GET /api/table/`
Get all `Tables`.
......@@ -3599,8 +3861,11 @@ Look up a database schema transform.
## User
/api/user endpoints.
`/api/ee/audit-app/user` endpoints. These only work if you have a premium token with the `:audit-app` feature.
- [DELETE /api/ee/audit-app/user/:id/subscriptions](#delete-apieeaudit-appuseridsubscriptions)
- [GET /api/ee/sandbox/user/attributes](#get-apieesandboxuserattributes)
- [PUT /api/ee/sandbox/user/:id/attributes](#put-apieesandboxuseridattributes)
- [DELETE /api/user/:id](#delete-apiuserid)
- [GET /api/user/](#get-apiuser)
- [GET /api/user/:id](#get-apiuserid)
......@@ -3612,6 +3877,30 @@ Look up a database schema transform.
- [PUT /api/user/:id/password](#put-apiuseridpassword)
- [PUT /api/user/:id/reactivate](#put-apiuseridreactivate)
### `DELETE /api/ee/audit-app/user/:id/subscriptions`
Delete all Alert and DashboardSubscription subscriptions for a User (i.e., so they will no longer receive them).
Archive all Alerts and DashboardSubscriptions created by the User. Only allowed for admins or for the current user.
##### PARAMS:
* **`id`**
### `GET /api/ee/sandbox/user/attributes`
Fetch a list of possible keys for User `login_attributes`. This just looks at keys that have already been set for
existing Users and returns those. .
### `PUT /api/ee/sandbox/user/:id/attributes`
Update the `login_attributes` for a User.
##### PARAMS:
* **`id`**
* **`login_attributes`** value must be a valid user attributes map (name -> value)
### `DELETE /api/user/:id`
Disable a `User`. This does not remove the `User` from the DB, but instead disables their account.
......
......@@ -15,7 +15,7 @@
;; The following routes are NAUGHTY and do not follow the naming convention (i.e., they do not start with
;; `/ee/<feature>/`).
;;
;; TODO -- Please fix them!
;; TODO -- Please fix them! See #22687
content-management/routes
sandbox/routes
;; The following routes are NICE and do follow the `/ee/<feature>/` naming convention. Please add new routes here
......
......@@ -21,13 +21,20 @@
(defn- endpoint-name
"Generate a string like `GET /api/meta/db/:id` for a defendpoint route."
[method route]
(format "%s %s%s"
(name method)
(str/replace (.getName *ns*) #"^metabase\.api\." "/api/")
(if (vector? route)
(first route)
route)))
([method route]
(endpoint-name *ns* method route))
([endpoint-namespace method route]
(format "%s %s%s"
(name method)
(-> (.getName (the-ns endpoint-namespace))
(str/replace #"^metabase\.api\." "/api/")
;; This is only correct for EE endpoints following the usual convention. Not all of them do. The right
;; way to fix this is to move them -- see #22687
(str/replace #"^metabase-enterprise\.([^\.]+)\.api\." "/api/ee/$1/"))
(if (vector? route)
(first route)
route))))
(defn- args-form-flatten
"A version of `flatten` that will actually flatten a form such as:
......@@ -101,7 +108,7 @@
[method route docstr args param->schema body]
(format-route-dox (endpoint-name method route)
(str (u/add-period docstr) (when (contains-superuser-check? body)
"\n\nYou must be a superuser to do this."))
"\n\nYou must be a superuser to do this."))
(merge (args-form-symbols args)
param->schema)))
......
(ns metabase.cmd.endpoint-dox
"Implementation for the `api-documentation` command, which generate"
(:require [clojure.java.io :as io]
(:require [clojure.java.classpath :as classpath]
[clojure.java.io :as io]
[clojure.string :as str]
[clojure.tools.namespace.find :as ns.find]
[metabase.config :as config]
[metabase.plugins.classloader :as classloader]
[metabase.util :as u]))
......@@ -82,11 +85,16 @@
:endpoint-str (endpoint-str endpoint)
:ns-name (endpoint-ns-name endpoint)))
(defn- api-namespaces []
(for [ns-symb (ns.find/find-namespaces (classpath/system-classpath))
:when (and (re-find #"^metabase(?:-enterprise\.[\w-]+)?\.api\." (name ns-symb))
(not (str/includes? (name ns-symb) "test")))]
ns-symb))
(defn- collect-endpoints
"Gets a list of all API endpoints. Currently excludes Enterprise endpoints."
[]
(for [ns-symb u/metabase-namespace-symbols
:when (str/includes? (name ns-symb) "metabase.api")
(for [ns-symb (api-namespaces)
[_sym varr] (do (classloader/require ns-symb)
(sort (ns-interns ns-symb)))
:when (:is-endpoint? (meta varr))]
......@@ -124,5 +132,12 @@
(defn generate-dox!
"Write markdown file containing documentation for all the API endpoints to `docs/api-documentation.md`."
[]
(when-not config/ee-available?
(println (u/colorize
:red (str "Warning: EE source code not available. EE endpoints will not be included. "
"If you want to include them, run the command with"
\newline
\newline
"clojure -M:ee:run api-documentation"))))
(spit (io/file "docs/api-documentation.md") (dox))
(println "Documentation generated at docs/api-documentation.md."))
# API Documentation for Metabase
_This file was generated from source comments by `clojure -M:run api-documentation`_.
_This file was generated from source comments by `clojure -M:ee:run api-documentation`_.
Check out an introduction to the [Metabase API](https://www.metabase.com/learn/administration/metabase-api.html).
(ns metabase.api.common.internal-test
(:require [clojure.test :refer :all]
[medley.core :as m]
[metabase.api.common.internal :as internal :refer :all]
[metabase.api.common.internal :as internal]
[metabase.config :as config]
[metabase.test :as mt]
[metabase.util :as u]))
......@@ -27,8 +28,8 @@
#\"[0-9]+\" -> \"#[0-9]+\""
{:style/indent 0}
[& body]
`(binding [*auto-parse-types* (m/map-vals #(update % :route-param-regex (partial str "#"))
*auto-parse-types*)]
`(binding [internal/*auto-parse-types* (m/map-vals #(update % :route-param-regex (partial str "#"))
internal/*auto-parse-types*)]
~@body))
(deftest route-param-regex-test
......@@ -113,3 +114,12 @@
;; should work with some wacky binding form
'[id :as {body :body}]
'(clojure.core/let [id (clojure.core/when id (metabase.api.common.internal/parse-int id))] 'body)))
(deftest enterprise-endpoint-name-test
(when config/ee-available?
(testing "Make sure the route name for enterprise API endpoints is somewhat correct"
(require 'metabase-enterprise.advanced-permissions.api.application)
(is (= "GET /api/ee/advanced-permissions/application/graph"
(#'internal/endpoint-name (the-ns 'metabase-enterprise.advanced-permissions.api.application)
'GET
"/graph"))))))
(ns metabase.cmd.endpoint-dox-test
(:require [clojure.test :refer :all]
[metabase.cmd.endpoint-dox :as endpoint-dox]))
[metabase.cmd.endpoint-dox :as endpoint-dox]
[metabase.config :as config]))
(def endpoints {"Activity"
[{:ns (find-ns 'metabase.api.activity),
......@@ -28,3 +29,14 @@
(deftest endpoint-section-test
(is (= (first (endpoint-dox/endpoint-section endpoints))
section-markdown)))
(deftest include-ee-test
(testing "Enterprise API endpoints should be included (#22396)"
(when config/ee-available?
(is (some (fn [an-endpoint]
;; this is just a random EE endpoint namespace; if it gets moved or removed just pick a different
;; namespace here I guess
(when (= (the-ns 'metabase-enterprise.advanced-permissions.api.application)
(:ns an-endpoint))
an-endpoint))
(#'endpoint-dox/collect-endpoints))))))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment