diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn index 608237347ebc99857d7643229bc6c1086529f16e..0a82507db117b108f50a33bfdfc6ceab027c4e97 100644 --- a/.clj-kondo/config.edn +++ b/.clj-kondo/config.edn @@ -353,6 +353,7 @@ metabase.util.i18n i18n metabase.util.i18n.impl i18n.impl metabase.util.malli mu + metabase.util.malli.schema ms metabase.util.password u.password metabase.util.schema su metabase.util.ui-logic ui-logic diff --git a/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions.clj b/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions.clj index 694b7b4992e08961cdec601583ff832c518fb071..89e7bbe38189e7a0eb343eddfdb20833d18c5691 100644 --- a/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions.clj +++ b/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions.clj @@ -91,7 +91,7 @@ - Permissions have three levels: full, limited, and none. - Native query download permissions are fully inferred from the non-native download permissions. For more details, see the docstring for [[metabase.models.permissions/update-native-download-permissions!]]." - [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic new-download-perms :- perms/DownloadPermissionsGraph] + [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero new-download-perms :- perms/DownloadPermissionsGraph] (when-not (premium-features/enable-advanced-permissions?) (throw (perms/ee-permissions-exception :download))) (when-let [schemas (:schemas new-download-perms)] @@ -157,7 +157,7 @@ (s/defn update-db-data-model-permissions! "Update the data model permissions graph for a database." - [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic new-data-model-perms :- perms/DataModelPermissionsGraph] + [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero new-data-model-perms :- perms/DataModelPermissionsGraph] (when-not (premium-features/enable-advanced-permissions?) (throw (perms/ee-permissions-exception :data-model))) (when-let [schemas (:schemas new-data-model-perms)] @@ -188,7 +188,7 @@ (s/defn update-db-details-permissions! "Update the DB details permissions for a database." - [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic new-perms :- perms/DetailsPermissions] + [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero new-perms :- perms/DetailsPermissions] (when-not (premium-features/enable-advanced-permissions?) (throw (perms/ee-permissions-exception :details))) (case new-perms @@ -202,7 +202,7 @@ (s/defn update-db-execute-permissions! "Update the DB details permissions for a database." - [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic new-perms :- perms/ExecutePermissions] + [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero new-perms :- perms/ExecutePermissions] (when-not (premium-features/enable-advanced-permissions?) (throw (perms/ee-permissions-exception :execute))) (revoke-permissions! :execute :all group-id db-id) diff --git a/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions/application_permissions.clj b/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions/application_permissions.clj index 1721ec42ee7a37c596aa3fdb2750416798193d43..b7cba0a968540caa06c27367175ce9ce17e3720c 100644 --- a/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions/application_permissions.clj +++ b/enterprise/backend/src/metabase_enterprise/advanced_permissions/models/permissions/application_permissions.clj @@ -18,7 +18,7 @@ (def ^:private ApplicationPermissionsGraph {:revision s/Int - :groups {su/IntGreaterThanZeroPlumatic GroupPermissionsGraph}}) + :groups {su/IntGreaterThanZero GroupPermissionsGraph}}) ;; -------------------------------------------------- Fetch Graph --------------------------------------------------- diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/interface.clj b/enterprise/backend/src/metabase_enterprise/audit_app/interface.clj index d53e27f32bbe59878049d467a91e021b86252ef8..e4e6ae53d97e24a00a73c3df2fce377b9a00986c 100644 --- a/enterprise/backend/src/metabase_enterprise/audit_app/interface.clj +++ b/enterprise/backend/src/metabase_enterprise/audit_app/interface.clj @@ -8,8 +8,8 @@ (def ResultsMetadata "Schema for the expected format for `:metadata` returned by an internal query function." (su/non-empty - [[(s/one su/KeywordOrStringPlumatic "field name") - (s/one {:base_type su/FieldTypePlumatic, :display_name su/NonBlankStringPlumatic, s/Keyword s/Any} + [[(s/one su/KeywordOrString "field name") + (s/one {:base_type su/FieldType, :display_name su/NonBlankString, s/Keyword s/Any} "field metadata")]])) (defmulti internal-query diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/common/card_and_dashboard_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/common/card_and_dashboard_detail.clj index d9e1633cfc8bab711cf7994dc6e9a7165d4867bc..071f64cb77c1d02989fe0d928501d2bad4d7911f 100644 --- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/common/card_and_dashboard_detail.clj +++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/common/card_and_dashboard_detail.clj @@ -22,7 +22,7 @@ ;; ORDER BY {{group-fn(timestamp}} ASC (s/defn views-by-time "Get views of a Card or Dashboard broken out by a time `unit`, e.g. `day` or `day-of-week`." - [model :- ModelName, model-id :- su/IntGreaterThanZeroPlumatic, unit :- common/DateTimeUnitStr] + [model :- ModelName, model-id :- su/IntGreaterThanZero, unit :- common/DateTimeUnitStr] {:metadata [[:date {:display_name "Date", :base_type (common/datetime-unit-str->base-type unit)}] [:views {:display_name "Views", :base_type :type/Integer}]] :results (let [grouped-timestamp (common/grouped-datetime unit :timestamp)] @@ -40,7 +40,7 @@ (s/defn cached-views-by-time "Get number of views of a Card broken out by a time `unit`, e.g. `day` or `day-of-week` and by cache status. Still here instead of in cards because of similarity to views-by-time" - [card-id :- su/IntGreaterThanZeroPlumatic, unit :- common/DateTimeUnitStr] + [card-id :- su/IntGreaterThanZero, unit :- common/DateTimeUnitStr] {:metadata [[:date {:display_name "Date", :base_type (common/datetime-unit-str->base-type unit)}] [:cached-views {:display_name "Cached Views", @@ -64,7 +64,7 @@ (s/defn avg-execution-time-by-time "Get average execution time of a Card broken out by a time `unit`, e.g. `day` or `day-of-week`. Still here instead of in cards because of similarity to views-by-time" - [card-id :- su/IntGreaterThanZeroPlumatic, unit :- common/DateTimeUnitStr] + [card-id :- su/IntGreaterThanZero, unit :- common/DateTimeUnitStr] {:metadata [[:date {:display_name "Date", :base_type (common/datetime-unit-str->base-type unit)}] [:avg_runtime {:display_name "Average Runtime", :base_type :type/Number}]] :results (let [grouped-timestamp (common/grouped-datetime unit :started_at)] @@ -80,7 +80,7 @@ (s/defn revision-history "Get a revision history table for a Card or Dashboard." [model-entity :- (s/cond-pre (mi/InstanceOf Card) (mi/InstanceOf Dashboard)) - model-id :- su/IntGreaterThanZeroPlumatic] + model-id :- su/IntGreaterThanZero] {:metadata [[:timestamp {:display_name "Edited on", :base_type :type/DateTime}] [:user_id {:display_name "User ID", :base_type :type/Integer, :remapped_to :user_name}] [:user_name {:display_name "Edited by", :base_type :type/Name, :remapped_from :user_id}] @@ -95,7 +95,7 @@ (s/defn audit-log "Get a view log for a Card or Dashboard." - [model :- ModelName, model-id :- su/IntGreaterThanZeroPlumatic] + [model :- ModelName, model-id :- su/IntGreaterThanZero] {:metadata [[:when {:display_name "When", :base_type :type/DateTime}] [:user_id {:display_name "User ID", :base_type :type/Integer, :remapped_to :who}] [:who {:display_name "Who", :base_type :type/Name, :remapped_from :user_id}] diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/dashboard_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/dashboard_detail.clj index 776c93c97713e5e1a7e0e206a4e07c4c7174bdf5..8fb58047290b4958fc89e4621dd5c55be5fc796e 100644 --- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/dashboard_detail.clj +++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/dashboard_detail.clj @@ -11,22 +11,22 @@ ;; Get views of a Dashboard broken out by a time `unit`, e.g. `day` or `day-of-week`. (s/defmethod audit.i/internal-query ::views-by-time - [_ dashboard-id :- su/IntGreaterThanZeroPlumatic datetime-unit :- common/DateTimeUnitStr] + [_ dashboard-id :- su/IntGreaterThanZero datetime-unit :- common/DateTimeUnitStr] (card-and-dash-detail/views-by-time "dashboard" dashboard-id datetime-unit)) ;; Revision history for a specific Dashboard. (s/defmethod audit.i/internal-query ::revision-history - [_ dashboard-id :- su/IntGreaterThanZeroPlumatic] + [_ dashboard-id :- su/IntGreaterThanZero] (card-and-dash-detail/revision-history Dashboard dashboard-id)) ;; View log for a specific Dashboard. (s/defmethod audit.i/internal-query ::audit-log - [_ dashboard-id :- su/IntGreaterThanZeroPlumatic] + [_ dashboard-id :- su/IntGreaterThanZero] (card-and-dash-detail/audit-log "dashboard" dashboard-id)) ;; Information about the Saved Questions (Cards) in this instance. (s/defmethod audit.i/internal-query ::cards - [_ dashboard-id :- su/IntGreaterThanZeroPlumatic] + [_ dashboard-id :- su/IntGreaterThanZero] {:metadata [[:card_id {:display_name "Card ID", :base_type :type/Integer, :remapped_to :card_name}] [:card_name {:display_name "Title", :base_type :type/Name, :remapped_from :card_id}] [:collection_id {:display_name "Collection ID", :base_type :type/Integer, :remapped_to :collection_name}] diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/database_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/database_detail.clj index c5e558d46a91e26c6fc7f7dd030835646e3c4cdf..3016e75fc8814f8c358fd1e6ebf8ae8a968f058b 100644 --- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/database_detail.clj +++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/database_detail.clj @@ -8,7 +8,7 @@ ;; Query execution history for queries against this Database. (s/defmethod audit.i/internal-query ::audit-log - [_ database-id :- su/IntGreaterThanZeroPlumatic] + [_ database-id :- su/IntGreaterThanZero] {:metadata [[:started_at {:display_name "Viewed on", :base_type :type/DateTime}] [:card_id {:display_name "Card ID", :base_type :type/Integer, :remapped_to :query}] [:query_hash {:display_name "Query Hash", :base_type :type/Text}] diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/query_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/query_detail.clj index 2febbbaa4de399ac6f65c0c44327cea46580695b..d21419466faab8a8d8d8bcf29d852e57426a70da 100644 --- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/query_detail.clj +++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/query_detail.clj @@ -61,7 +61,7 @@ ;; Details about a specific query (currently just average execution time). (s/defmethod audit.i/internal-query ::details - [_ query-hash :- su/NonBlankStringPlumatic] + [_ query-hash :- su/NonBlankString] {:metadata [[:query {:display_name "Query", :base_type :type/Dictionary}] [:average_execution_time {:display_name "Avg. Exec. Time (ms)", :base_type :type/Number}]] :results (common/reducible-query diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/question_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/question_detail.clj index c10f3c5eaec3eeb3bacbc4b575d2226562c92856..713d17f9dc8f73b70a6dd72526046d63e9e804f1 100644 --- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/question_detail.clj +++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/question_detail.clj @@ -10,25 +10,25 @@ ;; Get views of a Card broken out by a time `unit`, e.g. `day` or `day-of-week`. (s/defmethod audit.i/internal-query ::views-by-time - [_ card-id :- su/IntGreaterThanZeroPlumatic datetime-unit :- common/DateTimeUnitStr] + [_ card-id :- su/IntGreaterThanZero datetime-unit :- common/DateTimeUnitStr] (card-and-dash-detail/views-by-time "card" card-id datetime-unit)) ;; Get cached views of a Card broken out by a time `unit`, e.g. `day` or `day-of-week`. (s/defmethod audit.i/internal-query ::cached-views-by-time - [_ card-id :- su/IntGreaterThanZeroPlumatic, datetime-unit :- common/DateTimeUnitStr] + [_ card-id :- su/IntGreaterThanZero, datetime-unit :- common/DateTimeUnitStr] (card-and-dash-detail/cached-views-by-time card-id datetime-unit)) ;; Get the revision history for a Card. (s/defmethod audit.i/internal-query ::revision-history - [_ card-id :- su/IntGreaterThanZeroPlumatic] + [_ card-id :- su/IntGreaterThanZero] (card-and-dash-detail/revision-history Card card-id)) ;; Get a view log for a Card. (s/defmethod audit.i/internal-query ::audit-log - [_ card-id :- su/IntGreaterThanZeroPlumatic] + [_ card-id :- su/IntGreaterThanZero] (card-and-dash-detail/audit-log "card" card-id)) ;; Average execution time broken out by period (s/defmethod audit.i/internal-query ::avg-execution-time-by-time - [_ card-id :- su/IntGreaterThanZeroPlumatic datetime-unit :- common/DateTimeUnitStr] + [_ card-id :- su/IntGreaterThanZero datetime-unit :- common/DateTimeUnitStr] (card-and-dash-detail/avg-execution-time-by-time card-id datetime-unit)) diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/table_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/table_detail.clj index b0b30a587faa884bb4f04f4b95541db5273764a9..6139bb7210eee4025d3ab8c1a0d5c589c748dc68 100644 --- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/table_detail.clj +++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/table_detail.clj @@ -8,7 +8,7 @@ ;; View log for a specific Table. (s/defmethod audit.i/internal-query ::audit-log - [_ table-id :- su/IntGreaterThanZeroPlumatic] + [_ table-id :- su/IntGreaterThanZero] {:metadata [[:started_at {:display_name "Viewed on", :base_type :type/DateTime}] [:card_id {:display_name "Card ID", :base_type :type/Integer, :remapped_to :query}] [:query {:display_name "Query", :base_type :type/Text, :remapped_from :card_id}] diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/pages/user_detail.clj b/enterprise/backend/src/metabase_enterprise/audit_app/pages/user_detail.clj index 3d09bc57cec639203a029ad08ec519b65a310ab6..b67dbdba003282979f0c4a17b5f629979b8c1ff1 100644 --- a/enterprise/backend/src/metabase_enterprise/audit_app/pages/user_detail.clj +++ b/enterprise/backend/src/metabase_enterprise/audit_app/pages/user_detail.clj @@ -16,7 +16,7 @@ ;; ;; (TODO - in the designs, this is pivoted; should we do that here in Clojure-land?) (s/defmethod audit.i/internal-query ::table - [_ user-id :- su/IntGreaterThanZeroPlumatic] + [_ user-id :- su/IntGreaterThanZero] {:metadata [[:name {:display_name "Name", :base_type :type/Name}] [:role {:display_name "Role", :base_type :type/Text}] [:groups {:display_name "Groups", :base_type :type/Text}] @@ -79,7 +79,7 @@ ;; Return the 10 most-viewed Dashboards for a given User, in descending order. (s/defmethod audit.i/internal-query ::most-viewed-dashboards - [_ user-id :- su/IntGreaterThanZeroPlumatic] + [_ user-id :- su/IntGreaterThanZero] {:metadata [[:dashboard_id {:display_name "Dashboard ID", :base_type :type/Integer, :remapped_to :dashboard_name}] [:dashboard_name {:display_name "Dashboard", :base_type :type/Name, :remapped_from :dashboard_id}] [:count {:display_name "Views", :base_type :type/Integer}]] @@ -98,7 +98,7 @@ ;; Return the 10 most-viewed Questions for a given User, in descending order. (s/defmethod audit.i/internal-query ::most-viewed-questions - [_ user-id :- su/IntGreaterThanZeroPlumatic] + [_ user-id :- su/IntGreaterThanZero] {:metadata [[:card_id {:display_name "Card ID", :base_type :type/Integer, :remapped_to :card_name}] [:card_name {:display_name "Query", :base_type :type/Name, :remapped_from :card_id}] [:count {:display_name "Views", :base_type :type/Integer}]] @@ -117,7 +117,7 @@ ;; Query views by a specific User. (s/defmethod audit.i/internal-query ::query-views - [_ user-id :- su/IntGreaterThanZeroPlumatic] + [_ user-id :- su/IntGreaterThanZero] {:metadata [[:viewed_on {:display_name "Viewed On", :base_type :type/DateTime}] [:card_id {:display_name "Card ID" :base_type :type/Integer, :remapped_to :card_name}] [:card_name {:display_name "Query", :base_type :type/Text, :remapped_from :card_id}] @@ -157,7 +157,7 @@ ;; Dashboard views by a specific User. (s/defmethod audit.i/internal-query ::dashboard-views - [_ user-id :- su/IntGreaterThanZeroPlumatic] + [_ user-id :- su/IntGreaterThanZero] {:metadata [[:timestamp {:display_name "Viewed on", :base_type :type/DateTime}] [:dashboard_id {:display_name "Dashboard ID", :base_type :type/Integer, :remapped_to :dashboard_name}] [:dashboard_name {:display_name "Dashboard", :base_type :type/Text, :remapped_from :dashboard_id}] @@ -180,7 +180,7 @@ ;; Timeseries chart that shows the number of Question or Dashboard views for a User, broken out by `datetime-unit`. (s/defmethod audit.i/internal-query ::object-views-by-time [_ - user-id :- su/IntGreaterThanZeroPlumatic + user-id :- su/IntGreaterThanZero model :- (s/enum "card" "dashboard") datetime-unit :- common/DateTimeUnitStr] {:metadata [[:date {:display_name "Date", :base_type (common/datetime-unit-str->base-type datetime-unit)}] @@ -199,12 +199,12 @@ (s/defmethod audit.i/internal-query ::created-dashboards ([query-type user-id] (audit.i/internal-query query-type user-id nil)) - ([_ user-id :- su/IntGreaterThanZeroPlumatic query-string :- (s/maybe s/Str)] + ([_ user-id :- su/IntGreaterThanZero query-string :- (s/maybe s/Str)] (dashboards/table query-string [:= :u.id user-id]))) ;; Questions created by a specific User. (s/defmethod audit.i/internal-query ::created-questions - [_ user-id :- su/IntGreaterThanZeroPlumatic] + [_ user-id :- su/IntGreaterThanZero] {:metadata [[:card_id {:display_name "Card ID", :base_type :type/Integer, :remapped_to :card_name}] [:card_name {:display_name "Title", :base_type :type/Name, :remapped_from :card_id}] [:collection_id {:display_name "Collection ID", :base_type :type/Integer, :remapped_to :collection_name}] @@ -249,7 +249,7 @@ ;; Table of query downloads (i.e., queries whose results are returned as CSV/JSON/XLS) done by this user, ordered by ;; most recent. (s/defmethod audit.i/internal-query ::downloads - [_ user-id :- su/IntGreaterThanZeroPlumatic] + [_ user-id :- su/IntGreaterThanZero] {:metadata [[:downloaded_at {:display_name "Downloaded At", :base_type :type/DateTime}] [:rows_downloaded {:display_name "Rows Downloaded", :base_type :type/Integer}] [:card_id {:display_name "Card ID", :base_type :type/Integer, :remapped_to :card_name}] diff --git a/enterprise/backend/src/metabase_enterprise/audit_app/query_processor/middleware/handle_audit_queries.clj b/enterprise/backend/src/metabase_enterprise/audit_app/query_processor/middleware/handle_audit_queries.clj index a49c2962079b806b11068a7c1f74efe1530cf239..6442bc6e214575f64c17ee5c7ff7a03263d37cd9 100644 --- a/enterprise/backend/src/metabase_enterprise/audit_app/query_processor/middleware/handle_audit_queries.clj +++ b/enterprise/backend/src/metabase_enterprise/audit_app/query_processor/middleware/handle_audit_queries.clj @@ -68,7 +68,7 @@ (for [[k v] metadata] (assoc v :name (name k)))) -(s/defn ^:private format-results [{:keys [results metadata]} :- {:results [su/MapPlumatic] +(s/defn ^:private format-results [{:keys [results metadata]} :- {:results [su/Map] :metadata audit.i/ResultsMetadata}] (check-results-and-metadata-keys-match results metadata) {:cols (metadata->cols metadata) diff --git a/enterprise/backend/src/metabase_enterprise/content_management/api/review.clj b/enterprise/backend/src/metabase_enterprise/content_management/api/review.clj index 90d33305432cfe2a80bf8eee1568ee469313201d..e7dc37e8e22b4426963d38b490361c3e4a5e3756 100644 --- a/enterprise/backend/src/metabase_enterprise/content_management/api/review.clj +++ b/enterprise/backend/src/metabase_enterprise/content_management/api/review.clj @@ -12,7 +12,7 @@ "Create a new `ModerationReview`." [:as {{:keys [text moderated_item_id moderated_item_type status]} :body}] {text (s/maybe s/Str) - moderated_item_id su/IntGreaterThanZeroPlumatic + moderated_item_id su/IntGreaterThanZero moderated_item_type moderation/moderated-item-types status moderation-review/Statuses} (api/check-superuser) diff --git a/enterprise/backend/src/metabase_enterprise/enhancements/integrations/ldap.clj b/enterprise/backend/src/metabase_enterprise/enhancements/integrations/ldap.clj index 9f7f8fb5dd70af21cdb5cd16227be7139f242533..8890f8eed20594333ddece5af074af66ba0524a8 100644 --- a/enterprise/backend/src/metabase_enterprise/enhancements/integrations/ldap.clj +++ b/enterprise/backend/src/metabase_enterprise/enhancements/integrations/ldap.clj @@ -63,7 +63,7 @@ "Get user information for the supplied username." :feature :any [ldap-connection :- LDAPConnectionPool - username :- su/NonBlankStringPlumatic + username :- su/NonBlankString settings :- i/LDAPSettings] (when-let [result (default-impl/search ldap-connection username settings)] (when-let [user-info (default-impl/ldap-search-result->user-info diff --git a/enterprise/backend/src/metabase_enterprise/enhancements/models/native_query_snippet/permissions.clj b/enterprise/backend/src/metabase_enterprise/enhancements/models/native_query_snippet/permissions.clj index 9f61cac8fee3c75185fdf582c63d323b3ceabe75..affd3bd4035e432a543de45b5a2d73427a1ec7d6 100644 --- a/enterprise/backend/src/metabase_enterprise/enhancements/models/native_query_snippet/permissions.clj +++ b/enterprise/backend/src/metabase_enterprise/enhancements/models/native_query_snippet/permissions.clj @@ -9,7 +9,7 @@ [toucan.db :as db])) (s/defn ^:private has-parent-collection-perms? - [snippet :- {:collection_id (s/maybe su/IntGreaterThanZeroPlumatic), s/Keyword s/Any} + [snippet :- {:collection_id (s/maybe su/IntGreaterThanZero), s/Keyword s/Any} read-or-write :- (s/enum :read :write)] (mi/current-user-has-full-permissions? (perms/perms-objects-set-for-parent-collection "snippets" snippet read-or-write))) diff --git a/enterprise/backend/src/metabase_enterprise/sandbox/api/gtap.clj b/enterprise/backend/src/metabase_enterprise/sandbox/api/gtap.clj index 3d2f8001e1ec4867163f7ef47cd2302ffff8d689..963fec6008645a9a8051be7e4792910968b03c28 100644 --- a/enterprise/backend/src/metabase_enterprise/sandbox/api/gtap.clj +++ b/enterprise/backend/src/metabase_enterprise/sandbox/api/gtap.clj @@ -36,9 +36,9 @@ (api/defendpoint-schema POST "/" "Create a new GTAP." [:as {{:keys [table_id card_id group_id attribute_remappings]} :body}] - {table_id su/IntGreaterThanZeroPlumatic - card_id (s/maybe su/IntGreaterThanZeroPlumatic) - group_id su/IntGreaterThanZeroPlumatic + {table_id su/IntGreaterThanZero + card_id (s/maybe su/IntGreaterThanZero) + group_id su/IntGreaterThanZero #_attribute_remappings #_AttributeRemappings} ; TODO - fix me (db/insert! GroupTableAccessPolicy {:table_id table_id @@ -52,7 +52,7 @@ 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." [id :as {{:keys [card_id #_attribute_remappings], :as body} :body}] - {card_id (s/maybe su/IntGreaterThanZeroPlumatic) + {card_id (s/maybe su/IntGreaterThanZero) #_attribute_remappings #_AttributeRemappings} ; TODO - fix me (api/check-404 (GroupTableAccessPolicy id)) ;; Only update `card_id` and/or `attribute_remappings` if the values are present in the body of the request. diff --git a/enterprise/backend/src/metabase_enterprise/sandbox/api/table.clj b/enterprise/backend/src/metabase_enterprise/sandbox/api/table.clj index bffde827db27e3a27b901a48a0893842c6071767..83f8f63450a9310dc0ba8708d82cae3257a490e3 100644 --- a/enterprise/backend/src/metabase_enterprise/sandbox/api/table.clj +++ b/enterprise/backend/src/metabase_enterprise/sandbox/api/table.clj @@ -61,9 +61,9 @@ doesn't add/change anything from the OSS version. See the docs on the OSS version of the endpoint for more information." [id include_sensitive_fields include_hidden_fields include_editable_data_model] - {include_sensitive_fields (s/maybe su/BooleanStringPlumatic) - include_hidden_fields (s/maybe su/BooleanStringPlumatic) - include_editable_data_model (s/maybe su/BooleanStringPlumatic)} + {include_sensitive_fields (s/maybe su/BooleanString) + include_hidden_fields (s/maybe su/BooleanString) + include_editable_data_model (s/maybe su/BooleanString)} (let [table (api/check-404 (db/select-one Table :id id)) segmented-perms? (only-segmented-perms? table) thunk (fn [] diff --git a/enterprise/backend/src/metabase_enterprise/sandbox/api/user.clj b/enterprise/backend/src/metabase_enterprise/sandbox/api/user.clj index 5f29d6b872387e9fa310ac184c4197853dafe8d9..b9232dcae262e7a6cc4827cc96a5eb70ef71aff8 100644 --- a/enterprise/backend/src/metabase_enterprise/sandbox/api/user.clj +++ b/enterprise/backend/src/metabase_enterprise/sandbox/api/user.clj @@ -10,7 +10,7 @@ [toucan.db :as db])) (def ^:private UserAttributes - (su/with-api-error-message (s/maybe {su/NonBlankStringPlumatic s/Any}) + (su/with-api-error-message (s/maybe {su/NonBlankString s/Any}) "value must be a valid user attributes map (name -> value)")) ;; TODO - not sure we need this endpoint now that we're just letting you edit from the regular `PUT /api/user/:id diff --git a/enterprise/backend/src/metabase_enterprise/sandbox/models/group_table_access_policy.clj b/enterprise/backend/src/metabase_enterprise/sandbox/models/group_table_access_policy.clj index fee61b05f4541def03e8046ebe68c51ae6a125f5..b10b0a19cc262a6bc75fe25cda53054939d384d4 100644 --- a/enterprise/backend/src/metabase_enterprise/sandbox/models/group_table_access_policy.clj +++ b/enterprise/backend/src/metabase_enterprise/sandbox/models/group_table_access_policy.clj @@ -93,7 +93,7 @@ (when-let [result-metadata (db/select-one-field :result_metadata Card :id card-id)] (check-columns-match-table table-id result-metadata)))) - ([table-id :- su/IntGreaterThanZeroPlumatic result-metadata-columns] + ([table-id :- su/IntGreaterThanZero result-metadata-columns] ;; prevent circular refs (classloader/require 'metabase.query-processor) (let [table-cols (table-field-names->cols table-id)] diff --git a/enterprise/backend/src/metabase_enterprise/sandbox/query_processor/middleware/row_level_restrictions.clj b/enterprise/backend/src/metabase_enterprise/sandbox/query_processor/middleware/row_level_restrictions.clj index df372650dc5bedee381f9ce8d95ab6eeacf0cd6b..c768c848efb7c8e1ac10b0fc3418ea8e92a2f6e1 100644 --- a/enterprise/backend/src/metabase_enterprise/sandbox/query_processor/middleware/row_level_restrictions.clj +++ b/enterprise/backend/src/metabase_enterprise/sandbox/query_processor/middleware/row_level_restrictions.clj @@ -96,7 +96,7 @@ ;;; | Applying a GTAP | ;;; +----------------------------------------------------------------------------------------------------------------+ -(s/defn ^:private target-field->base-type :- (s/maybe su/FieldTypePlumatic) +(s/defn ^:private target-field->base-type :- (s/maybe su/FieldType) "If the `:target` of a parameter contains a `:field` clause, return the base type corresponding to the Field it references. Otherwise returns `nil`." [[_ target-field-clause]] @@ -160,7 +160,7 @@ (defn- table-gtap->source [{table-id :table_id, :as gtap}] {:source-query {:source-table table-id, :parameters (gtap->parameters gtap)}}) -(s/defn ^:private mbql-query-metadata :- (su/non-empty [su/MapPlumatic]) +(s/defn ^:private mbql-query-metadata :- (su/non-empty [su/Map]) [inner-query] (binding [api/*current-user-permissions-set* (atom #{"/"})] ((requiring-resolve 'metabase.query-processor/query->expected-cols) @@ -177,9 +177,9 @@ (mbql-query-metadata {:source-table table-id})) :ttl/threshold (u/minutes->ms 1))) -(s/defn ^:private reconcile-metadata :- (su/non-empty [su/MapPlumatic]) +(s/defn ^:private reconcile-metadata :- (su/non-empty [su/Map]) "Combine the metadata in `source-query-metadata` with the `table-metadata` from the Table being sandboxed." - [source-query-metadata :- (su/non-empty [su/MapPlumatic]) table-metadata] + [source-query-metadata :- (su/non-empty [su/Map]) table-metadata] (let [col-name->table-metadata (m/index-by :name table-metadata)] (vec (for [col source-query-metadata @@ -189,7 +189,7 @@ (gtap/check-column-types-match col table-col) table-col))))) -(s/defn ^:private native-query-metadata :- (su/non-empty [su/MapPlumatic]) +(s/defn ^:private native-query-metadata :- (su/non-empty [su/Map]) [source-query :- {:source-query s/Any, s/Keyword s/Any}] (let [result (binding [api/*current-user-permissions-set* (atom #{"/"})] ((requiring-resolve 'metabase.query-processor/process-query) @@ -203,13 +203,13 @@ :result result}))))) (s/defn ^:private source-query-form-ensure-metadata :- {:source-query s/Any - :source-metadata (su/non-empty [su/MapPlumatic]) + :source-metadata (su/non-empty [su/Map]) s/Keyword s/Any} "Add `:source-metadata` to a `source-query` if needed. If the source metadata had to be resolved (because Card with `card-id`) didn't already have it, save it so we don't have to resolve it again next time around." [{:keys [source-metadata], :as source-query} :- {:source-query s/Any, s/Keyword s/Any} - table-id :- su/IntGreaterThanZeroPlumatic - card-id :- (s/maybe su/IntGreaterThanZeroPlumatic)] + table-id :- su/IntGreaterThanZero + card-id :- (s/maybe su/IntGreaterThanZero)] (let [table-metadata (original-table-metadata table-id) ;; make sure source query has `:source-metadata`; add it if needed [metadata save?] (cond @@ -242,7 +242,7 @@ (s/optional-key :source-metadata) [mbql.s/SourceQueryMetadata] s/Keyword s/Any} "Get the source query associated with a `gtap`." - [{card-id :card_id, table-id :table_id, :as gtap} :- su/MapPlumatic] + [{card-id :card_id, table-id :table_id, :as gtap} :- su/Map] (-> ((if card-id card-gtap->source table-gtap->source) gtap) diff --git a/enterprise/backend/src/metabase_enterprise/serialization/api/serialize.clj b/enterprise/backend/src/metabase_enterprise/serialization/api/serialize.clj index de73002134f5f13417619d62b46c8d23e7789089..e207e30c014ef886ccc937cb29edabbaa33d2b1a 100644 --- a/enterprise/backend/src/metabase_enterprise/serialization/api/serialize.clj +++ b/enterprise/backend/src/metabase_enterprise/serialization/api/serialize.clj @@ -24,9 +24,9 @@ - The collections that they want to serialize (using selective serialization)" [:as {{:keys [collection_ids path]} :body}] {collection_ids (su/with-api-error-message - (su/distinct (su/non-empty [su/IntGreaterThanZeroPlumatic])) + (su/distinct (su/non-empty [su/IntGreaterThanZero])) "Non-empty, distinct array of Collection IDs") - path (su/with-api-error-message su/NonBlankStringPlumatic + path (su/with-api-error-message su/NonBlankString "Valid directory to serialize results to")} ;; Make sure all the specified collection IDs exist. (let [existing-collection-ids (db/select-ids Collection :id [:in (set collection_ids)])] diff --git a/enterprise/backend/src/metabase_enterprise/serialization/names.clj b/enterprise/backend/src/metabase_enterprise/serialization/names.clj index 1dc957df56dc1c764a379b263c0cbc4c26574f2a..3f760c09265cf058aaa8071056195da1c091bc11 100644 --- a/enterprise/backend/src/metabase_enterprise/serialization/names.clj +++ b/enterprise/backend/src/metabase_enterprise/serialization/names.clj @@ -129,18 +129,18 @@ ;; All the references in the dumps should resolved to entities already loaded. (def ^:private Context - {(s/optional-key :database) su/IntGreaterThanZeroPlumatic - (s/optional-key :table) su/IntGreaterThanZeroPlumatic + {(s/optional-key :database) su/IntGreaterThanZero + (s/optional-key :table) su/IntGreaterThanZero (s/optional-key :schema) (s/maybe s/Str) - (s/optional-key :field) su/IntGreaterThanZeroPlumatic - (s/optional-key :metric) su/IntGreaterThanZeroPlumatic - (s/optional-key :segment) su/IntGreaterThanZeroPlumatic - (s/optional-key :card) su/IntGreaterThanZeroPlumatic - (s/optional-key :dashboard) su/IntGreaterThanZeroPlumatic - (s/optional-key :collection) (s/maybe su/IntGreaterThanZeroPlumatic) ; root collection - (s/optional-key :pulse) su/IntGreaterThanZeroPlumatic - (s/optional-key :user) su/IntGreaterThanZeroPlumatic - (s/optional-key :snippet) (s/maybe su/IntGreaterThanZeroPlumatic)}) + (s/optional-key :field) su/IntGreaterThanZero + (s/optional-key :metric) su/IntGreaterThanZero + (s/optional-key :segment) su/IntGreaterThanZero + (s/optional-key :card) su/IntGreaterThanZero + (s/optional-key :dashboard) su/IntGreaterThanZero + (s/optional-key :collection) (s/maybe su/IntGreaterThanZero) ; root collection + (s/optional-key :pulse) su/IntGreaterThanZero + (s/optional-key :user) su/IntGreaterThanZero + (s/optional-key :snippet) (s/maybe su/IntGreaterThanZero)}) (defmulti ^:private path->context* (fn [_ model _ _] model)) diff --git a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj index 897881402721ba60c85c7800fc3ee4e5d947defb..52c401bbf84f0d7e7854a4f9ae734640723ab72d 100644 --- a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj +++ b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_settings.clj @@ -11,7 +11,7 @@ [schema.core :as s])) (def ^:private GroupMappings - (s/maybe {su/KeywordOrStringPlumatic [su/IntGreaterThanZeroPlumatic]})) + (s/maybe {su/KeywordOrString [su/IntGreaterThanZero]})) (def ^:private ^{:arglists '([group-mappings])} validate-group-mappings (s/validator GroupMappings)) diff --git a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_utils.clj b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_utils.clj index 4bbc648083cb51f9ec4e0524114604f7fba93eb7..cffff9bd3fc87e14c88a6e0d55faea2f49b4581d 100644 --- a/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_utils.clj +++ b/enterprise/backend/src/metabase_enterprise/sso/integrations/sso_utils.clj @@ -17,9 +17,9 @@ (java.util UUID))) (def ^:private UserAttributes - {:first_name (s/maybe su/NonBlankStringPlumatic) - :last_name (s/maybe su/NonBlankStringPlumatic) - :email su/EmailPlumatic + {:first_name (s/maybe su/NonBlankString) + :last_name (s/maybe su/NonBlankString) + :email su/Email ;; TODO - we should avoid hardcoding this to make it easier to add new integrations. Maybe look at something like ;; the keys of `(methods sso/sso-get)` :sso_source (s/enum "saml" "jwt") diff --git a/enterprise/backend/test/metabase_enterprise/enhancements/integrations/ldap_test.clj b/enterprise/backend/test/metabase_enterprise/enhancements/integrations/ldap_test.clj index 9f5e02f1cc095efeef068c2f6462757856b38e6d..778bea6908ab2c5d4ace79c4b9790a830cb58941 100644 --- a/enterprise/backend/test/metabase_enterprise/enhancements/integrations/ldap_test.clj +++ b/enterprise/backend/test/metabase_enterprise/enhancements/integrations/ldap_test.clj @@ -175,7 +175,7 @@ s/Keyword s/Any} (ldap/fetch-or-create-user! user-info)))) (testing "Call fetch-or-create-user! again to trigger update" - (is (schema= {:id su/IntGreaterThanZeroPlumatic, s/Keyword s/Any} + (is (schema= {:id su/IntGreaterThanZero, s/Keyword s/Any} (ldap/fetch-or-create-user! (assoc-in user-info [:attributes :unladenspeed] 100))))) (is (= {:first_name "John" :last_name "Smith" @@ -201,7 +201,7 @@ s/Keyword s/Any} (ldap/fetch-or-create-user! user-info)))) (testing "Call fetch-or-create-user! again to trigger update" - (is (schema= {:id su/IntGreaterThanZeroPlumatic, s/Keyword s/Any} + (is (schema= {:id su/IntGreaterThanZero, s/Keyword s/Any} (ldap/fetch-or-create-user! (assoc-in user-info [:attributes :unladenspeed] 100))))) (is (= {:first_name "John" :last_name "Smith" diff --git a/enterprise/backend/test/metabase_enterprise/sandbox/api/permissions_test.clj b/enterprise/backend/test/metabase_enterprise/sandbox/api/permissions_test.clj index 0a46b782e09cef810f8be91ab24ef439bba86886..1cab256e11a90d7c105d4ce0a4c5155c4a267d54 100644 --- a/enterprise/backend/test/metabase_enterprise/sandbox/api/permissions_test.clj +++ b/enterprise/backend/test/metabase_enterprise/sandbox/api/permissions_test.clj @@ -69,7 +69,7 @@ (get-in (mt/user-http-request :crowberto :get 200 "permissions/graph") (venues-perms-graph-keypath &group))))) (testing "GTAP should exist in application DB" - (is (schema= [(s/one {:id su/IntGreaterThanZeroPlumatic + (is (schema= [(s/one {:id su/IntGreaterThanZero :group_id (s/eq (u/the-id &group)) :table_id (s/eq (mt/id :venues)) :card_id (s/eq nil) @@ -101,7 +101,7 @@ :group_id (u/the-id &group) :table_id (mt/id :venues))))) (testing "GTAP for same group, other database should not be affected" - (is (schema= [(s/one {:id su/IntGreaterThanZeroPlumatic + (is (schema= [(s/one {:id su/IntGreaterThanZero :group_id (s/eq (u/the-id &group)) :table_id (s/eq (u/the-id db-2-table)) :card_id (s/eq nil) @@ -111,7 +111,7 @@ :group_id (u/the-id &group) :table_id (u/the-id db-2-table))))) (testing "GTAP for same table, other group should not be affected" - (is (schema= [(s/one {:id su/IntGreaterThanZeroPlumatic + (is (schema= [(s/one {:id su/IntGreaterThanZero :group_id (s/eq (u/the-id other-group)) :table_id (s/eq (mt/id :venues)) :card_id (s/eq nil) diff --git a/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj b/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj index c41ae91277e141d9f83333f2d10727e33f05bcf2..8c16b2e2dbe269c562d92f6ed875c3dd5aa8655e 100644 --- a/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj +++ b/modules/drivers/bigquery-cloud-sdk/src/metabase/driver/bigquery_cloud_sdk.clj @@ -110,8 +110,8 @@ ([{{:keys [project-id]} :details, :as database} dataset-id table-id] (get-table (database->client database) project-id dataset-id table-id)) - ([client :- BigQuery, project-id :- (s/maybe su/NonBlankStringPlumatic), dataset-id :- su/NonBlankStringPlumatic, - table-id :- su/NonBlankStringPlumatic] + ([client :- BigQuery, project-id :- (s/maybe su/NonBlankString), dataset-id :- su/NonBlankString, + table-id :- su/NonBlankString] (if project-id (.getTable client (TableId/of project-id dataset-id table-id) empty-table-options) (.getTable client dataset-id table-id empty-table-options)))) diff --git a/modules/drivers/bigquery-cloud-sdk/test/metabase/test/data/bigquery_cloud_sdk.clj b/modules/drivers/bigquery-cloud-sdk/test/metabase/test/data/bigquery_cloud_sdk.clj index 03770cec68644dab9e207bdf8e6b98b960988d26..1fc6af52e4746fb1cad69faa1d273f133f7f52ac 100644 --- a/modules/drivers/bigquery-cloud-sdk/test/metabase/test/data/bigquery_cloud_sdk.clj +++ b/modules/drivers/bigquery-cloud-sdk/test/metabase/test/data/bigquery_cloud_sdk.clj @@ -119,13 +119,13 @@ (def ^:private ValidFieldName #"^[A-Za-z_]\w{0,127}$") (s/defn ^:private delete-table! - [dataset-id :- su/NonBlankStringPlumatic, table-id :- su/NonBlankStringPlumatic] + [dataset-id :- su/NonBlankString, table-id :- su/NonBlankString] (.delete (bigquery) (TableId/of dataset-id table-id)) (println (u/format-color 'red "Deleted table `%s.%s.%s`" (project-id) dataset-id table-id))) (s/defn ^:private create-table! - [^String dataset-id :- su/NonBlankStringPlumatic - table-id :- su/NonBlankStringPlumatic + [^String dataset-id :- su/NonBlankString + table-id :- su/NonBlankString field-name->type :- {ValidFieldName (apply s/enum valid-field-types)}] (u/ignore-exceptions (delete-table! dataset-id table-id)) diff --git a/modules/drivers/googleanalytics/src/metabase/driver/googleanalytics/query_processor.clj b/modules/drivers/googleanalytics/src/metabase/driver/googleanalytics/query_processor.clj index 9a8d040441b6211a9ae07562820f15076ab82c83..d175c7e729b8f61a8a23a06479dc8173a44a8653 100644 --- a/modules/drivers/googleanalytics/src/metabase/driver/googleanalytics/query_processor.clj +++ b/modules/drivers/googleanalytics/src/metabase/driver/googleanalytics/query_processor.clj @@ -367,7 +367,7 @@ ;;; ------------------------------------------- filter (built-in segments) ------------------------------------------- -(s/defn ^:private built-in-segment :- (s/maybe su/NonBlankStringPlumatic) +(s/defn ^:private built-in-segment :- (s/maybe su/NonBlankString) [{filter-clause :filter}] (let [segments (mbql.u/match filter-clause [:segment (segment-name :guard mbql.u/ga-id?)] segment-name)] (when (> (count segments) 1) diff --git a/modules/drivers/mongo/src/metabase/driver/mongo/query_processor.clj b/modules/drivers/mongo/src/metabase/driver/mongo/query_processor.clj index dfd74196994f48b6ddf7ae9830e85be5238b16ff..e3e2bf3dddf9c69f17d5ae1b44f7b5f9b43a90fb 100644 --- a/modules/drivers/mongo/src/metabase/driver/mongo/query_processor.clj +++ b/modules/drivers/mongo/src/metabase/driver/mongo/query_processor.clj @@ -37,22 +37,22 @@ ;; this is just a very limited schema to make sure we're generating valid queries. We should expand it more in the ;; future -(def ^:private $ProjectStage {(s/eq $project) {su/NonBlankStringPlumatic s/Any}}) -(def ^:private $SortStage {(s/eq $sort) {su/NonBlankStringPlumatic (s/enum -1 1)}}) -(def ^:private $MatchStage {(s/eq $match) {(s/constrained (s/cond-pre su/NonBlankStringPlumatic s/Keyword) +(def ^:private $ProjectStage {(s/eq $project) {su/NonBlankString s/Any}}) +(def ^:private $SortStage {(s/eq $sort) {su/NonBlankString (s/enum -1 1)}}) +(def ^:private $MatchStage {(s/eq $match) {(s/constrained (s/cond-pre su/NonBlankString s/Keyword) #(not (#{:$not "$not"} %))) s/Any}}) -(def ^:private $GroupStage {(s/eq $group) {su/NonBlankStringPlumatic s/Any}}) -(def ^:private $AddFieldsStage {(s/eq :$addFields) {su/NonBlankStringPlumatic s/Any}}) -(def ^:private $LimitStage {(s/eq $limit) su/IntGreaterThanZeroPlumatic}) -(def ^:private $SkipStage {(s/eq $skip) su/IntGreaterThanZeroPlumatic}) +(def ^:private $GroupStage {(s/eq $group) {su/NonBlankString s/Any}}) +(def ^:private $AddFieldsStage {(s/eq :$addFields) {su/NonBlankString s/Any}}) +(def ^:private $LimitStage {(s/eq $limit) su/IntGreaterThanZero}) +(def ^:private $SkipStage {(s/eq $skip) su/IntGreaterThanZero}) (defn- is-stage? [stage] (fn [m] (= (first (keys m)) stage))) (def ^:private Stage (s/both - (s/constrained su/MapPlumatic #(= (count (keys %)) 1) "map with a single key") + (s/constrained su/Map #(= (count (keys %)) 1) "map with a single key") (s/conditional (is-stage? $project) $ProjectStage (is-stage? $sort) $SortStage @@ -817,7 +817,7 @@ (recur arg) ag)) -(s/defn ^:private breakouts-and-ags->projected-fields :- [(s/pair su/NonBlankStringPlumatic "projected-field-name" +(s/defn ^:private breakouts-and-ags->projected-fields :- [(s/pair su/NonBlankString "projected-field-name" s/Any "source")] "Determine field projections for MBQL breakouts and aggregations. Returns a sequence of pairs like `[projected-field-name source]`." diff --git a/modules/drivers/presto/src/metabase/driver/presto.clj b/modules/drivers/presto/src/metabase/driver/presto.clj index 0025abac69a8f6113b07f83cc2d4d956201cb1b7..7d462473bdbff292606307dc54ea13749befb0ec 100644 --- a/modules/drivers/presto/src/metabase/driver/presto.clj +++ b/modules/drivers/presto/src/metabase/driver/presto.clj @@ -37,9 +37,9 @@ ;;; Presto API helpers (def ^:private PrestoConnectionDetails - {:host su/NonBlankStringPlumatic - :port (s/cond-pre su/NonBlankStringPlumatic su/IntGreaterThanZeroPlumatic) - :catalog su/NonBlankStringPlumatic + {:host su/NonBlankString + :port (s/cond-pre su/NonBlankString su/IntGreaterThanZero) + :catalog su/NonBlankString s/Any s/Any}) (s/defn ^:private details->uri @@ -196,7 +196,7 @@ (sql.u/quote-name driver :database catalog)))] (= v "information_schema"))) -(s/defn ^:private database->all-schemas :- #{su/NonBlankStringPlumatic} +(s/defn ^:private database->all-schemas :- #{su/NonBlankString} "Return a set of all schema names in this `database`." [driver {{:keys [catalog] :as details} :details :as _database}] (let [sql (presto-common/describe-catalog-sql driver catalog) diff --git a/src/metabase/api/alert.clj b/src/metabase/api/alert.clj index 22a2d270ca963b86f5b7f81c25e30fa93127ec1a..fbf1f94403a7580fbdaa8a18b86ceaef8cb3b8a3 100644 --- a/src/metabase/api/alert.clj +++ b/src/metabase/api/alert.clj @@ -30,8 +30,8 @@ (api/defendpoint-schema GET "/" "Fetch all alerts" [archived user_id] - {archived (s/maybe su/BooleanStringPlumatic) - user_id (s/maybe su/IntGreaterThanZeroPlumatic)} + {archived (s/maybe su/BooleanString) + user_id (s/maybe su/IntGreaterThanZero)} (as-> (pulse/retrieve-alerts {:archived? (Boolean/parseBoolean archived) :user-id user_id}) <> (filter mi/can-read? <>) @@ -48,8 +48,8 @@ (api/defendpoint-schema GET "/question/:id" "Fetch all questions for the given question (`Card`) id" [id archived] - {id (s/maybe su/IntGreaterThanZeroPlumatic) - archived (s/maybe su/BooleanStringPlumatic)} + {id (s/maybe su/IntGreaterThanZero) + archived (s/maybe su/BooleanString)} (-> (if api/*is-superuser?* (pulse/retrieve-alerts-for-cards {:card-ids [id], :archived? (Boolean/parseBoolean archived)}) (pulse/retrieve-user-alerts-for-card {:card-id id, :user-id api/*current-user-id*, :archived? (Boolean/parseBoolean archived)})) @@ -140,7 +140,7 @@ alert_first_only s/Bool alert_above_goal (s/maybe s/Bool) card pulse/CardRef - channels (su/non-empty [su/MapPlumatic])} + channels (su/non-empty [su/Map])} (validation/check-has-application-permission :subscription false) ;; To create an Alert you need read perms for its Card (api/read-check Card (u/the-id card)) @@ -170,7 +170,7 @@ alert_first_only (s/maybe s/Bool) alert_above_goal (s/maybe s/Bool) card (s/maybe pulse/CardRef) - channels (s/maybe (su/non-empty [su/MapPlumatic])) + channels (s/maybe (su/non-empty [su/Map])) archived (s/maybe s/Bool)} (try (validation/check-has-application-permission :monitoring) diff --git a/src/metabase/api/bookmark.clj b/src/metabase/api/bookmark.clj index 5c7e0df8f457fff1d119a2e3f003dc6cb577f07c..392597826f4b6a1560b4722c583a4cbeae0a60fb 100644 --- a/src/metabase/api/bookmark.clj +++ b/src/metabase/api/bookmark.clj @@ -24,7 +24,7 @@ (def BookmarkOrderings "Schema for an ordered of boomark orderings" [{:type Models - :item_id su/IntGreaterThanZeroPlumatic}]) + :item_id su/IntGreaterThanZero}]) (def ^:private lookup "Lookup map from model as a string to [model bookmark-model item-id-key]." @@ -45,7 +45,7 @@ "Create a new bookmark for user." [model id] {model Models - id su/IntGreaterThanZeroPlumatic} + id su/IntGreaterThanZero} (let [[item-model bookmark-model item-key] (lookup model)] (api/read-check item-model id) (api/check (not (db/exists? bookmark-model item-key id @@ -58,7 +58,7 @@ "Delete a bookmark. Will delete a bookmark assigned to the user making the request by model and id." [model id] {model Models - id su/IntGreaterThanZeroPlumatic} + id su/IntGreaterThanZero} ;; todo: allow admins to include an optional user id to delete for so they can delete other's bookmarks. (let [[_ bookmark-model item-key] (lookup model)] (db/delete! bookmark-model diff --git a/src/metabase/api/card.clj b/src/metabase/api/card.clj index 3ef8b75da9c8b856238007e28562c769cd5105d4..f693af6cf7be6ae1d536595cb954d3927287827f 100644 --- a/src/metabase/api/card.clj +++ b/src/metabase/api/card.clj @@ -93,7 +93,7 @@ (s/defn ^:private cards-with-ids :- (s/maybe [CardInstance]) "Return unarchived Cards with `card-ids`. Make sure cards are returned in the same order as `card-ids`; `[in card-ids]` won't preserve the order." - [card-ids :- [su/IntGreaterThanZeroPlumatic]] + [card-ids :- [su/IntGreaterThanZero]] (when (seq card-ids) (let [card-id->card (m/index-by :id (db/select Card, :id [:in (set card-ids)], :archived false))] (filter identity (map card-id->card card-ids))))) @@ -156,7 +156,7 @@ option. :card_index:" [f model_id] {f (s/maybe CardFilterOption) - model_id (s/maybe su/IntGreaterThanZeroPlumatic)} + model_id (s/maybe su/IntGreaterThanZero)} (let [f (keyword f)] (when (contains? #{:database :table :using_model} f) (api/checkp (integer? model_id) "model_id" (format "model_id is a required parameter when filter mode is '%s'" @@ -201,8 +201,8 @@ "Get the timelines for card with ID. Looks up the collection the card is in and uses that." [id include start end] {include (s/maybe api.timeline/Include) - start (s/maybe su/TemporalStringPlumatic) - end (s/maybe su/TemporalStringPlumatic)} + start (s/maybe su/TemporalString) + end (s/maybe su/TemporalString)} (let [{:keys [collection_id] :as _card} (api/read-check Card id)] ;; subtlety here. timeline access is based on the collection at the moment so this check should be identical. If ;; we allow adding more timelines to a card in the future, we will need to filter on read-check and i don't think @@ -377,17 +377,17 @@ saved later when it is ready." "Create a new `Card`." [:as {{:keys [collection_id collection_position dataset_query description display name parameters parameter_mappings result_metadata visualization_settings cache_ttl], :as body} :body}] - {name su/NonBlankStringPlumatic - dataset_query su/MapPlumatic - parameters (s/maybe [su/ParameterPlumatic]) - parameter_mappings (s/maybe [su/ParameterMappingPlumatic]) - description (s/maybe su/NonBlankStringPlumatic) - display su/NonBlankStringPlumatic - visualization_settings su/MapPlumatic - collection_id (s/maybe su/IntGreaterThanZeroPlumatic) - collection_position (s/maybe su/IntGreaterThanZeroPlumatic) + {name su/NonBlankString + dataset_query su/Map + parameters (s/maybe [su/Parameter]) + parameter_mappings (s/maybe [su/ParameterMapping]) + description (s/maybe su/NonBlankString) + display su/NonBlankString + visualization_settings su/Map + collection_id (s/maybe su/IntGreaterThanZero) + collection_position (s/maybe su/IntGreaterThanZero) result_metadata (s/maybe qr/ResultsMetadata) - cache_ttl (s/maybe su/IntGreaterThanZeroPlumatic)} + cache_ttl (s/maybe su/IntGreaterThanZero)} ;; check that we have permissions to run the query that we're trying to save (check-data-permissions-for-query dataset_query) ;; check that we have permissions for the collection we're trying to save this card to, if applicable @@ -398,7 +398,7 @@ saved later when it is ready." (api/defendpoint-schema POST "/:id/copy" "Copy a `Card`, with the new name 'Copy of _name_'" [id] - {id (s/maybe su/IntGreaterThanZeroPlumatic)} + {id (s/maybe su/IntGreaterThanZero)} (let [orig-card (api/read-check Card id) new-name (str (trs "Copy of ") (:name orig-card)) new-card (assoc orig-card :name new-name)] @@ -607,20 +607,20 @@ saved later when it is ready." collection_position enable_embedding embedding_params result_metadata parameters cache_ttl dataset collection_preview] :as card-updates} :body}] - {name (s/maybe su/NonBlankStringPlumatic) - parameters (s/maybe [su/ParameterPlumatic]) - dataset_query (s/maybe su/MapPlumatic) + {name (s/maybe su/NonBlankString) + parameters (s/maybe [su/Parameter]) + dataset_query (s/maybe su/Map) dataset (s/maybe s/Bool) - display (s/maybe su/NonBlankStringPlumatic) + display (s/maybe su/NonBlankString) description (s/maybe s/Str) - visualization_settings (s/maybe su/MapPlumatic) + visualization_settings (s/maybe su/Map) archived (s/maybe s/Bool) enable_embedding (s/maybe s/Bool) - embedding_params (s/maybe su/EmbeddingParamsPlumatic) - collection_id (s/maybe su/IntGreaterThanZeroPlumatic) - collection_position (s/maybe su/IntGreaterThanZeroPlumatic) + embedding_params (s/maybe su/EmbeddingParams) + collection_id (s/maybe su/IntGreaterThanZero) + collection_position (s/maybe su/IntGreaterThanZero) result_metadata (s/maybe qr/ResultsMetadata) - cache_ttl (s/maybe su/IntGreaterThanZeroPlumatic) + cache_ttl (s/maybe su/IntGreaterThanZero) collection_preview (s/maybe s/Bool)} (let [card-before-update (hydrate (api/write-check Card id) [:moderation_reviews :moderator_details])] @@ -739,7 +739,7 @@ saved later when it is ready." "Bulk update endpoint for Card Collections. Move a set of `Cards` with CARD_IDS into a `Collection` with COLLECTION_ID, or remove them from any Collections by passing a `null` COLLECTION_ID." [:as {{:keys [card_ids collection_id]} :body}] - {card_ids [su/IntGreaterThanZeroPlumatic], collection_id (s/maybe su/IntGreaterThanZeroPlumatic)} + {card_ids [su/IntGreaterThanZero], collection_id (s/maybe su/IntGreaterThanZero)} (move-cards-to-collection! collection_id card_ids) {:status :ok}) @@ -753,7 +753,7 @@ saved later when it is ready." [card-id :as {{:keys [parameters ignore_cache dashboard_id collection_preview], :or {ignore_cache false dashboard_id nil}} :body}] {ignore_cache (s/maybe s/Bool) collection_preview (s/maybe s/Bool) - dashboard_id (s/maybe su/IntGreaterThanZeroPlumatic)} + dashboard_id (s/maybe su/IntGreaterThanZero)} ;; TODO -- we should probably warn if you pass `dashboard_id`, and tell you to use the new ;; ;; POST /api/dashboard/:dashboard-id/card/:card-id/query @@ -774,7 +774,7 @@ saved later when it is ready." `parameters` should be passed as query parameter encoded as a serialized JSON string (this is because this endpoint is normally used to power 'Download Results' buttons that use HTML `form` actions)." [card-id export-format :as {{:keys [parameters]} :params}] - {parameters (s/maybe su/JSONStringPlumatic) + {parameters (s/maybe su/JSONString) export-format api.dataset/ExportFormat} (qp.card/run-query-for-card-async card-id export-format @@ -862,7 +862,7 @@ saved later when it is ready." "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." [card-id] - {card-id su/IntGreaterThanZeroPlumatic} + {card-id su/IntGreaterThanZero} (api/let-404 [{:keys [dataset database_id] :as card} (db/select-one Card :id card-id)] (let [database (db/select-one Database :id database_id)] (api/write-check database) @@ -886,7 +886,7 @@ saved later when it is ready." (api/defendpoint-schema POST "/:card-id/refresh" "Refresh the persisted model caching `card-id`." [card-id] - {card-id su/IntGreaterThanZeroPlumatic} + {card-id su/IntGreaterThanZero} (api/let-404 [card (db/select-one Card :id card-id) persisted-info (db/select-one PersistedInfo :card_id card-id)] (when (not (:dataset card)) @@ -902,7 +902,7 @@ saved later when it is ready." "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." [card-id] - {card-id su/IntGreaterThanZeroPlumatic} + {card-id su/IntGreaterThanZero} (api/let-404 [_card (db/select-one Card :id card-id)] (api/let-404 [persisted-info (db/select-one PersistedInfo :card_id card-id)] (api/write-check (db/select-one Database :id (:database_id persisted-info))) diff --git a/src/metabase/api/collection.clj b/src/metabase/api/collection.clj index 22486f2793be4a1e27fa71a66acfa9d9c0bb4ce4..1375ce790b3e5fde38867742165ef85c849fa3e7 100644 --- a/src/metabase/api/collection.clj +++ b/src/metabase/api/collection.clj @@ -51,8 +51,8 @@ By default, this returns non-archived Collections, but instead you can show archived ones by passing `?archived=true`." [archived namespace] - {archived (s/maybe su/BooleanStringPlumatic) - namespace (s/maybe su/NonBlankStringPlumatic)} + {archived (s/maybe su/BooleanString) + namespace (s/maybe su/NonBlankString)} (let [archived? (Boolean/parseBoolean archived)] (as-> (db/select Collection {:where [:and @@ -100,8 +100,8 @@ The here and below keys indicate the types of items at this particular level of the tree (here) and in its subtree (below)." [exclude-archived namespace] - {exclude-archived (s/maybe su/BooleanStringPlumatic) - namespace (s/maybe su/NonBlankStringPlumatic)} + {exclude-archived (s/maybe su/BooleanString) + namespace (s/maybe su/NonBlankString)} (let [coll-type-ids (reduce (fn [acc {:keys [collection_id dataset] :as _x}] (update acc (if dataset :dataset :card) conj collection_id)) {:dataset #{} @@ -628,7 +628,7 @@ "Fetch the root Collection's timelines." [include archived] {include (s/maybe api.timeline/Include) - archived (s/maybe su/BooleanStringPlumatic)} + archived (s/maybe su/BooleanString)} (let [archived? (Boolean/parseBoolean archived)] (timeline/timelines-for-collection nil {:timeline/events? (= include "events") :timeline/archived? archived?}))) @@ -638,7 +638,7 @@ "Fetch a specific Collection's timelines." [id include archived] {include (s/maybe api.timeline/Include) - archived (s/maybe su/BooleanStringPlumatic)} + archived (s/maybe su/BooleanString)} (let [archived? (Boolean/parseBoolean archived)] (timeline/timelines-for-collection id {:timeline/events? (= include "events") :timeline/archived? archived?}))) @@ -654,7 +654,7 @@ when `all`, return everything. By default returns everything" [id models archived pinned_state sort_column sort_direction] {models (s/maybe models-schema) - archived (s/maybe su/BooleanStringPlumatic) + archived (s/maybe su/BooleanString) pinned_state (s/maybe (apply s/enum valid-pinned-state-values)) sort_column (s/maybe (apply s/enum valid-sort-columns)) sort_direction (s/maybe (apply s/enum valid-sort-directions))} @@ -676,7 +676,7 @@ (api/defendpoint-schema GET "/root" "Return the 'Root' Collection object with standard details added" [namespace] - {namespace (s/maybe su/NonBlankStringPlumatic)} + {namespace (s/maybe su/NonBlankString)} (-> (root-collection namespace) (api/read-check) (dissoc ::collection.root/is-root?))) @@ -710,8 +710,8 @@ `snippets`, you can pass the `?namespace=` parameter." [models archived namespace pinned_state sort_column sort_direction] {models (s/maybe models-schema) - archived (s/maybe su/BooleanStringPlumatic) - namespace (s/maybe su/NonBlankStringPlumatic) + archived (s/maybe su/BooleanString) + namespace (s/maybe su/NonBlankString) pinned_state (s/maybe (apply s/enum valid-pinned-state-values)) sort_column (s/maybe (apply s/enum valid-sort-columns)) sort_direction (s/maybe (apply s/enum valid-sort-directions))} @@ -762,11 +762,11 @@ (api/defendpoint-schema POST "/" "Create a new Collection." [:as {{:keys [name color description parent_id namespace authority_level] :as body} :body}] - {name su/NonBlankStringPlumatic + {name su/NonBlankString color collection/hex-color-regex - description (s/maybe su/NonBlankStringPlumatic) - parent_id (s/maybe su/IntGreaterThanZeroPlumatic) - namespace (s/maybe su/NonBlankStringPlumatic) + description (s/maybe su/NonBlankString) + parent_id (s/maybe su/IntGreaterThanZero) + namespace (s/maybe su/NonBlankString) authority_level collection/AuthorityLevel} (create-collection! body)) @@ -821,11 +821,11 @@ (api/defendpoint-schema PUT "/:id" "Modify an existing Collection, including archiving or unarchiving it, or moving it." [id, :as {{:keys [name color description archived parent_id authority_level], :as collection-updates} :body}] - {name (s/maybe su/NonBlankStringPlumatic) + {name (s/maybe su/NonBlankString) color (s/maybe collection/hex-color-regex) - description (s/maybe su/NonBlankStringPlumatic) + description (s/maybe su/NonBlankString) archived (s/maybe s/Bool) - parent_id (s/maybe su/IntGreaterThanZeroPlumatic) + parent_id (s/maybe su/IntGreaterThanZero) authority_level collection/AuthorityLevel} ;; do we have perms to edit this Collection? (let [collection-before-update (api/write-check Collection id)] @@ -857,7 +857,7 @@ (api/defendpoint-schema GET "/graph" "Fetch a graph of all Collection Permissions." [namespace] - {namespace (s/maybe su/NonBlankStringPlumatic)} + {namespace (s/maybe su/NonBlankString)} (api/check-superuser) (graph/graph namespace)) @@ -900,8 +900,8 @@ "Do a batch update of Collections Permissions by passing in a modified graph. Will overwrite parts of the graph that are present in the request, and leave the rest unchanged." [:as {{:keys [namespace], :as body} :body}] - {body su/MapPlumatic - namespace (s/maybe su/NonBlankStringPlumatic)} + {body su/Map + namespace (s/maybe su/NonBlankString)} (api/check-superuser) (->> (dissoc body :namespace) decode-graph diff --git a/src/metabase/api/common.clj b/src/metabase/api/common.clj index b448ea34935b04d528b22004dabd46ae72023e5b..5f16e2032fd752b1676dd46663a1f8f29920db01 100644 --- a/src/metabase/api/common.clj +++ b/src/metabase/api/common.clj @@ -485,7 +485,7 @@ (api/column-will-change? :archived (db/select-one Collection :id 10) {:archived false}) ; -> false, because value did not change (api/column-will-change? :archived (db/select-one Collection :id 10) {}) ; -> false; value not specified in updates (request body)" - [k :- schema/Keyword, object-before-updates :- su/MapPlumatic, object-updates :- su/MapPlumatic] + [k :- schema/Keyword, object-before-updates :- su/Map, object-updates :- su/Map] (boolean (and (contains? object-updates k) (not= (get object-before-updates k) @@ -496,9 +496,9 @@ (schema/defn reconcile-position-for-collection! "Compare `old-position` and `new-position` to determine what needs to be updated based on the position change. Used for fixing card/dashboard/pulse changes that impact other instances in the collection" - [collection-id :- (schema/maybe su/IntGreaterThanZeroPlumatic) - old-position :- (schema/maybe su/IntGreaterThanZeroPlumatic) - new-position :- (schema/maybe su/IntGreaterThanZeroPlumatic)] + [collection-id :- (schema/maybe su/IntGreaterThanZero) + old-position :- (schema/maybe su/IntGreaterThanZero) + new-position :- (schema/maybe su/IntGreaterThanZero)] (let [update-fn! (fn [plus-or-minus position-update-clause] (doseq [model '[Card Dashboard Pulse]] (db/update-where! model {:collection_id collection-id @@ -521,15 +521,15 @@ (def ^:private ModelWithPosition "Intended to cover Cards/Dashboards/Pulses, it only asserts collection id and position, allowing extra keys" - {:collection_id (schema/maybe su/IntGreaterThanZeroPlumatic) - :collection_position (schema/maybe su/IntGreaterThanZeroPlumatic) + {:collection_id (schema/maybe su/IntGreaterThanZero) + :collection_position (schema/maybe su/IntGreaterThanZero) schema/Any schema/Any}) (def ^:private ModelWithOptionalPosition "Intended to cover Cards/Dashboards/Pulses updates. Collection id and position are optional, if they are not present, they didn't change. If they are present, they might have changed and we need to compare." - {(schema/optional-key :collection_id) (schema/maybe su/IntGreaterThanZeroPlumatic) - (schema/optional-key :collection_position) (schema/maybe su/IntGreaterThanZeroPlumatic) + {(schema/optional-key :collection_id) (schema/maybe su/IntGreaterThanZero) + (schema/optional-key :collection_position) (schema/maybe su/IntGreaterThanZero) schema/Any schema/Any}) (schema/defn maybe-reconcile-collection-position! diff --git a/src/metabase/api/dashboard.clj b/src/metabase/api/dashboard.clj index 9c44a57aea5a704a7943c42b43c0251d00ec1967..defb929f79c93e111dd2a72484461f810a65fc1d 100644 --- a/src/metabase/api/dashboard.clj +++ b/src/metabase/api/dashboard.clj @@ -79,12 +79,12 @@ (api/defendpoint-schema POST "/" "Create a new Dashboard." [:as {{:keys [name description parameters cache_ttl collection_id collection_position], :as _dashboard} :body}] - {name su/NonBlankStringPlumatic - parameters (s/maybe [su/ParameterPlumatic]) + {name su/NonBlankString + parameters (s/maybe [su/Parameter]) description (s/maybe s/Str) - cache_ttl (s/maybe su/IntGreaterThanZeroPlumatic) - collection_id (s/maybe su/IntGreaterThanZeroPlumatic) - collection_position (s/maybe su/IntGreaterThanZeroPlumatic)} + cache_ttl (s/maybe su/IntGreaterThanZero) + collection_id (s/maybe su/IntGreaterThanZero) + collection_position (s/maybe su/IntGreaterThanZero)} ;; if we're trying to save the new dashboard in a Collection make sure we have permissions to do that (collection/check-write-perms-for-collection collection_id) (let [dashboard-data {:name name @@ -318,10 +318,10 @@ "Copy a Dashboard." [from-dashboard-id :as {{:keys [name description collection_id collection_position is_deep_copy], :as _dashboard} :body}] - {name (s/maybe su/NonBlankStringPlumatic) + {name (s/maybe su/NonBlankString) description (s/maybe s/Str) - collection_id (s/maybe su/IntGreaterThanZeroPlumatic) - collection_position (s/maybe su/IntGreaterThanZeroPlumatic) + collection_id (s/maybe su/IntGreaterThanZero) + collection_position (s/maybe su/IntGreaterThanZero) is_deep_copy (s/maybe s/Bool)} ;; if we're trying to save the new dashboard in a Collection make sure we have permissions to do that (collection/check-write-perms-for-collection collection_id) @@ -388,19 +388,19 @@ [id :as {{:keys [description name parameters caveats points_of_interest show_in_getting_started enable_embedding embedding_params position archived collection_id collection_position cache_ttl] :as dash-updates} :body}] - {name (s/maybe su/NonBlankStringPlumatic) + {name (s/maybe su/NonBlankString) description (s/maybe s/Str) caveats (s/maybe s/Str) points_of_interest (s/maybe s/Str) show_in_getting_started (s/maybe s/Bool) enable_embedding (s/maybe s/Bool) - embedding_params (s/maybe su/EmbeddingParamsPlumatic) - parameters (s/maybe [su/ParameterPlumatic]) - position (s/maybe su/IntGreaterThanZeroPlumatic) + embedding_params (s/maybe su/EmbeddingParams) + parameters (s/maybe [su/Parameter]) + position (s/maybe su/IntGreaterThanZero) archived (s/maybe s/Bool) - collection_id (s/maybe su/IntGreaterThanZeroPlumatic) - collection_position (s/maybe su/IntGreaterThanZeroPlumatic) - cache_ttl (s/maybe su/IntGreaterThanZeroPlumatic)} + collection_id (s/maybe su/IntGreaterThanZero) + collection_position (s/maybe su/IntGreaterThanZero) + cache_ttl (s/maybe su/IntGreaterThanZero)} (let [dash-before-update (api/write-check Dashboard id)] ;; Do various permissions checks as needed (collection/check-allowed-to-change-collection dash-before-update dash-updates) @@ -486,7 +486,7 @@ (api/defendpoint-schema POST "/:id/cards" "Add a `Card` to a Dashboard." [id :as {{:keys [cardId parameter_mappings], :as dashboard-card} :body}] - {cardId (s/maybe su/IntGreaterThanZeroPlumatic) + {cardId (s/maybe su/IntGreaterThanZero) parameter_mappings (s/maybe [dashboard-card/ParamMapping])} (api/check-not-archived (api/write-check Dashboard id)) (when cardId @@ -536,16 +536,16 @@ (def ^:private UpdatedDashboardCard (su/with-api-error-message - {:id (su/with-api-error-message su/IntGreaterThanOrEqualToZeroPlumatic + {:id (su/with-api-error-message su/IntGreaterThanOrEqualToZero "value must be a DashboardCard ID.") - (s/optional-key :size_x) (s/maybe su/IntGreaterThanZeroPlumatic) - (s/optional-key :size_y) (s/maybe su/IntGreaterThanZeroPlumatic) - (s/optional-key :row) (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic) - (s/optional-key :col) (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic) - (s/optional-key :parameter_mappings) (s/maybe [{:parameter_id su/NonBlankStringPlumatic + (s/optional-key :size_x) (s/maybe su/IntGreaterThanZero) + (s/optional-key :size_y) (s/maybe su/IntGreaterThanZero) + (s/optional-key :row) (s/maybe su/IntGreaterThanOrEqualToZero) + (s/optional-key :col) (s/maybe su/IntGreaterThanOrEqualToZero) + (s/optional-key :parameter_mappings) (s/maybe [{:parameter_id su/NonBlankString :target s/Any s/Keyword s/Any}]) - (s/optional-key :series) (s/maybe [su/MapPlumatic]) + (s/optional-key :series) (s/maybe [su/Map]) s/Keyword s/Any} "value must be a valid DashboardCard map.")) @@ -575,7 +575,7 @@ (api/defendpoint-schema DELETE "/:id/cards" "Remove a `DashboardCard` from a Dashboard." [id dashcardId] - {dashcardId su/IntStringGreaterThanZeroPlumatic} + {dashcardId su/IntStringGreaterThanZero} (api/check-not-archived (api/write-check Dashboard id)) (when-let [dashboard-card (db/select-one DashboardCard :id (Integer/parseInt dashcardId))] (api/check-500 (dashboard-card/delete-dashboard-card! dashboard-card api/*current-user-id*)) @@ -592,7 +592,7 @@ (api/defendpoint-schema POST "/:id/revert" "Revert a Dashboard to a prior `Revision`." [id :as {{:keys [revision_id]} :body}] - {revision_id su/IntGreaterThanZeroPlumatic} + {revision_id su/IntGreaterThanZero} (api/write-check Dashboard id) (revision/revert! :entity Dashboard @@ -681,7 +681,7 @@ "How many results to return when chain filtering" 1000) -(s/defn ^:private mappings->field-ids :- (s/maybe #{su/IntGreaterThanZeroPlumatic}) +(s/defn ^:private mappings->field-ids :- (s/maybe #{su/IntGreaterThanZero}) [parameter-mappings :- (s/maybe (s/cond-pre #{dashboard-card/ParamMapping} [dashboard-card/ParamMapping]))] (set (for [param parameter-mappings :let [field-clause (params/param-target->field-clause (:target param) (:dashcard param))] @@ -721,10 +721,10 @@ ([dashboard param-key constraint-param-key->value] (chain-filter dashboard param-key constraint-param-key->value nil)) - ([dashboard :- su/MapPlumatic - param-key :- su/NonBlankStringPlumatic - constraint-param-key->value :- su/MapPlumatic - query :- (s/maybe su/NonBlankStringPlumatic)] + ([dashboard :- su/Map + param-key :- su/NonBlankString + constraint-param-key->value :- su/Map + query :- (s/maybe su/NonBlankString)] (let [constraints (chain-filter-constraints dashboard constraint-param-key->value) field-ids (param-key->field-ids dashboard param-key)] (when (empty? field-ids) @@ -786,10 +786,10 @@ ([dashboard param-key query-params] (param-values dashboard param-key query-params nil)) - ([dashboard :- su/MapPlumatic - param-key :- su/NonBlankStringPlumatic - constraint-param-key->value :- su/MapPlumatic - query :- (s/maybe su/NonBlankStringPlumatic)] + ([dashboard :- su/Map + param-key :- su/NonBlankString + constraint-param-key->value :- su/Map + query :- (s/maybe su/NonBlankString)] (let [dashboard (hydrate dashboard :resolved-params) param (get (:resolved-params dashboard) param-key)] (when-not param @@ -849,10 +849,10 @@ `filtered` Field ID -> subset of `filtering` Field IDs that would be used in chain filter query" [:as {{:keys [filtered filtering]} :params}] - {filtered (s/cond-pre su/IntStringGreaterThanZeroPlumatic - (su/non-empty [su/IntStringGreaterThanZeroPlumatic])) - filtering (s/maybe (s/cond-pre su/IntStringGreaterThanZeroPlumatic - (su/non-empty [su/IntStringGreaterThanZeroPlumatic])))} + {filtered (s/cond-pre su/IntStringGreaterThanZero + (su/non-empty [su/IntStringGreaterThanZero])) + filtering (s/maybe (s/cond-pre su/IntStringGreaterThanZero + (su/non-empty [su/IntStringGreaterThanZero])))} ;; parse IDs for filtered/filtering (letfn [(parse-ids [s] (set (cond @@ -868,7 +868,7 @@ (def ParameterWithID "Schema for a parameter map with an string `:id`." (su/with-api-error-message - {:id su/NonBlankStringPlumatic + {:id su/NonBlankString s/Keyword s/Any} "value must be a parameter map with an 'id' key")) @@ -878,9 +878,9 @@ (api/defendpoint-schema GET "/:dashboard-id/dashcard/:dashcard-id/execute" "Fetches the values for filling in execution parameters. Pass PK parameters and values to select." [dashboard-id dashcard-id parameters] - {dashboard-id su/IntGreaterThanZeroPlumatic - dashcard-id su/IntGreaterThanZeroPlumatic - parameters su/JSONStringPlumatic} + {dashboard-id su/IntGreaterThanZero + dashcard-id su/IntGreaterThanZero + parameters su/JSONString} (api/read-check Dashboard dashboard-id) (actions.execution/fetch-values dashboard-id dashcard-id (json/parse-string parameters))) @@ -891,8 +891,8 @@ `parameters` should be the mapped dashboard parameters with values. `extra_parameters` should be the extra, user entered parameter values." [dashboard-id dashcard-id :as {{:keys [parameters], :as _body} :body}] - {dashboard-id su/IntGreaterThanZeroPlumatic - dashcard-id su/IntGreaterThanZeroPlumatic + {dashboard-id su/IntGreaterThanZero + dashcard-id su/IntGreaterThanZero parameters (s/maybe {s/Keyword s/Any})} (api/read-check Dashboard dashboard-id) ;; Undo middleware string->keyword coercion @@ -920,7 +920,7 @@ `parameters` should be passed as query parameter encoded as a serialized JSON string (this is because this endpoint is normally used to power 'Download Results' buttons that use HTML `form` actions)." [dashboard-id dashcard-id card-id export-format :as {{:keys [parameters], :as request-parameters} :params}] - {parameters (s/maybe su/JSONStringPlumatic) + {parameters (s/maybe su/JSONString) export-format api.dataset/ExportFormat} (m/mapply qp.dashboard/run-query-for-dashcard-async (merge diff --git a/src/metabase/api/database.clj b/src/metabase/api/database.clj index 611b7d6b74890d21abc1c3041f5fb2ce587f5147..4223317124f6bb997113635fe87d63f9cfd41164 100644 --- a/src/metabase/api/database.clj +++ b/src/metabase/api/database.clj @@ -53,7 +53,7 @@ (def DBEngineString "Schema for a valid database engine name, e.g. `h2` or `postgres`." (su/with-api-error-message (s/constrained - su/NonBlankStringPlumatic + su/NonBlankString #(u/ignore-exceptions (driver/the-driver %)) "Valid database engine") (deferred-tru "value must be a valid database engine."))) @@ -80,7 +80,7 @@ permissions; there was a specific option where you could give a Perms Group permissions to run existing Cards with native queries, but not to create new ones. With the advent of what is currently being called 'Space-Age Permissions', all Cards' permissions are based on their parent Collection, removing the need for native read perms." - [dbs :- [su/MapPlumatic]] + [dbs :- [su/Map]] (for [db dbs] (assoc db :native_permissions (if (perms/set-has-full-permissions? @api/*current-user-permissions-set* (perms/adhoc-native-query-path (u/the-id db))) @@ -262,12 +262,12 @@ * `exclude_uneditable_details` will only include DBs for which the current user can edit the DB details. Has no effect unless Enterprise Edition code is available and the advanced-permissions feature is enabled." [include_tables include_cards include saved include_editable_data_model exclude_uneditable_details] - {include_tables (s/maybe su/BooleanStringPlumatic) - include_cards (s/maybe su/BooleanStringPlumatic) + {include_tables (s/maybe su/BooleanString) + include_cards (s/maybe su/BooleanString) include FetchAllIncludeValues - saved (s/maybe su/BooleanStringPlumatic) - include_editable_data_model (s/maybe su/BooleanStringPlumatic) - exclude_uneditable_details (s/maybe su/BooleanStringPlumatic)} + saved (s/maybe su/BooleanString) + include_editable_data_model (s/maybe su/BooleanString) + exclude_uneditable_details (s/maybe su/BooleanString)} (when (and config/is-dev? (or include_tables include_cards)) ;; don't need to i18n since this is dev-facing only @@ -404,8 +404,8 @@ In addition, if the user has no data access for the DB (aka block permissions), it will return only the DB name, ID and tables, with no additional metadata." [id include_hidden include_editable_data_model] - {include_hidden (s/maybe su/BooleanStringPlumatic) - include_editable_data_model (s/maybe su/BooleanStringPlumatic)} + {include_hidden (s/maybe su/BooleanString) + include_editable_data_model (s/maybe su/BooleanString)} (db-metadata id (Boolean/parseBoolean include_hidden) (Boolean/parseBoolean include_editable_data_model))) @@ -527,8 +527,8 @@ When Fields lack a semantic_type, they are returned in the format `[field_name \"table_name base_type\"]`" [id prefix substring] {id s/Int - prefix (s/maybe su/NonBlankStringPlumatic) - substring (s/maybe su/NonBlankStringPlumatic)} + prefix (s/maybe su/NonBlankString) + substring (s/maybe su/NonBlankString)} (api/read-check Database id) (when (and (str/blank? prefix) (str/blank? substring)) (throw (ex-info "Must include prefix or search" {:status-code 400}))) @@ -548,7 +548,7 @@ This is intended for use with the ACE Editor when the User is typing in a template tag for a `Card`, e.g. {{#...}}." [id query] {id s/Int - query su/NonBlankStringPlumatic} + query su/NonBlankString} (api/read-check Database id) (try (->> (autocomplete-cards id query) @@ -640,14 +640,14 @@ (:name field)))] (contains? driver-props "ssl"))) -(s/defn ^:private test-connection-details :- su/MapPlumatic +(s/defn ^:private test-connection-details :- su/Map "Try a making a connection to database `engine` with `details`. If the `details` has SSL explicitly enabled, go with that and do not accept plaintext connections. If it is disabled, try twice: once with SSL, and a second time without if the first fails. If either attempt is successful, returns the details used to successfully connect. Otherwise returns a map with the connection error message. (This map will also contain the key `:valid` = `false`, which you can use to distinguish an error from valid details.)" - [engine :- DBEngineString, details :- su/MapPlumatic] + [engine :- DBEngineString, details :- su/Map] (let [;; Try SSL first if SSL is supported and not already enabled ;; If not successful or not applicable, details-with-ssl will be nil details-with-ssl (assoc details :ssl true) @@ -667,14 +667,14 @@ (api/defendpoint-schema POST "/" "Add a new `Database`." [:as {{:keys [name engine details is_full_sync is_on_demand schedules auto_run_queries cache_ttl]} :body}] - {name su/NonBlankStringPlumatic + {name su/NonBlankString engine DBEngineString - details su/MapPlumatic + details su/Map is_full_sync (s/maybe s/Bool) is_on_demand (s/maybe s/Bool) schedules (s/maybe sync.schedules/ExpandedSchedulesMap) auto_run_queries (s/maybe s/Bool) - cache_ttl (s/maybe su/IntGreaterThanZeroPlumatic)} + cache_ttl (s/maybe su/IntGreaterThanZero)} (api/check-superuser) (let [is-full-sync? (or (nil? is_full_sync) (boolean is_full_sync)) @@ -716,7 +716,7 @@ ;; TODO - why do we pass the DB in under the key `details`? [:as {{{:keys [engine details]} :details} :body}] {engine DBEngineString - details su/MapPlumatic} + details su/Map} (api/check-superuser) (let [details-or-error (test-connection-details engine details)] {:valid (not (false? (:valid details-or-error)))})) @@ -752,7 +752,7 @@ (api/defendpoint-schema POST "/:id/persist" "Attempt to enable model persistence for a database. If already enabled returns a generic 204." [id] - {:id su/IntGreaterThanZeroPlumatic} + {:id su/IntGreaterThanZero} (api/check (public-settings/persisted-models-enabled) 400 (tru "Persisting models is not enabled.")) @@ -779,7 +779,7 @@ (api/defendpoint-schema POST "/:id/unpersist" "Attempt to disable model persistence for a database. If already not enabled, just returns a generic 204." [id] - {:id su/IntGreaterThanZeroPlumatic} + {:id su/IntGreaterThanZero} (api/let-404 [database (db/select-one Database :id id)] (api/write-check database) (if (-> database :options :persist-models-enabled) @@ -796,17 +796,17 @@ "Update a `Database`." [id :as {{:keys [name engine details is_full_sync is_on_demand description caveats points_of_interest schedules auto_run_queries refingerprint cache_ttl settings]} :body}] - {name (s/maybe su/NonBlankStringPlumatic) + {name (s/maybe su/NonBlankString) engine (s/maybe DBEngineString) refingerprint (s/maybe s/Bool) - details (s/maybe su/MapPlumatic) + details (s/maybe su/Map) schedules (s/maybe sync.schedules/ExpandedSchedulesMap) description (s/maybe s/Str) ; s/Str instead of su/NonBlankString because we don't care caveats (s/maybe s/Str) ; whether someone sets these to blank strings points_of_interest (s/maybe s/Str) auto_run_queries (s/maybe s/Bool) - cache_ttl (s/maybe su/IntGreaterThanZeroPlumatic) - settings (s/maybe su/MapPlumatic)} + cache_ttl (s/maybe su/IntGreaterThanZero) + settings (s/maybe su/Map)} ;; TODO - ensure that custom schedules and let-user-control-scheduling go in lockstep (let [existing-database (api/write-check (db/select-one Database :id id)) details (driver.u/db-details-client->server engine details) diff --git a/src/metabase/api/dataset.clj b/src/metabase/api/dataset.clj index 26aec011a30cc8665369f117c711345aa187b652..bd8a8263c5a0875ba1c1dacf7824b3ff514a09a5 100644 --- a/src/metabase/api/dataset.clj +++ b/src/metabase/api/dataset.clj @@ -112,8 +112,8 @@ (api/defendpoint-schema ^:streaming POST ["/:export-format", :export-format export-format-regex] "Execute a query and download the result data as a file in the specified format." [export-format :as {{:keys [query visualization_settings] :or {visualization_settings "{}"}} :params}] - {query su/JSONStringPlumatic - visualization_settings su/JSONStringPlumatic + {query su/JSONString + visualization_settings su/JSONString export-format ExportFormat} (let [query (json/parse-string query keyword) viz-settings (-> (json/parse-string visualization_settings viz-setting-key-fn) diff --git a/src/metabase/api/email.clj b/src/metabase/api/email.clj index ac219908c4a9a03cd5052abcf72df2f798ef8b39..43bd6faf5dae9a23ed6398920c918effbce1502e 100644 --- a/src/metabase/api/email.clj +++ b/src/metabase/api/email.clj @@ -92,7 +92,7 @@ (api/defendpoint-schema PUT "/" "Update multiple email Settings. You must be a superuser or have `setting` permission to do this." [:as {settings :body}] - {settings su/MapPlumatic} + {settings su/Map} (validation/check-has-application-permission :setting) (let [;; the frontend has access to an obfuscated version of the password. Watch for whether it sent us a new password or ;; the obfuscated version diff --git a/src/metabase/api/embed.clj b/src/metabase/api/embed.clj index 25356a107b94ae028227412d6248df8e44c158ed..eefa2750a0b9fc813513cc2a8f97500d27d57c66 100644 --- a/src/metabase/api/embed.clj +++ b/src/metabase/api/embed.clj @@ -92,7 +92,7 @@ that ones that are required are specified by checking them against a Card or Dashboard's `object-embedding-params` (the object's value of `:embedding_params`). Throws a 400 if any of the checks fail. If all checks are successful, returns a *merged* parameters map." - [object-embedding-params :- su/EmbeddingParamsPlumatic + [object-embedding-params :- su/EmbeddingParams token-params :- {s/Keyword s/Any} user-params :- {s/Keyword s/Any}] (check-param-sets object-embedding-params @@ -115,7 +115,7 @@ "Remove the `:parameters` for `dashboard-or-card` that listed as `disabled` or `locked` in the `embedding-params` whitelist, or not present in the whitelist. This is done so the frontend doesn't display widgets for params the user can't set." - [dashboard-or-card embedding-params :- su/EmbeddingParamsPlumatic] + [dashboard-or-card embedding-params :- su/EmbeddingParams] (let [params-to-remove (set (concat (for [[param status] embedding-params :when (not= status "enabled")] param) @@ -178,7 +178,7 @@ [card] (update card :parameters concat (template-tag-parameters card))) -(s/defn ^:private apply-slug->value :- (s/maybe [{:slug su/NonBlankStringPlumatic +(s/defn ^:private apply-slug->value :- (s/maybe [{:slug su/NonBlankString :type s/Keyword :target s/Any :value s/Any}]) @@ -209,7 +209,7 @@ "Given a `dashboard-id` and parameters map in the format `slug->value`, return a sequence of parameters with `:id`s that can be passed to various functions in the `metabase.api.dashboard` namespace such as [[metabase.api.dashboard/run-query-for-dashcard-async]]." - [dashboard-id :- su/IntGreaterThanZeroPlumatic + [dashboard-id :- su/IntGreaterThanZero slug->value :- {s/Any s/Any}] (let [parameters (db/select-one-field :parameters Dashboard :id dashboard-id) slug->id (into {} (map (juxt :slug :id)) parameters)] @@ -468,8 +468,8 @@ (api/defendpoint-schema GET "/card/:token/field/:field-id/search/:search-field-id" "Search for values of a Field that is referenced by an embedded Card." [token field-id search-field-id value limit] - {value su/NonBlankStringPlumatic - limit (s/maybe su/IntStringGreaterThanZeroPlumatic)} + {value su/NonBlankString + limit (s/maybe su/IntStringGreaterThanZero)} (let [unsigned-token (embed/unsign token) card-id (embed/get-in-unsigned-token-or-throw unsigned-token [:resource :question])] (check-embedding-enabled-for-card card-id) @@ -479,8 +479,8 @@ (api/defendpoint-schema GET "/dashboard/:token/field/:field-id/search/:search-field-id" "Search for values of a Field that is referenced by a Card in an embedded Dashboard." [token field-id search-field-id value limit] - {value su/NonBlankStringPlumatic - limit (s/maybe su/IntStringGreaterThanZeroPlumatic)} + {value su/NonBlankString + limit (s/maybe su/IntStringGreaterThanZero)} (let [unsigned-token (embed/unsign token) dashboard-id (embed/get-in-unsigned-token-or-throw unsigned-token [:resource :dashboard])] (check-embedding-enabled-for-dashboard dashboard-id) @@ -495,7 +495,7 @@ "Fetch remapped Field values. This is the same as `GET /api/field/:id/remapping/:remapped-id`, but for use with embedded Cards." [token field-id remapped-id value] - {value su/NonBlankStringPlumatic} + {value su/NonBlankString} (let [unsigned-token (embed/unsign token) card-id (embed/get-in-unsigned-token-or-throw unsigned-token [:resource :question])] (check-embedding-enabled-for-card card-id) @@ -506,7 +506,7 @@ "Fetch remapped Field values. This is the same as `GET /api/field/:id/remapping/:remapped-id`, but for use with embedded Dashboards." [token field-id remapped-id value] - {value su/NonBlankStringPlumatic} + {value su/NonBlankString} (let [unsigned-token (embed/unsign token) dashboard-id (embed/get-in-unsigned-token-or-throw unsigned-token [:resource :dashboard])] (check-embedding-enabled-for-dashboard dashboard-id) @@ -538,7 +538,7 @@ ;; variables whose name includes `id-` e.g. `id-query-params` below are ones that are keyed by ID; ones whose name ;; includes `slug-` are keyed by slug. -(s/defn ^:private param-values-merged-params :- {su/NonBlankStringPlumatic s/Any} +(s/defn ^:private param-values-merged-params :- {su/NonBlankString s/Any} [id->slug slug->id embedding-params token-params id-query-params] (let [slug-query-params (into {} (for [[id v] id-query-params] diff --git a/src/metabase/api/field.clj b/src/metabase/api/field.clj index a0f8b775ad2b0d9b8815a79a0ef2801e8a0f814e..d41e539ecfb01ab8816c982c86d9c259fdffe616 100644 --- a/src/metabase/api/field.clj +++ b/src/metabase/api/field.clj @@ -101,17 +101,17 @@ [id :as {{:keys [caveats description display_name fk_target_field_id points_of_interest semantic_type coercion_strategy visibility_type has_field_values settings nfc_path] :as body} :body}] - {caveats (s/maybe su/NonBlankStringPlumatic) - description (s/maybe su/NonBlankStringPlumatic) - display_name (s/maybe su/NonBlankStringPlumatic) - fk_target_field_id (s/maybe su/IntGreaterThanZeroPlumatic) - points_of_interest (s/maybe su/NonBlankStringPlumatic) - semantic_type (s/maybe su/FieldSemanticOrRelationTypeKeywordOrStringPlumatic) - coercion_strategy (s/maybe su/CoercionStrategyKeywordOrStringPlumatic) + {caveats (s/maybe su/NonBlankString) + description (s/maybe su/NonBlankString) + display_name (s/maybe su/NonBlankString) + fk_target_field_id (s/maybe su/IntGreaterThanZero) + points_of_interest (s/maybe su/NonBlankString) + semantic_type (s/maybe su/FieldSemanticOrRelationTypeKeywordOrString) + coercion_strategy (s/maybe su/CoercionStrategyKeywordOrString) visibility_type (s/maybe FieldVisibilityType) has_field_values (s/maybe (apply s/enum (map name field/has-field-values-options))) - settings (s/maybe su/MapPlumatic) - nfc_path (s/maybe [su/NonBlankStringPlumatic])} + settings (s/maybe su/Map) + nfc_path (s/maybe [su/NonBlankString])} (let [field (hydrate (api/write-check Field id) :dimensions) new-semantic-type (keyword (get body :semantic_type (:semantic_type field))) [effective-type coercion-strategy] @@ -169,8 +169,8 @@ "Sets the dimension for the given field at ID" [id :as {{dimension-type :type, dimension-name :name, human_readable_field_id :human_readable_field_id} :body}] {dimension-type (su/api-param "type" (s/enum "internal" "external")) - dimension-name (su/api-param "name" su/NonBlankStringPlumatic) - human_readable_field_id (s/maybe su/IntGreaterThanZeroPlumatic)} + dimension-name (su/api-param "name" su/NonBlankString) + human_readable_field_id (s/maybe su/IntGreaterThanZero)} (api/write-check Field id) (api/check (or (= dimension-type "internal") (and (= dimension-type "external") @@ -278,7 +278,7 @@ "Update the fields values and human-readable values for a `Field` whose semantic type is `category`/`city`/`state`/`country` or whose base type is `type/Boolean`. The human-readable values are optional." [id :as {{value-pairs :values} :body}] - {value-pairs [[(s/one s/Any "value") (s/optional su/NonBlankStringPlumatic "human readable value")]]} + {value-pairs [[(s/one s/Any "value") (s/optional su/NonBlankString "human readable value")]]} (let [field (api/write-check Field id)] (api/check (field-values/field-should-have-field-values? field) [400 (str "You can only update the human readable values of a mapped values of a Field whose value of " @@ -391,7 +391,7 @@ "Search for values of a Field with `search-id` that start with `value`. See docstring for `metabase.api.field/search-values` for a more detailed explanation." [id search-id value] - {value su/NonBlankStringPlumatic} + {value su/NonBlankString} (let [field (api/check-404 (db/select-one Field :id id)) search-field (api/check-404 (db/select-one Field :id search-id))] (throw-if-no-read-or-segmented-perms field) diff --git a/src/metabase/api/geojson.clj b/src/metabase/api/geojson.clj index 96fe5ab5d0c1807f774923185d82633e1bb57250..332367a1cf531203df62dffe1164ef92a8667d44 100644 --- a/src/metabase/api/geojson.clj +++ b/src/metabase/api/geojson.clj @@ -24,8 +24,8 @@ :default true) (def ^:private CustomGeoJSON - {s/Keyword {:name su/NonBlankStringPlumatic - :url su/NonBlankStringPlumatic + {s/Keyword {:name su/NonBlankString + :url su/NonBlankString :region_key (s/maybe s/Str) :region_name (s/maybe s/Str) (s/optional-key :builtin) s/Bool}}) @@ -121,7 +121,7 @@ "Fetch a custom GeoJSON file as defined in the `custom-geojson` setting. (This just acts as a simple proxy for the file specified for `key`)." [{{:keys [key]} :params} respond raise] - {key su/NonBlankStringPlumatic} + {key su/NonBlankString} (when-not (or (custom-geojson-enabled) (builtin-geojson (keyword key))) (raise (ex-info (tru "Custom GeoJSON is not enabled") {:status-code 400}))) (if-let [url (get-in (custom-geojson) [(keyword key) :url])] @@ -136,7 +136,7 @@ "Load a custom GeoJSON file based on a URL or file path provided as a query parameter. This behaves similarly to /api/geojson/:key but doesn't require the custom map to be saved to the DB first." [{{:keys [url]} :params} respond raise] - {url su/NonBlankStringPlumatic} + {url su/NonBlankString} (validation/check-has-application-permission :setting) (when-not (custom-geojson-enabled) (raise (ex-info (tru "Custom GeoJSON is not enabled") {:status-code 400}))) diff --git a/src/metabase/api/ldap.clj b/src/metabase/api/ldap.clj index 38655e7dcb6a1f1e237aac1439a8b74d31ac6f60..f573222e378229eb560547d8d076e6f193262981 100644 --- a/src/metabase/api/ldap.clj +++ b/src/metabase/api/ldap.clj @@ -100,7 +100,7 @@ (api/defendpoint-schema PUT "/settings" "Update LDAP related settings. You must be a superuser or have `setting` permission to do this." [:as {settings :body}] - {settings su/MapPlumatic} + {settings su/Map} (api/check-superuser) (let [ldap-settings (-> settings (select-keys (keys ldap/mb-settings->ldap-details)) diff --git a/src/metabase/api/metric.clj b/src/metabase/api/metric.clj index 69353d5cca082023785b85b69f5a4106c1aad987..cafca0db4f8df636b749aa71f0ab5f5f8b3f44b0 100644 --- a/src/metabase/api/metric.clj +++ b/src/metabase/api/metric.clj @@ -24,9 +24,9 @@ (api/defendpoint-schema POST "/" "Create a new `Metric`." [:as {{:keys [name description table_id definition], :as body} :body}] - {name su/NonBlankStringPlumatic - table_id su/IntGreaterThanZeroPlumatic - definition su/MapPlumatic + {name su/NonBlankString + table_id su/IntGreaterThanZero + definition su/Map description (s/maybe s/Str)} ;; TODO - why can't set the other properties like `show_in_getting_started` when you create a Metric? (api/create-check Metric body) @@ -40,7 +40,7 @@ (-> (events/publish-event! :metric-create metric) (hydrate :creator)))) -(s/defn ^:private hydrated-metric [id :- su/IntGreaterThanZeroPlumatic] +(s/defn ^:private hydrated-metric [id :- su/IntGreaterThanZero] (-> (api/read-check (db/select-one Metric :id id)) (hydrate :creator))) @@ -104,9 +104,9 @@ [id :as {{:keys [name definition revision_message archived caveats description how_is_this_calculated points_of_interest show_in_getting_started] :as body} :body}] - {name (s/maybe su/NonBlankStringPlumatic) - definition (s/maybe su/MapPlumatic) - revision_message su/NonBlankStringPlumatic + {name (s/maybe su/NonBlankString) + definition (s/maybe su/Map) + revision_message su/NonBlankString archived (s/maybe s/Bool) caveats (s/maybe s/Str) description (s/maybe s/Str) @@ -120,7 +120,7 @@ "Update the important `Fields` for a `Metric` with ID. (This is used for the Getting Started guide)." [id :as {{:keys [important_field_ids]} :body}] - {important_field_ids [su/IntGreaterThanZeroPlumatic]} + {important_field_ids [su/IntGreaterThanZero]} (api/check-superuser) (api/write-check Metric id) (api/check (<= (count important_field_ids) 3) @@ -141,7 +141,7 @@ (api/defendpoint-schema DELETE "/:id" "Archive a Metric. (DEPRECATED -- Just pass updated value of `:archived` to the `PUT` endpoint instead.)" [id revision_message] - {revision_message su/NonBlankStringPlumatic} + {revision_message su/NonBlankString} (log/warn (trs "DELETE /api/metric/:id is deprecated. Instead, change its `archived` value via PUT /api/metric/:id.")) (write-check-and-update-metric! id {:archived true, :revision_message revision_message}) @@ -160,7 +160,7 @@ (api/defendpoint-schema POST "/:id/revert" "Revert a `Metric` to a prior `Revision`." [id :as {{:keys [revision_id]} :body}] - {revision_id su/IntGreaterThanZeroPlumatic} + {revision_id su/IntGreaterThanZero} (api/write-check Metric id) (revision/revert! :entity Metric diff --git a/src/metabase/api/native_query_snippet.clj b/src/metabase/api/native_query_snippet.clj index 048f105551c4a41ebf17419480e1a93d6f7e7afe..db0c63c7d0df9295f05eac584622f14daee6dd8d 100644 --- a/src/metabase/api/native_query_snippet.clj +++ b/src/metabase/api/native_query_snippet.clj @@ -16,7 +16,7 @@ [toucan.hydrate :refer [hydrate]])) (s/defn ^:private hydrated-native-query-snippet :- (s/maybe (mi/InstanceOf NativeQuerySnippet)) - [id :- su/IntGreaterThanZeroPlumatic] + [id :- su/IntGreaterThanZero] (-> (api/read-check (db/select-one NativeQuerySnippet :id id)) (hydrate :creator))) @@ -24,7 +24,7 @@ (api/defendpoint-schema GET "/" "Fetch all snippets" [archived] - {archived (s/maybe su/BooleanStringPlumatic)} + {archived (s/maybe su/BooleanString)} (let [snippets (db/select NativeQuerySnippet :archived (Boolean/parseBoolean archived) {:order-by [[:%lower.name :asc]]})] @@ -48,7 +48,7 @@ {content s/Str description (s/maybe s/Str) name native-query-snippet/NativeQuerySnippetName - collection_id (s/maybe su/IntGreaterThanZeroPlumatic)} + collection_id (s/maybe su/IntGreaterThanZero)} (check-snippet-name-is-unique name) (let [snippet {:content content :creator_id api/*current-user-id* @@ -82,7 +82,7 @@ content (s/maybe s/Str) description (s/maybe s/Str) name (s/maybe native-query-snippet/NativeQuerySnippetName) - collection_id (s/maybe su/IntGreaterThanZeroPlumatic)} + collection_id (s/maybe su/IntGreaterThanZero)} (check-perms-and-update-snippet! id body)) (api/define-routes) diff --git a/src/metabase/api/notify.clj b/src/metabase/api/notify.clj index 9d7217205f3fdaf106586fc86c207a4d79c79635..4d43fde3107d038025f1d208be111a49d65cad06 100644 --- a/src/metabase/api/notify.clj +++ b/src/metabase/api/notify.clj @@ -20,8 +20,8 @@ This endpoint is secured by an API key that needs to be passed as a `X-METABASE-APIKEY` header which needs to be defined in the `MB_API_KEY` [environment variable](https://www.metabase.com/docs/latest/configuring-metabase/environment-variables.html#mb_api_key)" [id :as {{:keys [table_id table_name scan synchronous?]} :body}] - {table_id (s/maybe su/IntGreaterThanZeroPlumatic) - table_name (s/maybe su/NonBlankStringPlumatic) + {table_id (s/maybe su/IntGreaterThanZero) + table_name (s/maybe su/NonBlankString) scan (s/maybe (s/enum "full" "schema"))} (let [schema? (when scan (#{"schema" :schema} scan)) table-sync-fn (if schema? sync-metadata/sync-table-metadata! sync/sync-table!) diff --git a/src/metabase/api/permissions.clj b/src/metabase/api/permissions.clj index c5b43702da1a5f4786b5d68ffb5bcdbf710fe9ce..126e75a28f73795ee7c0b33d06af5ca3ee68e139 100644 --- a/src/metabase/api/permissions.clj +++ b/src/metabase/api/permissions.clj @@ -60,7 +60,7 @@ response will be returned if this key is present and the server is not running the Enterprise Edition, and/or the `:sandboxes` feature flag is not present." [:as {body :body}] - {body su/MapPlumatic} + {body su/Map} (api/check-superuser) (let [graph (api.permission-graph/converted-json->graph ::api.permission-graph/data-permissions-graph body)] (when (= graph :clojure.spec.alpha/invalid) @@ -145,7 +145,7 @@ (api/defendpoint-schema POST "/group" "Create a new `PermissionsGroup`." [:as {{:keys [name]} :body}] - {name su/NonBlankStringPlumatic} + {name su/NonBlankString} (api/check-superuser) (db/insert! PermissionsGroup :name name)) @@ -154,7 +154,7 @@ (api/defendpoint-schema PUT "/group/:group-id" "Update the name of a `PermissionsGroup`." [group-id :as {{:keys [name]} :body}] - {name su/NonBlankStringPlumatic} + {name su/NonBlankString} (validation/check-manager-of-group group-id) (api/check-404 (db/exists? PermissionsGroup :id group-id)) (db/update! PermissionsGroup group-id @@ -199,8 +199,8 @@ (api/defendpoint-schema POST "/membership" "Add a `User` to a `PermissionsGroup`. Returns updated list of members belonging to the group." [:as {{:keys [group_id user_id is_group_manager]} :body}] - {group_id su/IntGreaterThanZeroPlumatic - user_id su/IntGreaterThanZeroPlumatic + {group_id su/IntGreaterThanZero + user_id su/IntGreaterThanZero is_group_manager (schema.core/maybe schema.core/Bool)} (let [is_group_manager (boolean is_group_manager)] (validation/check-manager-of-group group_id) @@ -275,7 +275,7 @@ modifies it before you can submit you revisions, the endpoint will instead make no changes and return a 409 (Conflict) response. In this case, you should fetch the updated graph and make desired changes to that." [:as {body :body}] - {body su/MapPlumatic} + {body su/Map} (api/check-superuser) (let [graph (api.permission-graph/converted-json->graph ::api.permission-graph/execution-permissions-graph body)] (when (= graph :clojure.spec.alpha/invalid) diff --git a/src/metabase/api/persist.clj b/src/metabase/api/persist.clj index e11c9401875c2b097ea6916c4dc7e11d0f89673e..acc2626a47c9772721536f9a2d4b6fdbe0d75f4f 100644 --- a/src/metabase/api/persist.clj +++ b/src/metabase/api/persist.clj @@ -81,7 +81,7 @@ (api/defendpoint-schema GET "/:persisted-info-id" "Fetch a particular [[PersistedInfo]] by id." [persisted-info-id] - {persisted-info-id (s/maybe su/IntGreaterThanZeroPlumatic)} + {persisted-info-id (s/maybe su/IntGreaterThanZero)} (api/let-404 [persisted-info (first (fetch-persisted-info {:persisted-info-id persisted-info-id} nil nil))] (api/write-check (db/select-one Database :id (:database_id persisted-info))) persisted-info)) @@ -90,7 +90,7 @@ (api/defendpoint-schema GET "/card/:card-id" "Fetch a particular [[PersistedInfo]] by card-id." [card-id] - {card-id (s/maybe su/IntGreaterThanZeroPlumatic)} + {card-id (s/maybe su/IntGreaterThanZero)} (api/let-404 [persisted-info (first (fetch-persisted-info {:card-id card-id} nil nil))] (api/write-check (db/select-one Database :id (:database_id persisted-info))) persisted-info)) diff --git a/src/metabase/api/public.clj b/src/metabase/api/public.clj index 87a0152ab28a8e885aa2f2158316a0a0085a2780..ef1b4aa4763bf670a1e1ea5d54924501e71a2ce7 100644 --- a/src/metabase/api/public.clj +++ b/src/metabase/api/public.clj @@ -148,7 +148,7 @@ "Fetch a publicly-accessible Card an return query results as well as `:card` information. Does not require auth credentials. Public sharing must be enabled." [uuid parameters] - {parameters (s/maybe su/JSONStringPlumatic)} + {parameters (s/maybe su/JSONString)} (run-query-for-card-with-public-uuid-async uuid :api (json/parse-string parameters keyword))) #_{:clj-kondo/ignore [:deprecated-var]} @@ -156,7 +156,7 @@ "Fetch a publicly-accessible Card and return query results in the specified format. Does not require auth credentials. Public sharing must be enabled." [uuid export-format :as {{:keys [parameters]} :params}] - {parameters (s/maybe su/JSONStringPlumatic) + {parameters (s/maybe su/JSONString) export-format api.dataset/ExportFormat} (run-query-for-card-with-public-uuid-async uuid @@ -231,7 +231,7 @@ "Fetch the results for a Card in a publicly-accessible Dashboard. Does not require auth credentials. Public sharing must be enabled." [uuid card-id dashcard-id parameters] - {parameters (s/maybe su/JSONStringPlumatic)} + {parameters (s/maybe su/JSONString)} (validation/check-public-sharing-enabled) (let [dashboard-id (api/check-404 (db/select-one-id Dashboard :public_uuid uuid, :archived false))] (public-dashcard-results-async @@ -245,8 +245,8 @@ (api/defendpoint-schema GET "/dashboard/:uuid/dashcard/:dashcard-id/execute" "Fetches the values for filling in execution parameters. Pass PK parameters and values to select." [uuid dashcard-id parameters] - {dashcard-id su/IntGreaterThanZeroPlumatic - parameters su/JSONStringPlumatic} + {dashcard-id su/IntGreaterThanZero + parameters su/JSONString} (validation/check-public-sharing-enabled) (let [dashboard-id (api/check-404 (db/select-one-id Dashboard :public_uuid uuid, :archived false))] (actions.execution/fetch-values dashboard-id dashcard-id (json/parse-string parameters)))) @@ -260,7 +260,7 @@ `parameters` should be the mapped dashboard parameters with values. `extra_parameters` should be the extra, user entered parameter values." [uuid dashcard-id :as {{:keys [parameters], :as _body} :body}] - {dashcard-id su/IntGreaterThanZeroPlumatic + {dashcard-id su/IntGreaterThanZero parameters (s/maybe {s/Keyword s/Any})} (let [throttle-message (try (throttle/check dashcard-execution-throttle dashcard-id) @@ -289,10 +289,10 @@ [url format maxheight maxwidth] ;; the format param is not used by the API, but is required as part of the oEmbed spec: http://oembed.com/#section2 ;; just return an error if `format` is specified and it's anything other than `json`. - {url su/NonBlankStringPlumatic + {url su/NonBlankString format (s/maybe (s/enum "json")) - maxheight (s/maybe su/IntStringPlumatic) - maxwidth (s/maybe su/IntStringPlumatic)} + maxheight (s/maybe su/IntString) + maxwidth (s/maybe su/IntString)} (let [height (if maxheight (Integer/parseInt maxheight) default-embed-max-height) width (if maxwidth (Integer/parseInt maxwidth) default-embed-max-width)] {:version "1.0" @@ -408,8 +408,8 @@ (api/defendpoint-schema GET "/card/:uuid/field/:field-id/search/:search-field-id" "Search for values of a Field that is referenced by a public Card." [uuid field-id search-field-id value limit] - {value su/NonBlankStringPlumatic - limit (s/maybe su/IntStringGreaterThanZeroPlumatic)} + {value su/NonBlankString + limit (s/maybe su/IntStringGreaterThanZero)} (validation/check-public-sharing-enabled) (let [card-id (db/select-one-id Card :public_uuid uuid, :archived false)] (search-card-fields card-id field-id search-field-id value (when limit (Integer/parseInt limit))))) @@ -418,8 +418,8 @@ (api/defendpoint-schema GET "/dashboard/:uuid/field/:field-id/search/:search-field-id" "Search for values of a Field that is referenced by a Card in a public Dashboard." [uuid field-id search-field-id value limit] - {value su/NonBlankStringPlumatic - limit (s/maybe su/IntStringGreaterThanZeroPlumatic)} + {value su/NonBlankString + limit (s/maybe su/IntStringGreaterThanZero)} (validation/check-public-sharing-enabled) (let [dashboard-id (api/check-404 (db/select-one-id Dashboard :public_uuid uuid, :archived false))] (search-dashboard-fields dashboard-id field-id search-field-id value (when limit (Integer/parseInt limit))))) @@ -452,7 +452,7 @@ "Fetch remapped Field values. This is the same as `GET /api/field/:id/remapping/:remapped-id`, but for use with public Cards." [uuid field-id remapped-id value] - {value su/NonBlankStringPlumatic} + {value su/NonBlankString} (validation/check-public-sharing-enabled) (let [card-id (api/check-404 (db/select-one-id Card :public_uuid uuid, :archived false))] (card-field-remapped-values card-id field-id remapped-id value))) @@ -462,7 +462,7 @@ "Fetch remapped Field values. This is the same as `GET /api/field/:id/remapping/:remapped-id`, but for use with public Dashboards." [uuid field-id remapped-id value] - {value su/NonBlankStringPlumatic} + {value su/NonBlankString} (validation/check-public-sharing-enabled) (let [dashboard-id (db/select-one-id Dashboard :public_uuid uuid, :archived false)] (dashboard-field-remapped-values dashboard-id field-id remapped-id value))) @@ -493,7 +493,7 @@ "Fetch a publicly-accessible Card an return query results as well as `:card` information. Does not require auth credentials. Public sharing must be enabled." [uuid parameters] - {parameters (s/maybe su/JSONStringPlumatic)} + {parameters (s/maybe su/JSONString)} (run-query-for-card-with-public-uuid-async uuid :api (json/parse-string parameters keyword) :qp-runner qp.pivot/run-pivot-query)) #_{:clj-kondo/ignore [:deprecated-var]} @@ -501,7 +501,7 @@ "Fetch the results for a Card in a publicly-accessible Dashboard. Does not require auth credentials. Public sharing must be enabled." [uuid card-id dashcard-id parameters] - {parameters (s/maybe su/JSONStringPlumatic)} + {parameters (s/maybe su/JSONString)} (validation/check-public-sharing-enabled) (let [dashboard-id (api/check-404 (db/select-one-id Dashboard :public_uuid uuid, :archived false))] (public-dashcard-results-async diff --git a/src/metabase/api/pulse.clj b/src/metabase/api/pulse.clj index 1c4b032f8ebcb6bb21990183ada1fe4cd9b0f962..55c60266e5281d4d1e81b351b2d2ae91c7a339fe 100644 --- a/src/metabase/api/pulse.clj +++ b/src/metabase/api/pulse.clj @@ -43,9 +43,9 @@ associated with that dashboard. If `user_id` is specified, restricts results to pulses or subscriptions created by the user, or for which the user is a known recipient." [archived dashboard_id user_id] - {archived (s/maybe su/BooleanStringPlumatic) - dashboard_id (s/maybe su/IntGreaterThanZeroPlumatic) - user_id (s/maybe su/IntGreaterThanZeroPlumatic)} + {archived (s/maybe su/BooleanString) + dashboard_id (s/maybe su/IntGreaterThanZero) + user_id (s/maybe su/IntGreaterThanZero)} (as-> (pulse/retrieve-pulses {:archived? (Boolean/parseBoolean archived) :dashboard-id dashboard_id :user-id user_id}) <> @@ -64,14 +64,14 @@ (api/defendpoint-schema POST "/" "Create a new `Pulse`." [:as {{:keys [name cards channels skip_if_empty collection_id collection_position dashboard_id parameters]} :body}] - {name su/NonBlankStringPlumatic + {name su/NonBlankString cards (su/non-empty [pulse/CoercibleToCardRef]) - channels (su/non-empty [su/MapPlumatic]) + channels (su/non-empty [su/Map]) skip_if_empty (s/maybe s/Bool) - collection_id (s/maybe su/IntGreaterThanZeroPlumatic) - collection_position (s/maybe su/IntGreaterThanZeroPlumatic) - dashboard_id (s/maybe su/IntGreaterThanZeroPlumatic) - parameters [su/MapPlumatic]} + collection_id (s/maybe su/IntGreaterThanZero) + collection_position (s/maybe su/IntGreaterThanZero) + dashboard_id (s/maybe su/IntGreaterThanZero) + parameters [su/Map]} (validation/check-has-application-permission :subscription false) ;; make sure we are allowed to *read* all the Cards we want to put in this Pulse (check-card-read-permissions cards) @@ -108,13 +108,13 @@ (api/defendpoint-schema PUT "/:id" "Update a Pulse with `id`." [id :as {{:keys [name cards channels skip_if_empty collection_id archived parameters], :as pulse-updates} :body}] - {name (s/maybe su/NonBlankStringPlumatic) + {name (s/maybe su/NonBlankString) cards (s/maybe (su/non-empty [pulse/CoercibleToCardRef])) - channels (s/maybe (su/non-empty [su/MapPlumatic])) + channels (s/maybe (su/non-empty [su/Map])) skip_if_empty (s/maybe s/Bool) - collection_id (s/maybe su/IntGreaterThanZeroPlumatic) + collection_id (s/maybe su/IntGreaterThanZero) archived (s/maybe s/Bool) - parameters [su/MapPlumatic]} + parameters [su/Map]} ;; do various perms checks (try (validation/check-has-application-permission :monitoring) @@ -243,13 +243,13 @@ (api/defendpoint-schema POST "/test" "Test send an unsaved pulse." [:as {{:keys [name cards channels skip_if_empty collection_id collection_position dashboard_id] :as body} :body}] - {name su/NonBlankStringPlumatic + {name su/NonBlankString cards (su/non-empty [pulse/CoercibleToCardRef]) - channels (su/non-empty [su/MapPlumatic]) + channels (su/non-empty [su/Map]) skip_if_empty (s/maybe s/Bool) - collection_id (s/maybe su/IntGreaterThanZeroPlumatic) - collection_position (s/maybe su/IntGreaterThanZeroPlumatic) - dashboard_id (s/maybe su/IntGreaterThanZeroPlumatic)} + collection_id (s/maybe su/IntGreaterThanZero) + collection_position (s/maybe su/IntGreaterThanZero) + dashboard_id (s/maybe su/IntGreaterThanZero)} (check-card-read-permissions cards) ;; make sure any email addresses that are specified are allowed before sending the test Pulse. (doseq [channel channels] diff --git a/src/metabase/api/search.clj b/src/metabase/api/search.clj index 339dd29a3506b5db12ac093d090bde6b59874b27..f77e59ce4e365cbdf6e4582cbc48c519fa072eb8 100644 --- a/src/metabase/api/search.clj +++ b/src/metabase/api/search.clj @@ -30,10 +30,10 @@ (def ^:private SearchContext "Map with the various allowed search parameters, used to construct the SQL query" - {:search-string (s/maybe su/NonBlankStringPlumatic) + {:search-string (s/maybe su/NonBlankString) :archived? s/Bool :current-user-perms #{perms/Path} - (s/optional-key :models) (s/maybe #{su/NonBlankStringPlumatic}) + (s/optional-key :models) (s/maybe #{su/NonBlankString}) (s/optional-key :table-db-id) (s/maybe s/Int) (s/optional-key :limit-int) (s/maybe s/Int) (s/optional-key :offset-int) (s/maybe s/Int)}) @@ -223,7 +223,7 @@ (s/defn ^:private add-collection-join-and-where-clauses "Add a `WHERE` clause to the query to only return Collections the Current User has access to; join against Collection so we can return its `:name`." - [honeysql-query :- su/MapPlumatic, collection-id-column :- s/Keyword, {:keys [current-user-perms]} :- SearchContext] + [honeysql-query :- su/Map, collection-id-column :- s/Keyword, {:keys [current-user-perms]} :- SearchContext] (let [visible-collections (collection/permissions-set->visible-collection-ids current-user-perms) collection-filter-clause (collection/visible-collection-ids->honeysql-filter-clause collection-id-column @@ -240,7 +240,7 @@ (s/defn ^:private add-table-db-id-clause "Add a WHERE clause to only return tables with the given DB id. Used in data picker for joins because we can't join across DB's." - [query :- su/MapPlumatic, id :- (s/maybe s/Int)] + [query :- su/Map, id :- (s/maybe s/Int)] (if (some? id) (hh/merge-where query [:= id :db_id]) query)) @@ -248,7 +248,7 @@ (s/defn ^:private add-card-db-id-clause "Add a WHERE clause to only return cards with the given DB id. Used in data picker for joins because we can't join across DB's." - [query :- su/MapPlumatic, id :- (s/maybe s/Int)] + [query :- su/Map, id :- (s/maybe s/Int)] (if (some? id) (hh/merge-where query [:= id :database_id]) query)) @@ -446,15 +446,15 @@ ;;; +----------------------------------------------------------------------------------------------------------------+ ; This is basically a union type. defendpoint splits the string if it only gets one -(def ^:private models-schema (s/conditional vector? [su/NonBlankStringPlumatic] :else su/NonBlankStringPlumatic)) +(def ^:private models-schema (s/conditional vector? [su/NonBlankString] :else su/NonBlankString)) (s/defn ^:private search-context :- SearchContext - [search-string :- (s/maybe su/NonBlankStringPlumatic), - archived-string :- (s/maybe su/BooleanStringPlumatic) - table-db-id :- (s/maybe su/IntGreaterThanZeroPlumatic) + [search-string :- (s/maybe su/NonBlankString), + archived-string :- (s/maybe su/BooleanString) + table-db-id :- (s/maybe su/IntGreaterThanZero) models :- (s/maybe models-schema) - limit :- (s/maybe su/IntGreaterThanZeroPlumatic) - offset :- (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic)] + limit :- (s/maybe su/IntGreaterThanZero) + offset :- (s/maybe su/IntGreaterThanOrEqualToZero)] (cond-> {:search-string search-string :archived? (Boolean/parseBoolean archived-string) :current-user-perms @api/*current-user-permissions-set*} @@ -480,9 +480,9 @@ To specify a list of models, pass in an array to `models`. " [q archived table_db_id models] - {q (s/maybe su/NonBlankStringPlumatic) - archived (s/maybe su/BooleanStringPlumatic) - table_db_id (s/maybe su/IntGreaterThanZeroPlumatic) + {q (s/maybe su/NonBlankString) + archived (s/maybe su/BooleanString) + table_db_id (s/maybe su/IntGreaterThanZero) models (s/maybe models-schema)} (api/check-valid-page-params mw.offset-paging/*limit* mw.offset-paging/*offset*) (search (search-context diff --git a/src/metabase/api/segment.clj b/src/metabase/api/segment.clj index 4041f7daaff56c6b6c465854185f5d076adb77a5..e1b92291dac736ecfdc10adbde06bd81feb15bfa 100644 --- a/src/metabase/api/segment.clj +++ b/src/metabase/api/segment.clj @@ -23,9 +23,9 @@ (api/defendpoint-schema POST "/" "Create a new `Segment`." [:as {{:keys [name description table_id definition], :as body} :body}] - {name su/NonBlankStringPlumatic - table_id su/IntGreaterThanZeroPlumatic - definition su/MapPlumatic + {name su/NonBlankString + table_id su/IntGreaterThanZero + definition su/Map description (s/maybe s/Str)} ;; TODO - why can't we set other properties like `show_in_getting_started` when we create the Segment? (api/create-check Segment body) @@ -39,7 +39,7 @@ (-> (events/publish-event! :segment-create segment) (hydrate :creator)))) -(s/defn ^:private hydrated-segment [id :- su/IntGreaterThanZeroPlumatic] +(s/defn ^:private hydrated-segment [id :- su/IntGreaterThanZero] (-> (api/read-check (db/select-one Segment :id id)) (hydrate :creator))) @@ -94,9 +94,9 @@ [id :as {{:keys [name definition revision_message archived caveats description points_of_interest show_in_getting_started] :as body} :body}] - {name (s/maybe su/NonBlankStringPlumatic) - definition (s/maybe su/MapPlumatic) - revision_message su/NonBlankStringPlumatic + {name (s/maybe su/NonBlankString) + definition (s/maybe su/Map) + revision_message su/NonBlankString archived (s/maybe s/Bool) caveats (s/maybe s/Str) description (s/maybe s/Str) @@ -108,7 +108,7 @@ (api/defendpoint-schema DELETE "/:id" "Archive a Segment. (DEPRECATED -- Just pass updated value of `:archived` to the `PUT` endpoint instead.)" [id revision_message] - {revision_message su/NonBlankStringPlumatic} + {revision_message su/NonBlankString} (log/warn (trs "DELETE /api/segment/:id is deprecated. Instead, change its `archived` value via PUT /api/segment/:id.")) (write-check-and-update-segment! id {:archived true, :revision_message revision_message}) @@ -127,7 +127,7 @@ (api/defendpoint-schema POST "/:id/revert" "Revert a `Segement` to a prior `Revision`." [id :as {{:keys [revision_id]} :body}] - {revision_id su/IntGreaterThanZeroPlumatic} + {revision_id su/IntGreaterThanZero} (api/write-check Segment id) (revision/revert! :entity Segment diff --git a/src/metabase/api/session.clj b/src/metabase/api/session.clj index 94292f1dd9f92dd88621cba5c1a00eebced4e7b9..ee356e0f71424aadaf61f2d9054012b2c1f6a7a8 100644 --- a/src/metabase/api/session.clj +++ b/src/metabase/api/session.clj @@ -32,7 +32,7 @@ (java.util UUID))) (s/defn ^:private record-login-history! - [session-id :- UUID user-id :- su/IntGreaterThanZeroPlumatic device-info :- request.u/DeviceInfo] + [session-id :- UUID user-id :- su/IntGreaterThanZero device-info :- request.u/DeviceInfo] (db/insert! LoginHistory (merge {:user_id user-id :session_id (str session-id)} device-info))) @@ -45,7 +45,7 @@ session-type)) (def ^:private CreateSessionUserInfo - {:id su/IntGreaterThanZeroPlumatic + {:id su/IntGreaterThanZero :last_login s/Any s/Keyword s/Any}) @@ -140,7 +140,7 @@ (s/defn ^:private login :- {:id UUID, :type (s/enum :normal :full-app-embed), s/Keyword s/Any} "Attempt to login with different avaialable methods with `username` and `password`, returning new Session ID or throwing an Exception if login could not be completed." - [username :- su/NonBlankStringPlumatic password :- su/NonBlankStringPlumatic device-info :- request.u/DeviceInfo] + [username :- su/NonBlankString password :- su/NonBlankString device-info :- request.u/DeviceInfo] ;; Primitive "strategy implementation", should be reworked for modular providers in #3210 (or (ldap-login username password device-info) ; First try LDAP if it's enabled (email-login username password device-info) ; Then try local authentication @@ -167,8 +167,8 @@ (api/defendpoint-schema POST "/" "Login." [:as {{:keys [username password]} :body, :as request}] - {username su/NonBlankStringPlumatic - password su/NonBlankStringPlumatic} + {username su/NonBlankString + password su/NonBlankString} (let [ip-address (request.u/ip-address request) request-time (t/zoned-date-time (t/zone-id "GMT")) do-login (fn [] @@ -224,7 +224,7 @@ (api/defendpoint-schema POST "/forgot_password" "Send a reset email when user has forgotten their password." [:as {{:keys [email]} :body, :as request}] - {email su/EmailPlumatic} + {email su/Email} ;; Don't leak whether the account doesn't exist, just pretend everything is ok (let [request-source (request.u/ip-address request)] (throttle-check (forgot-password-throttlers :ip-address) request-source)) @@ -256,8 +256,8 @@ (api/defendpoint-schema POST "/reset_password" "Reset password with a reset token." [:as {{:keys [token password]} :body, :as request}] - {token su/NonBlankStringPlumatic - password su/ValidPasswordPlumatic} + {token su/NonBlankString + password su/ValidPassword} (or (when-let [{user-id :id, :as user} (valid-reset-token->user token)] (user/set-password! user-id password) ;; if this is the first time the user has logged in it means that they're just accepted their Metabase invite. @@ -293,7 +293,7 @@ (api/defendpoint-schema POST "/google_auth" "Login with Google Auth." [:as {{:keys [token]} :body, :as request}] - {token su/NonBlankStringPlumatic} + {token su/NonBlankString} (when-not (google/google-auth-client-id) (throw (ex-info "Google Auth is disabled." {:status-code 400}))) ;; Verify the token is valid with Google diff --git a/src/metabase/api/setting.clj b/src/metabase/api/setting.clj index 68f7926f02ba052567132cf998812bf569cdb5ee..e67c78792aa51bb2761f6373a4671790e443283c 100644 --- a/src/metabase/api/setting.clj +++ b/src/metabase/api/setting.clj @@ -52,7 +52,7 @@ "Create/update a `Setting`. If called by a non-admin, only user-local settings can be updated. This endpoint can also be used to delete Settings by passing `nil` for `:value`." [key :as {{:keys [value]} :body}] - {key su/NonBlankStringPlumatic} + {key su/NonBlankString} (with-setting-access-control (setting/set! key value)) api/generic-204-no-content) diff --git a/src/metabase/api/setup.clj b/src/metabase/api/setup.clj index 7b732da1c8f33fd93e23ffcfc5e7e0b4d8aa497d..550803bd8353fb11dde54297ca97cbd100481e0d 100644 --- a/src/metabase/api/setup.clj +++ b/src/metabase/api/setup.clj @@ -39,7 +39,7 @@ (def ^:private SetupToken "Schema for a string that matches the instance setup token." - (su/with-api-error-message (s/constrained su/NonBlankStringPlumatic setup/token-match?) + (su/with-api-error-message (s/constrained su/NonBlankString setup/token-match?) "Token does not match the setup token.")) (def ^:dynamic ^:private *allow-api-setup-after-first-user-is-created* @@ -123,16 +123,16 @@ invited_email :email} :invite {:keys [allow_tracking site_name site_locale]} :prefs} :body, :as request}] {token SetupToken - site_name su/NonBlankStringPlumatic - site_locale (s/maybe su/ValidLocalePlumatic) - first_name (s/maybe su/NonBlankStringPlumatic) - last_name (s/maybe su/NonBlankStringPlumatic) - email su/EmailPlumatic - invited_first_name (s/maybe su/NonBlankStringPlumatic) - invited_last_name (s/maybe su/NonBlankStringPlumatic) - invited_email (s/maybe su/EmailPlumatic) - password su/ValidPasswordPlumatic - allow_tracking (s/maybe (s/cond-pre s/Bool su/BooleanStringPlumatic)) + site_name su/NonBlankString + site_locale (s/maybe su/ValidLocale) + first_name (s/maybe su/NonBlankString) + last_name (s/maybe su/NonBlankString) + email su/Email + invited_first_name (s/maybe su/NonBlankString) + invited_last_name (s/maybe su/NonBlankString) + invited_email (s/maybe su/Email) + password su/ValidPassword + allow_tracking (s/maybe (s/cond-pre s/Bool su/BooleanString)) schedules (s/maybe sync.schedules/ExpandedSchedulesMap) auto_run_queries (s/maybe s/Bool)} (letfn [(create! [] diff --git a/src/metabase/api/slack.clj b/src/metabase/api/slack.clj index 13dfd036441f00a36a4731968f14021558aaf51e..4d45ac903df99b758bd1c2a412adf2e346a506a9 100644 --- a/src/metabase/api/slack.clj +++ b/src/metabase/api/slack.clj @@ -19,8 +19,8 @@ 2. invalid token -> clear 3. truthy, valid token -> refresh " [:as {{slack-app-token :slack-app-token, slack-files-channel :slack-files-channel} :body}] - {slack-app-token (s/maybe su/NonBlankStringPlumatic) - slack-files-channel (s/maybe su/NonBlankStringPlumatic)} + {slack-app-token (s/maybe su/NonBlankString) + slack-files-channel (s/maybe su/NonBlankString)} (validation/check-has-application-permission :setting) (try (when (and slack-app-token diff --git a/src/metabase/api/table.clj b/src/metabase/api/table.clj index 937f0f515af790aafb669e1bf990c2f5a54a52ea..7bb9bfde1cafc569e1ef20ba5654074487678ef5 100644 --- a/src/metabase/api/table.clj +++ b/src/metabase/api/table.clj @@ -98,8 +98,8 @@ "Update `Table` with ID." [id :as {{:keys [display_name entity_type visibility_type description caveats points_of_interest show_in_getting_started field_order], :as body} :body}] - {display_name (s/maybe su/NonBlankStringPlumatic) - entity_type (s/maybe su/EntityTypeKeywordOrStringPlumatic) + {display_name (s/maybe su/NonBlankString) + entity_type (s/maybe su/EntityTypeKeywordOrString) visibility_type (s/maybe TableVisibilityType) description (s/maybe s/Str) caveats (s/maybe s/Str) @@ -113,9 +113,9 @@ "Update all `Table` in `ids`." [:as {{:keys [ids display_name entity_type visibility_type description caveats points_of_interest show_in_getting_started], :as body} :body}] - {ids (su/non-empty [su/IntGreaterThanZeroPlumatic]) - display_name (s/maybe su/NonBlankStringPlumatic) - entity_type (s/maybe su/EntityTypeKeywordOrStringPlumatic) + {ids (su/non-empty [su/IntGreaterThanZero]) + display_name (s/maybe su/NonBlankString) + entity_type (s/maybe su/EntityTypeKeywordOrString) visibility_type (s/maybe TableVisibilityType) description (s/maybe s/Str) caveats (s/maybe s/Str) @@ -307,9 +307,9 @@ These options are provided for use in the Admin Edit Metadata page." [id include_sensitive_fields include_hidden_fields include_editable_data_model] - {include_sensitive_fields (s/maybe su/BooleanStringPlumatic) - include_hidden_fields (s/maybe su/BooleanStringPlumatic) - include_editable_data_model (s/maybe su/BooleanStringPlumatic)} + {include_sensitive_fields (s/maybe su/BooleanString) + include_hidden_fields (s/maybe su/BooleanString) + include_editable_data_model (s/maybe su/BooleanString)} (fetch-query-metadata (db/select-one Table :id id) {:include-sensitive-fields? include_sensitive_fields :include-hidden-fields? include_hidden_fields :include-editable-data-model? include_editable_data_model})) @@ -456,7 +456,7 @@ (api/defendpoint-schema PUT "/:id/fields/order" "Reorder fields" [id :as {field_order :body}] - {field_order [su/IntGreaterThanZeroPlumatic]} + {field_order [su/IntGreaterThanZero]} (-> (db/select-one Table :id id) api/write-check (table/custom-order-fields! field_order))) (api/define-routes) diff --git a/src/metabase/api/tiles.clj b/src/metabase/api/tiles.clj index 617cd139e03af5b8b926140cdc4dd41e265d0e36..a7448fd4e169c25ba7d719b7252b9122e3a8e73b 100644 --- a/src/metabase/api/tiles.clj +++ b/src/metabase/api/tiles.clj @@ -174,12 +174,12 @@ appropriate ones. It's expected that to render a full map view several calls will be made to this endpoint in parallel." [zoom x y lat-field lon-field query] - {zoom su/IntStringPlumatic - x su/IntStringPlumatic - y su/IntStringPlumatic + {zoom su/IntString + x su/IntString + y su/IntString lat-field s/Str lon-field s/Str - query su/JSONStringPlumatic} + query su/JSONString} (let [zoom (Integer/parseInt zoom) x (Integer/parseInt x) y (Integer/parseInt y) diff --git a/src/metabase/api/timeline.clj b/src/metabase/api/timeline.clj index 30899a6b7e1af551b2a44aaef20b6a157a2752c5..c7519db0300337d8264de7ca82cdb5c73f6c1d0f 100644 --- a/src/metabase/api/timeline.clj +++ b/src/metabase/api/timeline.clj @@ -23,11 +23,11 @@ (api/defendpoint-schema POST "/" "Create a new [[Timeline]]." [:as {{:keys [name default description icon collection_id archived], :as body} :body}] - {name su/NonBlankStringPlumatic + {name su/NonBlankString default (s/maybe s/Bool) description (s/maybe s/Str) icon (s/maybe timeline/Icons) - collection_id (s/maybe su/IntGreaterThanZeroPlumatic) + collection_id (s/maybe su/IntGreaterThanZero) archived (s/maybe s/Bool)} (collection/check-write-perms-for-collection collection_id) (let [tl (merge @@ -42,7 +42,7 @@ "Fetch a list of [[Timelines]]. Can include `archived=true` to return archived timelines." [include archived] {include (s/maybe Include) - archived (s/maybe su/BooleanStringPlumatic)} + archived (s/maybe su/BooleanString)} (let [archived? (Boolean/parseBoolean archived) timelines (->> (db/select Timeline {:where [:and @@ -61,9 +61,9 @@ `archived=true` to return all events on the timeline, both archived and unarchived." [id include archived start end] {include (s/maybe Include) - archived (s/maybe su/BooleanStringPlumatic) - start (s/maybe su/TemporalStringPlumatic) - end (s/maybe su/TemporalStringPlumatic)} + archived (s/maybe su/BooleanString) + start (s/maybe su/TemporalString) + end (s/maybe su/TemporalString)} (let [archived? (Boolean/parseBoolean archived) timeline (api/read-check (db/select-one Timeline :id id))] (cond-> (hydrate timeline :creator [:collection :can_write]) @@ -82,11 +82,11 @@ "Update the [[Timeline]] with `id`. Returns the timeline without events. Archiving a timeline will archive all of the events in that timeline." [id :as {{:keys [name default description icon collection_id archived] :as timeline-updates} :body}] - {name (s/maybe su/NonBlankStringPlumatic) + {name (s/maybe su/NonBlankString) default (s/maybe s/Bool) description (s/maybe s/Str) icon (s/maybe timeline/Icons) - collection_id (s/maybe su/IntGreaterThanZeroPlumatic) + collection_id (s/maybe su/IntGreaterThanZero) archived (s/maybe s/Bool)} (let [existing (api/write-check Timeline id) current-archived (:archived (db/select-one Timeline :id id))] diff --git a/src/metabase/api/timeline_event.clj b/src/metabase/api/timeline_event.clj index f795d5c86768a2ed9688cd799209bf92a917ec60..42a395401d46a240900325cb7c9b2ec36254c3cc 100644 --- a/src/metabase/api/timeline_event.clj +++ b/src/metabase/api/timeline_event.clj @@ -20,15 +20,15 @@ (api/defendpoint-schema POST "/" "Create a new [[TimelineEvent]]." [:as {{:keys [name description timestamp time_matters timezone icon timeline_id source question_id archived] :as body} :body}] - {name su/NonBlankStringPlumatic + {name su/NonBlankString description (s/maybe s/Str) - timestamp su/TemporalStringPlumatic + timestamp su/TemporalString time_matters (s/maybe s/Bool) timezone s/Str icon (s/maybe timeline/Icons) - timeline_id su/IntGreaterThanZeroPlumatic + timeline_id su/IntGreaterThanZero source (s/maybe timeline-event/Sources) - question_id (s/maybe su/IntGreaterThanZeroPlumatic) + question_id (s/maybe su/IntGreaterThanZero) archived (s/maybe s/Bool)} ;; deliberately not using api/check-404 so we can have a useful error message. (let [timeline (db/select-one Timeline :id timeline_id)] @@ -64,13 +64,13 @@ "Update a [[TimelineEvent]]." [id :as {{:keys [name description timestamp time_matters timezone icon timeline_id archived] :as timeline-event-updates} :body}] - {name (s/maybe su/NonBlankStringPlumatic) + {name (s/maybe su/NonBlankString) description (s/maybe s/Str) - timestamp (s/maybe su/TemporalStringPlumatic) + timestamp (s/maybe su/TemporalString) time_matters (s/maybe s/Bool) timezone (s/maybe s/Str) icon (s/maybe timeline/Icons) - timeline_id (s/maybe su/IntGreaterThanZeroPlumatic) + timeline_id (s/maybe su/IntGreaterThanZero) archived (s/maybe s/Bool)} (let [existing (api/write-check TimelineEvent id) timeline-event-updates (cond-> timeline-event-updates diff --git a/src/metabase/api/user.clj b/src/metabase/api/user.clj index 30e36a7bb592b56b5ed5526b6f8cfec5a9d0a960..e219455153b9235114cfb84e86e4245c5061daa5 100644 --- a/src/metabase/api/user.clj +++ b/src/metabase/api/user.clj @@ -154,8 +154,8 @@ [status query group_id include_deactivated] {status (s/maybe s/Str) query (s/maybe s/Str) - group_id (s/maybe su/IntGreaterThanZeroPlumatic) - include_deactivated (s/maybe su/BooleanStringPlumatic)} + group_id (s/maybe su/IntGreaterThanZero) + include_deactivated (s/maybe su/BooleanString)} (when (or status include_deactivated) (validation/check-group-manager)) (let [include_deactivated (Boolean/parseBoolean include_deactivated)] @@ -245,9 +245,9 @@ (api/defendpoint-schema POST "/" "Create a new `User`, return a 400 if the email address is already taken" [:as {{:keys [first_name last_name email user_group_memberships login_attributes] :as body} :body}] - {first_name (s/maybe su/NonBlankStringPlumatic) - last_name (s/maybe su/NonBlankStringPlumatic) - email su/EmailPlumatic + {first_name (s/maybe su/NonBlankString) + last_name (s/maybe su/NonBlankString) + email su/Email user_group_memberships (s/maybe [user/UserGroupMembership]) login_attributes (s/maybe user/LoginAttributes)} (api/check-superuser) @@ -301,14 +301,14 @@ Group Managers can only add/remove users from groups they are manager of." [id :as {{:keys [email first_name last_name user_group_memberships is_superuser is_group_manager login_attributes locale] :as body} :body}] - {email (s/maybe su/EmailPlumatic) - first_name (s/maybe su/NonBlankStringPlumatic) - last_name (s/maybe su/NonBlankStringPlumatic) + {email (s/maybe su/Email) + first_name (s/maybe su/NonBlankString) + last_name (s/maybe su/NonBlankString) user_group_memberships (s/maybe [user/UserGroupMembership]) is_superuser (s/maybe s/Bool) is_group_manager (s/maybe s/Bool) login_attributes (s/maybe user/LoginAttributes) - locale (s/maybe su/ValidLocalePlumatic)} + locale (s/maybe su/ValidLocale)} (try (check-self-or-superuser id) (catch clojure.lang.ExceptionInfo _e @@ -382,7 +382,7 @@ (api/defendpoint-schema PUT "/:id/password" "Update a user's password." [id :as {{:keys [password old_password]} :body}] - {password su/ValidPasswordPlumatic} + {password su/ValidPassword} (check-self-or-superuser id) (api/let-404 [user (db/select-one [User :password_salt :password], :id id, :is_active true)] ;; admins are allowed to reset anyone's password (in the admin people list) so no need to check the value of diff --git a/src/metabase/api/util.clj b/src/metabase/api/util.clj index 488c78eb8fe118a1aa2c98835c2e574345e51a1f..d62369ad350a09843c4de5885eac2af8135e137f 100644 --- a/src/metabase/api/util.clj +++ b/src/metabase/api/util.clj @@ -16,7 +16,7 @@ (api/defendpoint-schema POST "/password_check" "Endpoint that checks if the supplied password meets the currently configured password complexity rules." [:as {{:keys [password]} :body}] - {password su/ValidPasswordPlumatic} ;; if we pass the su/ValidPassword test we're g2g + {password su/ValidPassword} ;; if we pass the su/ValidPassword test we're g2g {:valid true}) #_{:clj-kondo/ignore [:deprecated-var]} diff --git a/src/metabase/automagic_dashboards/core.clj b/src/metabase/automagic_dashboards/core.clj index d00e4931c689e6a4740743d92867f6148f3a7c52..cd55a64121a0b334c649358bd958cb2472d98957 100644 --- a/src/metabase/automagic_dashboards/core.clj +++ b/src/metabase/automagic_dashboards/core.clj @@ -48,7 +48,7 @@ (s/defn ->field :- (s/maybe (mi/InstanceOf Field)) "Return `Field` instance for a given ID or name in the context of root." [{{result-metadata :result_metadata} :source, :as root} - field-id-or-name-or-clause :- (s/cond-pre su/IntGreaterThanZeroPlumatic su/NonBlankStringPlumatic mbql.s/Field)] + field-id-or-name-or-clause :- (s/cond-pre su/IntGreaterThanZero su/NonBlankString mbql.s/Field)] (let [id-or-name (if (sequential? field-id-or-name-or-clause) (filters/field-reference->id field-id-or-name-or-clause) field-id-or-name-or-clause)] diff --git a/src/metabase/automagic_dashboards/filters.clj b/src/metabase/automagic_dashboards/filters.clj index b25af8064591274d38e1f6cebcd68238badf8d13..72186dfff5a2d0f09875966b7e6c3bdbea652358 100644 --- a/src/metabase/automagic_dashboards/filters.clj +++ b/src/metabase/automagic_dashboards/filters.clj @@ -14,7 +14,7 @@ "Is given form an MBQL field reference?" (complement (s/checker mbql.s/field))) -(s/defn field-reference->id :- (s/maybe (s/cond-pre su/NonBlankStringPlumatic su/IntGreaterThanZeroPlumatic)) +(s/defn field-reference->id :- (s/maybe (s/cond-pre su/NonBlankString su/IntGreaterThanZero)) "Extract field ID from a given field reference form." [clause] (mbql.u/match-one clause [:field id _] id)) diff --git a/src/metabase/automagic_dashboards/rules.clj b/src/metabase/automagic_dashboards/rules.clj index f88f4466d05d861e8b8db9b9871a3d4da17064e5..e97e0b255e1cf3a4329fb750b4f727d080d2b835 100644 --- a/src/metabase/automagic_dashboards/rules.clj +++ b/src/metabase/automagic_dashboards/rules.clj @@ -80,7 +80,7 @@ (def ^:private OrderByPair {Identifier (s/enum "descending" "ascending")}) -(def ^:private Visualization [(s/one s/Str "visualization") su/MapPlumatic]) +(def ^:private Visualization [(s/one s/Str "visualization") su/Map]) (def ^:private Width (s/constrained s/Int #(<= 1 % populate/grid-width) (deferred-trs "1 <= width <= {0}" populate/grid-width))) @@ -96,7 +96,7 @@ (s/optional-key :dimensions) [CardDimension] (s/optional-key :filters) [s/Str] (s/optional-key :metrics) [s/Str] - (s/optional-key :limit) su/IntGreaterThanZeroPlumatic + (s/optional-key :limit) su/IntGreaterThanZero (s/optional-key :order_by) [OrderByPair] (s/optional-key :description) LocalizedString (s/optional-key :query) s/Str @@ -127,7 +127,7 @@ [(s/one (s/constrained (s/cond-pre s/Str s/Keyword) (comp #{:dimension} qp.util/normalize-token)) "dimension") (s/one s/Str "identifier") - su/MapPlumatic]) + su/Map]) (def ^{:arglists '([form])} dimension-form? "Does form denote a dimension referece?" diff --git a/src/metabase/db/metadata_queries.clj b/src/metabase/db/metadata_queries.clj index d7bbecae778dd5a3533888c7ff47dc443248f2cb..3291f361caa93d05c11f84e42ee87ac5fe609ee9 100644 --- a/src/metabase/db/metadata_queries.clj +++ b/src/metabase/db/metadata_queries.clj @@ -61,7 +61,7 @@ ([field] (field-distinct-values field absolute-max-distinct-values-limit)) - ([field max-results :- su/IntGreaterThanZeroPlumatic] + ([field max-results :- su/IntGreaterThanZero] (mapv first (field-query field {:breakout [[:field (u/the-id field) nil]] :limit (min max-results absolute-max-distinct-values-limit)})))) diff --git a/src/metabase/db/util.clj b/src/metabase/db/util.clj index ccedabe56f799f522ba846a819e1daaf586beb45..3040c8637816a254704d14e9cd8e73e44779b6c0 100644 --- a/src/metabase/db/util.clj +++ b/src/metabase/db/util.clj @@ -18,7 +18,7 @@ (def ^:private NamespacedKeyword (s/constrained s/Keyword (comp seq namespace) "namespaced keyword")) -(s/defn ^:private type-keyword->descendants :- (su/non-empty #{su/NonBlankStringPlumatic}) +(s/defn ^:private type-keyword->descendants :- (su/non-empty #{su/NonBlankString}) "Return a set of descendents of Metabase `type-keyword`. This includes `type-keyword` itself, so the set will always have at least one element. diff --git a/src/metabase/driver/common/parameters/dates.clj b/src/metabase/driver/common/parameters/dates.clj index f200d61d69e1356d4c21b4915db2a63baa1dc86c..454ed60f8bf806419f5864c006fb5590d637ac20 100644 --- a/src/metabase/driver/common/parameters/dates.clj +++ b/src/metabase/driver/common/parameters/dates.clj @@ -403,7 +403,7 @@ (s/defn date-string->filter :- mbql.s/Filter "Takes a string description of a *date* (not datetime) range such as 'lastmonth' or '2016-07-15~2016-08-6' and returns a corresponding MBQL filter clause for a given field reference." - [date-string :- s/Str field :- (s/cond-pre su/IntGreaterThanZeroPlumatic mbql.s/Field)] + [date-string :- s/Str field :- (s/cond-pre su/IntGreaterThanZero mbql.s/Field)] (or (execute-decoders all-date-string-decoders :filter (params/wrap-field-id-if-needed field) date-string) (throw (ex-info (tru "Don''t know how to parse date string {0}" (pr-str date-string)) {:type qp.error-type/invalid-parameter diff --git a/src/metabase/driver/common/parameters/values.clj b/src/metabase/driver/common/parameters/values.clj index 6ede6309ab78e187f59e5ad6bf054b3bf946a707..40c7ea66a864c9048c0eddc5ada64f92f8fde158 100644 --- a/src/metabase/driver/common/parameters/values.clj +++ b/src/metabase/driver/common/parameters/values.clj @@ -54,7 +54,7 @@ (def ^:private ParsedParamValue "Schema for valid param value(s). Params can have one or more values." - (s/named (s/maybe (s/cond-pre params/SingleValue MultipleValues su/MapPlumatic)) + (s/named (s/maybe (s/cond-pre params/SingleValue MultipleValues su/Map)) "Valid param value(s)")) (s/defn ^:private tag-targets @@ -91,7 +91,7 @@ param-display-name) {:type qp.error-type/missing-required-parameter})) -(s/defn ^:private field-filter->field-id :- su/IntGreaterThanZeroPlumatic +(s/defn ^:private field-filter->field-id :- su/IntGreaterThanZero [field-filter] (second field-filter)) @@ -263,7 +263,7 @@ to parse it as appropriate based on the base type and semantic type of the Field associated with it). These are special cases for handling types that do not have an associated parameter type (such as `date` or `number`), such as UUID fields." - [effective-type :- su/FieldTypePlumatic value] + [effective-type :- su/FieldType value] (cond (isa? effective-type :type/UUID) (UUID/fromString value) @@ -340,7 +340,7 @@ :type (or (:type (ex-data e)) qp.error-type/invalid-parameter)} e))))) -(s/defn query->params-map :- {su/NonBlankStringPlumatic ParsedParamValue} +(s/defn query->params-map :- {su/NonBlankString ParsedParamValue} "Extract parameters info from `query`. Return a map of parameter name -> value. (query->params-map some-query) diff --git a/src/metabase/driver/sql.clj b/src/metabase/driver/sql.clj index 7cf7a0f9a5e84f3a781439c54110174be26894b0..0f8ef550a84ea44c6507324b2e4a12d2fbbc2c75 100644 --- a/src/metabase/driver/sql.clj +++ b/src/metabase/driver/sql.clj @@ -42,7 +42,7 @@ (sql.qp/mbql->native driver query)) (s/defmethod driver/substitute-native-parameters :sql - [_ {:keys [query] :as inner-query} :- {:query su/NonBlankStringPlumatic, s/Keyword s/Any}] + [_ {:keys [query] :as inner-query} :- {:query su/NonBlankString, s/Keyword s/Any}] (let [[query params] (-> query params.parse/parse (sql.params.substitute/substitute (params.values/query->params-map inner-query)))] diff --git a/src/metabase/driver/sql/parameters/substitution.clj b/src/metabase/driver/sql/parameters/substitution.clj index 0899e2707710f1df92e20ae2d5a680548545b9bd..9b7ac3904e959efd3575c6373d5cfdf5ff5a774a 100644 --- a/src/metabase/driver/sql/parameters/substitution.clj +++ b/src/metabase/driver/sql/parameters/substitution.clj @@ -246,7 +246,7 @@ ;; in case anyone needs to know we're compiling a Field filter. ::compiling-field-filter? true}]) -(s/defn ^:private field->identifier :- su/NonBlankStringPlumatic +(s/defn ^:private field->identifier :- su/NonBlankString "Return an approprate snippet to represent this `field` in SQL given its param type. For non-date Fields, this is just a quoted identifier; for dates, the SQL includes appropriately bucketing based on the `param-type`." diff --git a/src/metabase/driver/sql_jdbc/connection.clj b/src/metabase/driver/sql_jdbc/connection.clj index cc29f78746e213a583d334100e8d3695225388e8..5e74a8a7938bce01460af10ea440e5db08c80f86 100644 --- a/src/metabase/driver/sql_jdbc/connection.clj +++ b/src/metabase/driver/sql_jdbc/connection.clj @@ -161,7 +161,7 @@ (s/defn ^:private jdbc-spec-hash "Computes a hash value for the JDBC connection spec based on `database`'s `:details` map, for the purpose of determining if details changed and therefore the existing connection pool needs to be invalidated." - [{driver :engine, :keys [details], :as database} :- (s/maybe su/MapPlumatic)] + [{driver :engine, :keys [details], :as database} :- (s/maybe su/Map)] (when (some? database) (hash (connection-details->spec driver details)))) diff --git a/src/metabase/driver/util.clj b/src/metabase/driver/util.clj index 6f3ed2cd8291cefc2868e983b76531dd1ac09411..7c40abfe33febf33b93c214fe2b75eb169b4258f 100644 --- a/src/metabase/driver/util.clj +++ b/src/metabase/driver/util.clj @@ -213,7 +213,7 @@ (semantic-version-gte [4 0 1] [4 1]) => false (semantic-version-gte [4 1] [4]) => true (semantic-version-gte [3 1] [4]) => false" - [xv :- [su/IntGreaterThanOrEqualToZeroPlumatic] yv :- [su/IntGreaterThanOrEqualToZeroPlumatic]] :- s/Bool + [xv :- [su/IntGreaterThanOrEqualToZero] yv :- [su/IntGreaterThanOrEqualToZero]] :- s/Bool (loop [xv (seq xv), yv (seq yv)] (or (nil? yv) (let [[x & xs] xv diff --git a/src/metabase/email.clj b/src/metabase/email.clj index cabd82820c75889fe96013c268c70488c2deee99..887e8db6325c7c9008a72cecaa9d94ff401155a2 100644 --- a/src/metabase/email.clj +++ b/src/metabase/email.clj @@ -27,7 +27,7 @@ :visibility :settings-manager) (def ^:private ReplyToAddresses - (s/maybe [su/EmailPlumatic])) + (s/maybe [su/Email])) (def ^:private ^{:arglists '([reply-to-addresses])} validate-reply-to-addresses (s/validator ReplyToAddresses)) @@ -106,7 +106,7 @@ {:subject s/Str :recipients [(s/pred u/email?)] :message-type (s/enum :text :html :attachments) - :message (s/cond-pre s/Str [su/MapPlumatic])} ; TODO - what should this be a sequence of? + :message (s/cond-pre s/Str [su/Map])} ; TODO - what should this be a sequence of? (fn [{:keys [message-type message]}] (if (= message-type :attachments) (and (sequential? message) (every? map? message)) @@ -163,8 +163,8 @@ {::error e}))) (def ^:private SMTPSettings - {:host su/NonBlankStringPlumatic - :port su/IntGreaterThanZeroPlumatic + {:host su/NonBlankString + :port su/IntGreaterThanZero ;; TODO -- not sure which of these other ones are actually required or not, and which are optional. (s/optional-key :user) (s/maybe s/Str) (s/optional-key :security) (s/maybe (s/enum :tls :ssl :none :starttls)) diff --git a/src/metabase/integrations/ldap.clj b/src/metabase/integrations/ldap.clj index 2d923c89a5ad89d13e0016352f764bf7206b21e1..b504f265603940642b6032b0401fa6124281c421 100644 --- a/src/metabase/integrations/ldap.clj +++ b/src/metabase/integrations/ldap.clj @@ -223,11 +223,11 @@ (s/defn find-user :- (s/maybe i/UserInfo) "Get user information for the supplied username." - ([username :- su/NonBlankStringPlumatic] + ([username :- su/NonBlankString] (with-ldap-connection [conn] (find-user conn username))) - ([ldap-connection :- LDAPConnectionPool, username :- su/NonBlankStringPlumatic] + ([ldap-connection :- LDAPConnectionPool, username :- su/NonBlankString] (default-impl/find-user ldap-connection username (ldap-settings)))) (s/defn fetch-or-create-user! :- (mi/InstanceOf User) diff --git a/src/metabase/integrations/ldap/default_implementation.clj b/src/metabase/integrations/ldap/default_implementation.clj index 354a83ea4bd41bb82af8d5f79da188c9b9c83c46..2f23da5fdfbc891e76de73d427d9ee9a28c0081e 100644 --- a/src/metabase/integrations/ldap/default_implementation.clj +++ b/src/metabase/integrations/ldap/default_implementation.clj @@ -23,10 +23,10 @@ (def ^:private group-membership-filter "(member={dn})") -(s/defn search :- (s/maybe su/MapPlumatic) +(s/defn search :- (s/maybe su/Map) "Search for a LDAP user with `username`." [ldap-connection :- LDAPConnectionPool - username :- su/NonBlankStringPlumatic + username :- su/NonBlankString {:keys [user-base user-filter]} :- i/LDAPSettings] (some-> (first (ldap/search @@ -37,23 +37,23 @@ :size-limit 1})) u/lower-case-map-keys)) -(s/defn ^:private process-group-membership-filter :- su/NonBlankStringPlumatic +(s/defn ^:private process-group-membership-filter :- su/NonBlankString "Replace DN and UID placeholders with values returned by the LDAP server." - [group-membership-filter :- su/NonBlankStringPlumatic - dn :- su/NonBlankStringPlumatic - uid :- (s/maybe su/NonBlankStringPlumatic)] + [group-membership-filter :- su/NonBlankString + dn :- su/NonBlankString + uid :- (s/maybe su/NonBlankString)] (let [uid-string (or uid "")] (-> group-membership-filter (str/replace "{dn}" (Filter/encodeValue ^String dn)) (str/replace "{uid}" (Filter/encodeValue ^String uid-string))))) -(s/defn ^:private user-groups :- (s/maybe [su/NonBlankStringPlumatic]) +(s/defn ^:private user-groups :- (s/maybe [su/NonBlankString]) "Retrieve groups for a supplied DN." [ldap-connection :- LDAPConnectionPool - dn :- su/NonBlankStringPlumatic - uid :- (s/maybe su/NonBlankStringPlumatic) + dn :- su/NonBlankString + uid :- (s/maybe su/NonBlankString) {:keys [group-base]} :- i/LDAPSettings - group-membership-filter :- su/NonBlankStringPlumatic] + group-membership-filter :- su/NonBlankString] (when group-base (let [results (ldap/search ldap-connection @@ -65,13 +65,13 @@ (s/defn ldap-search-result->user-info :- (s/maybe i/UserInfo) "Convert the result " [ldap-connection :- LDAPConnectionPool - {:keys [dn uid], :as result} :- su/MapPlumatic + {:keys [dn uid], :as result} :- su/Map {:keys [first-name-attribute last-name-attribute email-attribute sync-groups?] :as settings} :- i/LDAPSettings - group-membership-filter :- su/NonBlankStringPlumatic] + group-membership-filter :- su/NonBlankString] (let [{first-name (keyword first-name-attribute) last-name (keyword last-name-attribute) email (keyword email-attribute)} result] @@ -90,7 +90,7 @@ "Get user information for the supplied username." metabase-enterprise.enhancements.integrations.ldap [ldap-connection :- LDAPConnectionPool - username :- su/NonBlankStringPlumatic + username :- su/NonBlankString settings :- i/LDAPSettings] (when-let [result (search ldap-connection username settings)] (ldap-search-result->user-info ldap-connection result settings group-membership-filter))) @@ -98,9 +98,9 @@ ;;; --------------------------------------------- fetch-or-create-user! ---------------------------------------------- -(s/defn ldap-groups->mb-group-ids :- #{su/IntGreaterThanZeroPlumatic} +(s/defn ldap-groups->mb-group-ids :- #{su/IntGreaterThanZero} "Translate a set of a user's group DNs to a set of MB group IDs using the configured mappings." - [ldap-groups :- (s/maybe [su/NonBlankStringPlumatic]) + [ldap-groups :- (s/maybe [su/NonBlankString]) {:keys [group-mappings]} :- (select-keys i/LDAPSettings [:group-mappings s/Keyword])] (-> group-mappings (select-keys (map #(DN. (str %)) ldap-groups)) @@ -108,7 +108,7 @@ flatten set)) -(s/defn all-mapped-group-ids :- #{su/IntGreaterThanZeroPlumatic} +(s/defn all-mapped-group-ids :- #{su/IntGreaterThanZero} "Returns the set of all MB group IDs that have configured mappings." [{:keys [group-mappings]} :- (select-keys i/LDAPSettings [:group-mappings s/Keyword])] (-> group-mappings diff --git a/src/metabase/integrations/ldap/interface.clj b/src/metabase/integrations/ldap/interface.clj index 69f29bf1be0def8acd27fcdc66a6f82d8f033029..042b51275ec9962ca41a4ddecdd5224c7a7caadf 100644 --- a/src/metabase/integrations/ldap/interface.clj +++ b/src/metabase/integrations/ldap/interface.clj @@ -15,23 +15,23 @@ (def UserInfo "Schema for LDAP User info as returned by `user-info` and used as input to `fetch-or-create-user!`." - {:dn su/NonBlankStringPlumatic - :first-name (s/maybe su/NonBlankStringPlumatic) - :last-name (s/maybe su/NonBlankStringPlumatic) - :email su/EmailPlumatic - :groups [su/NonBlankStringPlumatic] + {:dn su/NonBlankString + :first-name (s/maybe su/NonBlankString) + :last-name (s/maybe su/NonBlankString) + :email su/Email + :groups [su/NonBlankString] s/Keyword s/Any}) (def LDAPSettings "Options passed to LDAP integration implementations. These are just the various LDAP Settings from `metabase.integrations.ldap`, packaged up as a single map so implementations don't need to fetch Setting values directly." - {:first-name-attribute su/NonBlankStringPlumatic - :last-name-attribute su/NonBlankStringPlumatic - :email-attribute su/NonBlankStringPlumatic + {:first-name-attribute su/NonBlankString + :last-name-attribute su/NonBlankString + :email-attribute su/NonBlankString :sync-groups? s/Bool - :user-base su/NonBlankStringPlumatic - :user-filter su/NonBlankStringPlumatic - :group-base (s/maybe su/NonBlankStringPlumatic) - :group-mappings (s/maybe {DN [su/IntGreaterThanZeroPlumatic]}) + :user-base su/NonBlankString + :user-filter su/NonBlankString + :group-base (s/maybe su/NonBlankString) + :group-mappings (s/maybe {DN [su/IntGreaterThanZero]}) s/Keyword s/Any}) diff --git a/src/metabase/integrations/slack.clj b/src/metabase/integrations/slack.clj index c257100a82e7e1fe8503e9368e74bae86b11312f..f2892f2f0502013e4c2e20cda64cde674a75f677 100644 --- a/src/metabase/integrations/slack.clj +++ b/src/metabase/integrations/slack.clj @@ -199,7 +199,7 @@ (s/defn valid-token? "Check whether a Slack token is valid by checking if the `conversations.list` Slack api accepts it." - [token :- su/NonBlankStringPlumatic] + [token :- su/NonBlankString] (try (binding [*send-token-error-emails?* false] (boolean (take 1 (:channels (GET "conversations.list" :limit 1, :token token))))) @@ -286,7 +286,7 @@ (s/defn join-channel! "Given a channel ID, calls Slack API `conversations.join` endpoint to join the channel as the Metabase Slack app. This must be done before uploading a file to the channel, if using a Slack app integration." - [channel-id :- su/NonBlankStringPlumatic] + [channel-id :- su/NonBlankString] (POST "conversations.join" {:form-params {:channel channel-id}})) (defn- maybe-lookup-id @@ -303,7 +303,7 @@ (s/defn upload-file! "Calls Slack API `files.upload` endpoint and returns the URL of the uploaded file." - [file :- NonEmptyByteArray, filename :- su/NonBlankStringPlumatic, channel-id :- su/NonBlankStringPlumatic] + [file :- NonEmptyByteArray, filename :- su/NonBlankString, channel-id :- su/NonBlankString] {:pre [(slack-configured?)]} (let [request {:multipart [{:name "file", :content file} {:name "filename", :content filename} @@ -325,7 +325,7 @@ (s/defn post-chat-message! "Calls Slack API `chat.postMessage` endpoint and posts a message to a channel. `attachments` should be serialized JSON." - [channel-id :- su/NonBlankStringPlumatic, text-or-nil :- (s/maybe s/Str) & [attachments]] + [channel-id :- su/NonBlankString, text-or-nil :- (s/maybe s/Str) & [attachments]] ;; TODO: it would be nice to have an emoji or icon image to use here (POST "chat.postMessage" {:form-params diff --git a/src/metabase/models/bookmark.clj b/src/metabase/models/bookmark.clj index 39721f170acc2cff79f47ceb690fb8c4a5e9fcf2..15f8cf42eddb0f5cb01ad725525b30a06b75dbc0 100644 --- a/src/metabase/models/bookmark.clj +++ b/src/metabase/models/bookmark.clj @@ -26,8 +26,8 @@ although the compound key can be inferred from it." {:id s/Str :type (s/enum "card" "collection" "dashboard") - :item_id su/IntGreaterThanZeroPlumatic - :name su/NonBlankStringPlumatic + :item_id su/IntGreaterThanZero + :name su/NonBlankString (s/optional-key :dataset) (s/maybe s/Bool) (s/optional-key :display) (s/maybe s/Str) (s/optional-key :authority_level) (s/maybe s/Str) diff --git a/src/metabase/models/collection.clj b/src/metabase/models/collection.clj index 83f0bf39e33268a2c74667d1f7dfb3c44511c3cc..7293ee6501fff16425da05d02321823ec5a44301 100644 --- a/src/metabase/models/collection.clj +++ b/src/metabase/models/collection.clj @@ -118,7 +118,7 @@ "Build a 'location path' from a sequence of `collections-or-ids`. (location-path 10 20) ; -> \"/10/20/\"" - [& collections-or-ids :- [(s/cond-pre su/IntGreaterThanZeroPlumatic su/MapPlumatic)]] + [& collections-or-ids :- [(s/cond-pre su/IntGreaterThanZero su/Map)]] (if-not (seq collections-or-ids) "/" (str @@ -127,14 +127,14 @@ (u/the-id collection-or-id))) "/"))) -(s/defn location-path->ids :- [su/IntGreaterThanZeroPlumatic] +(s/defn location-path->ids :- [su/IntGreaterThanZero] "'Explode' a `location-path` into a sequence of Collection IDs, and parse them as integers. (location-path->ids \"/10/20/\") ; -> [10 20]" [location-path :- LocationPath] (unchecked-location-path->ids location-path)) -(s/defn location-path->parent-id :- (s/maybe su/IntGreaterThanZeroPlumatic) +(s/defn location-path->parent-id :- (s/maybe su/IntGreaterThanZero) "Given a `location-path` fetch the ID of the direct of a Collection. (location-path->parent-id \"/10/20/\") ; -> 20" @@ -212,7 +212,7 @@ (s/cond-pre RootCollection {:location LocationPath - :id su/IntGreaterThanZeroPlumatic + :id su/IntGreaterThanZero s/Keyword s/Any})) (s/defn ^:private parent :- CollectionWithLocationAndIDOrRoot @@ -237,7 +237,7 @@ (def VisibleCollections "Includes the possible values for visible collections, either `:all` or a set of ids, possibly including `\"root\"` to represent the root collection." - (s/cond-pre (s/eq :all) #{(s/cond-pre (s/eq "root") su/IntGreaterThanZeroPlumatic)})) + (s/cond-pre (s/eq :all) #{(s/cond-pre (s/eq "root") su/IntGreaterThanZero)})) (s/defn permissions-set->visible-collection-ids :- VisibleCollections "Given a `permissions-set` (presumably those of the current user), return a set of IDs of Collections that the @@ -396,7 +396,7 @@ [collection] (effective-ancestors* collection)) -(s/defn ^:private parent-id* :- (s/maybe su/IntGreaterThanZeroPlumatic) +(s/defn ^:private parent-id* :- (s/maybe su/IntGreaterThanZero) [{:keys [location]} :- CollectionWithLocationOrRoot] (some-> location location-path->parent-id)) @@ -467,7 +467,7 @@ ;; key :children))) -(s/defn descendant-ids :- (s/maybe #{su/IntGreaterThanZeroPlumatic}) +(s/defn descendant-ids :- (s/maybe #{su/IntGreaterThanZero}) "Return a set of IDs of all descendant Collections of a `collection`." [collection :- CollectionWithLocationAndIDOrRoot] (db/select-ids Collection :location [:like (str (children-location collection) \%)])) @@ -613,7 +613,7 @@ :set {:location (hsql/call :replace :location orig-children-location new-children-location)} :where [:like :location (str orig-children-location "%")]})))) -(s/defn ^:private collection->descendant-ids :- (s/maybe #{su/IntGreaterThanZeroPlumatic}) +(s/defn ^:private collection->descendant-ids :- (s/maybe #{su/IntGreaterThanZero}) [collection :- CollectionWithLocationAndIDOrRoot, & additional-conditions] (apply db/select-ids Collection :location [:like (str (children-location collection) "%")] @@ -656,7 +656,7 @@ "Schema for a Collection instance that has a valid `:location`, and a `:personal_owner_id` key *present* (but not neccesarily non-nil)." {:location LocationPath - :personal_owner_id (s/maybe su/IntGreaterThanZeroPlumatic) + :personal_owner_id (s/maybe su/IntGreaterThanZero) s/Keyword s/Any}) (s/defn is-personal-collection-or-descendant-of-one? :- s/Bool @@ -730,7 +730,7 @@ (s/defn ^:private check-changes-allowed-for-personal-collection "If we're trying to UPDATE a Personal Collection, make sure the proposed changes are allowed. Personal Collections have lots of restrictions -- you can't archive them, for example, nor can you transfer them to other Users." - [collection-before-updates :- CollectionWithLocationAndIDOrRoot, collection-updates :- su/MapPlumatic] + [collection-before-updates :- CollectionWithLocationAndIDOrRoot, collection-updates :- su/Map] ;; you're not allowed to change the `:personal_owner_id` of a Collection! ;; double-check and make sure it's not just the existing value getting passed back in for whatever reason (let [unchangeable {:personal_owner_id (tru "You are not allowed to change the owner of a Personal Collection.") @@ -749,7 +749,7 @@ (s/defn ^:private maybe-archive-or-unarchive! "If `:archived` specified in the updates map, archive/unarchive as needed." - [collection-before-updates :- CollectionWithLocationAndIDOrRoot, collection-updates :- su/MapPlumatic] + [collection-before-updates :- CollectionWithLocationAndIDOrRoot, collection-updates :- su/Map] ;; If the updates map contains a value for `:archived`, see if it's actually something different than current value (when (api/column-will-change? :archived collection-before-updates collection-updates) ;; check to make sure we're not trying to change location at the same time @@ -1052,7 +1052,7 @@ ;;; | Personal Collections | ;;; +----------------------------------------------------------------------------------------------------------------+ -(s/defn format-personal-collection-name :- su/NonBlankStringPlumatic +(s/defn format-personal-collection-name :- su/NonBlankString "Constructs the personal collection name from user name. When displaying to users we'll tranlsate it to user's locale, but to keeps things consistent in the database, we'll store the name in site's locale. @@ -1069,7 +1069,7 @@ (and first-name last-name) (trs "{0} {1}''s Personal Collection" first-name last-name) :else (trs "{0}''s Personal Collection" (or first-name last-name email))))) -(s/defn user->personal-collection-name :- su/NonBlankStringPlumatic +(s/defn user->personal-collection-name :- su/NonBlankString "Come up with a nice name for the Personal Collection for `user-or-id`." [user-or-id user-or-site] (let [{first-name :first_name diff --git a/src/metabase/models/collection/graph.clj b/src/metabase/models/collection/graph.clj index cb7c255b630cec1e3ae79ec7700977841f9da175..94d9c9a20b5d4257789f64e934864c642be0247d 100644 --- a/src/metabase/models/collection/graph.clj +++ b/src/metabase/models/collection/graph.clj @@ -27,11 +27,11 @@ (def ^:private GroupPermissionsGraph "collection-id -> status" {(s/optional-key :root) CollectionPermissions ; when doing a delta between old graph and new graph root won't always - su/IntGreaterThanZeroPlumatic CollectionPermissions}) ; be present, which is why it's *optional* + su/IntGreaterThanZero CollectionPermissions}) ; be present, which is why it's *optional* (def ^:private PermissionsGraph {:revision s/Int - :groups {su/IntGreaterThanZeroPlumatic GroupPermissionsGraph}}) + :groups {su/IntGreaterThanZero GroupPermissionsGraph}}) ;;; -------------------------------------------------- Fetch Graph --------------------------------------------------- @@ -55,10 +55,10 @@ (for [collection-id collection-ids] {collection-id (perms-type-for-collection permissions-set collection-id)}))) -(s/defn ^:private non-personal-collection-ids :- #{su/IntGreaterThanZeroPlumatic} +(s/defn ^:private non-personal-collection-ids :- #{su/IntGreaterThanZero} "Return a set of IDs of all Collections that are neither Personal Collections nor descendants of Personal Collections (i.e., things that you can set Permissions for, and that should go in the graph.)" - [collection-namespace :- (s/maybe su/KeywordOrStringPlumatic)] + [collection-namespace :- (s/maybe su/KeywordOrString)] (let [personal-collection-ids (db/select-ids Collection :personal_owner_id [:not= nil]) honeysql-form {:select [[:id :id]] :from [Collection] @@ -96,7 +96,7 @@ ([] (graph nil)) - ([collection-namespace :- (s/maybe su/KeywordOrStringPlumatic)] + ([collection-namespace :- (s/maybe su/KeywordOrString)] (db/transaction (-> collection-namespace non-personal-collection-ids @@ -108,9 +108,9 @@ (s/defn ^:private update-collection-permissions! "Update the permissions for group ID with `group-id` on collection with ID `collection-id` in the optional `collection-namespace` to `new-collection-perms`." - [collection-namespace :- (s/maybe su/KeywordOrStringPlumatic) - group-id :- su/IntGreaterThanZeroPlumatic - collection-id :- (s/cond-pre (s/eq :root) su/IntGreaterThanZeroPlumatic) + [collection-namespace :- (s/maybe su/KeywordOrString) + group-id :- su/IntGreaterThanZero + collection-id :- (s/cond-pre (s/eq :root) su/IntGreaterThanZero) new-collection-perms :- CollectionPermissions] (let [collection-id (if (= collection-id :root) (assoc collection/root-collection :namespace collection-namespace) @@ -123,8 +123,8 @@ :none nil))) (s/defn ^:private update-group-permissions! - [collection-namespace :- (s/maybe su/KeywordOrStringPlumatic) - group-id :- su/IntGreaterThanZeroPlumatic + [collection-namespace :- (s/maybe su/KeywordOrString) + group-id :- su/IntGreaterThanZero new-group-perms :- GroupPermissionsGraph] (doseq [[collection-id new-perms] new-group-perms] (update-collection-permissions! collection-namespace group-id collection-id new-perms))) @@ -136,7 +136,7 @@ ([new-graph] (update-graph! nil new-graph)) - ([collection-namespace :- (s/maybe su/KeywordOrStringPlumatic), new-graph :- PermissionsGraph] + ([collection-namespace :- (s/maybe su/KeywordOrString), new-graph :- PermissionsGraph] (let [old-graph (graph collection-namespace) old-perms (:groups old-graph) new-perms (:groups new-graph) diff --git a/src/metabase/models/dashboard.clj b/src/metabase/models/dashboard.clj index 00f4bf8d23deb50de368f046d7faf15df5c4e781..b193d5b05925c01cb0ec34b3b843b4de2c14d54d 100644 --- a/src/metabase/models/dashboard.clj +++ b/src/metabase/models/dashboard.clj @@ -391,14 +391,14 @@ dashboard)) (def ^:private ParamWithMapping - {:name su/NonBlankStringPlumatic - :id su/NonBlankStringPlumatic + {:name su/NonBlankString + :id su/NonBlankString :mappings (s/maybe #{dashboard-card/ParamMapping}) s/Keyword s/Any}) -(s/defn ^:private dashboard->resolved-params* :- (let [param-id su/NonBlankStringPlumatic] +(s/defn ^:private dashboard->resolved-params* :- (let [param-id su/NonBlankString] {param-id ParamWithMapping}) - [dashboard :- {(s/optional-key :parameters) (s/maybe [su/MapPlumatic]) + [dashboard :- {(s/optional-key :parameters) (s/maybe [su/Map]) s/Keyword s/Any}] (let [dashboard (hydrate dashboard [:ordered_cards :card]) param-key->mappings (apply diff --git a/src/metabase/models/dashboard_card.clj b/src/metabase/models/dashboard_card.clj index be295d7bbdd84cf8b4edf22014cb6777db5a1a3a..9d401ef4b75411c5fa62eb00528521fc048f6dd3 100644 --- a/src/metabase/models/dashboard_card.clj +++ b/src/metabase/models/dashboard_card.clj @@ -83,7 +83,7 @@ (s/defn retrieve-dashboard-card "Fetch a single DashboardCard by its ID value." - [id :- su/IntGreaterThanZeroPlumatic] + [id :- su/IntGreaterThanZero] (-> (db/select-one DashboardCard :id id) (hydrate :series))) @@ -118,8 +118,8 @@ * If an existing DashboardCardSeries has no corresponding ID in `card-ids`, it will be deleted. * All cards will be updated with a `position` according to their place in the collection of `card-ids`" {:arglists '([dashboard-card card-ids])} - [{:keys [id]} :- {:id su/IntGreaterThanZeroPlumatic, s/Keyword s/Any} - card-ids :- [su/IntGreaterThanZeroPlumatic]] + [{:keys [id]} :- {:id su/IntGreaterThanZero, s/Keyword s/Any} + card-ids :- [su/IntGreaterThanZero]] ;; first off, just delete all series on the dashboard card (we add them again below) (db/delete! DashboardCardSeries :dashboardcard_id id) ;; now just insert all of the series that were given to us @@ -130,12 +130,12 @@ (db/insert-many! DashboardCardSeries cards)))) (def ^:private DashboardCardUpdates - {:id su/IntGreaterThanZeroPlumatic - (s/optional-key :action_id) (s/maybe su/IntGreaterThanZeroPlumatic) - (s/optional-key :parameter_mappings) (s/maybe [su/MapPlumatic]) - (s/optional-key :visualization_settings) (s/maybe su/MapPlumatic) + {:id su/IntGreaterThanZero + (s/optional-key :action_id) (s/maybe su/IntGreaterThanZero) + (s/optional-key :parameter_mappings) (s/maybe [su/Map]) + (s/optional-key :visualization_settings) (s/maybe su/Map) ;; series is a sequence of IDs of additional cards after the first to include as "additional serieses" - (s/optional-key :series) (s/maybe [su/IntGreaterThanZeroPlumatic]) + (s/optional-key :series) (s/maybe [su/IntGreaterThanZero]) s/Keyword s/Any}) (s/defn update-dashboard-card! @@ -168,18 +168,18 @@ (def ParamMapping "Schema for a parameter mapping as it would appear in the DashboardCard `:parameter_mappings` column." - {:parameter_id su/NonBlankStringPlumatic + {:parameter_id su/NonBlankString ;; TODO -- validate `:target` as well... breaks a few tests tho so those will have to be fixed #_:target #_s/Any s/Keyword s/Any}) (def ^:private NewDashboardCard - {:dashboard_id su/IntGreaterThanZeroPlumatic - (s/optional-key :card_id) (s/maybe su/IntGreaterThanZeroPlumatic) - (s/optional-key :action_id) (s/maybe su/IntGreaterThanZeroPlumatic) + {:dashboard_id su/IntGreaterThanZero + (s/optional-key :card_id) (s/maybe su/IntGreaterThanZero) + (s/optional-key :action_id) (s/maybe su/IntGreaterThanZero) ;; TODO - use ParamMapping. Breaks too many tests right now tho - (s/optional-key :parameter_mappings) (s/maybe [#_ParamMapping su/MapPlumatic]) - (s/optional-key :visualization_settings) (s/maybe su/MapPlumatic) + (s/optional-key :parameter_mappings) (s/maybe [#_ParamMapping su/Map]) + (s/optional-key :visualization_settings) (s/maybe su/Map) ;; TODO - make the rest of the options explicit instead of just allowing whatever for other keys s/Keyword s/Any}) diff --git a/src/metabase/models/field_values.clj b/src/metabase/models/field_values.clj index 61f2457e4167d39b2e2ac8ff5eff0a8b77006daa..06a0f5b5d2725bb00d7269c79b65e26c598b7862 100644 --- a/src/metabase/models/field_values.clj +++ b/src/metabase/models/field_values.clj @@ -82,7 +82,7 @@ (models/defmodel FieldValues :metabase_fieldvalues) (defn- assert-valid-human-readable-values [{human-readable-values :human_readable_values}] - (when (s/check (s/maybe [(s/maybe su/NonBlankStringPlumatic)]) human-readable-values) + (when (s/check (s/maybe [(s/maybe su/NonBlankString)]) human-readable-values) (throw (ex-info (tru "Invalid human-readable-values: values must be a sequence; each item must be nil or a string") {:human-readable-values human-readable-values :status-code 400})))) @@ -201,9 +201,9 @@ visibility-type :visibility_type has-field-values :has_field_values :as field} field-or-field-id] - (s/check {:visibility_type su/KeywordOrStringPlumatic - :base_type (s/maybe su/KeywordOrStringPlumatic) - :has_field_values (s/maybe su/KeywordOrStringPlumatic) + (s/check {:visibility_type su/KeywordOrString + :base_type (s/maybe su/KeywordOrString) + :has_field_values (s/maybe su/KeywordOrString) s/Keyword s/Any} field) (boolean diff --git a/src/metabase/models/moderation_review.clj b/src/metabase/models/moderation_review.clj index 8c0ef1e923ea4e1092fe51719f3c57b0bab74b4d..17b21f4a41b296715194b8a358fc0136a0c34e6b 100644 --- a/src/metabase/models/moderation_review.clj +++ b/src/metabase/models/moderation_review.clj @@ -21,8 +21,8 @@ ;; TODO: Appears to be unused, remove? (def ReviewChanges "Schema for a ModerationReview that's being updated (so most keys are optional)" - {(s/optional-key :id) su/IntGreaterThanZeroPlumatic - (s/optional-key :moderated_item_id) su/IntGreaterThanZeroPlumatic + {(s/optional-key :id) su/IntGreaterThanZero + (s/optional-key :moderated_item_id) su/IntGreaterThanZero (s/optional-key :moderated_item_type) moderation/moderated-item-types (s/optional-key :status) Statuses (s/optional-key :text) (s/maybe s/Str) @@ -64,9 +64,9 @@ (s/defn create-review! "Create a new ModerationReview" [params :- - {:moderated_item_id su/IntGreaterThanZeroPlumatic + {:moderated_item_id su/IntGreaterThanZero :moderated_item_type moderation/moderated-item-types - :moderator_id su/IntGreaterThanZeroPlumatic + :moderator_id su/IntGreaterThanZero (s/optional-key :status) Statuses (s/optional-key :text) (s/maybe s/Str)}] (db/transaction diff --git a/src/metabase/models/params.clj b/src/metabase/models/params.clj index 8a011c4c72462c225f75e29c2b43e978584c1d66..09b07f30b533e98849a9fcb77faa7fec7c505385 100644 --- a/src/metabase/models/params.clj +++ b/src/metabase/models/params.clj @@ -23,14 +23,14 @@ (defn assert-valid-parameters "Receive a Paremeterized Object and check if its parameters is valid." [{:keys [parameters]}] - (when (s/check (s/maybe [su/ParameterPlumatic]) parameters) + (when (s/check (s/maybe [su/Parameter]) parameters) (throw (ex-info (tru ":parameters must be a sequence of maps with :id and :type keys") {:parameters parameters})))) (defn assert-valid-parameter-mappings "Receive a Paremeterized Object and check if its parameters is valid." [{:keys [parameter_mappings]}] - (when (s/check (s/maybe [su/ParameterMappingPlumatic]) parameter_mappings) + (when (s/check (s/maybe [su/ParameterMapping]) parameter_mappings) (throw (ex-info (tru ":parameter_mappings must be a sequence of maps with :parameter_id and :type keys") {:parameter_mappings parameter_mappings})))) @@ -153,7 +153,7 @@ "Get the Fields (as a map of Field ID -> Field) that shoudl be returned for hydrated `:param_fields` for a Card or Dashboard. These only contain the minimal amount of information necessary needed to power public or embedded parameter widgets." - [field-ids :- (s/maybe #{su/IntGreaterThanZeroPlumatic})] + [field-ids :- (s/maybe #{su/IntGreaterThanZero})] (when (seq field-ids) (m/index-by :id (-> (db/select Field:params-columns-only :id [:in field-ids]) (hydrate :has_field_values :name_field [:dimensions :human_readable_field]) @@ -198,7 +198,7 @@ (for [{card :card} (:ordered_cards dashboard)] (card->template-tag-field-ids card)))) -(s/defn dashboard->param-field-ids :- #{su/IntGreaterThanZeroPlumatic} +(s/defn dashboard->param-field-ids :- #{su/IntGreaterThanZero} "Return a set of Field IDs referenced by parameters in Cards in this `dashboard`, or `nil` if none are referenced. This also includes IDs of Fields that are to be found in the 'implicit' parameters for SQL template tag Field filters." [dashboard] @@ -225,7 +225,7 @@ :when field] field))) -(s/defn card->template-tag-field-ids :- #{su/IntGreaterThanZeroPlumatic} +(s/defn card->template-tag-field-ids :- #{su/IntGreaterThanZero} "Return a set of Field IDs referenced in template tag parameters in `card`. This is mostly used for determining Fields referenced by Cards for purposes other than processing queries. Filters out `:field` clauses using names." [card] diff --git a/src/metabase/models/params/card_values.clj b/src/metabase/models/params/card_values.clj index 350d088801e89bd754460de11ca4a501edd18c09..ba2b51a0f845956b0a63587d022c524c1851e5cc 100644 --- a/src/metabase/models/params/card_values.clj +++ b/src/metabase/models/params/card_values.clj @@ -43,9 +43,9 @@ ([card-id value-field-ref] (values-from-card card-id value-field-ref nil)) - ([card-id :- su/IntGreaterThanZeroPlumatic - value-field :- su/FieldPlumatic - query :- (s/maybe su/NonBlankStringPlumatic)] + ([card-id :- su/IntGreaterThanZero + value-field :- su/Field + query :- (s/maybe su/NonBlankString)] (let [mbql-query (values-from-card-query card-id value-field query) query-limit (get-in mbql-query [:query :limit]) result (qp/process-query mbql-query)] diff --git a/src/metabase/models/params/chain_filter.clj b/src/metabase/models/params/chain_filter.clj index 85bafaca608530c0eb4b8db7c3367022e25163e1..a6f437ea5de0f249cc4cb9c57bf032c0d3195ce9 100644 --- a/src/metabase/models/params/chain_filter.clj +++ b/src/metabase/models/params/chain_filter.clj @@ -355,19 +355,19 @@ (def ^:private Options ;; if original-field-id is specified, we'll include this in the results. For Field->Field remapping. - {(s/optional-key :original-field-id) (s/maybe su/IntGreaterThanZeroPlumatic) + {(s/optional-key :original-field-id) (s/maybe su/IntGreaterThanZero) ;; return at most the lesser of `limit` (if specified) and `max-results`. - (s/optional-key :limit) (s/maybe su/IntGreaterThanZeroPlumatic)}) + (s/optional-key :limit) (s/maybe su/IntGreaterThanZero)}) (def ^:private max-results 1000) (def ^:private ConstraintsMap "Schema for map of (other) Field ID -> value for additional constraints for the `chain-filter` results." - {su/IntGreaterThanZeroPlumatic s/Any}) + {su/IntGreaterThanZero s/Any}) (s/defn ^:private chain-filter-mbql-query "Generate the MBQL query powering `chain-filter`." - [field-id :- su/IntGreaterThanZeroPlumatic + [field-id :- su/IntGreaterThanZero constraints :- (s/maybe ConstraintsMap) {:keys [original-field-id limit]} :- (s/maybe Options)] {:database (field/field-id->database-id field-id) @@ -420,7 +420,7 @@ (s/defn ^:private unremapped-chain-filter "Chain filtering without all the fancy remapping stuff on top of it." - [field-id :- su/IntGreaterThanZeroPlumatic + [field-id :- su/IntGreaterThanZero constraints :- (s/maybe ConstraintsMap) {:keys [original-field-id], :as options} :- (s/maybe Options)] (let [mbql-query (chain-filter-mbql-query field-id constraints options)] @@ -467,7 +467,7 @@ (su/non-empty {s/Any (s/maybe s/Str)})) (s/defn ^:private human-readable-remapping-map :- (s/maybe HumanReadableRemappingMap) - [field-id :- su/IntGreaterThanZeroPlumatic] + [field-id :- su/IntGreaterThanZero] (when-let [{orig :values, remapped :human_readable_values} (db/select-one [FieldValues :values :human_readable_values] {:where [:and [:= :type "full"] @@ -489,7 +489,7 @@ "Chain filter, but for Fields that have human-readable values defined (e.g. you've went in and specified that enum value `1` should be displayed as `BIRD_TYPE_TOUCAN`). `v->human-readable` is a map of actual values in the database (e.g. `1`) to the human-readable version (`BIRD_TYPE_TOUCAN`)." - [field-id :- su/IntGreaterThanZeroPlumatic + [field-id :- su/IntGreaterThanZero v->human-readable :- HumanReadableRemappingMap constraints :- (s/maybe ConstraintsMap) options :- (s/maybe Options)] @@ -499,8 +499,8 @@ (s/defn ^:private field-to-field-remapped-chain-filter "Chain filter, but for Field->Field remappings (e.g. 'remap' `venue.category_id` -> `category.name`; search by `category.name` but return tuples of `[venue.category_id category.name]`." - [original-field-id :- su/IntGreaterThanZeroPlumatic - remapped-field-id :- su/IntGreaterThanZeroPlumatic + [original-field-id :- su/IntGreaterThanZero + remapped-field-id :- su/IntGreaterThanZero constraints :- (s/maybe ConstraintsMap) options :- (s/maybe Options)] (unremapped-chain-filter remapped-field-id constraints (assoc options :original-field-id original-field-id))) @@ -512,10 +512,10 @@ (hsql/call (u/qualified-name ::parens) x)) ;; TODO -- add some caching here? -(s/defn ^:private remapped-field-id :- (s/maybe su/IntGreaterThanZeroPlumatic) +(s/defn ^:private remapped-field-id :- (s/maybe su/IntGreaterThanZero) "Efficient query to find the ID of the Field we're remapping `field-id` to, if it has either type of Field -> Field remapping." - [field-id :- su/IntGreaterThanZeroPlumatic] + [field-id :- su/IntGreaterThanZero] (let [[{:keys [id]}] (db/query {:select [[:ids.id :id]] :from [[{:union [(parens {:select [[:dimension.human_readable_field_id :id]] @@ -572,7 +572,7 @@ (chain-filter %venues.price {} :limit 10) For remapped columns, this returns results as a sequence of `[value remapped-value]` pairs." - [field-id :- su/IntGreaterThanZeroPlumatic + [field-id :- su/IntGreaterThanZero constraints :- (s/maybe ConstraintsMap) & options] (assert (even? (count options))) @@ -606,9 +606,9 @@ :base-type base-type})))))) (s/defn ^:private unremapped-chain-filter-search - [field-id :- su/IntGreaterThanZeroPlumatic + [field-id :- su/IntGreaterThanZero constraints :- (s/maybe ConstraintsMap) - query :- su/NonBlankStringPlumatic + query :- su/NonBlankString options :- (s/maybe Options)] (check-valid-search-field field-id) (let [query-constraint {field-id [:contains query {:case-sensitive false}]} @@ -626,10 +626,10 @@ "Chain filter search, but for Fields that have human-readable values defined (e.g. you've went in and specified that enum value `1` should be displayed as `BIRD_TYPE_TOUCAN`). `v->human-readable` is a map of actual values in the database (e.g. `1`) to the human-readable version (`BIRD_TYPE_TOUCAN`)." - [field-id :- su/IntGreaterThanZeroPlumatic + [field-id :- su/IntGreaterThanZero v->human-readable :- HumanReadableRemappingMap constraints :- (s/maybe ConstraintsMap) - query :- su/NonBlankStringPlumatic + query :- su/NonBlankString options :- (s/maybe Options)] (or (when-let [unremapped-values (not-empty (matching-unremapped-values query v->human-readable))] (let [query-constraint {field-id (set unremapped-values)} @@ -669,10 +669,10 @@ (s/defn ^:private field-to-field-remapped-chain-filter-search "Chain filter search, but for Field->Field remappings e.g. 'remap' `venue.category_id` -> `category.name`; search by `category.name` but return tuples of `[venue.category_id category.name]`." - [original-field-id :- su/IntGreaterThanZeroPlumatic - remapped-field-id :- su/IntGreaterThanZeroPlumatic + [original-field-id :- su/IntGreaterThanZero + remapped-field-id :- su/IntGreaterThanZero constraints :- (s/maybe ConstraintsMap) - query :- su/NonBlankStringPlumatic + query :- su/NonBlankString options :- (s/maybe Options)] (unremapped-chain-filter-search remapped-field-id constraints query (assoc options :original-field-id original-field-id))) @@ -680,9 +680,9 @@ (s/defn chain-filter-search "Convenience version of `chain-filter` that adds a constraint to only return values of Field with `field-id` containing String `query`. Powers the `search/:query` version of the chain filter endpoint." - [field-id :- su/IntGreaterThanZeroPlumatic + [field-id :- su/IntGreaterThanZero constraints :- (s/maybe ConstraintsMap) - query :- (s/maybe su/NonBlankStringPlumatic) + query :- (s/maybe su/NonBlankString) & options] (assert (even? (count options))) (if (str/blank? query) @@ -705,8 +705,8 @@ ;; maybe we can't filter against Field 2 because there's no FK-> relationship (filterable-field-ids 1 #{2 3 4}) ; -> #{3 4}" - [field-id :- su/IntGreaterThanZeroPlumatic - filter-field-ids :- (s/maybe #{su/IntGreaterThanZeroPlumatic})] + [field-id :- su/IntGreaterThanZero + filter-field-ids :- (s/maybe #{su/IntGreaterThanZero})] (when (seq filter-field-ids) (let [mbql-query (chain-filter-mbql-query field-id (into {} (for [id filter-field-ids] [id nil])) diff --git a/src/metabase/models/permissions.clj b/src/metabase/models/permissions.clj index 5ccaa84c3c3350da00eca55fccaf695c70ca669e..30d9ab3e26ba5983e1451807eacfa1b2219033e0 100644 --- a/src/metabase/models/permissions.clj +++ b/src/metabase/models/permissions.clj @@ -373,7 +373,7 @@ ;;; ------------------------------------------------- Path Util Fns -------------------------------------------------- (def ^:private MapOrID - (s/cond-pre su/MapPlumatic su/IntGreaterThanZeroPlumatic)) + (s/cond-pre su/Map su/IntGreaterThanZero)) (s/defn data-perms-path :- Path "Return the [readwrite] permissions path for a Database, schema, or Table. (At the time of this writing, DBs and @@ -579,8 +579,8 @@ ([this read-or-write] (perms-objects-set-for-parent-collection nil this read-or-write)) - ([collection-namespace :- (s/maybe su/KeywordOrStringPlumatic) - this :- {:collection_id (s/maybe su/IntGreaterThanZeroPlumatic) s/Keyword s/Any} + ([collection-namespace :- (s/maybe su/KeywordOrString) + this :- {:collection_id (s/maybe su/IntGreaterThanZero) s/Keyword s/Any} read-or-write :- (s/enum :read :write)] ;; based on value of read-or-write determine the approprite function used to calculate the perms path (let [path-fn (case read-or-write @@ -653,7 +653,7 @@ (def ^:private SchemaPermissionsGraph (s/named (s/cond-pre (s/enum :none :all) - {su/IntGreaterThanZeroPlumatic TablePermissionsGraph}) + {su/IntGreaterThanZero TablePermissionsGraph}) "Valid perms graph for a schema")) (def ^:private NativePermissionsGraph @@ -704,7 +704,7 @@ (def ^:private DownloadSchemaPermissionsGraph (s/named (s/cond-pre (s/enum :full :limited :none) - {su/IntGreaterThanZeroPlumatic DownloadTablePermissionsGraph}) + {su/IntGreaterThanZero DownloadTablePermissionsGraph}) "Valid download perms graph for a schema")) (def ^:private DownloadNativePermissionsGraph @@ -728,7 +728,7 @@ (def ^:private DataModelSchemaPermissionsGraph (s/named (s/cond-pre (s/enum :all :none) - {su/IntGreaterThanZeroPlumatic DataModelTablePermissionsGraph}) + {su/IntGreaterThanZero DataModelTablePermissionsGraph}) "Valid data model perms graph for a schema")) (def DataModelPermissionsGraph @@ -746,22 +746,22 @@ "Valid details perms graph for a database")) (def ^:private StrictDBPermissionsGraph - {su/IntGreaterThanZeroPlumatic {(s/optional-key :data) StrictDataPermissionsGraph + {su/IntGreaterThanZero {(s/optional-key :data) StrictDataPermissionsGraph (s/optional-key :download) DownloadPermissionsGraph (s/optional-key :data-model) DataModelPermissionsGraph (s/optional-key :details) DetailsPermissions}}) (def ^:private StrictPermissionsGraph {:revision s/Int - :groups {su/IntGreaterThanZeroPlumatic StrictDBPermissionsGraph}}) + :groups {su/IntGreaterThanZero StrictDBPermissionsGraph}}) (def ^:private ExecutionGroupPermissionsGraph (s/cond-pre ExecutePermissions - {su/IntGreaterThanZeroPlumatic ExecutePermissions})) + {su/IntGreaterThanZero ExecutePermissions})) (def ^:private ExecutionPermissionsGraph {:revision s/Int - :groups {su/IntGreaterThanZeroPlumatic ExecutionGroupPermissionsGraph}}) + :groups {su/IntGreaterThanZero ExecutionGroupPermissionsGraph}}) ;;; +----------------------------------------------------------------------------------------------------------------+ ;;; | GRAPH FETCH | @@ -848,7 +848,7 @@ NOTE: This function is meant for internal usage in this namespace only; use one of the other functions like `revoke-data-perms!` elsewhere instead of calling this directly." {:style/indent 2} - [group-or-id :- (s/cond-pre su/MapPlumatic su/IntGreaterThanZeroPlumatic) path :- Path & other-conditions] + [group-or-id :- (s/cond-pre su/Map su/IntGreaterThanZero) path :- Path & other-conditions] (let [where {:where (apply list :and [:= :group_id (u/the-id group-or-id)] @@ -1037,7 +1037,7 @@ This lives in non-EE code because it needs to be called during sync, in case a new table was discovered or a table was deleted. This ensures that native download perms are always up to date, even on OSS instances, in case they are upgraded to EE." - [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic] + [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero] (let [permissions-set (download-permissions-set group-id) table-ids-and-schemas (db/select-id->field :schema 'Table :db_id db-id :active [:= true]) native-perm-level (reduce (fn [lowest-seen-perm-level [table-id table-schema]] @@ -1066,20 +1066,20 @@ (grant-permissions! group-id (native-feature-perms-path :download native-perm-level db-id))))) (s/defn ^:private update-table-read-permissions! - [group-id :- su/IntGreaterThanZeroPlumatic - db-id :- su/IntGreaterThanZeroPlumatic + [group-id :- su/IntGreaterThanZero + db-id :- su/IntGreaterThanZero schema :- s/Str - table-id :- su/IntGreaterThanZeroPlumatic + table-id :- su/IntGreaterThanZero new-read-perms :- (s/enum :all :none)] ((case new-read-perms :all grant-permissions! :none revoke-data-perms!) group-id (table-read-path db-id schema table-id))) (s/defn ^:private update-table-query-permissions! - [group-id :- su/IntGreaterThanZeroPlumatic - db-id :- su/IntGreaterThanZeroPlumatic + [group-id :- su/IntGreaterThanZero + db-id :- su/IntGreaterThanZero schema :- s/Str - table-id :- su/IntGreaterThanZeroPlumatic + table-id :- su/IntGreaterThanZero new-query-perms :- (s/enum :all :segmented :none)] (case new-query-perms :all (grant-permissions! group-id (table-query-path db-id schema table-id)) @@ -1087,10 +1087,10 @@ :none (revoke-data-perms! group-id (table-query-path db-id schema table-id)))) (s/defn ^:private update-table-data-access-permissions! - [group-id :- su/IntGreaterThanZeroPlumatic - db-id :- su/IntGreaterThanZeroPlumatic + [group-id :- su/IntGreaterThanZero + db-id :- su/IntGreaterThanZero schema :- s/Str - table-id :- su/IntGreaterThanZeroPlumatic + table-id :- su/IntGreaterThanZero new-table-perms :- TablePermissionsGraph] (cond (= new-table-perms :all) @@ -1110,8 +1110,8 @@ (when new-query-perms (update-table-query-permissions! group-id db-id schema table-id new-query-perms))))) (s/defn ^:private update-schema-data-access-permissions! - [group-id :- su/IntGreaterThanZeroPlumatic - db-id :- su/IntGreaterThanZeroPlumatic + [group-id :- su/IntGreaterThanZero + db-id :- su/IntGreaterThanZero schema :- s/Str new-schema-perms :- SchemaPermissionsGraph] (cond @@ -1122,7 +1122,7 @@ (update-table-data-access-permissions! group-id db-id schema table-id table-perms)))) (s/defn ^:private update-native-data-access-permissions! - [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic new-native-perms :- NativePermissionsGraph] + [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero new-native-perms :- NativePermissionsGraph] ;; revoke-native-permissions! will delete all entries that would give permissions for native access. Thus if you had ;; a root DB entry like `/db/11/` this will delete that too. In that case we want to create a new full schemas entry ;; so you don't lose access to all schemas when we modify native access. @@ -1135,7 +1135,7 @@ :none nil)) (s/defn ^:private update-db-data-access-permissions! - [group-id :- su/IntGreaterThanZeroPlumatic db-id :- su/IntGreaterThanZeroPlumatic new-db-perms :- StrictDataPermissionsGraph] + [group-id :- su/IntGreaterThanZero db-id :- su/IntGreaterThanZero new-db-perms :- StrictDataPermissionsGraph] (when-let [new-native-perms (:native new-db-perms)] (update-native-data-access-permissions! group-id db-id new-native-perms)) (when-let [schemas (:schemas new-db-perms)] @@ -1174,7 +1174,7 @@ (throw (ee-permissions-exception perm-type)))) (s/defn ^:private update-group-permissions! - [group-id :- su/IntGreaterThanZeroPlumatic new-group-perms :- StrictDBPermissionsGraph] + [group-id :- su/IntGreaterThanZero new-group-perms :- StrictDBPermissionsGraph] (doseq [[db-id new-db-perms] new-group-perms [perm-type new-perms] new-db-perms] (case perm-type @@ -1202,7 +1202,7 @@ (grant-permissions! group-id "/execute/"))) (s/defn ^:private update-execution-permissions! - [group-id :- su/IntGreaterThanZeroPlumatic new-group-perms :- ExecutionGroupPermissionsGraph] + [group-id :- su/IntGreaterThanZero new-group-perms :- ExecutionGroupPermissionsGraph] (if (map? new-group-perms) (doseq [[db-id new-db-perms] new-group-perms] (update-feature-level-permission! group-id db-id new-db-perms :execute)) diff --git a/src/metabase/models/persisted_info.clj b/src/metabase/models/persisted_info.clj index 363ce2e1ca7cee901dc0cb60580b7717247e7517..e012d7c5e6fccc950c1b3fea5f4f412727d2b5fd 100644 --- a/src/metabase/models/persisted_info.clj +++ b/src/metabase/models/persisted_info.clj @@ -25,8 +25,8 @@ (def Definition "Definition spec for a cached table." - {:table-name su/NonBlankStringPlumatic - :field-definitions [{:field-name su/NonBlankStringPlumatic + {:table-name su/NonBlankString + :field-definitions [{:field-name su/NonBlankString ;; TODO check (isa? :type/Integer :type/*) :base-type s/Keyword}]}) diff --git a/src/metabase/models/pulse.clj b/src/metabase/models/pulse.clj index 1d3bc177ba29bcc2c5b71efb8645f128748920e6..866c24265f3b2ef18c5f352ca501bdc53cd69d9d 100644 --- a/src/metabase/models/pulse.clj +++ b/src/metabase/models/pulse.clj @@ -47,7 +47,7 @@ (derive Pulse ::mi/read-policy.full-perms-for-perms-set) (defn- assert-valid-parameters [{:keys [parameters]}] - (when (s/check (s/maybe [{:id su/NonBlankStringPlumatic, s/Keyword s/Any}]) parameters) + (when (s/check (s/maybe [{:id su/NonBlankString, s/Keyword s/Any}]) parameters) (throw (ex-info (tru ":parameters must be a sequence of maps with String :id keys") {:parameters parameters})))) @@ -164,10 +164,10 @@ (def CardRef "Schema for the map we use to internally represent the fact that a Card is in a Notification and the details about its presence there." - (su/with-api-error-message {:id su/IntGreaterThanZeroPlumatic + (su/with-api-error-message {:id su/IntGreaterThanZero :include_csv s/Bool :include_xls s/Bool - (s/optional-key :dashboard_card_id) (s/maybe su/IntGreaterThanZeroPlumatic)} + (s/optional-key :dashboard_card_id) (s/maybe su/IntGreaterThanZero)} (deferred-tru "value must be a map with the keys `{0}`, `{1}`, `{2}`, and `{3}`." "id" "include_csv" "include_xls" "dashboard_card_id"))) (def HybridPulseCard @@ -178,10 +178,10 @@ (merge (:schema CardRef) {:name (s/maybe s/Str) :description (s/maybe s/Str) - :display (s/maybe su/KeywordOrStringPlumatic) - :collection_id (s/maybe su/IntGreaterThanZeroPlumatic) - :dashboard_id (s/maybe su/IntGreaterThanZeroPlumatic) - :parameter_mappings (s/maybe [su/MapPlumatic])}) + :display (s/maybe su/KeywordOrString) + :collection_id (s/maybe su/IntGreaterThanZero) + :dashboard_id (s/maybe su/IntGreaterThanZero) + :parameter_mappings (s/maybe [su/Map])}) (deferred-tru "value must be a map with the following keys `({0})`" (str/join ", " ["collection_id" "description" "display" "id" "include_csv" "include_xls" "name" "dashboard_id" "parameter_mappings"])))) @@ -381,7 +381,7 @@ (s/defn card->ref :- CardRef "Create a card reference from a card or id" - [card :- su/MapPlumatic] + [card :- su/Map] {:id (u/the-id card) :include_csv (get card :include_csv false) :include_xls (get card :include_xls false) @@ -445,7 +445,7 @@ * If an existing `PulseChannel` has no corresponding entry in `channels`, it will be deleted. * All previously existing channels will be updated with their most recent information." - [notification-or-id channels :- [su/MapPlumatic]] + [notification-or-id channels :- [su/Map]] (let [new-channels (group-by (comp keyword :channel_type) channels) old-channels (group-by (comp keyword :channel_type) (db/select PulseChannel :pulse_id (u/the-id notification-or-id))) @@ -479,13 +479,13 @@ {:style/indent 2} [cards :- [{s/Keyword s/Any}] channels :- [{s/Keyword s/Any}] - kvs :- {:name su/NonBlankStringPlumatic - :creator_id su/IntGreaterThanZeroPlumatic + kvs :- {:name su/NonBlankString + :creator_id su/IntGreaterThanZero (s/optional-key :skip_if_empty) (s/maybe s/Bool) - (s/optional-key :collection_id) (s/maybe su/IntGreaterThanZeroPlumatic) - (s/optional-key :collection_position) (s/maybe su/IntGreaterThanZeroPlumatic) - (s/optional-key :dashboard_id) (s/maybe su/IntGreaterThanZeroPlumatic) - (s/optional-key :parameters) [su/MapPlumatic]}] + (s/optional-key :collection_id) (s/maybe su/IntGreaterThanZero) + (s/optional-key :collection_position) (s/maybe su/IntGreaterThanZero) + (s/optional-key :dashboard_id) (s/maybe su/IntGreaterThanZero) + (s/optional-key :parameters) [su/Map]}] (let [pulse-id (create-notification-and-add-cards-and-channels! kvs cards channels)] ;; return the full Pulse (and record our create event) (events/publish-event! :pulse-create (retrieve-pulse pulse-id)))) @@ -516,18 +516,18 @@ (s/defn update-notification! "Update the supplied keys in a `notification`." - [notification :- {:id su/IntGreaterThanZeroPlumatic - (s/optional-key :name) su/NonBlankStringPlumatic + [notification :- {:id su/IntGreaterThanZero + (s/optional-key :name) su/NonBlankString (s/optional-key :alert_condition) AlertConditions (s/optional-key :alert_above_goal) s/Bool (s/optional-key :alert_first_only) s/Bool (s/optional-key :skip_if_empty) s/Bool - (s/optional-key :collection_id) (s/maybe su/IntGreaterThanZeroPlumatic) - (s/optional-key :collection_position) (s/maybe su/IntGreaterThanZeroPlumatic) + (s/optional-key :collection_id) (s/maybe su/IntGreaterThanZero) + (s/optional-key :collection_position) (s/maybe su/IntGreaterThanZero) (s/optional-key :cards) [CoercibleToCardRef] - (s/optional-key :channels) [su/MapPlumatic] + (s/optional-key :channels) [su/Map] (s/optional-key :archived) s/Bool - (s/optional-key :parameters) [su/MapPlumatic]}] + (s/optional-key :parameters) [su/Map]}] (db/update! Pulse (u/the-id notification) (u/select-keys-when notification :present [:collection_id :collection_position :archived] diff --git a/src/metabase/models/pulse_card.clj b/src/metabase/models/pulse_card.clj index 9b058be520a13810c3733f50d5d0b5042b7f7b86..1fbf750ce32de448100e9d4750cab4a2598739e8 100644 --- a/src/metabase/models/pulse_card.clj +++ b/src/metabase/models/pulse_card.clj @@ -32,10 +32,10 @@ (or 0))) (def ^:private NewPulseCard - {:card_id su/IntGreaterThanZeroPlumatic - :pulse_id su/IntGreaterThanZeroPlumatic - :dashboard_card_id su/IntGreaterThanZeroPlumatic - (s/optional-key :position) (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic) + {:card_id su/IntGreaterThanZero + :pulse_id su/IntGreaterThanZero + :dashboard_card_id su/IntGreaterThanZero + (s/optional-key :position) (s/maybe su/IntGreaterThanOrEqualToZero) (s/optional-key :include_csv) (s/maybe s/Bool) (s/optional-key :include_xls) (s/maybe s/Bool)}) diff --git a/src/metabase/models/query/permissions.clj b/src/metabase/models/query/permissions.clj index 4247f139ffc5a950ca4df5ea84e4b35a3abf0062..2a527b5b136ab85dbfb705f5e0f52ebcbf7618ce 100644 --- a/src/metabase/models/query/permissions.clj +++ b/src/metabase/models/query/permissions.clj @@ -40,7 +40,7 @@ ;; `table-segmented-query-path`. `perms-set` will require full access to the tables, `segmented-perms-set` will only ;; require segmented access -(s/defn query->source-table-ids :- #{(s/cond-pre (s/eq ::native) su/IntGreaterThanZeroPlumatic)} +(s/defn query->source-table-ids :- #{(s/cond-pre (s/eq ::native) su/IntGreaterThanZero)} "Return a sequence of all Table IDs referenced by `query`." [query] (set @@ -67,7 +67,7 @@ (def ^:private TableOrIDOrNativePlaceholder (s/cond-pre (s/eq ::native) - su/IntGreaterThanZeroPlumatic)) + su/IntGreaterThanZero)) (s/defn tables->permissions-path-set :- #{perms/Path} "Given a sequence of `tables-or-ids` referenced by a query, return a set of required permissions. A truthy value for @@ -75,7 +75,7 @@ Custom `table-perms-fn` and `native-perms-fn` can be passed as options to generate permissions paths for feature-level permissions, such as download permissions." - [database-or-id :- (s/cond-pre su/IntGreaterThanZeroPlumatic su/MapPlumatic) + [database-or-id :- (s/cond-pre su/IntGreaterThanZero su/Map) tables-or-ids :- #{TableOrIDOrNativePlaceholder} {:keys [segmented-perms? table-perms-fn @@ -103,7 +103,7 @@ (s/defn ^:private source-card-read-perms :- #{perms/Path} "Calculate the permissions needed to run an ad-hoc query that uses a Card with `source-card-id` as its source query." - [source-card-id :- su/IntGreaterThanZeroPlumatic] + [source-card-id :- su/IntGreaterThanZero] (mi/perms-objects-set (or (db/select-one ['Card :collection_id] :id source-card-id) (throw (Exception. (tru "Card {0} does not exist." source-card-id)))) :read)) @@ -122,7 +122,7 @@ things when a single Card is busted (e.g. API endpoints that filter out unreadable Cards) and instead returns 'only admins can see this' permissions -- `#{\"db/0\"}` (DB 0 will never exist, thus normal users will never be able to get permissions for it, but admins have root perms and will still get to see (and hopefully fix) it)." - [query :- {:query su/MapPlumatic, s/Keyword s/Any} + [query :- {:query su/Map, s/Keyword s/Any} {:keys [throw-exceptions? already-preprocessed?], :as perms-opts} :- PermsOptions] (try (let [query (mbql.normalize/normalize query)] diff --git a/src/metabase/models/revision/last_edit.clj b/src/metabase/models/revision/last_edit.clj index bbeace2b7f196186e9460235684df7b7c46afdb3..6173c363186ae7e177584c5eefaf272f4c28fc45 100644 --- a/src/metabase/models/revision/last_edit.clj +++ b/src/metabase/models/revision/last_edit.clj @@ -22,7 +22,7 @@ (def LastEditInfo "Schema of the `:last-edit-info` map. A subset of a user with a timestamp indicating when the last edit was." {:timestamp (s/maybe s/Any) - :id (s/maybe su/IntGreaterThanZeroPlumatic) + :id (s/maybe su/IntGreaterThanZero) :first_name (s/maybe s/Str) :last_name (s/maybe s/Str) :email (s/maybe s/Str)}) diff --git a/src/metabase/models/task_history.clj b/src/metabase/models/task_history.clj index 64b58e171181f13d5769cf29471c99206e44565d..4422801683d45a8213262cdee7c22ef275001407 100644 --- a/src/metabase/models/task_history.clj +++ b/src/metabase/models/task_history.clj @@ -71,8 +71,8 @@ (s/defn all "Return all TaskHistory entries, applying `limit` and `offset` if not nil" - [limit :- (s/maybe su/IntGreaterThanZeroPlumatic) - offset :- (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic)] + [limit :- (s/maybe su/IntGreaterThanZero) + offset :- (s/maybe su/IntGreaterThanOrEqualToZero)] (db/select TaskHistory (merge {:order-by [[:ended_at :desc]]} (when limit {:limit limit}) @@ -86,9 +86,9 @@ (def ^:private TaskHistoryInfo "Schema for `info` passed to the `with-task-history` macro." - {:task su/NonBlankStringPlumatic ; task name, i.e. `send-pulses`. Conventionally lisp-cased + {:task su/NonBlankString ; task name, i.e. `send-pulses`. Conventionally lisp-cased (s/optional-key :db_id) (s/maybe s/Int) ; DB involved, for sync operations or other tasks where this is applicable. - (s/optional-key :task_details) (s/maybe su/MapPlumatic)}) ; additional map of details to include in the recorded row + (s/optional-key :task_details) (s/maybe su/Map)}) ; additional map of details to include in the recorded row (defn- save-task-history! [start-time-ms info] (let [end-time-ms (System/currentTimeMillis) diff --git a/src/metabase/models/user.clj b/src/metabase/models/user.clj index 93aa74beba3566f393527325da6b476a30195d9e..42eeb4168128c282a5f5abad994886f80747314e 100644 --- a/src/metabase/models/user.clj +++ b/src/metabase/models/user.clj @@ -174,7 +174,7 @@ (def UserGroupMembership "Group Membership info of a User. In which :is_group_manager is only included if `advanced-permissions` is enabled." - {:id su/IntGreaterThanZeroPlumatic + {:id su/IntGreaterThanZero ;; is_group_manager only included if `advanced-permissions` is enabled (schema/optional-key :is_group_manager) schema/Bool}) @@ -273,23 +273,23 @@ (def LoginAttributes "Login attributes, currently not collected for LDAP or Google Auth. Will ultimately be stored as JSON." (su/with-api-error-message - {su/KeywordOrStringPlumatic schema/Any} + {su/KeywordOrString schema/Any} (deferred-tru "login attribute keys must be a keyword or string"))) (def NewUser "Required/optionals parameters needed to create a new user (for any backend)" - {(schema/optional-key :first_name) (schema/maybe su/NonBlankStringPlumatic) - (schema/optional-key :last_name) (schema/maybe su/NonBlankStringPlumatic) - :email su/EmailPlumatic - (schema/optional-key :password) (schema/maybe su/NonBlankStringPlumatic) + {(schema/optional-key :first_name) (schema/maybe su/NonBlankString) + (schema/optional-key :last_name) (schema/maybe su/NonBlankString) + :email su/Email + (schema/optional-key :password) (schema/maybe su/NonBlankString) (schema/optional-key :login_attributes) (schema/maybe LoginAttributes) (schema/optional-key :google_auth) schema/Bool (schema/optional-key :ldap_auth) schema/Bool}) (def ^:private Invitor "Map with info about the admin creating the user, used in the new user notification code" - {:email su/EmailPlumatic - :first_name (schema/maybe su/NonBlankStringPlumatic) + {:email su/Email + :first_name (schema/maybe su/NonBlankString) schema/Any schema/Any}) (schema/defn ^:private insert-new-user! diff --git a/src/metabase/public_settings/premium_features.clj b/src/metabase/public_settings/premium_features.clj index 228e14b35a3e4da2e9c84f3eb75d298f71215868..69d071b8123162ad97b1b1261ef82dd99cdca099 100644 --- a/src/metabase/public_settings/premium_features.clj +++ b/src/metabase/public_settings/premium_features.clj @@ -57,11 +57,11 @@ (def ^:private TokenStatus {:valid schema/Bool - :status su/NonBlankStringPlumatic - (schema/optional-key :error-details) (schema/maybe su/NonBlankStringPlumatic) - (schema/optional-key :features) [su/NonBlankStringPlumatic] + :status su/NonBlankString + (schema/optional-key :error-details) (schema/maybe su/NonBlankString) + (schema/optional-key :features) [su/NonBlankString] (schema/optional-key :trial) schema/Bool - (schema/optional-key :valid_thru) su/NonBlankStringPlumatic ; ISO 8601 timestamp + (schema/optional-key :valid_thru) su/NonBlankString ; ISO 8601 timestamp ;; don't explode in the future if we add more to the response! lol schema/Any schema/Any}) @@ -113,7 +113,7 @@ fetch-token-status* :ttl/threshold (* 1000 60 5))) -(schema/defn ^:private valid-token->features* :- #{su/NonBlankStringPlumatic} +(schema/defn ^:private valid-token->features* :- #{su/NonBlankString} [token :- ValidToken] (let [{:keys [valid status features error-details]} (fetch-token-status token)] ;; if token isn't valid throw an Exception with the `:status` message @@ -170,7 +170,7 @@ (log/debug e (trs "Error validating token"))) ;; log every five minutes :ttl/threshold (* 1000 60 5))] - (schema/defn ^:private token-features :- #{su/NonBlankStringPlumatic} + (schema/defn ^:private token-features :- #{su/NonBlankString} "Get the features associated with the system's premium features token." [] (try diff --git a/src/metabase/query_processor/card.clj b/src/metabase/query_processor/card.clj index 3a4779dd9082a01ec4dfc166966b291393c40554..73b56594349612527dcbfb00e4d3000ca39c9f16 100644 --- a/src/metabase/query_processor/card.clj +++ b/src/metabase/query_processor/card.clj @@ -152,7 +152,7 @@ (s/defn ^:private validate-card-parameters "Unless [[*allow-arbitrary-mbql-parameters*]] is truthy, check to make all supplied `parameters` actually match up with template tags in the query for Card with `card-id`." - [card-id :- su/IntGreaterThanZeroPlumatic parameters :- mbql.s/ParameterList] + [card-id :- su/IntGreaterThanZero parameters :- mbql.s/ParameterList] (when-not *allow-arbitrary-mbql-parameters* (let [template-tags (card-template-tag-parameters card-id)] (doseq [request-parameter parameters diff --git a/src/metabase/query_processor/dashboard.clj b/src/metabase/query_processor/dashboard.clj index e605ca9359bba8b9b84027417c350089f712b14b..77699438940b6f8aa72a5776241fbf5c06116532 100644 --- a/src/metabase/query_processor/dashboard.clj +++ b/src/metabase/query_processor/dashboard.clj @@ -111,14 +111,14 @@ target))) dashboard-param-id->param)) -(s/defn ^:private resolve-params-for-query :- (s/maybe [su/MapPlumatic]) +(s/defn ^:private resolve-params-for-query :- (s/maybe [su/Map]) "Given a sequence of parameters included in a query-processing request to run the query for a Dashboard/Card, validate that those parameters exist and have allowed types, and merge in default values and other info from the parameter mappings." - [dashboard-id :- su/IntGreaterThanZeroPlumatic - card-id :- su/IntGreaterThanZeroPlumatic - dashcard-id :- su/IntGreaterThanZeroPlumatic - request-params :- (s/maybe [su/MapPlumatic])] + [dashboard-id :- su/IntGreaterThanZero + card-id :- su/IntGreaterThanZero + dashcard-id :- su/IntGreaterThanZero + request-params :- (s/maybe [su/Map])] (log/tracef "Resolving Dashboard %d Card %d query request parameters" dashboard-id card-id) (let [request-params (mbql.normalize/normalize-fragment [:parameters] request-params) ;; ignore default values in request params as well. (#20516) diff --git a/src/metabase/query_processor/middleware/add_dimension_projections.clj b/src/metabase/query_processor/middleware/add_dimension_projections.clj index cfd298cc522b1c8cdef3c867db33296e2c8bb3d1..07c652e5819b10f6a86ce55648831d9aec1185f7 100644 --- a/src/metabase/query_processor/middleware/add_dimension_projections.clj +++ b/src/metabase/query_processor/middleware/add_dimension_projections.clj @@ -41,21 +41,21 @@ (def ^:private ExternalRemappingDimensionInitialInfo "External remapping dimensions when they're first fetched from the app DB. We'll add extra info to this." - {:id su/IntGreaterThanZeroPlumatic ; unique ID for the remapping - :name su/NonBlankStringPlumatic ; display name for the remapping - :field_id su/IntGreaterThanZeroPlumatic ; ID of the Field being remapped - :human_readable_field_id su/IntGreaterThanZeroPlumatic}) ; ID of the FK Field to remap values to + {:id su/IntGreaterThanZero ; unique ID for the remapping + :name su/NonBlankString ; display name for the remapping + :field_id su/IntGreaterThanZero ; ID of the Field being remapped + :human_readable_field_id su/IntGreaterThanZero}) ; ID of the FK Field to remap values to (def ^:private ExternalRemappingDimension "Schema for the info we fetch about `external` type Dimensions that will be used for remappings in this Query. Fetched by the pre-processing portion of the middleware, and passed along to the post-processing portion." (assoc ExternalRemappingDimensionInitialInfo - :field_name su/NonBlankStringPlumatic ; Name of the Field being remapped - :human_readable_field_name su/NonBlankStringPlumatic)) ; Name of the FK field to remap values to + :field_name su/NonBlankString ; Name of the Field being remapped + :human_readable_field_name su/NonBlankString)) ; Name of the FK field to remap values to ;;;; Pre-processing -(s/defn ^:private fields->field-id->remapping-dimension :- (s/maybe {su/IntGreaterThanZeroPlumatic ExternalRemappingDimensionInitialInfo}) +(s/defn ^:private fields->field-id->remapping-dimension :- (s/maybe {su/IntGreaterThanZero ExternalRemappingDimensionInitialInfo}) "Given a sequence of field clauses (from the `:fields` clause), return a map of `:field-id` clause (other clauses are ineligable) to a remapping dimension information for any Fields that have an `external` type dimension remapping." [fields :- [mbql.s/Field]] @@ -235,29 +235,29 @@ {;; index of original column :col-index s/Int ;; names - :from su/NonBlankStringPlumatic + :from su/NonBlankString ;; I'm not convinced this works if there's already a column with the same name in the results. - :to su/NonBlankStringPlumatic + :to su/NonBlankString ;; map of original value -> human readable value - :value->readable su/MapPlumatic + :value->readable su/Map ;; Info about the new column we will tack on to end of `:cols` - :new-column su/MapPlumatic}) + :new-column su/Map}) (def ^:private InternalColumnsInfo {:internal-only-dims (s/maybe [InternalDimensionInfo]) ;; this is just (map :new-column internal-only-dims) - :internal-only-cols (s/maybe [su/MapPlumatic])}) + :internal-only-cols (s/maybe [su/Map])}) ;;;; Metadata -(s/defn ^:private merge-metadata-for-internally-remapped-column :- [su/MapPlumatic] +(s/defn ^:private merge-metadata-for-internally-remapped-column :- [su/Map] "If one of the internal remapped columns says it's remapped from this column, merge in the `:remapped_to` info." - [columns :- [su/MapPlumatic] {:keys [col-index to]} :- InternalDimensionInfo] + [columns :- [su/Map] {:keys [col-index to]} :- InternalDimensionInfo] (update (vec columns) col-index assoc :remapped_to to)) -(s/defn ^:private merge-metadata-for-internal-remaps :- [su/MapPlumatic] - [columns :- [su/MapPlumatic] {:keys [internal-only-dims]} :- (s/maybe InternalColumnsInfo)] +(s/defn ^:private merge-metadata-for-internal-remaps :- [su/Map] + [columns :- [su/Map] {:keys [internal-only-dims]} :- (s/maybe InternalColumnsInfo)] (reduce merge-metadata-for-internally-remapped-column columns @@ -286,7 +286,7 @@ ;; :options {::new-field-dimension-id 1000} ;; :name "NAME" ;; :display_name "Sender ID"} -(s/defn ^:private merge-metadata-for-externally-remapped-column* :- su/MapPlumatic +(s/defn ^:private merge-metadata-for-externally-remapped-column* :- su/Map [columns {{::keys [original-field-dimension-id new-field-dimension-id]} :options :as column} @@ -330,25 +330,25 @@ (when (not= column <>) (log/tracef "Added metadata:\n%s" (u/pprint-to-str 'green (second (data/diff column <>))))))) -(s/defn ^:private merge-metadata-for-externally-remapped-column :- [su/MapPlumatic] - [columns :- [su/MapPlumatic] dimension :- ExternalRemappingDimension] +(s/defn ^:private merge-metadata-for-externally-remapped-column :- [su/Map] + [columns :- [su/Map] dimension :- ExternalRemappingDimension] (log/tracef "Merging metadata for external dimension\n%s" (u/pprint-to-str 'yellow (into {} dimension))) (mapv #(merge-metadata-for-externally-remapped-column* columns % dimension) columns)) -(s/defn ^:private merge-metadata-for-external-remaps :- [su/MapPlumatic] - [columns :- [su/MapPlumatic] remapping-dimensions :- (s/maybe [ExternalRemappingDimension])] +(s/defn ^:private merge-metadata-for-external-remaps :- [su/Map] + [columns :- [su/Map] remapping-dimensions :- (s/maybe [ExternalRemappingDimension])] (reduce merge-metadata-for-externally-remapped-column columns remapping-dimensions)) -(s/defn ^:private add-remapping-info :- [su/MapPlumatic] +(s/defn ^:private add-remapping-info :- [su/Map] "Add `:display_name`, `:remapped_to`, and `:remapped_from` keys to columns for the results, needed by the frontend. To get this critical information, this uses the `remapping-dimensions` info saved by the pre-processing portion of this middleware for external remappings, and the internal-only remapped columns handled by post-processing middleware below for internal columns." - [columns :- [su/MapPlumatic] + [columns :- [su/Map] remapping-dimensions :- (s/maybe [ExternalRemappingDimension]) internal-cols-info :- (s/maybe InternalColumnsInfo)] (-> columns diff --git a/src/metabase/query_processor/middleware/add_implicit_clauses.clj b/src/metabase/query_processor/middleware/add_implicit_clauses.clj index e550acffba9b0a6db049b18e56d57d6a5db66e45..d1657ea32ed2ba91e7fd68a73db7c65941010477 100644 --- a/src/metabase/query_processor/middleware/add_implicit_clauses.clj +++ b/src/metabase/query_processor/middleware/add_implicit_clauses.clj @@ -42,7 +42,7 @@ (s/defn sorted-implicit-fields-for-table :- mbql.s/Fields "For use when adding implicit Field IDs to a query. Return a sequence of field clauses, sorted by the rules listed in [[metabase.query-processor.sort]], for all the Fields in a given Table." - [table-id :- su/IntGreaterThanZeroPlumatic] + [table-id :- su/IntGreaterThanZero] (let [fields (table->sorted-fields table-id)] (when (empty? fields) (throw (ex-info (tru "No fields found for table {0}." (pr-str (:name (qp.store/table table-id)))) diff --git a/src/metabase/query_processor/middleware/annotate.clj b/src/metabase/query_processor/middleware/annotate.clj index 43ad2a764b647da85d9bd452a9598c0d2b26a4ef..55a2e857be74028fc6ac8e874ef79da758afc815 100644 --- a/src/metabase/query_processor/middleware/annotate.clj +++ b/src/metabase/query_processor/middleware/annotate.clj @@ -29,7 +29,7 @@ {:name s/Str :display_name s/Str ;; type of the Field. For Native queries we look at the values in the first 100 rows to make an educated guess - :base_type su/FieldTypePlumatic + :base_type su/FieldType ;; effective_type, coercion, etc don't go here. probably best to rename base_type to effective type in the return ;; from the metadata but that's for another day ;; where this column came from in the original query. @@ -100,7 +100,7 @@ ;;; +----------------------------------------------------------------------------------------------------------------+ (s/defn ^:private join-with-alias :- (s/maybe mbql.s/Join) - [{:keys [joins source-query]} :- su/MapPlumatic, join-alias :- su/NonBlankStringPlumatic] + [{:keys [joins source-query]} :- su/Map, join-alias :- su/NonBlankString] (or (some (fn [{:keys [alias], :as join}] (when (= alias join-alias) @@ -292,7 +292,7 @@ (s/defn ^:private col-info-for-field-clause :- {:field_ref mbql.s/Field, s/Keyword s/Any} "Return results column metadata for a `:field` or `:expression` clause, in the format that gets returned by QP results" - [inner-query :- su/MapPlumatic, clause :- mbql.s/Field] + [inner-query :- su/Map, clause :- mbql.s/Field] (mbql.u/match-one clause :expression (col-info-for-expression inner-query &match) @@ -326,7 +326,7 @@ ;; otherwise for things like numbers just use that directly _ &match)) -(s/defn aggregation-name :- su/NonBlankStringPlumatic +(s/defn aggregation-name :- su/NonBlankString "Return an appropriate aggregation name/alias *used inside a query* for an `:aggregation` subclause (an aggregation or expression). Takes an options map as schema won't support passing keypairs directly as a varargs. @@ -365,7 +365,7 @@ (declare aggregation-display-name) -(s/defn ^:private aggregation-arg-display-name :- su/NonBlankStringPlumatic +(s/defn ^:private aggregation-arg-display-name :- su/NonBlankString "Name to use for an aggregation clause argument such as a Field when constructing the complete aggregation name." [inner-query, ag-arg :- Object] (or (when (mbql.preds/Field? ag-arg) @@ -373,7 +373,7 @@ (some info [:display_name :name]))) (aggregation-display-name inner-query ag-arg))) -(s/defn aggregation-display-name :- su/NonBlankStringPlumatic +(s/defn aggregation-display-name :- su/NonBlankString "Return an appropriate user-facing display name for an aggregation clause." [inner-query ag-clause] (mbql.u/match-one ag-clause @@ -424,7 +424,7 @@ "Return appropriate column metadata for an `:aggregation` clause." ;; `clause` is normally an aggregation clause but this function can call itself recursively; see comments by the ;; `match` pattern for field clauses below - [inner-query :- su/MapPlumatic, clause] + [inner-query :- su/Map, clause] (mbql.u/match-one clause ;; ok, if this is a aggregation w/ options recurse so we can get information about the ag it wraps [:aggregation-options ag _] @@ -497,13 +497,13 @@ :actual (:cols results)})))))) (s/defn ^:private cols-for-fields - [{:keys [fields], :as inner-query} :- su/MapPlumatic] + [{:keys [fields], :as inner-query} :- su/Map] (for [field fields] (assoc (col-info-for-field-clause inner-query field) :source :fields))) (s/defn ^:private cols-for-ags-and-breakouts - [{aggregations :aggregation, breakouts :breakout, :as inner-query} :- su/MapPlumatic] + [{aggregations :aggregation, breakouts :breakout, :as inner-query} :- su/Map] (concat (for [breakout breakouts] (assoc (col-info-for-field-clause inner-query breakout) @@ -515,15 +515,15 @@ (s/defn cols-for-mbql-query "Return results metadata about the expected columns in an 'inner' MBQL query." - [inner-query :- su/MapPlumatic] + [inner-query :- su/Map] (concat (cols-for-ags-and-breakouts inner-query) (cols-for-fields inner-query))) -(s/defn ^:private merge-source-metadata-col :- (s/maybe su/MapPlumatic) - [source-metadata-col :- (s/maybe su/MapPlumatic) col :- (s/maybe su/MapPlumatic)] +(s/defn ^:private merge-source-metadata-col :- (s/maybe su/Map) + [source-metadata-col :- (s/maybe su/Map) col :- (s/maybe su/Map)] (merge {} ;; ensure the type is not FieldInstance (when-let [field-id (:id source-metadata-col)] diff --git a/src/metabase/query_processor/middleware/auto_bucket_datetimes.clj b/src/metabase/query_processor/middleware/auto_bucket_datetimes.clj index a683296ca19a97447ef9d4a5077cbc990d7e0a48..1ce4659de9f6f0c89366b5950a75bd6036f51bf1 100644 --- a/src/metabase/query_processor/middleware/auto_bucket_datetimes.clj +++ b/src/metabase/query_processor/middleware/auto_bucket_datetimes.clj @@ -15,12 +15,12 @@ [toucan.db :as db])) (def ^:private FieldTypeInfo - {:base-type (s/maybe su/FieldTypePlumatic) - (s/optional-key :semantic-type) (s/maybe su/FieldSemanticOrRelationTypePlumatic) + {:base-type (s/maybe su/FieldType) + (s/optional-key :semantic-type) (s/maybe su/FieldSemanticOrRelationType) s/Keyword s/Any}) (def ^:private FieldIDOrName->TypeInfo - {(s/cond-pre su/NonBlankStringPlumatic su/IntGreaterThanZeroPlumatic) (s/maybe FieldTypeInfo)}) + {(s/cond-pre su/NonBlankString su/IntGreaterThanZero) (s/maybe FieldTypeInfo)}) ;; Unfortunately these Fields won't be in the store yet since Field resolution can't happen before we add the implicit ;; `:fields` clause, which happens after this diff --git a/src/metabase/query_processor/middleware/auto_parse_filter_values.clj b/src/metabase/query_processor/middleware/auto_parse_filter_values.clj index c6072d33b585680dd0eba1af603831debedf5e07..cb236ec617d1d846a487a59fe0d3c7aad6b20beb 100644 --- a/src/metabase/query_processor/middleware/auto_parse_filter_values.clj +++ b/src/metabase/query_processor/middleware/auto_parse_filter_values.clj @@ -12,7 +12,7 @@ [metabase.util.schema :as su] [schema.core :as s])) -(s/defn ^:private parse-value-for-base-type [v :- s/Str, base-type :- su/FieldTypePlumatic] +(s/defn ^:private parse-value-for-base-type [v :- s/Str, base-type :- su/FieldType] {:pre [(string? v)]} (try (condp #(isa? %2 %1) base-type diff --git a/src/metabase/query_processor/middleware/binning.clj b/src/metabase/query_processor/middleware/binning.clj index 9ee49032b4734d6364d05a7f98d9473ba7e9767e..c32a3c3e8113834646bb787116e4c1b10ad20bd8 100644 --- a/src/metabase/query_processor/middleware/binning.clj +++ b/src/metabase/query_processor/middleware/binning.clj @@ -15,7 +15,7 @@ ;;; ----------------------------------------------- Extracting Bounds ------------------------------------------------ -(def ^:private FieldID->Filters {su/IntGreaterThanZeroPlumatic [mbql.s/Filter]}) +(def ^:private FieldID->Filters {su/IntGreaterThanZero [mbql.s/Filter]}) (s/defn ^:private filter->field-map :- FieldID->Filters "Find any comparison or `:between` filter and return a map of referenced Field ID -> all the clauses the reference @@ -32,7 +32,7 @@ "Given query criteria, find a min/max value for the binning strategy using the greatest user specified min value and the smallest user specified max value. When a user specified min or max is not found, use the global min/max for the given field." - [field-id :- (s/maybe su/IntGreaterThanZeroPlumatic), fingerprint :- (s/maybe su/MapPlumatic), field-id->filters :- FieldID->Filters] + [field-id :- (s/maybe su/IntGreaterThanZero), fingerprint :- (s/maybe su/Map), field-id->filters :- FieldID->Filters] (let [{global-min :min, global-max :max} (get-in fingerprint [:type :type/Number]) filter-clauses (get field-id->filters field-id) ;; [:between <field> <min> <max>] or [:< <field> <x>] @@ -58,11 +58,11 @@ (s/defn ^:private calculate-bin-width :- s/Num "Calculate bin width required to cover interval [`min-value`, `max-value`] with `num-bins`." - [min-value :- s/Num, max-value :- s/Num, num-bins :- su/IntGreaterThanZeroPlumatic] + [min-value :- s/Num, max-value :- s/Num, num-bins :- su/IntGreaterThanZero] (u/round-to-decimals 5 (/ (- max-value min-value) num-bins))) -(s/defn ^:private calculate-num-bins :- su/IntGreaterThanZeroPlumatic +(s/defn ^:private calculate-num-bins :- su/IntGreaterThanZero "Calculate number of bins of width `bin-width` required to cover interval [`min-value`, `max-value`]." [min-value :- s/Num max-value :- s/Num @@ -72,9 +72,9 @@ 1)) (s/defn ^:private resolve-default-strategy :- [(s/one (s/enum :bin-width :num-bins) "strategy") - (s/one {:bin-width s/Num, :num-bins su/IntGreaterThanZeroPlumatic} "opts")] + (s/one {:bin-width s/Num, :num-bins su/IntGreaterThanZero} "opts")] "Determine the approprate strategy & options to use when `:default` strategy was specified." - [metadata :- {(s/optional-key :semantic_type) (s/maybe su/FieldSemanticOrRelationTypePlumatic), s/Any s/Any} + [metadata :- {(s/optional-key :semantic_type) (s/maybe su/FieldSemanticOrRelationType), s/Any s/Any} min-value :- s/Num max-value :- s/Num] (if (isa? (:semantic_type metadata) :type/Coordinate) @@ -103,7 +103,7 @@ (def ^:private ^:const pleasing-numbers [1 1.25 2 2.5 3 5 7.5 10]) (s/defn ^:private nicer-bin-width - [min-value :- s/Num, max-value :- s/Num, num-bins :- su/IntGreaterThanZeroPlumatic] + [min-value :- s/Num, max-value :- s/Num, num-bins :- su/IntGreaterThanZero] (let [min-bin-width (calculate-bin-width min-value max-value num-bins) scale (expt 10 (u/order-of-magnitude min-bin-width))] (->> pleasing-numbers @@ -126,11 +126,11 @@ (drop-while (partial apply not=)) ffirst))) -(s/defn ^:private nicer-breakout* :- su/MapPlumatic +(s/defn ^:private nicer-breakout* :- su/Map "Humanize binning: extend interval to start and end on a \"nice\" number and, when number of bins is fixed, have a \"nice\" step (bin width)." [strategy :- mbql.s/BinningStrategyName - {:keys [min-value max-value bin-width num-bins]} :- su/MapPlumatic] + {:keys [min-value max-value bin-width num-bins]} :- su/Map] (let [bin-width (if (= strategy :num-bins) (nicer-bin-width min-value max-value num-bins) bin-width) @@ -142,8 +142,8 @@ (calculate-num-bins min-value max-value bin-width)) :bin-width bin-width})) -(s/defn ^:private nicer-breakout :- (s/maybe su/MapPlumatic) - [strategy :- mbql.s/BinningStrategyName, opts :- su/MapPlumatic] +(s/defn ^:private nicer-breakout :- (s/maybe su/Map) + [strategy :- mbql.s/BinningStrategyName, opts :- su/Map] (let [f (partial nicer-breakout* strategy)] ((fixed-point f) opts))) @@ -166,7 +166,7 @@ (resolve-default-strategy metadata min-value max-value))) (s/defn ^:private matching-metadata - [field-id-or-name :- (s/cond-pre su/IntGreaterThanZeroPlumatic su/NonBlankStringPlumatic) source-metadata] + [field-id-or-name :- (s/cond-pre su/IntGreaterThanZero su/NonBlankString) source-metadata] (if (integer? field-id-or-name) ;; for Field IDs, just fetch the Field from the Store (qp.store/field field-id-or-name) diff --git a/src/metabase/query_processor/middleware/expand_macros.clj b/src/metabase/query_processor/middleware/expand_macros.clj index ede25fc3b9dcf5e5182e07d9ecf831888f8ff63e..5ff371fc0661d2fca993685d07fb323da2a79a38 100644 --- a/src/metabase/query_processor/middleware/expand_macros.clj +++ b/src/metabase/query_processor/middleware/expand_macros.clj @@ -51,15 +51,15 @@ (mbql.u/match query [:metric (_ :guard (complement mbql.u/ga-id?))])) (def ^:private MetricInfo - {:id su/IntGreaterThanZeroPlumatic - :name su/NonBlankStringPlumatic + {:id su/IntGreaterThanZero + :name su/NonBlankString :definition {:aggregation [(s/one mbql.s/Aggregation "aggregation clause")] (s/optional-key :filter) (s/maybe mbql.s/Filter) s/Keyword s/Any}}) (def ^:private ^{:arglists '([metric-info])} metric-info-validation-errors (s/checker MetricInfo)) -(s/defn ^:private metric-clauses->id->info :- {su/IntGreaterThanZeroPlumatic MetricInfo} +(s/defn ^:private metric-clauses->id->info :- {su/IntGreaterThanZero MetricInfo} [metric-clauses :- [mbql.s/metric]] (when (seq metric-clauses) (m/index-by :id (for [metric (db/select [Metric :id :name :definition] :id [:in (set (map second metric-clauses))]) @@ -70,7 +70,7 @@ metric)))) (s/defn ^:private add-metrics-filters-this-level :- mbql.s/MBQLQuery - [inner-query :- mbql.s/MBQLQuery this-level-metric-id->info :- {su/IntGreaterThanZeroPlumatic MetricInfo}] + [inner-query :- mbql.s/MBQLQuery this-level-metric-id->info :- {su/IntGreaterThanZero MetricInfo}] (let [filters (for [{{filter-clause :filter} :definition} (vals this-level-metric-id->info) :when filter-clause] filter-clause)] @@ -95,7 +95,7 @@ [:aggregation-options &match {:display-name metric-name}]))) (s/defn ^:private replace-metrics-aggregations-this-level :- mbql.s/MBQLQuery - [inner-query :- mbql.s/MBQLQuery this-level-metric-id->info :- {su/IntGreaterThanZeroPlumatic MetricInfo}] + [inner-query :- mbql.s/MBQLQuery this-level-metric-id->info :- {su/IntGreaterThanZero MetricInfo}] (letfn [(metric [metric-id] (or (get this-level-metric-id->info metric-id) (throw (ex-info (tru "Metric {0} does not exist, or is invalid." metric-id) @@ -119,7 +119,7 @@ [:metric (metric-id :guard (complement mbql.u/ga-id?))] (metric-info->ag-clause (metric metric-id) {:use-metric-name-as-display-name? true})))) -(s/defn ^:private metric-ids-this-level :- (s/maybe #{su/IntGreaterThanZeroPlumatic}) +(s/defn ^:private metric-ids-this-level :- (s/maybe #{su/IntGreaterThanZero}) [inner-query] (when (map? inner-query) (when-let [aggregations (:aggregation inner-query)] @@ -133,19 +133,19 @@ mbql.s/MBQLQuery (complement metric-ids-this-level) "Inner MBQL query with no :metric clauses at this level") - [inner-query :- mbql.s/MBQLQuery metric-id->info :- {su/IntGreaterThanZeroPlumatic MetricInfo}] + [inner-query :- mbql.s/MBQLQuery metric-id->info :- {su/IntGreaterThanZero MetricInfo}] (let [this-level-metric-ids (metric-ids-this-level inner-query) this-level-metric-id->info (select-keys metric-id->info this-level-metric-ids)] (-> inner-query (add-metrics-filters-this-level this-level-metric-id->info) (replace-metrics-aggregations-this-level this-level-metric-id->info)))) -(s/defn ^:private expand-metrics-clauses :- su/MapPlumatic +(s/defn ^:private expand-metrics-clauses :- su/Map "Add appropriate `filter` and `aggregation` clauses for a sequence of Metrics. (expand-metrics-clauses {:query {}} [[:metric 10]]) ;; -> {:query {:aggregation [[:count]], :filter [:= [:field-id 10] 20]}}" - [query :- su/MapPlumatic metric-id->info :- (su/non-empty {su/IntGreaterThanZeroPlumatic MetricInfo})] + [query :- su/Map metric-id->info :- (su/non-empty {su/IntGreaterThanZero MetricInfo})] (mbql.u/replace query (m :guard metric-ids-this-level) (-> m diff --git a/src/metabase/query_processor/middleware/fetch_source_query.clj b/src/metabase/query_processor/middleware/fetch_source_query.clj index 6816c9c70b58388a87d625c8067ffcb9c0242150..20607496d9f3180b86b9a31538a2b426d8904cb8 100644 --- a/src/metabase/query_processor/middleware/fetch_source_query.clj +++ b/src/metabase/query_processor/middleware/fetch_source_query.clj @@ -59,7 +59,7 @@ {:database mbql.s/DatabaseID :source-metadata [mbql.s/SourceQueryMetadata] :source-query mbql.s/SourceQuery - :source-card-id su/IntGreaterThanZeroPlumatic + :source-card-id su/IntGreaterThanZero s/Keyword s/Any} (complement :source-table) "`:source-table` should be removed")) @@ -89,11 +89,11 @@ ;;; | Resolving card__id -> source query | ;;; +----------------------------------------------------------------------------------------------------------------+ -(s/defn ^:private trim-sql-query :- su/NonBlankStringPlumatic +(s/defn ^:private trim-sql-query :- su/NonBlankString "Native queries can have trailing SQL comments. This works when executed directly, but when we use the query in a nested query, we wrap it in another query, which can cause the last part of the query to be unintentionally commented out, causing it to fail. This function removes any trailing SQL comment." - [card-id :- su/IntGreaterThanZeroPlumatic, query-str :- su/NonBlankStringPlumatic] + [card-id :- su/IntGreaterThanZero, query-str :- su/NonBlankString] (let [trimmed-string (str/replace query-str #"--.*(\n|$)" "")] (if (= query-str trimmed-string) query-str @@ -112,9 +112,9 @@ (s/defn card-id->source-query-and-metadata :- SourceQueryAndMetadata "Return the source query info for Card with `card-id`. Pass true as the optional second arg `log?` to enable logging. (The circularity check calls this and will print more than desired)" - ([card-id :- su/IntGreaterThanZeroPlumatic] + ([card-id :- su/IntGreaterThanZero] (card-id->source-query-and-metadata card-id false)) - ([card-id :- su/IntGreaterThanZeroPlumatic log? :- s/Bool] + ([card-id :- su/IntGreaterThanZero log? :- s/Bool] (let [;; todo: we need to cache this. We are running this in preprocess, compile, and then again card (or (db/select-one Card :id card-id) (throw (ex-info (tru "Card {0} does not exist." card-id) @@ -167,7 +167,7 @@ persisted? sub-cached-field-refs)} dataset? (assoc :source-query/dataset? dataset?))))) -(s/defn ^:private source-table-str->card-id :- su/IntGreaterThanZeroPlumatic +(s/defn ^:private source-table-str->card-id :- su/IntGreaterThanZero [source-table-str :- mbql.s/source-table-card-id-regex] (when-let [[_ card-id-str] (re-find #"^card__(\d+)$" source-table-str)] (Integer/parseInt card-id-str))) @@ -265,22 +265,22 @@ (&match :guard (every-pred map? :database (comp integer? :database))) (recur (dissoc &match :database)))) -(s/defn ^:private extract-resolved-card-id :- {:card-id (s/maybe su/IntGreaterThanZeroPlumatic) - :query su/MapPlumatic} +(s/defn ^:private extract-resolved-card-id :- {:card-id (s/maybe su/IntGreaterThanZero) + :query su/Map} "If the ID of the Card we've resolved (`:source-card-id`) was added by a previous step, add it to `:query` `:info` (so it can be included in the QueryExecution log), then return a map with the resolved `:card-id` and updated `:query`." - [query :- su/MapPlumatic] + [query :- su/Map] (let [card-id (get-in query [:query :source-card-id])] {:query (cond-> query card-id (update-in [:info :card-id] #(or % card-id))) :card-id card-id})) -(s/defn ^:private resolve-all :- {:card-id (s/maybe su/IntGreaterThanZeroPlumatic) - :query su/MapPlumatic} +(s/defn ^:private resolve-all :- {:card-id (s/maybe su/IntGreaterThanZero) + :query su/Map} "Recursively replace all Card ID source tables in `query` with resolved `:source-query` and `:source-metadata`. Since the `:database` is only useful for top-level source queries, we'll remove it from all other levels." - [query :- su/MapPlumatic] + [query :- su/Map] ;; if a `:source-card-id` is already in the query, remove it, so we don't pull user-supplied input up into `:info` ;; allowing someone to bypass permissions (-> (m/dissoc-in query [:query :source-card-id]) @@ -290,7 +290,7 @@ remove-unneeded-database-ids extract-resolved-card-id)) -(s/defn ^:private resolve-card-id-source-tables* :- {:card-id (s/maybe su/IntGreaterThanZeroPlumatic) +(s/defn ^:private resolve-card-id-source-tables* :- {:card-id (s/maybe su/IntGreaterThanZero) :query FullyResolvedQuery} "Resolve `card__n`-style `:source-tables` in `query`." [{inner-query :query, :as outer-query} :- mbql.s/Query] diff --git a/src/metabase/query_processor/middleware/permissions.clj b/src/metabase/query_processor/middleware/permissions.clj index 5d7775b139e9637315f97548261673e9ecb7e605..7aae7bd5b082833670edbf6b449a909bad2d0d18 100644 --- a/src/metabase/query_processor/middleware/permissions.clj +++ b/src/metabase/query_processor/middleware/permissions.clj @@ -57,7 +57,7 @@ (s/defn ^:private check-card-read-perms "Check that the current user has permissions to read Card with `card-id`, or throw an Exception. " - [card-id :- su/IntGreaterThanZeroPlumatic] + [card-id :- su/IntGreaterThanZero] (let [card (or (db/select-one [Card :collection_id] :id card-id) (throw (ex-info (tru "Card {0} does not exist." card-id) {:type qp.error-type/invalid-query @@ -91,7 +91,7 @@ (s/defn ^:private check-query-permissions* "Check that User with `user-id` has permissions to run `query`, or throw an exception." - [outer-query :- su/MapPlumatic] + [outer-query :- su/Map] (when *current-user-id* (log/tracef "Checking query permissions. Current user perms set = %s" (pr-str @*current-user-permissions-set*)) (if *card-id* @@ -128,7 +128,7 @@ (s/defn check-query-action-permissions* "Check that User with `user-id` has permissions to run query action `query`, or throw an exception." - [outer-query :- su/MapPlumatic] + [outer-query :- su/Map] (log/tracef "Checking query permissions. Current user perms set = %s" (pr-str @*current-user-permissions-set*)) (when *card-id* (check-card-read-perms *card-id*)) diff --git a/src/metabase/query_processor/middleware/resolve_joined_fields.clj b/src/metabase/query_processor/middleware/resolve_joined_fields.clj index e6ee0121206c7ee68846d100635e95b33467b0fd..8ac2f1f0f135ebb4c3c4031817bffd958b695725 100644 --- a/src/metabase/query_processor/middleware/resolve_joined_fields.clj +++ b/src/metabase/query_processor/middleware/resolve_joined_fields.clj @@ -13,7 +13,7 @@ [schema.core :as s])) (def ^:private InnerQuery - (s/constrained su/MapPlumatic (every-pred (some-fn :source-table :source-query :joins) + (s/constrained su/Map (every-pred (some-fn :source-table :source-query :joins) (complement :condition)))) (s/defn ^:private add-join-alias diff --git a/src/metabase/query_processor/middleware/resolve_source_table.clj b/src/metabase/query_processor/middleware/resolve_source_table.clj index 38dbda66660090e44e28414c5ec6e0c42271ce9a..22569f74d82a8161187c6f19ad6866773d2042e6 100644 --- a/src/metabase/query_processor/middleware/resolve_source_table.clj +++ b/src/metabase/query_processor/middleware/resolve_source_table.clj @@ -18,7 +18,7 @@ (tru "Invalid :source-table ''{0}'': should be resolved to a Table ID by now." (:source-table m)) {:form m})))) -(s/defn ^:private query->source-table-ids :- (s/maybe (su/non-empty #{su/IntGreaterThanZeroPlumatic})) +(s/defn ^:private query->source-table-ids :- (s/maybe (su/non-empty #{su/IntGreaterThanZero})) "Fetch a set of all `:source-table` IDs anywhere in `query`." [query] (some-> diff --git a/src/metabase/query_processor/store.clj b/src/metabase/query_processor/store.clj index da777ab6af91fe209be386bcb64350e015473e8a..5148d29bf047232af73d9dd296e523a256ada26c 100644 --- a/src/metabase/query_processor/store.clj +++ b/src/metabase/query_processor/store.clj @@ -64,11 +64,11 @@ (def ^:private DatabaseInstanceWithRequiredStoreKeys (s/both (mi/InstanceOf Database) - {:id su/IntGreaterThanZeroPlumatic + {:id su/IntGreaterThanZero :engine s/Keyword - :name su/NonBlankStringPlumatic - :details su/MapPlumatic - :settings (s/maybe su/MapPlumatic) + :name su/NonBlankString + :details su/Map + :settings (s/maybe su/Map) s/Any s/Any})) (def ^:private table-columns-to-fetch @@ -82,7 +82,7 @@ (s/both (mi/InstanceOf Table) {:schema (s/maybe s/Str) - :name su/NonBlankStringPlumatic + :name su/NonBlankString s/Any s/Any})) @@ -109,19 +109,19 @@ (def ^:private FieldInstanceWithRequiredStorekeys (s/both (mi/InstanceOf Field) - {:name su/NonBlankStringPlumatic - :display_name su/NonBlankStringPlumatic + {:name su/NonBlankString + :display_name su/NonBlankString :description (s/maybe s/Str) - :database_type su/NonBlankStringPlumatic - :base_type su/FieldTypePlumatic + :database_type su/NonBlankString + :base_type su/FieldType ;; there's a tension as we sometimes store fields from the db, and sometimes store computed fields. ideally we ;; would make everything just use base_type. - (s/optional-key :effective_type) (s/maybe su/FieldTypePlumatic) - (s/optional-key :coercion_strategy) (s/maybe su/CoercionStrategyPlumatic) - :semantic_type (s/maybe su/FieldSemanticOrRelationTypePlumatic) - :fingerprint (s/maybe su/MapPlumatic) - :parent_id (s/maybe su/IntGreaterThanZeroPlumatic) - :nfc_path (s/maybe [su/NonBlankStringPlumatic]) + (s/optional-key :effective_type) (s/maybe su/FieldType) + (s/optional-key :coercion_strategy) (s/maybe su/CoercionStrategy) + :semantic_type (s/maybe su/FieldSemanticOrRelationType) + :fingerprint (s/maybe su/Map) + :parent_id (s/maybe su/IntGreaterThanZero) + :nfc_path (s/maybe [su/NonBlankString]) s/Any s/Any})) @@ -150,7 +150,7 @@ ;;; ----------------------- Fetching objects from application DB, and saving them in the store ----------------------- -(s/defn ^:private db-id :- su/IntGreaterThanZeroPlumatic +(s/defn ^:private db-id :- su/IntGreaterThanZero [] (or (get-in @*store* [:database :id]) (throw (Exception. (tru "Cannot store Tables or Fields before Database is stored."))))) @@ -159,7 +159,7 @@ "Fetch the Database this query will run against from the application database, and store it in the QP Store for the duration of the current query execution. If Database has already been fetched, this function will no-op. Throws an Exception if Table does not exist." - [database-id :- su/IntGreaterThanZeroPlumatic] + [database-id :- su/IntGreaterThanZero] (if-let [existing-db-id (get-in @*store* [:database :id])] ;; if there's already a DB in the Store, double-check it has the same ID as the one that we were asked to fetch (when-not (= existing-db-id database-id) @@ -174,8 +174,8 @@ (def ^:private IDs (s/maybe (s/cond-pre - #{su/IntGreaterThanZeroPlumatic} - [su/IntGreaterThanZeroPlumatic]))) + #{su/IntGreaterThanZero} + [su/IntGreaterThanZero]))) (s/defn fetch-and-store-tables! "Fetch Table(s) from the application database, and store them in the QP Store for the duration of the current query @@ -248,7 +248,7 @@ (s/defn table :- TableInstanceWithRequiredStoreKeys "Fetch Table with `table-id` from the QP Store. Throws an Exception if valid item is not returned." - [table-id :- su/IntGreaterThanZeroPlumatic] + [table-id :- su/IntGreaterThanZero] (*table* table-id)) (defn- default-field @@ -263,7 +263,7 @@ (s/defn field :- FieldInstanceWithRequiredStorekeys "Fetch Field with `field-id` from the QP Store. Throws an Exception if valid item is not returned." - [field-id :- su/IntGreaterThanZeroPlumatic] + [field-id :- su/IntGreaterThanZero] (*field* field-id)) diff --git a/src/metabase/query_processor/util.clj b/src/metabase/query_processor/util.clj index db53076c1955fea10d3f28833dc252f68f585665..269a781d897902278c01e46bbcc13c14f56225a2 100644 --- a/src/metabase/query_processor/util.clj +++ b/src/metabase/query_processor/util.clj @@ -59,7 +59,7 @@ (s/defn ^:deprecated normalize-token :- s/Keyword "Convert a string or keyword in various cases (`lisp-case`, `snake_case`, or `SCREAMING_SNAKE_CASE`) to a lisp-cased keyword." - [token :- su/KeywordOrStringPlumatic] + [token :- su/KeywordOrString] (-> (name token) str/lower-case (str/replace #"_" "-") diff --git a/src/metabase/server/middleware/browser_cookie.clj b/src/metabase/server/middleware/browser_cookie.clj index dfeda32036c6a811cad348ddf54418bc5a89d98e..0f4ac584ebe974cc34a9b8d75e36313ec9e1bcb4 100644 --- a/src/metabase/server/middleware/browser_cookie.clj +++ b/src/metabase/server/middleware/browser_cookie.clj @@ -29,7 +29,7 @@ {:same-site :none, :secure true} {:same-site :lax}))) -(s/defn ^:private add-browser-id-cookie [request response browser-id :- su/NonBlankStringPlumatic] +(s/defn ^:private add-browser-id-cookie [request response browser-id :- su/NonBlankString] (response/set-cookie response browser-id-cookie-name browser-id (cookie-options request))) (defn ensure-browser-id-cookie diff --git a/src/metabase/server/request/util.clj b/src/metabase/server/request/util.clj index bf93a0818e291a25d4b0ffb3bfad84b19153f5ac..e81a5ad6fdfa398efde20599aff0c1f6121a596c 100644 --- a/src/metabase/server/request/util.clj +++ b/src/metabase/server/request/util.clj @@ -89,9 +89,9 @@ (def DeviceInfo "Schema for the device info returned by `device-info`." - {:device_id su/NonBlankStringPlumatic - :device_description su/NonBlankStringPlumatic - :ip_address su/NonBlankStringPlumatic}) + {:device_id su/NonBlankString + :device_description su/NonBlankString + :ip_address su/NonBlankString}) (s/defn device-info :- DeviceInfo "Information about the device that made this request, as recorded by the `LoginHistory` table." @@ -137,10 +137,10 @@ 5000) (def ^:private IPAddress - (s/constrained su/NonBlankStringPlumatic u/ip-address? "valid IP address string")) + (s/constrained su/NonBlankString u/ip-address? "valid IP address string")) ;; TODO -- replace with something better, like built-in database once we find one that's GPL compatible -(s/defn geocode-ip-addresses :- (s/maybe {IPAddress {:description su/NonBlankStringPlumatic +(s/defn geocode-ip-addresses :- (s/maybe {IPAddress {:description su/NonBlankString :timezone (s/maybe java.time.ZoneId)}}) "Geocode multiple IP addresses, returning a map of IP address -> info, with each info map containing human-friendly `:description` of the location and a `java.time.ZoneId` `:timezone`, if that information is available." diff --git a/src/metabase/sync/analyze/classifiers/category.clj b/src/metabase/sync/analyze/classifiers/category.clj index f872258c71067f2f6df422b24ea45fdec647ae04..3466091056ea6bc3d7ad372611cd5033226d1dc4 100644 --- a/src/metabase/sync/analyze/classifiers/category.clj +++ b/src/metabase/sync/analyze/classifiers/category.clj @@ -30,7 +30,7 @@ (isa? semantic_type :type/FK))) (s/defn ^:private field-should-be-category? :- (s/maybe s/Bool) - [fingerprint :- (s/maybe i/Fingerprint), field :- su/MapPlumatic] + [fingerprint :- (s/maybe i/Fingerprint), field :- su/Map] (let [distinct-count (get-in fingerprint [:global :distinct-count]) nil% (get-in fingerprint [:global :nil%])] ;; Only mark a Field as a Category if it doesn't already have a semantic type. diff --git a/src/metabase/sync/analyze/classifiers/name.clj b/src/metabase/sync/analyze/classifiers/name.clj index b0220dc58e8d81df8ee1af2505abe0ffe20a509c..abcd24a52053cef5ef84044612aaa7d62742d45b 100644 --- a/src/metabase/sync/analyze/classifiers/name.clj +++ b/src/metabase/sync/analyze/classifiers/name.clj @@ -119,9 +119,9 @@ (assert (or (isa? semantic-type :Semantic/*) (isa? semantic-type :Relation/*))))) -(s/defn ^:private semantic-type-for-name-and-base-type :- (s/maybe su/FieldSemanticOrRelationTypePlumatic) +(s/defn ^:private semantic-type-for-name-and-base-type :- (s/maybe su/FieldSemanticOrRelationType) "If `name` and `base-type` matches a known pattern, return the `semantic_type` we should assign to it." - [field-name :- su/NonBlankStringPlumatic, base-type :- su/FieldTypePlumatic] + [field-name :- su/NonBlankString, base-type :- su/FieldType] (let [field-name (str/lower-case field-name)] (some (fn [[name-pattern valid-base-types semantic-type]] (when (and (some (partial isa? base-type) valid-base-types) diff --git a/src/metabase/sync/analyze/classifiers/text_fingerprint.clj b/src/metabase/sync/analyze/classifiers/text_fingerprint.clj index 1a642817c7a6c4b6c39a8593bcff0a305fbbe3c6..c2097d259aeed64e01b550163f3ea56bf6ce7a1a 100644 --- a/src/metabase/sync/analyze/classifiers/text_fingerprint.clj +++ b/src/metabase/sync/analyze/classifiers/text_fingerprint.clj @@ -33,7 +33,7 @@ :percent-email [:type/Email percent-valid-threshold] :percent-state [:type/State lower-percent-valid-threshold]}) -(s/defn ^:private infer-semantic-type-for-text-fingerprint :- (s/maybe su/FieldTypePlumatic) +(s/defn ^:private infer-semantic-type-for-text-fingerprint :- (s/maybe su/FieldType) "Check various percentages inside the TEXT-FINGERPRINT and return the corresponding semantic type to mark the Field as if the percent passes the threshold." [text-fingerprint :- i/TextFingerprint] diff --git a/src/metabase/sync/analyze/fingerprint.clj b/src/metabase/sync/analyze/fingerprint.clj index 9546cb338303351f447cb10922640912d23c9d64..aa54d1b2410cf5ab61fc84575d08b28a5a9fbd40 100644 --- a/src/metabase/sync/analyze/fingerprint.clj +++ b/src/metabase/sync/analyze/fingerprint.clj @@ -96,10 +96,10 @@ ;; (fingerprint_version < 2 AND ;; base_type IN ("type/Text", "type/SerializedJSON"))) -(s/defn ^:private base-types->descendants :- #{su/FieldTypeKeywordOrStringPlumatic} +(s/defn ^:private base-types->descendants :- #{su/FieldTypeKeywordOrString} "Given a set of BASE-TYPES return an expanded set that includes those base types as well as all of their descendants. These types are converted to strings so HoneySQL doesn't confuse them for columns." - [base-types :- #{su/FieldTypePlumatic}] + [base-types :- #{su/FieldType}] (->> (for [base-type base-types] (cons base-type (descendants base-type))) (reduce set/union) diff --git a/src/metabase/sync/analyze/query_results.clj b/src/metabase/sync/analyze/query_results.clj index 8015a2365e725df0462097afb08ad33b459b0190..f8008003e15358bcc096395b19a8fa1b85413549 100644 --- a/src/metabase/sync/analyze/query_results.clj +++ b/src/metabase/sync/analyze/query_results.clj @@ -20,7 +20,7 @@ (def ^:private DateTimeUnitKeywordOrString "Schema for a valid datetime unit string like \"default\" or \"minute-of-hour\"." - (s/constrained su/KeywordOrStringPlumatic + (s/constrained su/KeywordOrString #(mbql.preds/DateTimeUnit? (keyword %)) "Valid field datetime unit keyword or string")) @@ -31,11 +31,11 @@ {:name s/Str :display_name s/Str (s/optional-key :description) (s/maybe s/Str) - :base_type su/FieldTypeKeywordOrStringPlumatic - (s/optional-key :semantic_type) (s/maybe su/FieldSemanticOrRelationTypeKeywordOrStringPlumatic) + :base_type su/FieldTypeKeywordOrString + (s/optional-key :semantic_type) (s/maybe su/FieldSemanticOrRelationTypeKeywordOrString) (s/optional-key :unit) (s/maybe DateTimeUnitKeywordOrString) (s/optional-key :fingerprint) (s/maybe i/Fingerprint) - (s/optional-key :id) (s/maybe su/IntGreaterThanZeroPlumatic) + (s/optional-key :id) (s/maybe su/IntGreaterThanZero) ;; only optional because it's not present right away, but it should be present at the end. (s/optional-key :field_ref) (s/cond-pre mbql.s/FieldOrAggregationReference diff --git a/src/metabase/sync/interface.clj b/src/metabase/sync/interface.clj index b4af454474f06e029dea20760e44fbae081c98ff..7146c6e7743b45349f27f43c22d3f3bff4a72ee8 100644 --- a/src/metabase/sync/interface.clj +++ b/src/metabase/sync/interface.clj @@ -10,26 +10,26 @@ (def DatabaseMetadataTable "Schema for the expected output of `describe-database` for a Table." - {:name su/NonBlankStringPlumatic - :schema (s/maybe su/NonBlankStringPlumatic) + {:name su/NonBlankString + :schema (s/maybe su/NonBlankString) ;; `:description` in this case should be a column/remark on the Table, if there is one. (s/optional-key :description) (s/maybe s/Str)}) (def DatabaseMetadata "Schema for the expected output of `describe-database`." {:tables #{DatabaseMetadataTable} - (s/optional-key :version) (s/maybe su/NonBlankStringPlumatic)}) + (s/optional-key :version) (s/maybe su/NonBlankString)}) (def TableMetadataField "Schema for a given Field as provided in `describe-table`." - {:name su/NonBlankStringPlumatic - :database-type (s/maybe su/NonBlankStringPlumatic) ; blank if the Field is all NULL & untyped, i.e. in Mongo - :base-type su/FieldTypePlumatic - :database-position su/IntGreaterThanOrEqualToZeroPlumatic - (s/optional-key :semantic-type) (s/maybe su/FieldSemanticOrRelationTypePlumatic) - (s/optional-key :effective-type) (s/maybe su/FieldTypePlumatic) - (s/optional-key :coercion-strategy) (s/maybe su/CoercionStrategyPlumatic) - (s/optional-key :field-comment) (s/maybe su/NonBlankStringPlumatic) + {:name su/NonBlankString + :database-type (s/maybe su/NonBlankString) ; blank if the Field is all NULL & untyped, i.e. in Mongo + :base-type su/FieldType + :database-position su/IntGreaterThanOrEqualToZero + (s/optional-key :semantic-type) (s/maybe su/FieldSemanticOrRelationType) + (s/optional-key :effective-type) (s/maybe su/FieldType) + (s/optional-key :coercion-strategy) (s/maybe su/CoercionStrategy) + (s/optional-key :field-comment) (s/maybe su/NonBlankString) (s/optional-key :pk?) s/Bool (s/optional-key :nested-fields) #{(s/recursive #'TableMetadataField)} (s/optional-key :nfc-path) [s/Any] @@ -40,8 +40,8 @@ (def TableMetadata "Schema for the expected output of `describe-table`." - {:name su/NonBlankStringPlumatic - :schema (s/maybe su/NonBlankStringPlumatic) + {:name su/NonBlankString + :schema (s/maybe su/NonBlankString) :fields #{TableMetadataField} (s/optional-key :description) (s/maybe s/Str)}) @@ -51,10 +51,10 @@ (def FKMetadataEntry "Schema for an individual entry in `FKMetadata`." - {:fk-column-name su/NonBlankStringPlumatic - :dest-table {:name su/NonBlankStringPlumatic - :schema (s/maybe su/NonBlankStringPlumatic)} - :dest-column-name su/NonBlankStringPlumatic}) + {:fk-column-name su/NonBlankString + :dest-table {:name su/NonBlankString + :schema (s/maybe su/NonBlankString)} + :dest-column-name su/NonBlankString}) (def FKMetadata "Schema for the expected output of `describe-table-fks`." @@ -68,7 +68,7 @@ (def DatabaseInstance "Schema for a valid instance of a Metabase Database." (mi/InstanceOf Database)) (def TableInstance "Schema for a valid instance of a Metabase Table." (mi/InstanceOf Table)) (def FieldInstance "Schema for a valid instance of a Metabase Field." (mi/InstanceOf Field)) -(def ResultColumnMetadataInstance "Schema for result column metadata." su/MapPlumatic) +(def ResultColumnMetadataInstance "Schema for result column metadata." su/Map) ;;; +----------------------------------------------------------------------------------------------------------------+ diff --git a/src/metabase/sync/sync_metadata/dbms_version.clj b/src/metabase/sync/sync_metadata/dbms_version.clj index a484cd765f70bd5fa3da1c0411f632fed791dc93..838576d89f6b8faf93377fe23ae5a38546c49429 100644 --- a/src/metabase/sync/sync_metadata/dbms_version.clj +++ b/src/metabase/sync/sync_metadata/dbms_version.clj @@ -10,7 +10,7 @@ (def DBMSVersion "Schema for the expected output of `describe-table-fks`." - {:version su/NonBlankStringPlumatic + {:version su/NonBlankString s/Keyword s/Any}) (s/defn sync-dbms-version! diff --git a/src/metabase/sync/sync_metadata/fields.clj b/src/metabase/sync/sync_metadata/fields.clj index b8e3bca2a03ffd907a27a4b73fc7ddecbd6dde4f..dd76b164c0ad7a223b7f07ae8acde3d429a764ef 100644 --- a/src/metabase/sync/sync_metadata/fields.clj +++ b/src/metabase/sync/sync_metadata/fields.clj @@ -53,7 +53,7 @@ ;;; | PUTTING IT ALL TOGETHER | ;;; +----------------------------------------------------------------------------------------------------------------+ -(s/defn ^:private sync-and-update! :- su/IntGreaterThanOrEqualToZeroPlumatic +(s/defn ^:private sync-and-update! :- su/IntGreaterThanOrEqualToZero "Sync Field instances (i.e., rows in the Field table in the Metabase application DB) for a Table, and update metadata properties (e.g. base type and comment/remark) as needed. Returns number of Fields synced." [table :- i/TableInstance, db-metadata :- #{i/TableMetadataField}] @@ -75,8 +75,8 @@ :updated-fields (sync-and-update! table db-metadata)})))) -(s/defn sync-fields! :- (s/maybe {:updated-fields su/IntGreaterThanOrEqualToZeroPlumatic - :total-fields su/IntGreaterThanOrEqualToZeroPlumatic}) +(s/defn sync-fields! :- (s/maybe {:updated-fields su/IntGreaterThanOrEqualToZero + :total-fields su/IntGreaterThanOrEqualToZero}) "Sync the Fields in the Metabase application database for all the Tables in a `database`." [database :- i/DatabaseInstance] (->> database diff --git a/src/metabase/sync/sync_metadata/fields/common.clj b/src/metabase/sync/sync_metadata/fields/common.clj index 6895bd299749cf90a3ce20c9ec3579085b8ee1ae..49b7cbbda22d13eea2aa0cb1001b6bb4bd1e9ea6 100644 --- a/src/metabase/sync/sync_metadata/fields/common.clj +++ b/src/metabase/sync/sync_metadata/fields/common.clj @@ -10,20 +10,20 @@ (def ParentID "Schema for the `parent-id` of a Field, i.e. an optional ID." - (s/maybe su/IntGreaterThanZeroPlumatic)) + (s/maybe su/IntGreaterThanZero)) (def TableMetadataFieldWithID "Schema for `TableMetadataField` with an included ID of the corresponding Metabase Field object. `our-metadata` is always returned in this format. (The ID is needed in certain places so we know which Fields to retire, and the parent ID of any nested-fields.)" (assoc i/TableMetadataField - :id su/IntGreaterThanZeroPlumatic + :id su/IntGreaterThanZero (s/optional-key :nested-fields) #{(s/recursive #'TableMetadataFieldWithID)})) (def TableMetadataFieldWithOptionalID "Schema for either `i/TableMetadataField` (`db-metadata`) or `TableMetadataFieldWithID` (`our-metadata`)." (assoc i/TableMetadataField - (s/optional-key :id) su/IntGreaterThanZeroPlumatic + (s/optional-key :id) su/IntGreaterThanZero (s/optional-key :nested-fields) #{(s/recursive #'TableMetadataFieldWithOptionalID)})) (s/defn field-metadata-name-for-logging :- s/Str @@ -39,7 +39,7 @@ [field] (str/lower-case (:name field))) -(s/defn semantic-type :- (s/maybe su/FieldSemanticOrRelationTypePlumatic) +(s/defn semantic-type :- (s/maybe su/FieldSemanticOrRelationType) "Determine a the appropriate `semantic-type` for a Field with `field-metadata`." [field-metadata :- (s/maybe i/TableMetadataField)] (and field-metadata diff --git a/src/metabase/sync/sync_metadata/fields/sync_instances.clj b/src/metabase/sync/sync_metadata/fields/sync_instances.clj index bf7343895cdcf6df4abdbf4649f7dc203bd464d3..3404aabd9830abbc7f7598142be5bb62885db83d 100644 --- a/src/metabase/sync/sync_metadata/fields/sync_instances.clj +++ b/src/metabase/sync/sync_metadata/fields/sync_instances.clj @@ -98,7 +98,7 @@ "Schema for the value returned by `sync-active-instances!`. Because we need to know about newly-inserted/reactivated parent Fields when recursively syncing nested Fields, we need to propogate the updates to `our-metadata` made by this function and pass them to other steps of the `sync-instances!` process." - {:num-updates su/IntGreaterThanOrEqualToZeroPlumatic + {:num-updates su/IntGreaterThanOrEqualToZero :our-metadata #{common/TableMetadataFieldWithID}}) (s/defn ^:private sync-active-instances! :- Updates @@ -141,7 +141,7 @@ (when (db/update! Field (u/the-id metabase-field) :active false) 1)) -(s/defn ^:private retire-fields! :- su/IntGreaterThanOrEqualToZeroPlumatic +(s/defn ^:private retire-fields! :- su/IntGreaterThanOrEqualToZero "Mark inactive any Fields in the application database that are no longer present in the DB being synced. These Fields are ones that are in `our-metadata`, but not in `db-metadata`. Does *NOT* recurse over nested Fields. Returns `1` if a Field was marked inactive." @@ -162,7 +162,7 @@ (declare sync-instances!) -(s/defn ^:private sync-nested-fields-of-one-field! :- (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic) +(s/defn ^:private sync-nested-fields-of-one-field! :- (s/maybe su/IntGreaterThanOrEqualToZero) "Recursively sync Field instances (i.e., rows in application DB) for nested Fields of a single Field, one or both `field-metadata` (from synced DB) and `metabase-field` (from application DB)." [table :- i/TableInstance @@ -178,7 +178,7 @@ (set metabase-nested-fields) (some-> metabase-field u/the-id))))) -(s/defn ^:private sync-nested-field-instances! :- (s/maybe su/IntGreaterThanOrEqualToZeroPlumatic) +(s/defn ^:private sync-nested-field-instances! :- (s/maybe su/IntGreaterThanOrEqualToZero) "Recursively sync Field instances (i.e., rows in application DB) for *all* the nested Fields of all Fields in `db-metadata` and `our-metadata`. Not for the flattened nested fields for JSON columns in normal RDBMSes (nested field columns)" @@ -194,7 +194,7 @@ metabase-field (get name->metabase-field field-name)]] (sync-nested-fields-of-one-field! table field-metadata metabase-field)))) -(s/defn sync-instances! :- su/IntGreaterThanOrEqualToZeroPlumatic +(s/defn sync-instances! :- su/IntGreaterThanOrEqualToZero "Sync rows in the Field table with `db-metadata` describing the current schema of the Table currently being synced, creating Field objects or marking them active/inactive as needed." ([table :- i/TableInstance diff --git a/src/metabase/sync/sync_metadata/fields/sync_metadata.clj b/src/metabase/sync/sync_metadata/fields/sync_metadata.clj index ffdb3797b0f78c45be19e68fb8985d93d0f7ffe4..6e793e7664528efd056add8baa1ee7c287e43cc6 100644 --- a/src/metabase/sync/sync_metadata/fields/sync_metadata.clj +++ b/src/metabase/sync/sync_metadata/fields/sync_metadata.clj @@ -111,7 +111,7 @@ (declare update-metadata!) -(s/defn ^:private update-nested-fields-metadata! :- su/IntGreaterThanOrEqualToZeroPlumatic +(s/defn ^:private update-nested-fields-metadata! :- su/IntGreaterThanOrEqualToZero "Recursively call `update-metadata!` for all the nested Fields in a `metabase-field`." [table :- i/TableInstance, field-metadata :- i/TableMetadataField, metabase-field :- common/TableMetadataFieldWithID] (let [nested-fields-metadata (:nested-fields field-metadata) @@ -120,7 +120,7 @@ (update-metadata! table (set nested-fields-metadata) (set metabase-nested-fields)) 0))) -(s/defn update-metadata! :- su/IntGreaterThanOrEqualToZeroPlumatic +(s/defn update-metadata! :- su/IntGreaterThanOrEqualToZero "Make sure things like PK status and base-type are in sync with what has come back from the DB. Recursively updates nested Fields. Returns total number of Fields updated." [table :- i/TableInstance diff --git a/src/metabase/sync/sync_metadata/metabase_metadata.clj b/src/metabase/sync/sync_metadata/metabase_metadata.clj index de717bfdf6905fa23b0f4267d21b626717e63f5f..5ee72f221838c7a82da3d82b4d9848f622bf217f 100644 --- a/src/metabase/sync/sync_metadata/metabase_metadata.clj +++ b/src/metabase/sync/sync_metadata/metabase_metadata.clj @@ -22,14 +22,14 @@ [toucan.db :as db])) (def ^:private KeypathComponents - {:table-name (s/maybe su/NonBlankStringPlumatic) - :field-name (s/maybe su/NonBlankStringPlumatic) + {:table-name (s/maybe su/NonBlankString) + :field-name (s/maybe su/NonBlankString) :k s/Keyword}) (s/defn ^:private parse-keypath :- KeypathComponents "Parse a KEYPATH into components for easy use." ;; TODO: this does not support schemas in dbs :( - [keypath :- su/NonBlankStringPlumatic] + [keypath :- su/NonBlankString] ;; keypath will have one of three formats: ;; property (for database-level properties) ;; table_name.property diff --git a/src/metabase/sync/util.clj b/src/metabase/sync/util.clj index 53c5d4794f681398cc3791483a2cec34e11b03cc..e8fed7b1fcc5c6e5ed11af325bf79bbf606b1300 100644 --- a/src/metabase/sync/util.clj +++ b/src/metabase/sync/util.clj @@ -435,7 +435,7 @@ StepRunMetadata)) (s/defn ^:private create-task-history - [task-name :- su/NonBlankStringPlumatic + [task-name :- su/NonBlankString database :- i/DatabaseInstance {:keys [start-time end-time]} :- SyncOperationOrStepRunMetadata] {:task task-name diff --git a/src/metabase/task/sync_databases.clj b/src/metabase/task/sync_databases.clj index b753b06894296dcaabf4eb0b4c16b0d98133f78d..c915104a6efb34f814e9eadea76534fb15f155ca 100644 --- a/src/metabase/task/sync_databases.clj +++ b/src/metabase/task/sync_databases.clj @@ -34,7 +34,7 @@ (declare unschedule-tasks-for-db!) -(s/defn ^:private job-context->database-id :- (s/maybe su/IntGreaterThanZeroPlumatic) +(s/defn ^:private job-context->database-id :- (s/maybe su/IntGreaterThanZero) "Get the Database ID referred to in `job-context`." [job-context] (u/the-id (get (qc/from-job-data job-context) "db-id"))) diff --git a/src/metabase/transforms/core.clj b/src/metabase/transforms/core.clj index df0e38a2f5705da0c88c9e1d9b52c0cdc4cf445d..58c6f7ab86a1ba4cec867aec591166330b2e05e9 100644 --- a/src/metabase/transforms/core.clj +++ b/src/metabase/transforms/core.clj @@ -171,7 +171,7 @@ (map first matches)))) (s/defn ^:private tableset :- Tableset - [db-id :- su/IntGreaterThanZeroPlumatic, schema :- (s/maybe s/Str)] + [db-id :- su/IntGreaterThanZero, schema :- (s/maybe s/Str)] (table/with-fields (de/with-domain-entity (db/select 'Table :db_id db-id :schema schema)))) @@ -186,7 +186,7 @@ cols to the bindings. 4) Check that all output cards have the expected result shape. 5) Return the output cards." - [db-id :- su/IntGreaterThanZeroPlumatic, schema :- (s/maybe s/Str), spec :- TransformSpec] + [db-id :- su/IntGreaterThanZero, schema :- (s/maybe s/Str), spec :- TransformSpec] (tf.materialize/fresh-collection-for-transform! spec) (some-> (tableset db-id schema) (tables-matching-requirements spec) diff --git a/src/metabase/transforms/specs.clj b/src/metabase/transforms/specs.clj index 218f49be41b0f92dab8523c68b28408e5b8b717d..4c9c83990953d2ef888ba488cb4bb0cea565e420 100644 --- a/src/metabase/transforms/specs.clj +++ b/src/metabase/transforms/specs.clj @@ -25,7 +25,7 @@ (def ^:private Filter MBQL) -(def ^:private Limit su/IntGreaterThanZeroPlumatic) +(def ^:private Limit su/IntGreaterThanZero) (def ^:private Joins [{(s/required-key :source) Source (s/required-key :condition) MBQL diff --git a/src/metabase/util/cron.clj b/src/metabase/util/cron.clj index b4c94818ed03db6181047c9cbfccf9ae0bd1410c..b002e83fbca7abf618b50198231f0f632a640509 100644 --- a/src/metabase/util/cron.clj +++ b/src/metabase/util/cron.clj @@ -15,7 +15,7 @@ "Schema for a valid cron schedule string." (su/with-api-error-message (s/constrained - su/NonBlankStringPlumatic + su/NonBlankString (fn [^String s] (try (CronExpression/validateExpression s) true @@ -148,7 +148,7 @@ :schedule_hour (cron->digit hours) :schedule_type (cron->schedule-type hours day-of-month day-of-week)})) -(s/defn describe-cron-string :- su/NonBlankStringPlumatic +(s/defn describe-cron-string :- su/NonBlankString "Return a human-readable description of a cron expression, localized for the current User." [cron-string :- CronScheduleString] (CronExpressionDescriptor/getDescription ^String cron-string, ^java.util.Locale (i18n/user-locale))) diff --git a/src/metabase/util/honey_sql_1_extensions.clj b/src/metabase/util/honey_sql_1_extensions.clj index 19bcc037d85568c872601253c22e0a03dab0d661..575d26244ed6f41de6eb7432d018a4e4c448d884 100644 --- a/src/metabase/util/honey_sql_1_extensions.clj +++ b/src/metabase/util/honey_sql_1_extensions.clj @@ -177,7 +177,7 @@ (def ^:private NormalizedTypeInfo {(s/optional-key :metabase.util.honeysql-extensions/database-type) (s/constrained - su/NonBlankStringPlumatic + su/NonBlankString (fn [s] (= s (u/lower-case-en s))) "lowercased string")}) @@ -247,7 +247,7 @@ (with-database-type-info :field \"text\") ;; -> #TypedHoneySQLForm{:form :field, :info {::hx/database-type \"text\"}}" {:style/indent [:form]} - [honeysql-form db-type :- (s/maybe su/KeywordOrStringPlumatic)] + [honeysql-form db-type :- (s/maybe su/KeywordOrString)] (if (some? db-type) (with-type-info honeysql-form {:metabase.util.honeysql-extensions/database-type db-type}) (unwrap-typed-honeysql-form honeysql-form))) diff --git a/src/metabase/util/honey_sql_2_extensions.clj b/src/metabase/util/honey_sql_2_extensions.clj index aaeafe7e8f1964cb9fe9d98c7c0afa9efcc1cb72..43ad7f1afb200404e433db4c6602d3b8397a5bbc 100644 --- a/src/metabase/util/honey_sql_2_extensions.clj +++ b/src/metabase/util/honey_sql_2_extensions.clj @@ -9,7 +9,7 @@ [honey.sql :as sql] [metabase.util :as u] [metabase.util.malli :as mu] - [metabase.util.schema :as su] + [metabase.util.malli.schema :as ms] [potemkin.types :as p.types]) (:import (java.util Locale))) @@ -177,7 +177,7 @@ [:metabase.util.honeysql-extensions/database-type {:optional true} [:and - su/NonBlankString + ms/NonBlankString [:fn {:error/message "lowercased string"} (fn [s] @@ -261,7 +261,7 @@ (with-database-type-info :field \"text\") ;; -> #TypedHoneySQLForm{:form :field, :info {::hx/database-type \"text\"}}" {:style/indent [:form]} - [honeysql-form db-type :- [:maybe su/KeywordOrString]] + [honeysql-form db-type :- [:maybe ms/KeywordOrString]] (if (some? db-type) (with-type-info honeysql-form {:metabase.util.honeysql-extensions/database-type db-type}) (unwrap-typed-honeysql-form honeysql-form))) diff --git a/src/metabase/util/malli/schema.clj b/src/metabase/util/malli/schema.clj new file mode 100644 index 0000000000000000000000000000000000000000..ea4dd23d5fe0dec75e4a70cf9cba317cab47cb93 --- /dev/null +++ b/src/metabase/util/malli/schema.clj @@ -0,0 +1,270 @@ +(ns metabase.util.malli.schema + (:require + [cheshire.core :as json] + [malli.core :as mc] + [metabase.mbql.normalize :as mbql.normalize] + [metabase.mbql.schema :as mbql.s] + [metabase.util :as u] + [metabase.util.date-2 :as u.date] + [metabase.util.i18n :as i18n :refer [deferred-tru]] + [metabase.util.password :as u.password] + [schema.core :as s])) + +(def NonBlankString + "Schema for a string that cannot be blank." + (mc/schema + [:string {:min 1}])) + +(def IntGreaterThanOrEqualToZero + "Schema representing an integer than must also be greater than or equal to zero." + (mc/schema + [:int {:min 0}])) + +;; TODO - rename this to `PositiveInt`? +(def IntGreaterThanZero + "Schema representing an integer than must also be greater than zero." + (mc/schema + [:int {:min 1 + :error/fn (constantly (deferred-tru "value must be an integer greater than zero."))}])) + +(def PositiveNum + "Schema representing a numeric value greater than zero. This allows floating point numbers and integers." + (mc/schema + [pos? {:error/fn (constantly (deferred-tru "value must be a number greater than zero."))}])) + +(def KeywordOrString + "Schema for something that can be either a `Keyword` or a `String`." + (mc/schema + [:or {:error/fn (constantly (deferred-tru "value must be a keyword or string."))} + :string :keyword])) + +(def FieldType + "Schema for a valid Field base or effective (data) type (does it derive from `:type/*`)?" + (mc/schema + [:fn {:error/fn (constantly (deferred-tru "value must be a valid field type."))} + #(isa? % :type/*)])) + +(def FieldSemanticType + "Schema for a valid Field semantic type deriving from `:Semantic/*`." + (mc/schema + [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic type."))} + #(isa? % :Semantic/*)])) + +(def FieldRelationType + "Schema for a valid Field relation type deriving from `:Relation/*`" + (mc/schema + [:fn {:error/fn (constantly (deferred-tru "value must be a valid field relation type."))} + #(isa? % :Relation/*)])) + +(def FieldSemanticOrRelationType + "Schema for a valid Field semantic *or* Relation type. This is currently needed because the `semantic_column` is used + to store either the semantic type or relation type info. When this is changed in the future we can get rid of this + schema. See #15486." + (mc/schema + [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic or relation type."))} + (fn [k] (or (isa? k :Semantic/*) (isa? k :Relation/*)))])) + +(def CoercionStrategy + "Schema for a valid Field coercion strategy (does it derive from `:Coercion/*`)?" + (mc/schema + [:fn {:error/fn (constantly (deferred-tru "value must be a valid coercion strategy."))} + #(isa? % :Coercion/*)])) + +(def FieldTypeKeywordOrString + "Like `FieldType` (e.g. a valid derivative of `:type/*`) but allows either a keyword or a string. + This is useful especially for validating API input or objects coming out of the DB as it is unlikely + those values will be encoded as keywords at that point." + (mc/schema + [:fn {:error/fn (constantly (deferred-tru "value must be a valid field data type (keyword or string)."))} + #(isa? (keyword %) :type/*)])) + +(def FieldSemanticTypeKeywordOrString + "Like `FieldSemanticType` but accepts either a keyword or string." + (mc/schema + [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic type (keyword or string)."))} + #(isa? (keyword %) :Semantic/*)])) + +(def FieldRelationTypeKeywordOrString + "Like `FieldRelationType` but accepts either a keyword or string." + (mc/schema + [:fn {:error/fn (constantly (deferred-tru "value must be a valid field relation type (keyword or string)."))} + #(isa? (keyword %) :Relation/*)])) + +(def FieldSemanticOrRelationTypeKeywordOrString + "Like `FieldSemanticOrRelationType` but accepts either a keyword or string." + (mc/schema + [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic or relation type (keyword or string)."))} + (fn [k] + (let [k (keyword k)] + (or (isa? k :Semantic/*) + (isa? k :Relation/*))))])) + +(def Field + "Schema for a valid Field for API usage." + (mc/schema + [:fn {:error/fn (constantly (deferred-tru "value must an array with :field id-or-name and an options map"))} + (fn [k] + ((comp (complement (s/checker mbql.s/Field)) + mbql.normalize/normalize-tokens) k))])) + +(def CoercionStrategyKeywordOrString + "Like `CoercionStrategy` but accepts either a keyword or string." + (mc/schema + [:fn {:error/fn (constantly (deferred-tru "value must be a valid coercion strategy (keyword or string)."))} + #(isa? (keyword %) :Coercion/*)])) + +(def EntityTypeKeywordOrString + "Validates entity type derivatives of `:entity/*`. Allows strings or keywords" + (mc/schema + [:fn {:error/fn (constantly (deferred-tru "value must be a valid entity type (keyword or string)."))} + #(isa? (keyword %) :entity/*)])) + +(def Map + "Schema for a valid map." + (mc/schema + [:map {:error/fn (constantly (deferred-tru "Value must be a map."))}])) + +(def Email + "Schema for a valid email string." + (mc/schema + [:and + :string + [:fn {:error/fn (constantly (deferred-tru "value must be a valid email address."))} + u/email?]])) + +(def ValidPassword + "Schema for a valid password of sufficient complexity which is not found on a common password list." + (mc/schema + [:and + :string + [:fn {:error/fn (constantly (fn [_ _] (deferred-tru "password is too common.")))} + u.password/is-valid?]])) + +(def IntString + "Schema for a string that can be parsed as an integer. + Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`." + (mc/schema + [:and + :string + [:fn {:error/fn (constantly (deferred-tru "value must be a valid integer."))} + #(u/ignore-exceptions (Integer/parseInt %))]])) + +(def IntStringGreaterThanZero + "Schema for a string that can be parsed as an integer, and is greater than zero. + Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`." + (mc/schema + [:and + :string + [:fn {:error/fn (constantly (deferred-tru "value must be a valid integer greater than zero."))} + #(u/ignore-exceptions (< 0 (Integer/parseInt %)))]])) + +(def IntStringGreaterThanOrEqualToZero + "Schema for a string that can be parsed as an integer, and is greater than or equal to zero. + Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`." + (mc/schema + [:and + :string + [:fn {:error/fn (constantly (deferred-tru "value must be a valid integer greater than or equal to zero."))} + #(u/ignore-exceptions (<= 0 (Integer/parseInt %)))]])) + +(def BooleanString + "Schema for a string that is a valid representation of a boolean (either `true` or `false`). + Something that adheres to this schema is guaranteed to to work with `Boolean/parseBoolean`." + (mc/schema + [:enum "true" "false"])) + +(def TemporalString + "Schema for a string that can be parsed by date2/parse." + (mc/schema + [:and + :string + [:fn {:error/fn (constantly (deferred-tru "value must be a valid date string"))} + #(u/ignore-exceptions (boolean (u.date/parse %)))]])) + +(def JSONString + "Schema for a string that is valid serialized JSON." + (mc/schema + [:and + :string + [:fn {:error/fn (constantly (deferred-tru "value must be a valid JSON string."))} + #(try + (json/parse-string %) + true + (catch Throwable _ + false))]])) + +(def ^:private keyword-or-non-blank-str-malli + (mc/schema + [:or :keyword NonBlankString])) + +(def ValuesSourceConfig + "Schema for valid source_options within a Parameter" + ;; TODO: This should be tighter + (mc/schema + [:map + [:values {:optional true} [:* :any]] + [:card_id {:optional true} IntGreaterThanZero] + [:value_field {:optional true} Field] + [:label_field {:optional true} Field]])) + +#_(def ParameterSource + (mc/schema + [:multi {:dispatch :values_source_type} + ["card" [:map + [:values_source_type :string] + [:values_source_config + [:map {:closed true} + [:card_id {:optional true} IntGreaterThanZero] + [:value_field {:optional true} Field] + [:label_field {:optional true} Field]]]]] + ["static-list" [:map + [:values_source_type :string] + [:values_source_config + [:map {:closed true} + [:values {:optional true} [:* :any]]]]]]])) + +(def Parameter + "Schema for a valid Parameter. + We're not using [metabase.mbql.schema/Parameter] here because this Parameter is meant to be used for + Parameters we store on dashboard/card, and it has some difference with Parameter in MBQL." + ;; TODO we could use :multi to dispatch values_source_type to the correct values_source_config + (mc/schema + [:map {:error/fn (constantly (deferred-tru "parameter must be a map with :id and :type keys"))} + [:id NonBlankString] + [:type keyword-or-non-blank-str-malli] + ;; TODO how to merge this with ParameterSource above? + [:values_source_type {:optional true} [:enum "static-list" "card" nil]] + [:values_source_config {:optional true} ValuesSourceConfig] + [:slug {:optional true} :string] + [:name {:optional true} :string] + [:default {:optional true} :any] + [:sectionId {:optional true} NonBlankString]])) + +(def ParameterMapping + "Schema for a valid Parameter Mapping" + (mc/schema + [:map {:error/fn (constantly (deferred-tru "parameter_mapping must be a map with :parameter_id and :target keys"))} + [:parameter_id NonBlankString] + [:target :any] + [:card_id {:optional true} IntGreaterThanZero]])) + +(def EmbeddingParams + "Schema for a valid map of embedding params." + (mc/schema + [:map-of {:error/fn (constantly (deferred-tru "value must be a valid embedding params map."))} + :keyword + [:enum "disabled" "enabled" "locked"]])) + +(def ValidLocale + "Schema for a valid ISO Locale code e.g. `en` or `en-US`. Case-insensitive and allows dashes or underscores." + (mc/schema + [:and + NonBlankString + [:fn {:error/fn (constantly (deferred-tru "String must be a valid two-letter ISO language or language-country code e.g. 'en' or 'en_US'."))} + i18n/available-locale?]])) + +(def NanoIdString + "Schema for a 21-character NanoID string, like \"FReCLx5hSWTBU7kjCWfuu\"." + (mc/schema + [:re {:error/fn (constantly (deferred-tru "String must be a valid 21-character NanoID string."))} + #"^[A-Za-z0-9_\-]{21}$"])) diff --git a/src/metabase/util/schema.clj b/src/metabase/util/schema.clj index 8abb7fa93bcfc4f62ee5bb80a5abc647a58faa34..d36fab91b192c9fa11014fade594365b5d5df002 100644 --- a/src/metabase/util/schema.clj +++ b/src/metabase/util/schema.clj @@ -1,11 +1,13 @@ -(ns metabase.util.schema - "Various schemas that are useful throughout the app." +(ns ^{:deprecated "0.46.0"} metabase.util.schema + "Various schemas that are useful throughout the app. + + Schemas defined are deprecated and should be replaced with Malli schema defined in [[metabase.util.malli.schema]]. + If you update schemas in this ns, please make sure you update the malli schema too. It'll help us makes the transition easier." (:refer-clojure :exclude [distinct]) (:require [cheshire.core :as json] [clojure.string :as str] [clojure.walk :as walk] - [malli.core :as mc] [medley.core :as m] [metabase.mbql.normalize :as mbql.normalize] [metabase.mbql.schema :as mbql.s] @@ -199,98 +201,53 @@ ;;; | USEFUL SCHEMAS | ;;; +----------------------------------------------------------------------------------------------------------------+ -(def NonBlankStringPlumatic +(def NonBlankString "Schema for a string that cannot be blank." (with-api-error-message (s/constrained s/Str (complement str/blank?) "Non-blank string") (deferred-tru "value must be a non-blank string."))) -(def NonBlankString - "Schema for a string that cannot be blank." - (mc/schema - [:string {:min 1}])) - -(def IntGreaterThanOrEqualToZeroPlumatic +(def IntGreaterThanOrEqualToZero "Schema representing an integer than must also be greater than or equal to zero." (with-api-error-message (s/constrained s/Int (partial <= 0) (deferred-tru "Integer greater than or equal to zero")) (deferred-tru "value must be an integer greater than or equal to zero."))) -(def IntGreaterThanOrEqualToZero - "Schema representing an integer than must also be greater than or equal to zero." - (mc/schema - [:int {:min 0}])) - ;; TODO - rename this to `PositiveInt`? -(def IntGreaterThanZeroPlumatic +(def IntGreaterThanZero "Schema representing an integer than must also be greater than zero." (with-api-error-message (s/constrained s/Int (partial < 0) (deferred-tru "Integer greater than zero")) (deferred-tru "value must be an integer greater than zero."))) -(def IntGreaterThanZero - "Schema representing an integer than must also be greater than zero." - (mc/schema - [:int {:min 1 - :error/fn (constantly (deferred-tru "value must be an integer greater than zero."))}])) - -(def PositiveNumPlumatic +(def PositiveNum "Schema representing a numeric value greater than zero. This allows floating point numbers and integers." (with-api-error-message (s/constrained s/Num (partial < 0) (deferred-tru "Number greater than zero")) (deferred-tru "value must be a number greater than zero."))) -(def PositiveNum - "Schema representing a numeric value greater than zero. This allows floating point numbers and integers." - (mc/schema - [pos? {:error/fn (constantly (deferred-tru "value must be a number greater than zero."))}])) - -(def KeywordOrStringPlumatic +(def KeywordOrString "Schema for something that can be either a `Keyword` or a `String`." (with-api-error-message (s/named (s/cond-pre s/Keyword s/Str) (deferred-tru "Keyword or string")) (deferred-tru "value must be a keyword or string."))) -(def KeywordOrString - "Schema for something that can be either a `Keyword` or a `String`." - (mc/schema - [:or {:error/fn (constantly (deferred-tru "value must be a keyword or string."))} - :string :keyword])) - -(def FieldTypePlumatic +(def FieldType "Schema for a valid Field base or effective (data) type (does it derive from `:type/*`)?" (with-api-error-message (s/pred #(isa? % :type/*) (deferred-tru "Valid field type")) (deferred-tru "value must be a valid field type."))) -(def FieldType - "Schema for a valid Field base or effective (data) type (does it derive from `:type/*`)?" - (mc/schema - [:fn {:error/fn (constantly (deferred-tru "value must be a valid field type."))} - #(isa? % :type/*)])) - -(def FieldSemanticTypePlumatic +(def FieldSemanticType "Schema for a valid Field semantic type deriving from `:Semantic/*`." (with-api-error-message (s/pred #(isa? % :Semantic/*) (deferred-tru "Valid field semantic type")) (deferred-tru "value must be a valid field semantic type."))) -(def FieldSemanticType - "Schema for a valid Field semantic type deriving from `:Semantic/*`." - (mc/schema - [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic type."))} - #(isa? % :Semantic/*)])) - -(def FieldRelationTypePlumatic +(def FieldRelationType "Schema for a valid Field relation type deriving from `:Relation/*`" (with-api-error-message (s/pred #(isa? % :Relation/*) (deferred-tru "Valid field relation type")) (deferred-tru "value must be a valid field relation type."))) -(def FieldRelationType - "Schema for a valid Field relation type deriving from `:Relation/*`" - (mc/schema - [:fn {:error/fn (constantly (deferred-tru "value must be a valid field relation type."))} - #(isa? % :Relation/*)])) - -(def FieldSemanticOrRelationTypePlumatic +(def FieldSemanticOrRelationType "Schema for a valid Field semantic *or* Relation type. This is currently needed because the `semantic_column` is used to store either the semantic type or relation type info. When this is changed in the future we can get rid of this schema. See #15486." @@ -300,63 +257,29 @@ (deferred-tru "Valid field semantic or relation type")) (deferred-tru "value must be a valid field semantic or relation type."))) -(def FieldSemanticOrRelationType - "Schema for a valid Field semantic *or* Relation type. This is currently needed because the `semantic_column` is used - to store either the semantic type or relation type info. When this is changed in the future we can get rid of this - schema. See #15486." - (mc/schema - [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic or relation type."))} - (fn [k] (or (isa? k :Semantic/*) (isa? k :Relation/*)))])) - -(def CoercionStrategyPlumatic +(def CoercionStrategy "Schema for a valid Field coercion strategy (does it derive from `:Coercion/*`)?" (with-api-error-message (s/pred #(isa? % :Coercion/*) (deferred-tru "Valid coercion strategy")) (deferred-tru "value must be a valid coercion strategy."))) -(def CoercionStrategy - "Schema for a valid Field coercion strategy (does it derive from `:Coercion/*`)?" - (mc/schema - [:fn {:error/fn (constantly (deferred-tru "value must be a valid coercion strategy."))} - #(isa? % :Coercion/*)])) - -(def FieldTypeKeywordOrStringPlumatic +(def FieldTypeKeywordOrString "Like `FieldType` (e.g. a valid derivative of `:type/*`) but allows either a keyword or a string. This is useful especially for validating API input or objects coming out of the DB as it is unlikely those values will be encoded as keywords at that point." (with-api-error-message (s/pred #(isa? (keyword %) :type/*) (deferred-tru "Valid field data type (keyword or string)")) (deferred-tru "value must be a valid field data type (keyword or string)."))) -(def FieldTypeKeywordOrString - "Like `FieldType` (e.g. a valid derivative of `:type/*`) but allows either a keyword or a string. - This is useful especially for validating API input or objects coming out of the DB as it is unlikely - those values will be encoded as keywords at that point." - (mc/schema - [:fn {:error/fn (constantly (deferred-tru "value must be a valid field data type (keyword or string)."))} - #(isa? (keyword %) :type/*)])) - -(def FieldSemanticTypeKeywordOrStringPlumatic +(def FieldSemanticTypeKeywordOrString "Like `FieldSemanticType` but accepts either a keyword or string." (with-api-error-message (s/pred #(isa? (keyword %) :Semantic/*) (deferred-tru "Valid field semantic type (keyword or string)")) (deferred-tru "value must be a valid field semantic type (keyword or string)."))) -(def FieldSemanticTypeKeywordOrString - "Like `FieldSemanticType` but accepts either a keyword or string." - (mc/schema - [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic type (keyword or string)."))} - #(isa? (keyword %) :Semantic/*)])) - -(def FieldRelationTypeKeywordOrStringPlumatic +(def FieldRelationTypeKeywordOrString "Like `FieldRelationType` but accepts either a keyword or string." (with-api-error-message (s/pred #(isa? (keyword %) :Relation/*) (deferred-tru "Valid field relation type (keyword or string)")) (deferred-tru "value must be a valid field relation type (keyword or string)."))) -(def FieldRelationTypeKeywordOrString - "Like `FieldRelationType` but accepts either a keyword or string." - (mc/schema - [:fn {:error/fn (constantly (deferred-tru "value must be a valid field relation type (keyword or string)."))} - #(isa? (keyword %) :Relation/*)])) - -(def FieldSemanticOrRelationTypeKeywordOrStringPlumatic +(def FieldSemanticOrRelationTypeKeywordOrString "Like `FieldSemanticOrRelationType` but accepts either a keyword or string." (with-api-error-message (s/pred (fn [k] (let [k (keyword k)] @@ -365,167 +288,73 @@ (deferred-tru "Valid field semantic or relation type (keyword or string)")) (deferred-tru "value must be a valid field semantic or relation type (keyword or string)."))) -(def FieldSemanticOrRelationTypeKeywordOrString - "Like `FieldSemanticOrRelationType` but accepts either a keyword or string." - (mc/schema - [:fn {:error/fn (constantly (deferred-tru "value must be a valid field semantic or relation type (keyword or string)."))} - (fn [k] - (let [k (keyword k)] - (or (isa? k :Semantic/*) - (isa? k :Relation/*))))])) - -(def FieldPlumatic +(def Field "Schema for a valid Field for API usage." (with-api-error-message (s/pred (comp (complement (s/checker mbql.s/Field)) mbql.normalize/normalize-tokens)) (deferred-tru "value must an array with :field id-or-name and an options map"))) -(def Field - "Schema for a valid Field for API usage." - (mc/schema - [:fn {:error/fn (constantly (deferred-tru "value must an array with :field id-or-name and an options map"))} - (fn [k] - ((comp (complement (s/checker mbql.s/Field)) - mbql.normalize/normalize-tokens) k))])) - -(def CoercionStrategyKeywordOrStringPlumatic +(def CoercionStrategyKeywordOrString "Like `CoercionStrategy` but accepts either a keyword or string." (with-api-error-message (s/pred #(isa? (keyword %) :Coercion/*) (deferred-tru "Valid coercion strategy")) (deferred-tru "value must be a valid coercion strategy (keyword or string)."))) -(def CoercionStrategyKeywordOrString - "Like `CoercionStrategy` but accepts either a keyword or string." - (mc/schema - [:fn {:error/fn (constantly (deferred-tru "value must be a valid coercion strategy (keyword or string)."))} - #(isa? (keyword %) :Coercion/*)])) - -(def EntityTypeKeywordOrStringPlumatic +(def EntityTypeKeywordOrString "Validates entity type derivatives of `:entity/*`. Allows strings or keywords" (with-api-error-message (s/pred #(isa? (keyword %) :entity/*) (deferred-tru "Valid entity type (keyword or string)")) (deferred-tru "value must be a valid entity type (keyword or string)."))) -(def EntityTypeKeywordOrString - "Validates entity type derivatives of `:entity/*`. Allows strings or keywords" - (mc/schema - [:fn {:error/fn (constantly (deferred-tru "value must be a valid entity type (keyword or string)."))} - #(isa? (keyword %) :entity/*)])) - -(def MapPlumatic +(def Map "Schema for a valid map." (with-api-error-message (s/named clojure.lang.IPersistentMap (deferred-tru "Valid map")) (deferred-tru "value must be a map."))) -(def Map - "Schema for a valid map." - (mc/schema - [:map {:error/fn (constantly (deferred-tru "Value must be a map."))}])) - -(def EmailPlumatic +(def Email "Schema for a valid email string." (with-api-error-message (s/constrained s/Str u/email? (deferred-tru "Valid email address")) (deferred-tru "value must be a valid email address."))) -(def Email - "Schema for a valid email string." - (mc/schema - [:and - :string - [:fn {:error/fn (constantly (deferred-tru "value must be a valid email address."))} - u/email?]])) - -(def ValidPasswordPlumatic +(def ValidPassword "Schema for a valid password of sufficient complexity which is not found on a common password list." (with-api-error-message (s/constrained s/Str u.password/is-valid?) (deferred-tru "password is too common."))) -(def ValidPassword - "Schema for a valid password of sufficient complexity which is not found on a common password list." - (mc/schema - [:and - :string - [:fn {:error/fn (constantly (fn [_ _] (deferred-tru "password is too common.")))} - u.password/is-valid?]])) - -(def IntStringPlumatic +(def IntString "Schema for a string that can be parsed as an integer. Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`." (with-api-error-message (s/constrained s/Str #(u/ignore-exceptions (Integer/parseInt %))) (deferred-tru "value must be a valid integer."))) -(def IntString - "Schema for a string that can be parsed as an integer. - Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`." - (mc/schema - [:and - :string - [:fn {:error/fn (constantly (deferred-tru "value must be a valid integer."))} - #(u/ignore-exceptions (Integer/parseInt %))]])) - -(def IntStringGreaterThanZeroPlumatic +(def IntStringGreaterThanZero "Schema for a string that can be parsed as an integer, and is greater than zero. Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`." (with-api-error-message (s/constrained s/Str #(u/ignore-exceptions (< 0 (Integer/parseInt %)))) (deferred-tru "value must be a valid integer greater than zero."))) -(def IntStringGreaterThanZero - "Schema for a string that can be parsed as an integer, and is greater than zero. - Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`." - (mc/schema - [:and - :string - [:fn {:error/fn (constantly (deferred-tru "value must be a valid integer greater than zero."))} - #(u/ignore-exceptions (< 0 (Integer/parseInt %)))]])) - -(def IntStringGreaterThanOrEqualToZeroPlumatic +(def IntStringGreaterThanOrEqualToZero "Schema for a string that can be parsed as an integer, and is greater than or equal to zero. Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`." (with-api-error-message (s/constrained s/Str #(u/ignore-exceptions (<= 0 (Integer/parseInt %)))) (deferred-tru "value must be a valid integer greater than or equal to zero."))) -(def IntStringGreaterThanOrEqualToZero - "Schema for a string that can be parsed as an integer, and is greater than or equal to zero. - Something that adheres to this schema is guaranteed to to work with `Integer/parseInt`." - (mc/schema - [:and - :string - [:fn {:error/fn (constantly (deferred-tru "value must be a valid integer greater than or equal to zero."))} - #(u/ignore-exceptions (<= 0 (Integer/parseInt %)))]])) - (defn- boolean-string? ^Boolean [s] (boolean (when (string? s) (let [s (u/lower-case-en s)] (contains? #{"true" "false"} s))))) -(def BooleanStringPlumatic +(def BooleanString "Schema for a string that is a valid representation of a boolean (either `true` or `false`). Something that adheres to this schema is guaranteed to to work with `Boolean/parseBoolean`." (with-api-error-message (s/constrained s/Str boolean-string?) (deferred-tru "value must be a valid boolean string (''true'' or ''false'')."))) -(def BooleanString - "Schema for a string that is a valid representation of a boolean (either `true` or `false`). - Something that adheres to this schema is guaranteed to to work with `Boolean/parseBoolean`." - (mc/schema - [:and - :string - [:fn {:error/fn (constantly (deferred-tru "value must be a valid boolean string (''true'' or ''false'')."))} - boolean-string?]])) - -(def TemporalStringPlumatic +(def TemporalString "Schema for a string that can be parsed by date2/parse." (with-api-error-message (s/constrained s/Str #(u/ignore-exceptions (boolean (u.date/parse %)))) (deferred-tru "value must be a valid date string"))) -(def TemporalString - "Schema for a string that can be parsed by date2/parse." - (mc/schema - [:and - :string - [:fn {:error/fn (constantly (deferred-tru "value must be a valid date string"))} - #(u/ignore-exceptions (boolean (u.date/parse %)))]])) - -(def JSONStringPlumatic +(def JSONString "Schema for a string that is valid serialized JSON." (with-api-error-message (s/constrained s/Str #(try (json/parse-string %) @@ -534,145 +363,58 @@ false))) (deferred-tru "value must be a valid JSON string."))) -(def JSONString - "Schema for a string that is valid serialized JSON." - (mc/schema - [:and - :string - [:fn {:error/fn (constantly (deferred-tru "value must be a valid JSON string."))} - #(try - (json/parse-string %) - true - (catch Throwable _ - false))]])) - (def ^:private keyword-or-non-blank-str (s/conditional - string? NonBlankStringPlumatic + string? NonBlankString keyword? s/Keyword)) -(def ^:private keyword-or-non-blank-str-malli - (mc/schema - [:or :keyword NonBlankString])) - -(def ValuesSourceConfigPlumatic +(def ValuesSourceConfig "Schema for valid source_options within a Parameter" ;; TODO: This should be tighter {;; for source_type = 'static-list' (s/optional-key :values) (s/cond-pre [s/Any]) ;; for source_type = 'card' - (s/optional-key :card_id) IntGreaterThanZeroPlumatic - (s/optional-key :value_field) FieldPlumatic + (s/optional-key :card_id) IntGreaterThanZero + (s/optional-key :value_field) Field ;; label_field is optional - (s/optional-key :label_field) FieldPlumatic}) + (s/optional-key :label_field) Field}) -(def ValuesSourceConfig - "Schema for valid source_options within a Parameter" - (mc/schema - [:map - [:values {:optional true} [:* :any]] - [:card_id {:optional true} IntGreaterThanZero] - [:value_field {:optional true} Field] - [:label_field {:optional true} Field]])) - -(def ParameterPlumatic +(def Parameter "Schema for a valid Parameter. We're not using [metabase.mbql.schema/Parameter] here because this Parameter is meant to be used for Parameters we store on dashboard/card, and it has some difference with Parameter in MBQL." - (with-api-error-message {:id NonBlankStringPlumatic + (with-api-error-message {:id NonBlankString :type keyword-or-non-blank-str (s/optional-key :values_source_type) (s/enum "static-list" "card" nil) - (s/optional-key :values_source_config) ValuesSourceConfigPlumatic + (s/optional-key :values_source_config) ValuesSourceConfig ;; Allow blank name and slug #15279 (s/optional-key :slug) s/Str (s/optional-key :name) s/Str (s/optional-key :default) s/Any - (s/optional-key :sectionId) NonBlankStringPlumatic + (s/optional-key :sectionId) NonBlankString s/Keyword s/Any} (deferred-tru "parameter must be a map with :id and :type keys"))) -#_(def ParameterSource - (mc/schema - [:multi {:dispatch :values_source_type} - ["card" [:map - [:values_source_type :string] - [:values_source_config - [:map {:closed true} - [:card_id {:optional true} IntGreaterThanZero] - [:value_field {:optional true} Field] - [:label_field {:optional true} Field]]]]] - ["static-list" [:map - [:values_source_type :string] - [:values_source_config - [:map {:closed true} - [:values {:optional true} [:* :any]]]]]]])) - -(def Parameter - "Schema for a valid Parameter. - We're not using [metabase.mbql.schema/Parameter] here because this Parameter is meant to be used for - Parameters we store on dashboard/card, and it has some difference with Parameter in MBQL." - ;; TODO we could use :multi to dispatch values_source_type to the correct values_source_config - (mc/schema - [:map {:error/fn (constantly (deferred-tru "parameter must be a map with :id and :type keys"))} - [:id NonBlankString] - [:type keyword-or-non-blank-str-malli] - ;; TODO how to merge this with ParameterSource above? - [:values_source_type {:optional true} [:enum "static-list" "card" nil]] - [:values_source_config {:optional true} ValuesSourceConfig] - [:slug {:optional true} :string] - [:name {:optional true} :string] - [:default {:optional true} :any] - [:sectionId {:optional true} NonBlankString]])) - -(def ParameterMappingPlumatic +(def ParameterMapping "Schema for a valid Parameter Mapping" - (with-api-error-message {:parameter_id NonBlankStringPlumatic + (with-api-error-message {:parameter_id NonBlankString :target s/Any - (s/optional-key :card_id) IntGreaterThanZeroPlumatic + (s/optional-key :card_id) IntGreaterThanZero s/Keyword s/Any} (deferred-tru "parameter_mapping must be a map with :parameter_id and :target keys"))) -(def ParameterMapping - "Schema for a valid Parameter Mapping" - (mc/schema - [:map {:error/fn (constantly (deferred-tru "parameter_mapping must be a map with :parameter_id and :target keys"))} - [:parameter_id NonBlankString] - [:target :any] - [:card_id {:optional true} IntGreaterThanZero]])) - -(def EmbeddingParamsPlumatic +(def EmbeddingParams "Schema for a valid map of embedding params." (with-api-error-message (s/maybe {s/Keyword (s/enum "disabled" "enabled" "locked")}) (deferred-tru "value must be a valid embedding params map."))) -(def EmbeddingParams - "Schema for a valid map of embedding params." - (mc/schema - [:map-of {:error/fn (constantly (deferred-tru "value must be a valid embedding params map."))} - :keyword - [:enum "disabled" "enabled" "locked"]])) - -(def ValidLocalePlumatic - "Schema for a valid ISO Locale code e.g. `en` or `en-US`. Case-insensitive and allows dashes or underscores." - (with-api-error-message (s/constrained NonBlankStringPlumatic i18n/available-locale?) - (deferred-tru "String must be a valid two-letter ISO language or language-country code e.g. 'en' or 'en_US'."))) - (def ValidLocale "Schema for a valid ISO Locale code e.g. `en` or `en-US`. Case-insensitive and allows dashes or underscores." - (mc/schema - [:and - NonBlankString - [:fn {:error/fn (constantly (deferred-tru "String must be a valid two-letter ISO language or language-country code e.g. 'en' or 'en_US'."))} - i18n/available-locale?]])) + (with-api-error-message (s/constrained NonBlankString i18n/available-locale?) + (deferred-tru "String must be a valid two-letter ISO language or language-country code e.g. 'en' or 'en_US'."))) -(def NanoIdStringPlumatic +(def NanoIdString "Schema for a 21-character NanoID string, like \"FReCLx5hSWTBU7kjCWfuu\"." (with-api-error-message #"^[A-Za-z0-9_\-]{21}$" (deferred-tru "String must be a valid 21-character NanoID string."))) - -(def NanoIdString - "Schema for a 21-character NanoID string, like \"FReCLx5hSWTBU7kjCWfuu\"." - (mc/schema - [:re {:error/fn (constantly (deferred-tru "String must be a valid 21-character NanoID string."))} - #"^[A-Za-z0-9_\-]{21}$"])) diff --git a/test/metabase/actions_test.clj b/test/metabase/actions_test.clj index 17bbae1015cf1dd562c808722e5f8050f2bc7a84..546f9351ddf58424ea4d1203b3974958be31427f 100644 --- a/test/metabase/actions_test.clj +++ b/test/metabase/actions_test.clj @@ -110,8 +110,8 @@ :request-body (assoc (mt/mbql-query categories) :create-row {(format-field-name :name) "created_row"}) :expect-fn (fn [result] ;; check that we return the entire row - (is (schema= {:created-row {(format-field-name :id) su/IntGreaterThanZeroPlumatic - (format-field-name :name) su/NonBlankStringPlumatic}} + (is (schema= {:created-row {(format-field-name :id) su/IntGreaterThanZero + (format-field-name :name) su/NonBlankString}} result)))} {:action :row/update :request-body (assoc (mt/mbql-query categories {:filter [:= $id 1]}) diff --git a/test/metabase/analytics/stats_test.clj b/test/metabase/analytics/stats_test.clj index 21e9e802b20f662e0d5a347443dbd74bacc6edb0..bfce9779514bf0f31310768852a8e8d75ebec4d0 100644 --- a/test/metabase/analytics/stats_test.clj +++ b/test/metabase/analytics/stats_test.clj @@ -69,7 +69,7 @@ "10000+" 100000)) (def DBMSVersionStats - {s/Str su/IntGreaterThanOrEqualToZeroPlumatic}) + {s/Str su/IntGreaterThanOrEqualToZero}) (deftest anonymous-usage-stats-test (with-redefs [email/email-configured? (constantly false) diff --git a/test/metabase/api/action_test.clj b/test/metabase/api/action_test.clj index 4702fb914e691dee02931ae640cb73b3e562935d..ed2f7bf9d24aad284eaffa229fc4596ab304bf36 100644 --- a/test/metabase/api/action_test.clj +++ b/test/metabase/api/action_test.clj @@ -13,18 +13,18 @@ (def ^:private ExpectedGetQueryActionAPIResponse "Expected schema for a query action as it should appear in the response for an API request to one of the GET endpoints." - {:id su/IntGreaterThanOrEqualToZeroPlumatic + {:id su/IntGreaterThanOrEqualToZero :type (s/eq "query") - :model_id su/IntGreaterThanOrEqualToZeroPlumatic - :database_id su/IntGreaterThanOrEqualToZeroPlumatic - :dataset_query {:database su/IntGreaterThanOrEqualToZeroPlumatic + :model_id su/IntGreaterThanOrEqualToZero + :database_id su/IntGreaterThanOrEqualToZero + :dataset_query {:database su/IntGreaterThanOrEqualToZero :type (s/eq "native") :native {:query s/Str s/Keyword s/Any} s/Keyword s/Any} :parameters s/Any :parameter_mappings s/Any - :visualization_settings su/MapPlumatic + :visualization_settings su/Map s/Keyword s/Any}) (deftest list-actions-test diff --git a/test/metabase/api/card_test.clj b/test/metabase/api/card_test.clj index 5788d132f8e2ed5dc4268e79765178585a8e01d3..e9067d7da572ee361b7910be13b9e4bb2034b9c3 100644 --- a/test/metabase/api/card_test.clj +++ b/test/metabase/api/card_test.clj @@ -499,7 +499,7 @@ (testing query-description (mt/with-model-cleanup [Card] (testing "without result metadata" - (is (schema= {:id su/IntGreaterThanZeroPlumatic + (is (schema= {:id su/IntGreaterThanZero s/Keyword s/Any} (mt/user-http-request :rasta :post 200 "card" (merge (mt/with-temp-defaults Card) @@ -510,7 +510,7 @@ :columns)] (testing (format "with result metadata\n%s" (u/pprint-to-str metadata)) (is (some? metadata)) - (is (schema= {:id su/IntGreaterThanZeroPlumatic + (is (schema= {:id su/IntGreaterThanZero s/Keyword s/Any} (mt/user-http-request :rasta :post 200 "card" (merge (mt/with-temp-defaults Card) @@ -521,7 +521,7 @@ (testing "we should be able to save a Card if the `result_metadata` is *empty* (but not nil) (#9286)" (mt/with-model-cleanup [Card] (let [card (card-with-name-and-query)] - (is (schema= {:id su/IntGreaterThanZeroPlumatic, s/Keyword s/Any} + (is (schema= {:id su/IntGreaterThanZero, s/Keyword s/Any} (mt/user-http-request :rasta :post 200 diff --git a/test/metabase/api/collection_test.clj b/test/metabase/api/collection_test.clj index 53f489b9e5620087579639b2452f32c488667d59..95696bb44407f4012d840d93fe5bf278751ec49b 100644 --- a/test/metabase/api/collection_test.clj +++ b/test/metabase/api/collection_test.clj @@ -1349,7 +1349,7 @@ :authority_level (s/eq "official") :id s/Int :location (s/eq "/") - :entity_id (s/maybe su/NanoIdStringPlumatic) + :entity_id (s/maybe su/NanoIdString) :namespace (s/eq nil) :created_at java.time.temporal.Temporal} (mt/user-http-request :crowberto :post 200 "collection" diff --git a/test/metabase/api/database_test.clj b/test/metabase/api/database_test.clj index 6b1970bbeb5bb725cd563d6680f4df16114884c6..75ec9eacf039751565d8af5a260dedc74e742b76 100644 --- a/test/metabase/api/database_test.clj +++ b/test/metabase/api/database_test.clj @@ -180,10 +180,10 @@ :cache_field_values_schedule #"0 \d{1,2} \d{1,2} \* \* \? \*"} {:created_at java.time.temporal.Temporal :engine (s/eq ::test-driver) - :id su/IntGreaterThanZeroPlumatic + :id su/IntGreaterThanZero :details (s/eq {:db "my_db"}) :updated_at java.time.temporal.Temporal - :name su/NonBlankStringPlumatic + :name su/NonBlankString :features (s/eq (driver.u/features ::test-driver (mt/db))) :creator_id (s/eq (mt/user->id :crowberto))}) (create-db-via-api!)))) @@ -659,7 +659,7 @@ :moderated_status (s/enum nil "verified") :schema s/Str ; collection name :description (s/maybe s/Str) - :fields [su/MapPlumatic]}]} + :fields [su/Map]}]} response)) (check-tables-included response diff --git a/test/metabase/api/dataset_test.clj b/test/metabase/api/dataset_test.clj index 1d1c5f21bc5c367fdd68d69c60d991fc66af364e..4cc8512e87486fb6b575fa4ecf68c534f67963fd 100644 --- a/test/metabase/api/dataset_test.clj +++ b/test/metabase/api/dataset_test.clj @@ -139,7 +139,7 @@ (testing "\nSaved QueryExecution" (is (schema= {:hash (Class/forName "[B") - :id su/IntGreaterThanZeroPlumatic + :id su/IntGreaterThanZero :result_rows (s/eq 0) :row_count (s/eq 0) :context (s/eq :ad-hoc) diff --git a/test/metabase/api/geojson_test.clj b/test/metabase/api/geojson_test.clj index 02c2f95a4521f8232cb5be35d66712321d70d5d7..b997d0c112ecb11afbe7720521a241ea67a2b0ad 100644 --- a/test/metabase/api/geojson_test.clj +++ b/test/metabase/api/geojson_test.clj @@ -188,7 +188,7 @@ :value (s/eq nil) :is_env_setting (s/eq true) :env_name (s/eq "MB_CUSTOM_GEOJSON") - :description su/NonBlankStringPlumatic + :description su/NonBlankString :default (s/eq "Using value of env var $MB_CUSTOM_GEOJSON") s/Keyword s/Any} (some diff --git a/test/metabase/api/native_query_snippet_test.clj b/test/metabase/api/native_query_snippet_test.clj index e003ff7c801033ce6b595254e96b7e7081d90ecc..d6ad35356fa21e9697d5f9fb8e97a4cb4525025c 100644 --- a/test/metabase/api/native_query_snippet_test.clj +++ b/test/metabase/api/native_query_snippet_test.clj @@ -74,7 +74,7 @@ (try (let [snippet-input {:name "test-snippet", :description "Just null", :content "NULL"} snippet-from-api (mt/user-http-request user :post 200 (snippet-url) snippet-input)] - (is (schema= {:id su/IntGreaterThanZeroPlumatic + (is (schema= {:id su/IntGreaterThanZero :name (s/eq "test-snippet") :description (s/eq "Just null") :content (s/eq "NULL") diff --git a/test/metabase/api/permissions_test.clj b/test/metabase/api/permissions_test.clj index 8a4de348d4cf0026ebb63ec64097fb28968f0b70..e050d58ea84aa6518cc45167ae4bd1139d006f22 100644 --- a/test/metabase/api/permissions_test.clj +++ b/test/metabase/api/permissions_test.clj @@ -37,12 +37,12 @@ (testing "All Users Group should be returned" (is (schema= {:id (s/eq (:id (perms-group/all-users))) :name (s/eq "All Users") - :member_count su/IntGreaterThanZeroPlumatic} + :member_count su/IntGreaterThanZero} (get id->group (:id (perms-group/all-users)))))) (testing "Administrators Group should be returned" (is (schema= {:id (s/eq (:id (perms-group/admin))) :name (s/eq "Administrators") - :member_count su/IntGreaterThanZeroPlumatic} + :member_count su/IntGreaterThanZero} (get id->group (:id (perms-group/admin)))))))] (let [id->group (m/index-by :id (fetch-groups))] (check-default-groups-returned id->group)) @@ -52,8 +52,8 @@ (let [id->group (m/index-by :id (fetch-groups))] (check-default-groups-returned id->group) (testing "empty group should be returned" - (is (schema= {:id su/IntGreaterThanZeroPlumatic - :name su/NonBlankStringPlumatic + (is (schema= {:id su/IntGreaterThanZero + :name su/NonBlankString :member_count (s/eq 0)} (get id->group (:id group))))))))) (testing "requires superuser" @@ -80,19 +80,19 @@ :last_name (s/eq "Corv") :email (s/eq "crowberto@metabase.com") :user_id (s/eq (mt/user->id :crowberto)) - :membership_id su/IntGreaterThanZeroPlumatic} + :membership_id su/IntGreaterThanZero} (get id->member (mt/user->id :crowberto)))) (is (schema= {:first_name (s/eq "Lucky") :last_name (s/eq "Pigeon") :email (s/eq "lucky@metabase.com") :user_id (s/eq (mt/user->id :lucky)) - :membership_id su/IntGreaterThanZeroPlumatic} + :membership_id su/IntGreaterThanZero} (get id->member (mt/user->id :lucky)))) (is (schema= {:first_name (s/eq "Rasta") :last_name (s/eq "Toucan") :email (s/eq "rasta@metabase.com") :user_id (s/eq (mt/user->id :rasta)) - :membership_id su/IntGreaterThanZeroPlumatic} + :membership_id su/IntGreaterThanZero} (get id->member (mt/user->id :rasta)))) (testing "Should *not* include inactive users" (is (= nil @@ -251,10 +251,10 @@ (testing "Return a graph of membership" (let [result (mt/user-http-request :crowberto :get 200 "permissions/membership")] - (is (schema= {su/IntGreaterThanZeroPlumatic - [{:membership_id su/IntGreaterThanZeroPlumatic - :group_id su/IntGreaterThanZeroPlumatic - :user_id su/IntGreaterThanZeroPlumatic + (is (schema= {su/IntGreaterThanZero + [{:membership_id su/IntGreaterThanZero + :group_id su/IntGreaterThanZero + :user_id su/IntGreaterThanZero :is_group_manager s/Bool}]} result)) (is (= (db/select-field :id 'User) (set (keys result)))))))) diff --git a/test/metabase/api/session_test.clj b/test/metabase/api/session_test.clj index 02fb0a9f0b86c8d7ef60830582246152ce56992d..dd222888c0f345dfae35262ed3613d8668422fe5 100644 --- a/test/metabase/api/session_test.clj +++ b/test/metabase/api/session_test.clj @@ -55,12 +55,12 @@ (is (schema= SessionResponse response)) (testing "Login should record a LoginHistory item" - (is (schema= {:id su/IntGreaterThanZeroPlumatic + (is (schema= {:id su/IntGreaterThanZero :timestamp java.time.OffsetDateTime :user_id (s/eq (mt/user->id :rasta)) :device_id client/UUIDString - :device_description su/NonBlankStringPlumatic - :ip_address su/NonBlankStringPlumatic + :device_description su/NonBlankString + :ip_address su/NonBlankString :active (s/eq true) s/Keyword s/Any} (db/select-one LoginHistory :user_id (mt/user->id :rasta), :session_id (:id response))))))) @@ -210,8 +210,8 @@ :timestamp java.time.OffsetDateTime :user_id (s/eq (mt/user->id :rasta)) :device_id client/UUIDString - :device_description su/NonBlankStringPlumatic - :ip_address su/NonBlankStringPlumatic + :device_description su/NonBlankString + :ip_address su/NonBlankString :active (s/eq false) s/Keyword s/Any} (db/select-one LoginHistory :id login-history-id)))))))) diff --git a/test/metabase/api/setup_test.clj b/test/metabase/api/setup_test.clj index c4142742b2ab2333802f6b4e57006f838ff226f3..eeda71a228ea4ed93110f628e327a587b1c0cfb7 100644 --- a/test/metabase/api/setup_test.clj +++ b/test/metabase/api/setup_test.clj @@ -190,7 +190,7 @@ :details (:details (mt/db))}} (testing ":database-create events should have been fired" (is (schema= {:topic (schema/eq :database-create) - :item {:id su/IntGreaterThanZeroPlumatic + :item {:id su/IntGreaterThanZero :name (schema/eq db-name) schema/Keyword schema/Any}} (mt/wait-for-result chan 100)))) diff --git a/test/metabase/driver/common/parameters/values_test.clj b/test/metabase/driver/common/parameters/values_test.clj index eb8b55196aadd79b7eb4fec4e13b1179aaae2e9a..e273400e16f87ef02e23a3a0c6a4d85fb51ddbc4 100644 --- a/test/metabase/driver/common/parameters/values_test.clj +++ b/test/metabase/driver/common/parameters/values_test.clj @@ -529,7 +529,7 @@ :breakout [!month.created_at]})}] (let [card-tag (str "#" (u/the-id card))] (is (schema= {:card-id (s/eq (u/the-id card)) - :query su/NonBlankStringPlumatic + :query su/NonBlankString :params (s/eq ["G%"]) s/Keyword s/Any} (#'params.values/parse-tag diff --git a/test/metabase/driver/sql/parameters/substitute_test.clj b/test/metabase/driver/sql/parameters/substitute_test.clj index 0b883b3e060d71d7b18d00774402700830184719..3c2039e3c40a400ae62000423c9ff1b473e8d325 100644 --- a/test/metabase/driver/sql/parameters/substitute_test.clj +++ b/test/metabase/driver/sql/parameters/substitute_test.clj @@ -519,7 +519,7 @@ ;;; -------------------------------------------- "REAL" END-TO-END-TESTS --------------------------------------------- -(s/defn ^:private checkins-identifier :- su/NonBlankStringPlumatic +(s/defn ^:private checkins-identifier :- su/NonBlankString "Get the identifier used for `checkins` for the current driver by looking at what the driver uses when converting MBQL to SQL. Different drivers qualify to different degrees (i.e. `table` vs `schema.table` vs `database.schema.table`)." [] diff --git a/test/metabase/driver/sql_jdbc/native_test.clj b/test/metabase/driver/sql_jdbc/native_test.clj index 6d6e13eb207b929dbce090eca6813233e71b5f55..0f49828f1ec568645f2111b09ccea4d3aabd61c1 100644 --- a/test/metabase/driver/sql_jdbc/native_test.clj +++ b/test/metabase/driver/sql_jdbc/native_test.clj @@ -67,7 +67,7 @@ (is (schema= {:status (s/eq :failed) :class (s/eq org.h2.jdbc.JdbcSQLSyntaxErrorException) :error #"^Column \"ZID\" not found" - :stacktrace [su/NonBlankStringPlumatic] + :stacktrace [su/NonBlankString] :json_query {:native {:query (s/eq "SELECT ZID FROM CHECKINS LIMIT 2")} :type (s/eq :native) s/Keyword s/Any} diff --git a/test/metabase/http_client.clj b/test/metabase/http_client.clj index ba08bcc41b0a06ea9d632ae227604089e9ccea52..4a402c157e5144791b003da4cd8ca3bb7943c99f 100644 --- a/test/metabase/http_client.clj +++ b/test/metabase/http_client.clj @@ -105,12 +105,12 @@ (declare client) (def ^:private Credentials - {:username su/NonBlankStringPlumatic, :password su/NonBlankStringPlumatic}) + {:username su/NonBlankString, :password su/NonBlankString}) (def UUIDString "Schema for a canonical string representation of a UUID." (schema/constrained - su/NonBlankStringPlumatic + su/NonBlankString (partial re-matches #"^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$"))) (schema/defn authenticate :- UUIDString @@ -179,15 +179,15 @@ (def ^:private ClientParamsMap {(schema/optional-key :credentials) (schema/maybe (schema/cond-pre UUIDString Credentials)) :method (apply schema/enum (keys method->request-fn)) - (schema/optional-key :expected-status) (schema/maybe su/IntGreaterThanZeroPlumatic) - :url su/NonBlankStringPlumatic + (schema/optional-key :expected-status) (schema/maybe su/IntGreaterThanZero) + :url su/NonBlankString ;; body can be either a map or a vector -- we encode it as JSON. Of course, other things are valid JSON as well, but ;; currently none of our endpoints accept them -- add them if needed. (schema/optional-key :http-body) (schema/cond-pre - (schema/maybe su/MapPlumatic) + (schema/maybe su/Map) (schema/maybe clojure.lang.IPersistentVector)) - (schema/optional-key :query-parameters) (schema/maybe su/MapPlumatic) - (schema/optional-key :request-options) (schema/maybe su/MapPlumatic)}) + (schema/optional-key :query-parameters) (schema/maybe su/Map) + (schema/optional-key :request-options) (schema/maybe su/Map)}) (schema/defn ^:private -client ;; Since the params for this function can get a little complicated make sure we validate them diff --git a/test/metabase/models/collection/graph_test.clj b/test/metabase/models/collection/graph_test.clj index dc25ace37c5ee8371ad60c9d9a227868abaeec52..8d9c5d87df9edd0b17323e97f8af9828445ab1f1 100644 --- a/test/metabase/models/collection/graph_test.clj +++ b/test/metabase/models/collection/graph_test.clj @@ -339,7 +339,7 @@ (nice-graph (graph/graph :currency))))) (testing "A CollectionPermissionGraphRevision recording the *changes* to the perms graph should be saved." - (is (schema= {:id su/IntGreaterThanZeroPlumatic + (is (schema= {:id su/IntGreaterThanZero :before (s/eq (mt/obj->json->obj (assoc before :namespace nil))) :after (s/eq {(keyword (str group-id)) {(keyword (str default-ab)) "write"}}) :user_id (s/eq (mt/user->id :crowberto)) @@ -358,7 +358,7 @@ (nice-graph (graph/graph))))) (testing "A CollectionPermissionGraphRevision recording the *changes* to the perms graph should be saved." - (is (schema= {:id su/IntGreaterThanZeroPlumatic + (is (schema= {:id su/IntGreaterThanZero :before (s/eq (mt/obj->json->obj (assoc before :namespace "currency"))) :after (s/eq {(keyword (str group-id)) {(keyword (str currency-a)) "write"}}) :user_id (s/eq (mt/user->id :crowberto)) diff --git a/test/metabase/models/collection_test.clj b/test/metabase/models/collection_test.clj index dbeb58301ac3dd3bd15b262fda6646360427dd9a..3093835c580cdb73b5f118081da7469d8607e428 100644 --- a/test/metabase/models/collection_test.clj +++ b/test/metabase/models/collection_test.clj @@ -1252,7 +1252,7 @@ (testing "Does hydrating `:personal_collection_id` force creation of Personal Collections?" (mt/with-temp User [temp-user] - (is (schema= {:personal_collection_id su/IntGreaterThanZeroPlumatic + (is (schema= {:personal_collection_id su/IntGreaterThanZero s/Keyword s/Any} (hydrate temp-user :personal_collection_id)))))) diff --git a/test/metabase/models/login_history_test.clj b/test/metabase/models/login_history_test.clj index 76da5d044cbf824af3bb40d46b939028022ff8f7..32e8d675c0c6e660585952404b75617509d86047 100644 --- a/test/metabase/models/login_history_test.clj +++ b/test/metabase/models/login_history_test.clj @@ -62,7 +62,7 @@ :timestamp #t "2021-04-02T15:52:00-07:00[US/Pacific]"}]] (is (schema= {(s/eq email) - [{:from su/EmailPlumatic + [{:from su/Email :to (s/eq [email]) :subject (s/eq (format "We've Noticed a New Metabase Login, %s" first-name)) :body [(s/one {:type (s/eq "text/html; charset=utf-8") diff --git a/test/metabase/models/permissions_group_test.clj b/test/metabase/models/permissions_group_test.clj index 254c5033d84d17e3d8c7a267c07f67c67ec62ab4..4474509c9fad34105e681a575d495ec5709cde24 100644 --- a/test/metabase/models/permissions_group_test.clj +++ b/test/metabase/models/permissions_group_test.clj @@ -70,7 +70,7 @@ (s/defn ^:private group-has-full-access? "Does a group have permissions for `object` and *all* of its children?" - [group-id :- su/IntGreaterThanOrEqualToZeroPlumatic object :- perms/Path] + [group-id :- su/IntGreaterThanOrEqualToZero object :- perms/Path] ;; e.g. WHERE (object || '%') LIKE '/db/1000/' (db/exists? Permissions :group_id group-id diff --git a/test/metabase/query_processor/middleware/parameters/native_test.clj b/test/metabase/query_processor/middleware/parameters/native_test.clj index 06bd645b16fa6a5addbf0eedc50ceefc5e753025..d81062e5550584e2b8d4c5efa279a517ed163808 100644 --- a/test/metabase/query_processor/middleware/parameters/native_test.clj +++ b/test/metabase/query_processor/middleware/parameters/native_test.clj @@ -27,7 +27,7 @@ :type :card :card-id (u/the-id card)}}}] (binding [driver/*driver* :h2] - (is (schema= {:native su/NonBlankStringPlumatic + (is (schema= {:native su/NonBlankString :params (s/eq ["G%"]) s/Keyword s/Any} (qp.native/expand-inner query))))))))) diff --git a/test/metabase/query_processor/middleware/parameters_test.clj b/test/metabase/query_processor/middleware/parameters_test.clj index 3b9cc1fd4c4c14b8857392834e36fa7f54c40c80..3c2b6a48bbde3b4982a30f7d8a3590f2e35d41c5 100644 --- a/test/metabase/query_processor/middleware/parameters_test.clj +++ b/test/metabase/query_processor/middleware/parameters_test.clj @@ -303,7 +303,7 @@ :display-name card-tag :type :card :card-id (u/the-id card)}}})] - (is (schema= {:native {:query su/NonBlankStringPlumatic + (is (schema= {:native {:query su/NonBlankString :params (s/eq ["G%"]) s/Keyword s/Any} s/Keyword s/Any} diff --git a/test/metabase/query_processor/test_util.clj b/test/metabase/query_processor/test_util.clj index 847029ab22d2728c1cf44a348c7f5eeec663e492..fa4dcfbff88e4d42e48d9975a6eddaf8035e28a1 100644 --- a/test/metabase/query_processor/test_util.clj +++ b/test/metabase/query_processor/test_util.clj @@ -24,7 +24,7 @@ ;; TODO - I don't think we different QP test util namespaces? We should roll this namespace into ;; `metabase.query-processor-test` -(s/defn ^:private everything-store-table [table-id :- (s/maybe su/IntGreaterThanZeroPlumatic)] +(s/defn ^:private everything-store-table [table-id :- (s/maybe su/IntGreaterThanZero)] (assert (= (:id (qp.store/database)) (data/id)) "with-everything-store currently does not support switching drivers. Make sure you call with-driver *before* with-everything-store.") (or (get-in @@#'qp.store/*store* [:tables table-id]) @@ -32,7 +32,7 @@ (qp.store/fetch-and-store-tables! [table-id]) (qp.store/table table-id)))) -(s/defn ^:private everything-store-field [field-id :- (s/maybe su/IntGreaterThanZeroPlumatic)] +(s/defn ^:private everything-store-field [field-id :- (s/maybe su/IntGreaterThanZero)] (assert (= (:id (qp.store/database)) (data/id)) "with-everything-store currently does not support switching drivers. Make sure you call with-driver *before* with-everything-store.") (or (get-in @@#'qp.store/*store* [:fields field-id]) diff --git a/test/metabase/query_processor_test/failure_test.clj b/test/metabase/query_processor_test/failure_test.clj index 54271260d7663edcc6600cc47d064262cfb26637..bceaa03abe6749cbb0ea372c3ecf68b5a08a4f27 100644 --- a/test/metabase/query_processor_test/failure_test.clj +++ b/test/metabase/query_processor_test/failure_test.clj @@ -45,7 +45,7 @@ (is (schema= {:status (s/eq :failed) :class Class :error s/Str - :stacktrace [su/NonBlankStringPlumatic] + :stacktrace [su/NonBlankString] ;; `:database` is removed by the catch-exceptions middleware for historical reasons :json_query (bad-query-schema) :preprocessed (bad-query-preprocessed-schema) @@ -61,9 +61,9 @@ :native bad-query-native-schema :status (s/eq :failed) :class Class - :stacktrace [su/NonBlankStringPlumatic] + :stacktrace [su/NonBlankString] :context (s/eq :question) - :error su/NonBlankStringPlumatic + :error su/NonBlankString :row_count (s/eq 0) :running_time (s/constrained s/Int (complement neg?)) :preprocessed (bad-query-preprocessed-schema) diff --git a/test/metabase/task_test.clj b/test/metabase/task_test.clj index 09ad7ef35b7865032feb2ceed7da515945e1a646..b23523eb0d046e98faa90fa0bff6430bae676d59 100644 --- a/test/metabase/task_test.clj +++ b/test/metabase/task_test.clj @@ -89,12 +89,12 @@ (testing "Make sure scheduler-info doesn't explode and returns info in the general shape we expect" (mt/with-temp-scheduler (is (schema= {:scheduler (su/non-empty [s/Str]) - :jobs [{:key su/NonBlankStringPlumatic - :description su/NonBlankStringPlumatic - :triggers [{:key su/NonBlankStringPlumatic - :description su/NonBlankStringPlumatic - :misfire-instruction su/NonBlankStringPlumatic - :state su/NonBlankStringPlumatic + :jobs [{:key su/NonBlankString + :description su/NonBlankString + :triggers [{:key su/NonBlankString + :description su/NonBlankString + :misfire-instruction su/NonBlankString + :state su/NonBlankString s/Keyword s/Any}] s/Keyword s/Any}]} (task/scheduler-info)))))) diff --git a/test/metabase/test/automagic_dashboards.clj b/test/metabase/test/automagic_dashboards.clj index 74dc357177a7eb1b719fccac81f283adb1f6b6d1..6482f9873ffecce286c26f384afb7afa9320a9ed 100644 --- a/test/metabase/test/automagic_dashboards.clj +++ b/test/metabase/test/automagic_dashboards.clj @@ -28,8 +28,8 @@ [dashboard] (doseq [url (collect-urls dashboard)] (testing (format "\nURL = %s" (pr-str url)) - (is (schema= {:name su/NonBlankStringPlumatic - :description su/NonBlankStringPlumatic + (is (schema= {:name su/NonBlankString + :description su/NonBlankString s/Keyword s/Any} (mt/user-http-request :rasta :get 200 (format "automagic-dashboards/%s" (subs url 16)))))))) diff --git a/test/metabase/test/data/interface.clj b/test/metabase/test/data/interface.clj index b8c5dc29d5ef6a902bd1fcaf0ca8981f70a8d5ce..4303750b515842ab072013bf3d7edc395264d615 100644 --- a/test/metabase/test/data/interface.clj +++ b/test/metabase/test/data/interface.clj @@ -40,40 +40,40 @@ (p.types/defrecord+ DatabaseDefinition [database-name table-definitions]) (def ^:private FieldDefinitionSchema - {:field-name su/NonBlankStringPlumatic + {:field-name su/NonBlankString :base-type (s/conditional #(and (map? %) (contains? % :natives)) - {:natives {s/Keyword su/NonBlankStringPlumatic}} + {:natives {s/Keyword su/NonBlankString}} #(and (map? %) (contains? % :native)) - {:native su/NonBlankStringPlumatic} + {:native su/NonBlankString} :else - su/FieldTypePlumatic) + su/FieldType) ;; this was added pretty recently (in the 44 cycle) so it might not be supported everywhere. It should work for ;; drivers using `:sql/test-extensions` and [[metabase.test.data.sql/field-definition-sql]] but you might need to add ;; support for it elsewhere if you want to use it. It only really matters for testing things that modify test ;; datasets e.g. [[metabase.actions.test-util/with-actions-test-data]] (s/optional-key :not-null?) (s/maybe s/Bool) - (s/optional-key :semantic-type) (s/maybe su/FieldSemanticOrRelationTypePlumatic) - (s/optional-key :effective-type) (s/maybe su/FieldTypePlumatic) - (s/optional-key :coercion-strategy) (s/maybe su/CoercionStrategyPlumatic) + (s/optional-key :semantic-type) (s/maybe su/FieldSemanticOrRelationType) + (s/optional-key :effective-type) (s/maybe su/FieldType) + (s/optional-key :coercion-strategy) (s/maybe su/CoercionStrategy) (s/optional-key :visibility-type) (s/maybe (apply s/enum field/visibility-types)) - (s/optional-key :fk) (s/maybe su/KeywordOrStringPlumatic) - (s/optional-key :field-comment) (s/maybe su/NonBlankStringPlumatic)}) + (s/optional-key :fk) (s/maybe su/KeywordOrString) + (s/optional-key :field-comment) (s/maybe su/NonBlankString)}) (def ^:private ValidFieldDefinition (s/constrained FieldDefinitionSchema (partial instance? FieldDefinition))) (def ^:private ValidTableDefinition (s/constrained - {:table-name su/NonBlankStringPlumatic + {:table-name su/NonBlankString :field-definitions [ValidFieldDefinition] :rows [[s/Any]] - (s/optional-key :table-comment) (s/maybe su/NonBlankStringPlumatic)} + (s/optional-key :table-comment) (s/maybe su/NonBlankString)} (partial instance? TableDefinition))) (def ^:private ValidDatabaseDefinition (s/constrained - {:database-name su/NonBlankStringPlumatic + {:database-name su/NonBlankString :table-definitions [ValidTableDefinition]} (partial instance? DatabaseDefinition))) @@ -428,7 +428,7 @@ (def ^:private DatasetTableDefinition "Schema for a Table in a test dataset defined by a `defdataset` form or in a dataset defnition EDN file." - [(s/one su/NonBlankStringPlumatic "table name") + [(s/one su/NonBlankString "table name") (s/one [DatasetFieldDefinition] "fields") (s/one [[s/Any]] "rows")]) @@ -447,7 +447,7 @@ ([tabledef :- DatasetTableDefinition] (apply dataset-table-definition tabledef)) - ([table-name :- su/NonBlankStringPlumatic, field-definition-maps, rows] + ([table-name :- su/NonBlankString, field-definition-maps, rows] (map->TableDefinition {:table-name table-name :rows rows @@ -456,7 +456,7 @@ (s/defn dataset-definition :- ValidDatabaseDefinition "Parse a dataset definition (from a `defdatset` form or EDN file) and return a DatabaseDefinition instance for comsumption by various test-data-loading methods." - [database-name :- su/NonBlankStringPlumatic & table-definitions] + [database-name :- su/NonBlankString & table-definitions] (s/validate DatabaseDefinition (map->DatabaseDefinition @@ -508,7 +508,7 @@ (s/defn edn-dataset-definition "Define a new test dataset using the definition in an EDN file in the `test/metabase/test/data/dataset_definitions/` directory. (Filename should be `dataset-name` + `.edn`.)" - [dataset-name :- su/NonBlankStringPlumatic] + [dataset-name :- su/NonBlankString] (let [get-def (delay (let [file-contents (edn/read-string {:eof nil, :readers {'t #'u.date/parse}} @@ -536,7 +536,7 @@ (s/defn transformed-dataset-definition "Create a dataset definition that is a transformation of an some other one, seqentially applying `transform-fns` to it. The results of `transform-fns` are cached." - [new-name :- su/NonBlankStringPlumatic wrapped-definition & transform-fns :- [(s/pred fn?)]] + [new-name :- su/NonBlankString wrapped-definition & transform-fns :- [(s/pred fn?)]] (let [transform-fn (apply comp (reverse transform-fns)) get-def (delay (transform-fn @@ -585,7 +585,7 @@ (s/defn ^:private tabledef-with-name :- ValidTableDefinition "Return `TableDefinition` with `table-name` in `dbdef`." - [{:keys [table-definitions]} :- DatabaseDefinition, table-name :- su/NonBlankStringPlumatic] + [{:keys [table-definitions]} :- DatabaseDefinition, table-name :- su/NonBlankString] (some (fn [{this-name :table-name, :as tabledef}] (when (= table-name this-name) @@ -594,23 +594,23 @@ (s/defn ^:private fielddefs-for-table-with-name :- [ValidFieldDefinition] "Return the `FieldDefinitions` associated with table with `table-name` in `dbdef`." - [dbdef :- DatabaseDefinition, table-name :- su/NonBlankStringPlumatic] + [dbdef :- DatabaseDefinition, table-name :- su/NonBlankString] (:field-definitions (tabledef-with-name dbdef table-name))) -(s/defn ^:private tabledef->id->row :- {su/IntGreaterThanZeroPlumatic {su/NonBlankStringPlumatic s/Any}} +(s/defn ^:private tabledef->id->row :- {su/IntGreaterThanZero {su/NonBlankString s/Any}} [{:keys [field-definitions rows]} :- TableDefinition] (let [field-names (map :field-name field-definitions)] (into {} (for [[i values] (m/indexed rows)] [(inc i) (zipmap field-names values)])))) -(s/defn ^:private dbdef->table->id->row :- {su/NonBlankStringPlumatic {su/IntGreaterThanZeroPlumatic {su/NonBlankStringPlumatic s/Any}}} +(s/defn ^:private dbdef->table->id->row :- {su/NonBlankString {su/IntGreaterThanZero {su/NonBlankString s/Any}}} "Return a map of table name -> map of row ID -> map of column key -> value." [{:keys [table-definitions]} :- DatabaseDefinition] (into {} (for [{:keys [table-name] :as tabledef} table-definitions] [table-name (tabledef->id->row tabledef)]))) (s/defn ^:private nest-fielddefs - [dbdef :- DatabaseDefinition, table-name :- su/NonBlankStringPlumatic] + [dbdef :- DatabaseDefinition, table-name :- su/NonBlankString] (let [nest-fielddef (fn nest-fielddef [{:keys [fk field-name], :as fielddef}] (if-not fk [fielddef] @@ -619,7 +619,7 @@ (update nested-fielddef :field-name (partial vector field-name fk))))))] (mapcat nest-fielddef (fielddefs-for-table-with-name dbdef table-name)))) -(s/defn ^:private flatten-rows [dbdef :- DatabaseDefinition, table-name :- su/NonBlankStringPlumatic] +(s/defn ^:private flatten-rows [dbdef :- DatabaseDefinition, table-name :- su/NonBlankString] (let [nested-fielddefs (nest-fielddefs dbdef table-name) table->id->k->v (dbdef->table->id->row dbdef) resolve-field (fn resolve-field [table id field-name] @@ -644,7 +644,7 @@ (s/defn flattened-dataset-definition "Create a flattened version of `dbdef` by following resolving all FKs and flattening all rows into the table with `table-name`. For use with timeseries databases like Druid." - [dataset-definition, table-name :- su/NonBlankStringPlumatic] + [dataset-definition, table-name :- su/NonBlankString] (transformed-dataset-definition table-name dataset-definition (fn [dbdef] (assoc dbdef diff --git a/test/metabase/util/schema_test.clj b/test/metabase/util/schema_test.clj index 3c26f997d9335153ba18c79c5a6f98edb4a7d9cf..b28db7225a36ffa5ce866bd5c7cdc0ed74ccd791 100644 --- a/test/metabase/util/schema_test.clj +++ b/test/metabase/util/schema_test.clj @@ -8,6 +8,7 @@ [metabase.api.common :as api] [metabase.test :as mt] [metabase.util :as u] + [metabase.util.malli.schema :as ms] [metabase.util.schema :as su] [schema.core :as s])) @@ -16,7 +17,7 @@ (is (= (str "value may be nil, or if non-nil, value must satisfy one of the following requirements: " "1) value must be a boolean. " "2) value must be a valid boolean string ('true' or 'false').") - (str (su/api-error-message (s/maybe (s/cond-pre s/Bool su/BooleanStringPlumatic)))))) + (str (su/api-error-message (s/maybe (s/cond-pre s/Bool su/BooleanString)))))) (is (= (str/join "\n" ["value must be a map with schema: (" " a : value must be a map with schema: (" @@ -40,7 +41,7 @@ #_{:clj-kondo/ignore [:unused-binding :deprecated-var]} [id :as {{dimension-type :type, dimension-name :name} :body}] {dimension-type (su/api-param "type" (s/enum "internal" "external")) - dimension-name su/NonBlankStringPlumatic}) + dimension-name su/NonBlankString}) (deftest ^:parallel api-param-test (testing "check that API error message respects `api-param` when specified" @@ -67,10 +68,10 @@ (deftest translate-exception-message-test (mt/with-mock-i18n-bundles {"zz" {:messages {"Integer greater than zero" "INTEGER GREATER THAN ZERO"}}} (is (re= #".*Integer greater than zero.*" - (ex-info-msg #(s/validate su/IntGreaterThanZeroPlumatic -1)))) + (ex-info-msg #(s/validate su/IntGreaterThanZero -1)))) (mt/with-user-locale "zz" (is (re= #".*INTEGER GREATER THAN ZERO.*" - (ex-info-msg #(s/validate su/IntGreaterThanZeroPlumatic -1))))))) + (ex-info-msg #(s/validate su/IntGreaterThanZero -1))))))) (deftest ^:parallel distinct-test (is (= nil @@ -135,100 +136,100 @@ (deftest malli-and-plumatic-compatibility (doseq [{:keys [plumatic malli failed-cases success-cases]} - [{:plumatic su/NonBlankStringPlumatic - :malli su/NonBlankString + [{:plumatic su/NonBlankString + :malli ms/NonBlankString :failed-cases ["" 1] :success-cases ["a thing"]} - {:plumatic su/IntGreaterThanOrEqualToZeroPlumatic - :malli su/IntGreaterThanOrEqualToZero + {:plumatic su/IntGreaterThanOrEqualToZero + :malli ms/IntGreaterThanOrEqualToZero :failed-cases ["1" -1 1.5] :success-cases [0 1]} - {:plumatic su/IntGreaterThanZeroPlumatic - :malli su/IntGreaterThanZero + {:plumatic su/IntGreaterThanZero + :malli ms/IntGreaterThanZero :failed-cases ["1" 0 1.5] :success-cases [1 2]} - {:plumatic su/PositiveNumPlumatic - :malli su/PositiveNum + {:plumatic su/PositiveNum + :malli ms/PositiveNum :failed-cases [0 "1"] :success-cases [1.5 2]} - {:plumatic su/KeywordOrStringPlumatic - :malli su/KeywordOrString + {:plumatic su/KeywordOrString + :malli ms/KeywordOrString :failed-cases [1 [1] {:a 1}] :success-cases [:a "a"]} - {:plumatic su/FieldTypePlumatic - :malli su/FieldType + {:plumatic su/FieldType + :malli ms/FieldType :failed-cases [:type/invalid :Semantic/*] :success-cases [:type/Float]} - {:plumatic su/FieldSemanticTypePlumatic - :malli su/FieldSemanticType + {:plumatic su/FieldSemanticType + :malli ms/FieldSemanticType :failed-cases [:Semantic/invalid :type/Float] :success-cases [:type/Category]} - {:plumatic su/FieldRelationTypePlumatic - :malli su/FieldRelationType + {:plumatic su/FieldRelationType + :malli ms/FieldRelationType :failed-cases [:Relation/invalid :type/Category :type/Float] :success-cases [:type/FK]} - {:plumatic su/FieldSemanticOrRelationTypePlumatic - :malli su/FieldSemanticOrRelationType + {:plumatic su/FieldSemanticOrRelationType + :malli ms/FieldSemanticOrRelationType :failed-cases [:Relation/invalid :type/Float] :success-cases [:type/FK :type/Category]} - {:plumatic su/CoercionStrategyPlumatic - :malli su/CoercionStrategy + {:plumatic su/CoercionStrategy + :malli ms/CoercionStrategy :failed-cases [:type/Category :type/Float] :success-cases [:Coercion/ISO8601->Date]} - {:plumatic su/FieldTypeKeywordOrStringPlumatic - :malli su/FieldTypeKeywordOrString + {:plumatic su/FieldTypeKeywordOrString + :malli ms/FieldTypeKeywordOrString :failed-cases [1 :type/FK] :success-cases [:type/Float "type/Float"]} - {:plumatic su/FieldSemanticTypeKeywordOrStringPlumatic - :malli su/FieldSemanticTypeKeywordOrString + {:plumatic su/FieldSemanticTypeKeywordOrString + :malli ms/FieldSemanticTypeKeywordOrString :failed-cases [1 :type/FK] :success-cases [:type/Category "type/Category"]} - {:plumatic su/FieldPlumatic - :malli su/Field + {:plumatic su/Field + :malli ms/Field :failed-cases [[:aggregation 0] [:field "name" {}]] :success-cases [[:field 3 nil] ["field" "name" {:base-type :type/Float}]]} - {:plumatic su/MapPlumatic - :malli su/Map + {:plumatic su/Map + :malli ms/Map :failed-cases [[] 1 "a"] :success-cases [{} {:a :b}]} - {:plumatic su/EmailPlumatic - :malli su/Email + {:plumatic su/Email + :malli ms/Email :failed-cases ["abc.com" 1] :success-cases ["ngoc@metabase.com"]} - {:plumatic su/ValidPasswordPlumatic - :malli su/ValidPassword + {:plumatic su/ValidPassword + :malli ms/ValidPassword :failed-cases ["abc.com" 1 "PASSW0RD"] :success-cases ["unc0mmonpw"]} - {:plumatic su/IntStringPlumatic - :malli su/IntString + {:plumatic su/IntString + :malli ms/IntString :failed-cases [:a "a" "1.5"] :success-cases ["1"]} - {:plumatic su/BooleanStringPlumatic - :malli su/BooleanString + {:plumatic su/BooleanString + :malli ms/BooleanString :failed-cases [:false :true true "f"] :success-cases ["true" "false"]} - {:plumatic su/TemporalStringPlumatic - :malli su/TemporalString + {:plumatic su/TemporalString + :malli ms/TemporalString :failed-cases ["random string"] :success-cases ["2019-10-28T13:14:15" "2019-10-28"]} - {:plumatic su/JSONStringPlumatic - :malli su/JSONString + {:plumatic su/JSONString + :malli ms/JSONString :failed-cases ["string"] :success-cases ["{\"a\": 1}"]} - {:plumatic su/EmbeddingParamsPlumatic - :malli su/EmbeddingParams + {:plumatic su/EmbeddingParams + :malli ms/EmbeddingParams :failed-cases [{:key "value"}] :success-cases [{:key "disabled"}]} - {:plumatic su/ValidLocalePlumatic - :malli su/ValidLocale + {:plumatic su/ValidLocale + :malli ms/ValidLocale :failed-cases ["locale"] :success-cases ["en" "es"]} - {:plumatic su/NanoIdStringPlumatic - :malli su/NanoIdString + {:plumatic su/NanoIdString + :malli ms/NanoIdString :failed-cases ["random"] :success-cases ["FReCLx5hSWTBU7kjCWfuu"]} - {:plumatic su/ParameterPlumatic - :malli su/Parameter + {:plumatic su/Parameter + :malli ms/Parameter :failed-cases [{:id "param-id" :name "param-name"} {:id "param-id" @@ -250,8 +251,8 @@ :type "number" :values_source_type "static-list" :values_source_config {:values [[1 2 3]]}}]} - {:plumatic su/ParameterMappingPlumatic - :malli su/ParameterMapping + {:plumatic su/ParameterMapping + :malli ms/ParameterMapping :failed-cases [{:parameter_id "param-id"} {:parameter_id "param-id" :target [:field 3 nil]