From 18d190cf05df4233aa6d14d6580faa68293ba980 Mon Sep 17 00:00:00 2001 From: Ngoc Khuat <qn.khuat@gmail.com> Date: Wed, 11 Jan 2023 21:48:26 +0700 Subject: [PATCH] Move Plumatic schema in `metabase.util.schema` to `metabase.util.malli.schema` (#27622) * move malli schema from metabase.util.schema to a new ns metabase.util.malli.schema * revert name changes for plumatic schema. e.g: NonBlankStringPlumatic -> NonBlankString * add clj-kondo rule to enforce consistent alias for metabase.util.malli.schema --- .clj-kondo/config.edn | 1 + .../models/permissions.clj | 8 +- .../permissions/application_permissions.clj | 2 +- .../audit_app/interface.clj | 4 +- .../common/card_and_dashboard_detail.clj | 10 +- .../audit_app/pages/dashboard_detail.clj | 8 +- .../audit_app/pages/database_detail.clj | 2 +- .../audit_app/pages/query_detail.clj | 2 +- .../audit_app/pages/question_detail.clj | 10 +- .../audit_app/pages/table_detail.clj | 2 +- .../audit_app/pages/user_detail.clj | 18 +- .../middleware/handle_audit_queries.clj | 2 +- .../content_management/api/review.clj | 2 +- .../enhancements/integrations/ldap.clj | 2 +- .../native_query_snippet/permissions.clj | 2 +- .../metabase_enterprise/sandbox/api/gtap.clj | 8 +- .../metabase_enterprise/sandbox/api/table.clj | 6 +- .../metabase_enterprise/sandbox/api/user.clj | 2 +- .../models/group_table_access_policy.clj | 2 +- .../middleware/row_level_restrictions.clj | 18 +- .../serialization/api/serialize.clj | 4 +- .../serialization/names.clj | 22 +- .../sso/integrations/sso_settings.clj | 2 +- .../sso/integrations/sso_utils.clj | 6 +- .../enhancements/integrations/ldap_test.clj | 4 +- .../sandbox/api/permissions_test.clj | 6 +- .../metabase/driver/bigquery_cloud_sdk.clj | 4 +- .../metabase/test/data/bigquery_cloud_sdk.clj | 6 +- .../googleanalytics/query_processor.clj | 2 +- .../metabase/driver/mongo/query_processor.clj | 18 +- .../presto/src/metabase/driver/presto.clj | 8 +- src/metabase/api/alert.clj | 12 +- src/metabase/api/bookmark.clj | 6 +- src/metabase/api/card.clj | 60 +-- src/metabase/api/collection.clj | 40 +- src/metabase/api/common.clj | 16 +- src/metabase/api/dashboard.clj | 90 ++--- src/metabase/api/database.clj | 48 +-- src/metabase/api/dataset.clj | 4 +- src/metabase/api/email.clj | 2 +- src/metabase/api/embed.clj | 22 +- src/metabase/api/field.clj | 26 +- src/metabase/api/geojson.clj | 8 +- src/metabase/api/ldap.clj | 2 +- src/metabase/api/metric.clj | 20 +- src/metabase/api/native_query_snippet.clj | 8 +- src/metabase/api/notify.clj | 4 +- src/metabase/api/permissions.clj | 12 +- src/metabase/api/persist.clj | 4 +- src/metabase/api/public.clj | 34 +- src/metabase/api/pulse.clj | 36 +- src/metabase/api/search.clj | 28 +- src/metabase/api/segment.clj | 18 +- src/metabase/api/session.clj | 18 +- src/metabase/api/setting.clj | 2 +- src/metabase/api/setup.clj | 22 +- src/metabase/api/slack.clj | 4 +- src/metabase/api/table.clj | 18 +- src/metabase/api/tiles.clj | 8 +- src/metabase/api/timeline.clj | 16 +- src/metabase/api/timeline_event.clj | 14 +- src/metabase/api/user.clj | 20 +- src/metabase/api/util.clj | 2 +- src/metabase/automagic_dashboards/core.clj | 2 +- src/metabase/automagic_dashboards/filters.clj | 2 +- src/metabase/automagic_dashboards/rules.clj | 6 +- src/metabase/db/metadata_queries.clj | 2 +- src/metabase/db/util.clj | 2 +- .../driver/common/parameters/dates.clj | 2 +- .../driver/common/parameters/values.clj | 8 +- src/metabase/driver/sql.clj | 2 +- .../driver/sql/parameters/substitution.clj | 2 +- src/metabase/driver/sql_jdbc/connection.clj | 2 +- src/metabase/driver/util.clj | 2 +- src/metabase/email.clj | 8 +- src/metabase/integrations/ldap.clj | 4 +- .../ldap/default_implementation.clj | 32 +- src/metabase/integrations/ldap/interface.clj | 24 +- src/metabase/integrations/slack.clj | 8 +- src/metabase/models/bookmark.clj | 4 +- src/metabase/models/collection.clj | 26 +- src/metabase/models/collection/graph.clj | 22 +- src/metabase/models/dashboard.clj | 8 +- src/metabase/models/dashboard_card.clj | 28 +- src/metabase/models/field_values.clj | 8 +- src/metabase/models/moderation_review.clj | 8 +- src/metabase/models/params.clj | 10 +- src/metabase/models/params/card_values.clj | 6 +- src/metabase/models/params/chain_filter.clj | 46 +-- src/metabase/models/permissions.clj | 54 +-- src/metabase/models/persisted_info.clj | 4 +- src/metabase/models/pulse.clj | 42 +-- src/metabase/models/pulse_card.clj | 8 +- src/metabase/models/query/permissions.clj | 10 +- src/metabase/models/revision/last_edit.clj | 2 +- src/metabase/models/task_history.clj | 8 +- src/metabase/models/user.clj | 16 +- .../public_settings/premium_features.clj | 12 +- src/metabase/query_processor/card.clj | 2 +- src/metabase/query_processor/dashboard.clj | 10 +- .../middleware/add_dimension_projections.clj | 46 +-- .../middleware/add_implicit_clauses.clj | 2 +- .../query_processor/middleware/annotate.clj | 24 +- .../middleware/auto_bucket_datetimes.clj | 6 +- .../middleware/auto_parse_filter_values.clj | 2 +- .../query_processor/middleware/binning.clj | 24 +- .../middleware/expand_macros.clj | 18 +- .../middleware/fetch_source_query.clj | 26 +- .../middleware/permissions.clj | 6 +- .../middleware/resolve_joined_fields.clj | 2 +- .../middleware/resolve_source_table.clj | 2 +- src/metabase/query_processor/store.clj | 42 +-- src/metabase/query_processor/util.clj | 2 +- .../server/middleware/browser_cookie.clj | 2 +- src/metabase/server/request/util.clj | 10 +- .../sync/analyze/classifiers/category.clj | 2 +- .../sync/analyze/classifiers/name.clj | 4 +- .../analyze/classifiers/text_fingerprint.clj | 2 +- src/metabase/sync/analyze/fingerprint.clj | 4 +- src/metabase/sync/analyze/query_results.clj | 8 +- src/metabase/sync/interface.clj | 36 +- .../sync/sync_metadata/dbms_version.clj | 2 +- src/metabase/sync/sync_metadata/fields.clj | 6 +- .../sync/sync_metadata/fields/common.clj | 8 +- .../sync_metadata/fields/sync_instances.clj | 10 +- .../sync_metadata/fields/sync_metadata.clj | 4 +- .../sync/sync_metadata/metabase_metadata.clj | 6 +- src/metabase/sync/util.clj | 2 +- src/metabase/task/sync_databases.clj | 2 +- src/metabase/transforms/core.clj | 4 +- src/metabase/transforms/specs.clj | 2 +- src/metabase/util/cron.clj | 4 +- src/metabase/util/honey_sql_1_extensions.clj | 4 +- src/metabase/util/honey_sql_2_extensions.clj | 6 +- src/metabase/util/malli/schema.clj | 270 ++++++++++++++ src/metabase/util/schema.clj | 352 +++--------------- test/metabase/actions_test.clj | 4 +- test/metabase/analytics/stats_test.clj | 2 +- test/metabase/api/action_test.clj | 10 +- test/metabase/api/card_test.clj | 6 +- test/metabase/api/collection_test.clj | 2 +- test/metabase/api/database_test.clj | 6 +- test/metabase/api/dataset_test.clj | 2 +- test/metabase/api/geojson_test.clj | 2 +- .../api/native_query_snippet_test.clj | 2 +- test/metabase/api/permissions_test.clj | 22 +- test/metabase/api/session_test.clj | 10 +- test/metabase/api/setup_test.clj | 2 +- .../driver/common/parameters/values_test.clj | 2 +- .../driver/sql/parameters/substitute_test.clj | 2 +- test/metabase/driver/sql_jdbc/native_test.clj | 2 +- test/metabase/http_client.clj | 14 +- .../metabase/models/collection/graph_test.clj | 4 +- test/metabase/models/collection_test.clj | 2 +- test/metabase/models/login_history_test.clj | 2 +- .../models/permissions_group_test.clj | 2 +- .../middleware/parameters/native_test.clj | 2 +- .../middleware/parameters_test.clj | 2 +- test/metabase/query_processor/test_util.clj | 4 +- .../query_processor_test/failure_test.clj | 6 +- test/metabase/task_test.clj | 12 +- test/metabase/test/automagic_dashboards.clj | 4 +- test/metabase/test/data/interface.clj | 48 +-- test/metabase/util/schema_test.clj | 109 +++--- 164 files changed, 1256 insertions(+), 1242 deletions(-) create mode 100644 src/metabase/util/malli/schema.clj diff --git a/.clj-kondo/config.edn b/.clj-kondo/config.edn index 608237347eb..0a82507db11 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 694b7b4992e..89e7bbe3818 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 1721ec42ee7..b7cba0a9685 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 d53e27f32bb..e4e6ae53d97 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 d9e1633cfc8..071f64cb77c 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 776c93c9771..8fb58047290 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 c5e558d46a9..3016e75fc88 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 2febbbaa4de..d21419466fa 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 c10f3c5eaec..713d17f9dc8 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 b0b30a587fa..6139bb7210e 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 3d09bc57cec..b67dbdba003 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 a49c2962079..6442bc6e214 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 90d33305432..e7dc37e8e22 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 9f7f8fb5dd7..8890f8eed20 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 9f61cac8fee..affd3bd4035 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 3d2f8001e1e..963fec60086 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 bffde827db2..83f8f63450a 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 5f29d6b8723..b9232dcae26 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 fee61b05f45..b10b0a19cc2 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 df372650dc5..c768c848efb 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 de73002134f..e207e30c014 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 1dc957df56d..3f760c09265 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 89788140272..52c401bbf84 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 4bbc648083c..cffff9bd3fc 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 9f5e02f1cc0..778bea6908a 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 0a46b782e09..1cab256e11a 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 c41ae91277e..8c16b2e2dbe 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 03770cec686..1fc6af52e47 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 9a8d040441b..d175c7e729b 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 dfd74196994..e3e2bf3dddf 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 0025abac69a..7d462473bdb 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 22a2d270ca9..fbf1f94403a 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 5c7e0df8f45..392597826f4 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 3ef8b75da9c..f693af6cf7b 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 22486f2793b..1375ce790b3 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 b448ea34935..5f16e2032fd 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 9c44a57aea5..defb929f79c 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 611b7d6b748..4223317124f 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 26aec011a30..bd8a8263c5a 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 ac219908c4a..43bd6faf5da 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 25356a107b9..eefa2750a0b 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 a0f8b775ad2..d41e539ecfb 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 96fe5ab5d0c..332367a1cf5 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 38655e7dcb6..f573222e378 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 69353d5cca0..cafca0db4f8 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 048f105551c..db0c63c7d0d 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 9d7217205f3..4d43fde3107 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 c5b43702da1..126e75a28f7 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 e11c9401875..acc2626a47c 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 87a0152ab28..ef1b4aa4763 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 1c4b032f8eb..55c60266e52 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 339dd29a350..f77e59ce4e3 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 4041f7daaff..e1b92291dac 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 94292f1dd9f..ee356e0f714 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 68f7926f02b..e67c78792aa 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 7b732da1c8f..550803bd835 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 13dfd036441..4d45ac903df 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 937f0f515af..7bb9bfde1ca 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 617cd139e03..a7448fd4e16 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 30899a6b7e1..c7519db0300 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 f795d5c8676..42a395401d4 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 30e36a7bb59..e219455153b 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 488c78eb8fe..d62369ad350 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 d00e4931c68..cd55a64121a 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 b25af806459..72186dfff5a 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 f88f4466d05..e97e0b255e1 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 d7bbecae778..3291f361caa 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 ccedabe56f7..3040c863781 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 f200d61d69e..454ed60f8bf 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 6ede6309ab7..40c7ea66a86 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 7cf7a0f9a5e..0f8ef550a84 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 0899e270771..9b7ac3904e9 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 cc29f78746e..5e74a8a7938 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 6f3ed2cd829..7c40abfe33f 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 cabd82820c7..887e8db6325 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 2d923c89a5a..b504f265603 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 354a83ea4bd..2f23da5fdfb 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 69f29bf1be0..042b51275ec 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 c257100a82e..f2892f2f050 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 39721f170ac..15f8cf42edd 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 83f0bf39e33..7293ee6501f 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 cb7c255b630..94d9c9a20b5 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 00f4bf8d23d..b193d5b0592 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 be295d7bbdd..9d401ef4b75 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 61f2457e416..06a0f5b5d27 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 8c0ef1e923e..17b21f4a41b 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 8a011c4c724..09b07f30b53 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 350d088801e..ba2b51a0f84 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 85bafaca608..a6f437ea5de 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 5ccaa84c3c3..30d9ab3e26b 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 363ce2e1ca7..e012d7c5e6f 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 1d3bc177ba2..866c24265f3 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 9b058be520a..1fbf750ce32 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 4247f139ffc..2a527b5b136 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 bbeace2b7f1..6173c363186 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 64b58e17118..4422801683d 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 93aa74beba3..42eeb416812 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 228e14b35a3..69d071b8123 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 3a4779dd908..73b56594349 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 e605ca9359b..77699438940 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 cfd298cc522..07c652e5819 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 e550acffba9..d1657ea32ed 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 43ad2a764b6..55a2e857be7 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 a683296ca19..1ce4659de9f 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 c6072d33b58..cb236ec617d 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 9ee49032b47..c32a3c3e811 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 ede25fc3b9d..5ff371fc066 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 6816c9c70b5..20607496d9f 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 5d7775b139e..7aae7bd5b08 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 e6ee0121206..8ac2f1f0f13 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 38dbda66660..22569f74d82 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 da777ab6af9..5148d29bf04 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 db53076c195..269a781d897 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 dfeda32036c..0f4ac584ebe 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 bf93a0818e2..e81a5ad6fdf 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 f872258c710..3466091056e 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 b0220dc58e8..abcd24a5205 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 1a642817c7a..c2097d259ae 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 9546cb33830..aa54d1b2410 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 8015a2365e7..f8008003e15 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 b4af454474f..7146c6e7743 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 a484cd765f7..838576d89f6 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 b8e3bca2a03..dd76b164c0a 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 6895bd29974..49b7cbbda22 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 bf7343895cd..3404aabd983 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 ffdb3797b0f..6e793e76645 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 de717bfdf69..5ee72f22183 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 53c5d4794f6..e8fed7b1fcc 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 b753b068942..c915104a6ef 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 df0e38a2f57..58c6f7ab86a 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 218f49be41b..4c9c8399095 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 b4c94818ed0..b002e83fbca 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 19bcc037d85..575d26244ed 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 aaeafe7e8f1..43ad7f1afb2 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 00000000000..ea4dd23d5fe --- /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 8abb7fa93bc..d36fab91b19 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 17bbae1015c..546f9351ddf 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 21e9e802b20..bfce9779514 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 4702fb914e6..ed2f7bf9d24 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 5788d132f8e..e9067d7da57 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 53f489b9e56..95696bb4440 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 6b1970bbeb5..75ec9eacf03 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 1d1c5f21bc5..4cc8512e874 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 02c2f95a452..b997d0c112e 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 e003ff7c801..d6ad35356fa 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 8a4de348d4c..e050d58ea84 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 02fb0a9f0b8..dd222888c0f 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 c4142742b2a..eeda71a228e 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 eb8b55196aa..e273400e16f 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 0b883b3e060..3c2039e3c40 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 6d6e13eb207..0f49828f1ec 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 ba08bcc41b0..4a402c157e5 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 dc25ace37c5..8d9c5d87df9 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 dbeb58301ac..3093835c580 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 76da5d044cb..32e8d675c0c 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 254c5033d84..4474509c9fa 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 06bd645b16f..d81062e5550 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 3b9cc1fd4c4..3c2b6a48bbd 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 847029ab22d..fa4dcfbff88 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 54271260d76..bceaa03abe6 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 09ad7ef35b7..b23523eb0d0 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 74dc357177a..6482f9873ff 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 b8c5dc29d5e..4303750b515 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 3c26f997d93..b28db7225a3 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] -- GitLab