Merge pull request #4681 from penpot/niwinz-enhancements-2

🔥 Replace spec usage on RPC methods with schema
This commit is contained in:
Alejandro 2024-07-04 12:56:41 +02:00 committed by GitHub
commit 85579b253f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
50 changed files with 358 additions and 357 deletions

View File

@ -4,6 +4,7 @@
:remove-consecutive-blank-lines? false :remove-consecutive-blank-lines? false
:extra-indents {rumext.v2/fnc [[:inner 0]] :extra-indents {rumext.v2/fnc [[:inner 0]]
cljs.test/async [[:inner 0]] cljs.test/async [[:inner 0]]
app.common.schema/register! [[:inner 0] [:inner 1]]
promesa.exec/thread [[:inner 0]] promesa.exec/thread [[:inner 0]]
specify! [[:inner 0] [:inner 1]]} specify! [[:inner 0] [:inner 1]]}
} }

View File

@ -20,12 +20,19 @@
<span>WEBHOOK</span> <span>WEBHOOK</span>
</span> </span>
{% endif %} {% endif %}
{% if item.params-schema-js %} {% if item.params-schema-js %}
<span class="tag"> <span class="tag">
<span>SCHEMA</span> <span>SCHEMA</span>
</span> </span>
{% endif %} {% endif %}
{% if item.spec %}
<span class="tag">
<span>SPEC</span>
</span>
{% endif %}
{% if item.sse %} {% if item.sse %}
<span class="tag"> <span class="tag">
<span>SSE</span> <span>SSE</span>

View File

@ -54,9 +54,10 @@
"A convencience toplevel function for gradual migration to a new API "A convencience toplevel function for gradual migration to a new API
convention." convention."
([cfg-or-client request] ([cfg-or-client request]
(let [client (resolve-client cfg-or-client)] (let [client (resolve-client cfg-or-client)
request (update request :uri str)]
(send! client request {:sync? true}))) (send! client request {:sync? true})))
([cfg-or-client request options] ([cfg-or-client request options]
(let [client (resolve-client cfg-or-client)] (let [client (resolve-client cfg-or-client)
request (update request :uri str)]
(send! client request (merge {:sync? true} options))))) (send! client request (merge {:sync? true} options)))))

View File

@ -47,7 +47,7 @@
(s/keys :req-un [::path] (s/keys :req-un [::path]
:opt-un [::mtype])) :opt-un [::mtype]))
(sm/def! ::fs/path (sm/register! ::fs/path
{:type ::fs/path {:type ::fs/path
:pred fs/path? :pred fs/path?
:type-properties :type-properties
@ -59,7 +59,7 @@
::oapi/format "unix-path" ::oapi/format "unix-path"
::oapi/decode fs/path}}) ::oapi/decode fs/path}})
(sm/def! ::upload (sm/register! ::upload
[:map {:title "Upload"} [:map {:title "Upload"}
[:filename :string] [:filename :string]
[:size :int] [:size :int]

View File

@ -6,7 +6,7 @@
(ns app.rpc.commands.access-token (ns app.rpc.commands.access-token
(:require (:require
[app.common.spec :as us] [app.common.schema :as sm]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.db :as db] [app.db :as db]
[app.main :as-alias main] [app.main :as-alias main]
@ -16,8 +16,7 @@
[app.setup :as-alias setup] [app.setup :as-alias setup]
[app.tokens :as tokens] [app.tokens :as tokens]
[app.util.services :as sv] [app.util.services :as sv]
[app.util.time :as dt] [app.util.time :as dt]))
[clojure.spec.alpha :as s]))
(defn- decode-row (defn- decode-row
[row] [row]
@ -44,7 +43,7 @@
:perms (db/create-array conn "text" [])}))) :perms (db/create-array conn "text" [])})))
(defn repl-create-access-token (defn repl:create-access-token
[{:keys [::db/pool] :as system} profile-id name expiration] [{:keys [::db/pool] :as system} profile-id name expiration]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(let [props (:app.setup/props system)] (let [props (:app.setup/props system)]
@ -53,16 +52,14 @@
name name
expiration)))) expiration))))
(s/def ::name ::us/not-empty-string) (def ^:private schema:create-access-token
(s/def ::expiration ::dt/duration) [:map {:title "create-access-token"}
[:name [:string {:max 250 :min 1}]]
(s/def ::create-access-token [:expiration {:optional true} ::dt/duration]])
(s/keys :req [::rpc/profile-id]
:req-un [::name]
:opt-un [::expiration]))
(sv/defmethod ::create-access-token (sv/defmethod ::create-access-token
{::doc/added "1.18"} {::doc/added "1.18"
::sm/params schema:create-access-token}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id name expiration]}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id name expiration]}]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(let [cfg (assoc cfg ::db/conn conn)] (let [cfg (assoc cfg ::db/conn conn)]
@ -72,21 +69,23 @@
(-> (create-access-token cfg profile-id name expiration) (-> (create-access-token cfg profile-id name expiration)
(decode-row))))) (decode-row)))))
(s/def ::delete-access-token (def ^:private schema:delete-access-token
(s/keys :req [::rpc/profile-id] [:map {:title "delete-access-token"}
:req-un [::us/id])) [:id ::sm/uuid]])
(sv/defmethod ::delete-access-token (sv/defmethod ::delete-access-token
{::doc/added "1.18"} {::doc/added "1.18"
::sm/params schema:delete-access-token}
[{:keys [::db/pool]} {:keys [::rpc/profile-id id]}] [{:keys [::db/pool]} {:keys [::rpc/profile-id id]}]
(db/delete! pool :access-token {:id id :profile-id profile-id}) (db/delete! pool :access-token {:id id :profile-id profile-id})
nil) nil)
(s/def ::get-access-tokens (def ^:private schema:get-access-tokens
(s/keys :req [::rpc/profile-id])) [:map {:title "get-access-tokens"}])
(sv/defmethod ::get-access-tokens (sv/defmethod ::get-access-tokens
{::doc/added "1.18"} {::doc/added "1.18"
::sm/params schema:get-access-tokens}
[{:keys [::db/pool]} {:keys [::rpc/profile-id]}] [{:keys [::db/pool]} {:keys [::rpc/profile-id]}]
(->> (db/query pool :access-token (->> (db/query pool :access-token
{:profile-id profile-id} {:profile-id profile-id}

View File

@ -30,9 +30,10 @@
;; --- Command: export-binfile ;; --- Command: export-binfile
(def ^:private schema:export-binfile (def ^:private
schema:export-binfile
[:map {:title "export-binfile"} [:map {:title "export-binfile"}
[:name :string] [:name [:string {:max 250}]]
[:file-id ::sm/uuid] [:file-id ::sm/uuid]
[:include-libraries :boolean] [:include-libraries :boolean]
[:embed-assets :boolean]]) [:embed-assets :boolean]])
@ -74,9 +75,10 @@
{:id project-id}) {:id project-id})
result)) result))
(def ^:private schema:import-binfile (def ^:private
schema:import-binfile
[:map {:title "import-binfile"} [:map {:title "import-binfile"}
[:name :string] [:name [:string {:max 250}]]
[:project-id ::sm/uuid] [:project-id ::sm/uuid]
[:file ::media/upload]]) [:file ::media/upload]])

View File

@ -292,7 +292,7 @@
[:map {:title "create-comment-thread"} [:map {:title "create-comment-thread"}
[:file-id ::sm/uuid] [:file-id ::sm/uuid]
[:position ::gpt/point] [:position ::gpt/point]
[:content :string] [:content [:string {:max 250}]]
[:page-id ::sm/uuid] [:page-id ::sm/uuid]
[:frame-id ::sm/uuid] [:frame-id ::sm/uuid]
[:share-id {:optional true} [:maybe ::sm/uuid]]]) [:share-id {:optional true} [:maybe ::sm/uuid]]])
@ -418,7 +418,7 @@
schema:create-comment schema:create-comment
[:map {:title "create-comment"} [:map {:title "create-comment"}
[:thread-id ::sm/uuid] [:thread-id ::sm/uuid]
[:content :string] [:content [:string {:max 250}]]
[:share-id {:optional true} [:maybe ::sm/uuid]]]) [:share-id {:optional true} [:maybe ::sm/uuid]]])
(sv/defmethod ::create-comment (sv/defmethod ::create-comment
@ -477,7 +477,7 @@
schema:update-comment schema:update-comment
[:map {:title "update-comment"} [:map {:title "update-comment"}
[:id ::sm/uuid] [:id ::sm/uuid]
[:content :string] [:content [:string {:max 250}]]
[:share-id {:optional true} [:maybe ::sm/uuid]]]) [:share-id {:optional true} [:maybe ::sm/uuid]]])
(sv/defmethod ::update-comment (sv/defmethod ::update-comment

View File

@ -18,10 +18,7 @@
[app.util.services :as sv] [app.util.services :as sv]
[app.util.time :as dt] [app.util.time :as dt]
[buddy.core.codecs :as bc] [buddy.core.codecs :as bc]
[buddy.core.nonce :as bn] [buddy.core.nonce :as bn]))
[clojure.spec.alpha :as s]))
(s/def ::create-demo-profile any?)
(sv/defmethod ::create-demo-profile (sv/defmethod ::create-demo-profile
"A command that is responsible of creating a demo purpose "A command that is responsible of creating a demo purpose

View File

@ -8,29 +8,25 @@
"A general purpose feedback module." "A general purpose feedback module."
(:require (:require
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.spec :as us] [app.common.schema :as sm]
[app.config :as cf] [app.config :as cf]
[app.db :as db] [app.db :as db]
[app.email :as eml] [app.email :as eml]
[app.rpc :as-alias rpc] [app.rpc :as-alias rpc]
[app.rpc.commands.profile :as profile] [app.rpc.commands.profile :as profile]
[app.rpc.doc :as-alias doc] [app.rpc.doc :as-alias doc]
[app.util.services :as sv] [app.util.services :as sv]))
[clojure.spec.alpha :as s]))
(declare ^:private send-feedback!) (declare ^:private send-feedback!)
(s/def ::content ::us/string) (def ^:private schema:send-user-feedback
(s/def ::from ::us/email) [:map {:title "send-user-feedback"}
(s/def ::subject ::us/string) [:subject [:string {:max 250}]]
[:content [:string {:max 250}]]])
(s/def ::send-user-feedback
(s/keys :req [::rpc/profile-id]
:req-un [::subject
::content]))
(sv/defmethod ::send-user-feedback (sv/defmethod ::send-user-feedback
{::doc/added "1.18"} {::doc/added "1.18"
::sm/params schema:send-user-feedback}
[{:keys [::db/pool]} {:keys [::rpc/profile-id] :as params}] [{:keys [::db/pool]} {:keys [::rpc/profile-id] :as params}]
(when-not (contains? cf/flags :user-feedback) (when-not (contains? cf/flags :user-feedback)
(ex/raise :type :restriction (ex/raise :type :restriction

View File

@ -15,7 +15,6 @@
[app.common.logging :as l] [app.common.logging :as l]
[app.common.schema :as sm] [app.common.schema :as sm]
[app.common.schema.desc-js-like :as-alias smdj] [app.common.schema.desc-js-like :as-alias smdj]
[app.common.spec :as us]
[app.common.types.components-list :as ctkl] [app.common.types.components-list :as ctkl]
[app.common.types.file :as ctf] [app.common.types.file :as ctf]
[app.config :as cf] [app.config :as cf]
@ -36,7 +35,6 @@
[app.util.services :as sv] [app.util.services :as sv]
[app.util.time :as dt] [app.util.time :as dt]
[app.worker :as wrk] [app.worker :as wrk]
[clojure.spec.alpha :as s]
[cuerdas.core :as str])) [cuerdas.core :as str]))
;; --- FEATURES ;; --- FEATURES
@ -46,18 +44,6 @@
(when media-id (when media-id
(str (cf/get :public-uri) "/assets/by-id/" media-id))) (str (cf/get :public-uri) "/assets/by-id/" media-id)))
;; --- SPECS
(s/def ::features ::us/set-of-strings)
(s/def ::file-id ::us/uuid)
(s/def ::frame-id ::us/uuid)
(s/def ::id ::us/uuid)
(s/def ::is-shared ::us/boolean)
(s/def ::name ::us/string)
(s/def ::project-id ::us/uuid)
(s/def ::search-term ::us/string)
(s/def ::team-id ::us/uuid)
;; --- HELPERS ;; --- HELPERS
(def long-cache-duration (def long-cache-duration
@ -191,7 +177,7 @@
[:features ::cfeat/features] [:features ::cfeat/features]
[:has-media-trimmed :boolean] [:has-media-trimmed :boolean]
[:comment-thread-seqn {:min 0} :int] [:comment-thread-seqn {:min 0} :int]
[:name :string] [:name [:string {:max 250}]]
[:revn {:min 0} :int] [:revn {:min 0} :int]
[:modified-at ::dt/instant] [:modified-at ::dt/instant]
[:is-shared :boolean] [:is-shared :boolean]
@ -761,19 +747,19 @@
[:map {:title "RenameFileEvent"} [:map {:title "RenameFileEvent"}
[:id ::sm/uuid] [:id ::sm/uuid]
[:project-id ::sm/uuid] [:project-id ::sm/uuid]
[:name :string] [:name [:string {:max 250}]]
[:created-at ::dt/instant] [:created-at ::dt/instant]
[:modified-at ::dt/instant]] [:modified-at ::dt/instant]]
::sm/params ::sm/params
[:map {:title "RenameFileParams"} [:map {:title "RenameFileParams"}
[:name {:min 1} :string] [:name [:string {:min 1 :max 250}]]
[:id ::sm/uuid]] [:id ::sm/uuid]]
::sm/result ::sm/result
[:map {:title "SimplifiedFile"} [:map {:title "SimplifiedFile"}
[:id ::sm/uuid] [:id ::sm/uuid]
[:name :string] [:name [:string {:max 250}]]
[:created-at ::dt/instant] [:created-at ::dt/instant]
[:modified-at ::dt/instant]]} [:modified-at ::dt/instant]]}
@ -1047,14 +1033,16 @@
{:id file-id} {:id file-id}
{::db/return-keys true})) {::db/return-keys true}))
(s/def ::ignore-file-library-sync-status (def ^:private schema:ignore-file-library-sync-status
(s/keys :req [::rpc/profile-id] [:map {:title "ignore-file-library-sync-status"}
:req-un [::file-id ::date])) [:file-id ::sm/uuid]
[:date ::dt/duration]])
;; TODO: improve naming ;; TODO: improve naming
(sv/defmethod ::ignore-file-library-sync-status (sv/defmethod ::ignore-file-library-sync-status
"Ignore updates in linked files" "Ignore updates in linked files"
{::doc/added "1.17"} {::doc/added "1.17"
::sm/params schema:ignore-file-library-sync-status}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(check-edition-permissions! conn profile-id file-id) (check-edition-permissions! conn profile-id file-id)

View File

@ -88,7 +88,7 @@
(def ^:private schema:create-file (def ^:private schema:create-file
[:map {:title "create-file"} [:map {:title "create-file"}
[:name :string] [:name [:string {:max 250}]]
[:project-id ::sm/uuid] [:project-id ::sm/uuid]
[:id {:optional true} ::sm/uuid] [:id {:optional true} ::sm/uuid]
[:is-shared {:optional true} :boolean] [:is-shared {:optional true} :boolean]

View File

@ -7,29 +7,24 @@
(ns app.rpc.commands.files-share (ns app.rpc.commands.files-share
"Share link related rpc mutation methods." "Share link related rpc mutation methods."
(:require (:require
[app.common.spec :as us] [app.common.schema :as sm]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.db :as db] [app.db :as db]
[app.rpc :as-alias rpc] [app.rpc :as-alias rpc]
[app.rpc.commands.files :as files] [app.rpc.commands.files :as files]
[app.rpc.doc :as-alias doc] [app.rpc.doc :as-alias doc]
[app.util.services :as sv] [app.util.services :as sv]))
[clojure.spec.alpha :as s]))
;; --- Helpers & Specs
(s/def ::file-id ::us/uuid)
(s/def ::who-comment ::us/string)
(s/def ::who-inspect ::us/string)
(s/def ::pages (s/every ::us/uuid :kind set?))
;; --- MUTATION: Create Share Link ;; --- MUTATION: Create Share Link
(declare create-share-link) (declare create-share-link)
(s/def ::create-share-link (def ^:private schema:create-share-link
(s/keys :req [::rpc/profile-id] [:map {:title "create-share-link"}
:req-un [::file-id ::who-comment ::who-inspect ::pages])) [:file-id ::sm/uuid]
[:who-comment [:string {:max 250}]]
[:who-inspect [:string {:max 250}]]
[:pages [:set ::sm/uuid]]])
(sv/defmethod ::create-share-link (sv/defmethod ::create-share-link
"Creates a share-link object. "Creates a share-link object.
@ -37,7 +32,8 @@
Share links are resources that allows external users access to specific Share links are resources that allows external users access to specific
pages of a file with specific permissions (who-comment and who-inspect)." pages of a file with specific permissions (who-comment and who-inspect)."
{::doc/added "1.18" {::doc/added "1.18"
::doc/module :files} ::doc/module :files
::sm/params schema:create-share-link}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(files/check-edition-permissions! conn profile-id file-id) (files/check-edition-permissions! conn profile-id file-id)
@ -58,13 +54,14 @@
;; --- MUTATION: Delete Share Link ;; --- MUTATION: Delete Share Link
(s/def ::delete-share-link (def ^:private schema:delete-share-link
(s/keys :req [::rpc/profile-id] [:map {:title "delete-share-link"}
:req-un [::us/id])) [:id ::sm/uuid]])
(sv/defmethod ::delete-share-link (sv/defmethod ::delete-share-link
{::doc/added "1.18" {::doc/added "1.18"
::doc/module ::files} ::doc/module ::files
::sm/params schema:delete-share-link}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id] :as params}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id] :as params}]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(let [slink (db/get-by-id conn :share-link id)] (let [slink (db/get-by-id conn :share-link id)]

View File

@ -35,7 +35,7 @@
(def ^:private schema:create-temp-file (def ^:private schema:create-temp-file
[:map {:title "create-temp-file"} [:map {:title "create-temp-file"}
[:name :string] [:name [:string {:max 250}]]
[:project-id ::sm/uuid] [:project-id ::sm/uuid]
[:id {:optional true} ::sm/uuid] [:id {:optional true} ::sm/uuid]
[:is-shared :boolean] [:is-shared :boolean]

View File

@ -33,7 +33,6 @@
[app.util.pointer-map :as pmap] [app.util.pointer-map :as pmap]
[app.util.services :as sv] [app.util.services :as sv]
[app.util.time :as dt] [app.util.time :as dt]
[clojure.spec.alpha :as s]
[cuerdas.core :as str])) [cuerdas.core :as str]))
;; --- FEATURES ;; --- FEATURES
@ -86,8 +85,8 @@
::doc/module :files ::doc/module :files
::sm/params [:map {:title "get-file-object-thumbnails"} ::sm/params [:map {:title "get-file-object-thumbnails"}
[:file-id ::sm/uuid] [:file-id ::sm/uuid]
[:tag {:optional true} :string]] [:tag {:optional true} [:string {:max 50}]]]
::sm/result [:map-of :string :string]} ::sm/result [:map-of [:string {:max 250}] [:string {:max 250}]]}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id tag] :as params}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id tag] :as params}]
(dm/with-open [conn (db/open pool)] (dm/with-open [conn (db/open pool)]
(files/check-read-permissions! conn profile-id file-id) (files/check-read-permissions! conn profile-id file-id)
@ -276,9 +275,9 @@
schema:create-file-object-thumbnail schema:create-file-object-thumbnail
[:map {:title "create-file-object-thumbnail"} [:map {:title "create-file-object-thumbnail"}
[:file-id ::sm/uuid] [:file-id ::sm/uuid]
[:object-id :string] [:object-id [:string {:max 250}]]
[:media ::media/upload] [:media ::media/upload]
[:tag {:optional true} :string]]) [:tag {:optional true} [:string {:max 50}]]])
(sv/defmethod ::create-file-object-thumbnail (sv/defmethod ::create-file-object-thumbnail
{::doc/added "1.19" {::doc/added "1.19"
@ -314,13 +313,15 @@
:object-id object-id :object-id object-id
:tag tag}))) :tag tag})))
(s/def ::delete-file-object-thumbnail (def ^:private schema:delete-file-object-thumbnail
(s/keys :req [::rpc/profile-id] [:map {:title "delete-file-object-thumbnail"}
:req-un [::file-id ::object-id])) [:file-id ::sm/uuid]
[:object-id [:string {:max 250}]]])
(sv/defmethod ::delete-file-object-thumbnail (sv/defmethod ::delete-file-object-thumbnail
{::doc/added "1.19" {::doc/added "1.19"
::doc/module :files ::doc/module :files
::sm/params schema:delete-file-object-thumbnail
::audit/skip true} ::audit/skip true}
[cfg {:keys [::rpc/profile-id file-id object-id]}] [cfg {:keys [::rpc/profile-id file-id object-id]}]
(files/check-edition-permissions! cfg profile-id file-id) (files/check-edition-permissions! cfg profile-id file-id)

View File

@ -51,7 +51,7 @@
[:vector [:map [:vector [:map
[:changes [:vector ::cpc/change]] [:changes [:vector ::cpc/change]]
[:hint-origin {:optional true} :keyword] [:hint-origin {:optional true} :keyword]
[:hint-events {:optional true} [:vector :string]]]]] [:hint-events {:optional true} [:vector [:string {:max 250}]]]]]]
[:skip-validate {:optional true} :boolean]]) [:skip-validate {:optional true} :boolean]])
(def ^:private (def ^:private

View File

@ -8,7 +8,7 @@
(:require (:require
[app.auth.ldap :as ldap] [app.auth.ldap :as ldap]
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.spec :as us] [app.common.schema :as sm]
[app.db :as db] [app.db :as db]
[app.http.session :as session] [app.http.session :as session]
[app.loggers.audit :as-alias audit] [app.loggers.audit :as-alias audit]
@ -19,27 +19,25 @@
[app.rpc.helpers :as rph] [app.rpc.helpers :as rph]
[app.setup :as-alias setup] [app.setup :as-alias setup]
[app.tokens :as tokens] [app.tokens :as tokens]
[app.util.services :as sv] [app.util.services :as sv]))
[clojure.spec.alpha :as s]))
;; --- COMMAND: login-with-ldap ;; --- COMMAND: login-with-ldap
(declare login-or-register) (declare login-or-register)
(s/def ::email ::us/email) (def schema:login-with-ldap
(s/def ::password ::us/string) [:map {:title "login-with-ldap"}
(s/def ::invitation-token ::us/string) [:email ::sm/email]
[:password auth/schema:password]
(s/def ::login-with-ldap [:invitation-token {:optional true} auth/schema:token]])
(s/keys :req-un [::email ::password]
:opt-un [::invitation-token]))
(sv/defmethod ::login-with-ldap (sv/defmethod ::login-with-ldap
"Performs the authentication using LDAP backend. Only works if LDAP "Performs the authentication using LDAP backend. Only works if LDAP
is properly configured and enabled with `login-with-ldap` flag." is properly configured and enabled with `login-with-ldap` flag."
{::rpc/auth false {::rpc/auth false
::doc/added "1.15" ::doc/added "1.15"
::doc/module :auth} ::doc/module :auth
::sm/params schema:login-with-ldap}
[{:keys [::setup/props ::ldap/provider] :as cfg} params] [{:keys [::setup/props ::ldap/provider] :as cfg} params]
(when-not provider (when-not provider
(ex/raise :type :restriction (ex/raise :type :restriction

View File

@ -91,7 +91,7 @@
(sm/define (sm/define
[:map {:title "duplicate-file"} [:map {:title "duplicate-file"}
[:file-id ::sm/uuid] [:file-id ::sm/uuid]
[:name {:optional true} :string]])) [:name {:optional true} [:string {:max 250}]]]))
(sv/defmethod ::duplicate-file (sv/defmethod ::duplicate-file
"Duplicate a single file in the same team." "Duplicate a single file in the same team."
@ -153,7 +153,7 @@
(sm/define (sm/define
[:map {:title "duplicate-project"} [:map {:title "duplicate-project"}
[:project-id ::sm/uuid] [:project-id ::sm/uuid]
[:name {:optional true} :string]])) [:name {:optional true} [:string {:max 250}]]]))
(sv/defmethod ::duplicate-project (sv/defmethod ::duplicate-project
"Duplicate an entire project with all the files" "Duplicate an entire project with all the files"

View File

@ -9,7 +9,7 @@
[app.common.data :as d] [app.common.data :as d]
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.media :as cm] [app.common.media :as cm]
[app.common.spec :as us] [app.common.schema :as sm]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.config :as cf] [app.config :as cf]
[app.db :as db] [app.db :as db]
@ -25,7 +25,6 @@
[app.util.services :as sv] [app.util.services :as sv]
[app.util.time :as dt] [app.util.time :as dt]
[app.worker :as-alias wrk] [app.worker :as-alias wrk]
[clojure.spec.alpha :as s]
[cuerdas.core :as str] [cuerdas.core :as str]
[datoteka.io :as io] [datoteka.io :as io]
[promesa.exec :as px])) [promesa.exec :as px]))
@ -39,25 +38,21 @@
:quality 85 :quality 85
:format :jpeg}) :format :jpeg})
(s/def ::id ::us/uuid)
(s/def ::name ::us/string)
(s/def ::file-id ::us/uuid)
(s/def ::team-id ::us/uuid)
;; --- Create File Media object (upload) ;; --- Create File Media object (upload)
(declare create-file-media-object) (declare create-file-media-object)
(s/def ::content ::media/upload) (def ^:private schema:upload-file-media-object
(s/def ::is-local ::us/boolean) [:map {:title "upload-file-media-object"}
[:id {:optional true} ::sm/uuid]
(s/def ::upload-file-media-object [:file-id ::sm/uuid]
(s/keys :req [::rpc/profile-id] [:is-local :boolean]
:req-un [::file-id ::is-local ::name ::content] [:name [:string {:max 250}]]
:opt-un [::id])) [:content ::media/upload]])
(sv/defmethod ::upload-file-media-object (sv/defmethod ::upload-file-media-object
{::doc/added "1.17" {::doc/added "1.17"
::sm/params schema:upload-file-media-object
::climit/id [[:process-image/by-profile ::rpc/profile-id] ::climit/id [[:process-image/by-profile ::rpc/profile-id]
[:process-image/global]]} [:process-image/global]]}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id content] :as params}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id content] :as params}]
@ -176,14 +171,17 @@
(declare ^:private create-file-media-object-from-url) (declare ^:private create-file-media-object-from-url)
(s/def ::create-file-media-object-from-url (def ^:private schema:create-file-media-object-from-url
(s/keys :req [::rpc/profile-id] [:map {:title "create-file-media-object-from-url"}
:req-un [::file-id ::is-local ::url] [:file-id ::sm/uuid]
:opt-un [::id ::name])) [:is-local :boolean]
[:url ::sm/uri]
[:id {:optional true} ::sm/uuid]
[:name {:optional true} [:string {:max 250}]]])
(sv/defmethod ::create-file-media-object-from-url (sv/defmethod ::create-file-media-object-from-url
{::doc/added "1.17" {::doc/added "1.17"
::doc/deprecated "1.19"} ::sm/params schema:create-file-media-object-from-url}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}]
(let [cfg (update cfg ::sto/storage media/configure-assets-storage)] (let [cfg (update cfg ::sto/storage media/configure-assets-storage)]
(files/check-edition-permissions! pool profile-id file-id) (files/check-edition-permissions! pool profile-id file-id)
@ -255,12 +253,15 @@
(declare clone-file-media-object) (declare clone-file-media-object)
(s/def ::clone-file-media-object (def ^:private schema:clone-file-media-object
(s/keys :req [::rpc/profile-id] [:map {:title "clone-file-media-object"}
:req-un [::file-id ::is-local ::id])) [:file-id ::sm/uuid]
[:is-local :boolean]
[:id ::sm/uuid]])
(sv/defmethod ::clone-file-media-object (sv/defmethod ::clone-file-media-object
{::doc/added "1.17"} {::doc/added "1.17"
::sm/params schema:clone-file-media-object}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(files/check-edition-permissions! conn profile-id file-id) (files/check-edition-permissions! conn profile-id file-id)

View File

@ -8,7 +8,7 @@
(:require (:require
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.spec :as us] [app.common.schema :as sm]
[app.db :as db] [app.db :as db]
[app.db.sql :as-alias sql] [app.db.sql :as-alias sql]
[app.loggers.audit :as-alias audit] [app.loggers.audit :as-alias audit]
@ -21,11 +21,7 @@
[app.rpc.quotes :as quotes] [app.rpc.quotes :as quotes]
[app.util.services :as sv] [app.util.services :as sv]
[app.util.time :as dt] [app.util.time :as dt]
[app.worker :as wrk] [app.worker :as wrk]))
[clojure.spec.alpha :as s]))
(s/def ::id ::us/uuid)
(s/def ::name ::us/string)
;; --- Check Project Permissions ;; --- Check Project Permissions
@ -75,13 +71,13 @@
(declare get-projects) (declare get-projects)
(s/def ::team-id ::us/uuid) (def ^:private schema:get-projects
(s/def ::get-projects [:map {:title "get-projects"}
(s/keys :req [::rpc/profile-id] [:team-id ::sm/uuid]])
:req-un [::team-id]))
(sv/defmethod ::get-projects (sv/defmethod ::get-projects
{::doc/added "1.18"} {::doc/added "1.18"
::sm/params schema:get-projects}
[{:keys [::db/pool]} {:keys [::rpc/profile-id team-id]}] [{:keys [::db/pool]} {:keys [::rpc/profile-id team-id]}]
(dm/with-open [conn (db/open pool)] (dm/with-open [conn (db/open pool)]
(teams/check-read-permissions! conn profile-id team-id) (teams/check-read-permissions! conn profile-id team-id)
@ -112,11 +108,12 @@
(declare get-all-projects) (declare get-all-projects)
(s/def ::get-all-projects (def ^:private schema:get-all-projects
(s/keys :req [::rpc/profile-id])) [:map {:title "get-all-projects"}])
(sv/defmethod ::get-all-projects (sv/defmethod ::get-all-projects
{::doc/added "1.18"} {::doc/added "1.18"
::sm/params schema:get-all-projects}
[{:keys [::db/pool]} {:keys [::rpc/profile-id]}] [{:keys [::db/pool]} {:keys [::rpc/profile-id]}]
(dm/with-open [conn (db/open pool)] (dm/with-open [conn (db/open pool)]
(get-all-projects conn profile-id))) (get-all-projects conn profile-id)))
@ -154,12 +151,13 @@
;; --- QUERY: Get project ;; --- QUERY: Get project
(s/def ::get-project (def ^:private schema:get-project
(s/keys :req [::rpc/profile-id] [:map {:title "get-project"}
:req-un [::id])) [:id ::sm/uuid]])
(sv/defmethod ::get-project (sv/defmethod ::get-project
{::doc/added "1.18"} {::doc/added "1.18"
::sm/params schema:get-project}
[{:keys [::db/pool]} {:keys [::rpc/profile-id id]}] [{:keys [::db/pool]} {:keys [::rpc/profile-id id]}]
(dm/with-open [conn (db/open pool)] (dm/with-open [conn (db/open pool)]
(let [project (db/get-by-id conn :project id)] (let [project (db/get-by-id conn :project id)]
@ -170,14 +168,16 @@
;; --- MUTATION: Create Project ;; --- MUTATION: Create Project
(s/def ::create-project (def ^:private schema:create-project
(s/keys :req [::rpc/profile-id] [:map {:title "create-project"}
:req-un [::team-id ::name] [:team-id ::sm/uuid]
:opt-un [::id])) [:name [:string {:max 250 :min 1}]]
[:id {:optional true} ::sm/uuid]])
(sv/defmethod ::create-project (sv/defmethod ::create-project
{::doc/added "1.18" {::doc/added "1.18"
::webhooks/event? true} ::webhooks/event? true
::sm/params schema:create-project}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id] :as params}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id] :as params}]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(teams/check-edition-permissions! conn profile-id team-id) (teams/check-edition-permissions! conn profile-id team-id)
@ -205,14 +205,15 @@
on conflict (team_id, project_id, profile_id) on conflict (team_id, project_id, profile_id)
do update set is_pinned=?") do update set is_pinned=?")
(s/def ::is-pinned ::us/boolean) (def ^:private schema:update-project-pin
(s/def ::project-id ::us/uuid) [:map {:title "update-project-pin"}
(s/def ::update-project-pin [:team-id ::sm/uuid]
(s/keys :req [::rpc/profile-id] [:is-pinned :boolean]
:req-un [::id ::team-id ::is-pinned])) [:id ::sm/uuid]])
(sv/defmethod ::update-project-pin (sv/defmethod ::update-project-pin
{::doc/added "1.18" {::doc/added "1.18"
::sm/params schema:update-project-pin
::webhooks/batch-timeout (dt/duration "5s") ::webhooks/batch-timeout (dt/duration "5s")
::webhooks/batch-key (webhooks/key-fn ::rpc/profile-id :id) ::webhooks/batch-key (webhooks/key-fn ::rpc/profile-id :id)
::webhooks/event? true} ::webhooks/event? true}
@ -226,12 +227,14 @@
(declare rename-project) (declare rename-project)
(s/def ::rename-project (def ^:private schema:rename-project
(s/keys :req [::rpc/profile-id] [:map {:title "rename-project"}
:req-un [::name ::id])) [:name [:string {:max 250 :min 1}]]
[:id ::sm/uuid]])
(sv/defmethod ::rename-project (sv/defmethod ::rename-project
{::doc/added "1.18" {::doc/added "1.18"
::sm/params schema:rename-project
::webhooks/event? true} ::webhooks/event? true}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id name] :as params}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id name] :as params}]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
@ -266,12 +269,14 @@
project)) project))
(s/def ::delete-project
(s/keys :req [::rpc/profile-id] (def ^:private schema:delete-project
:req-un [::id])) [:map {:title "delete-project"}
[:id ::sm/uuid]])
(sv/defmethod ::delete-project (sv/defmethod ::delete-project
{::doc/added "1.18" {::doc/added "1.18"
::sm/params schema:delete-project
::webhooks/event? true} ::webhooks/event? true}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id] :as params}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id] :as params}]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]

View File

@ -6,13 +6,12 @@
(ns app.rpc.commands.search (ns app.rpc.commands.search
(:require (:require
[app.common.spec :as us] [app.common.schema :as sm]
[app.db :as db] [app.db :as db]
[app.rpc :as-alias rpc] [app.rpc :as-alias rpc]
[app.rpc.commands.files :refer [resolve-public-uri]] [app.rpc.commands.files :refer [resolve-public-uri]]
[app.rpc.doc :as-alias doc] [app.rpc.doc :as-alias doc]
[app.util.services :as sv] [app.util.services :as sv]))
[clojure.spec.alpha :as s]))
(def ^:private sql:search-files (def ^:private sql:search-files
"with projects as ( "with projects as (
@ -65,16 +64,14 @@
(assoc :thumbnail-uri (resolve-public-uri media-id))) (assoc :thumbnail-uri (resolve-public-uri media-id)))
(dissoc row :media-id)))))) (dissoc row :media-id))))))
(s/def ::team-id ::us/uuid) (def ^:private schema:search-files
(s/def ::search-files ::us/string) [:map {:title "search-files"}
[:team-id ::sm/uuid]
(s/def ::search-files [:search-term {:optional true} :string]])
(s/keys :req [::rpc/profile-id]
:req-un [::team-id]
:opt-un [::search-term]))
(sv/defmethod ::search-files (sv/defmethod ::search-files
{::doc/added "1.17" {::doc/added "1.17"
::doc/module :files} ::doc/module :files
::sm/params schema:search-files}
[{:keys [::db/pool]} {:keys [::rpc/profile-id team-id search-term]}] [{:keys [::db/pool]} {:keys [::rpc/profile-id team-id search-term]}]
(some->> search-term (search-files pool profile-id team-id))) (some->> search-term (search-files pool profile-id team-id)))

View File

@ -873,7 +873,7 @@
(def ^:private schema:create-team-with-invitations (def ^:private schema:create-team-with-invitations
[:map {:title "create-team-with-invitations"} [:map {:title "create-team-with-invitations"}
[:name :string] [:name [:string {:max 250}]]
[:features {:optional true} ::cfeat/features] [:features {:optional true} ::cfeat/features]
[:id {:optional true} ::sm/uuid] [:id {:optional true} ::sm/uuid]
[:emails ::sm/set-of-emails] [:emails ::sm/set-of-emails]

View File

@ -7,7 +7,7 @@
(ns app.rpc.commands.verify-token (ns app.rpc.commands.verify-token
(:require (:require
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.spec :as us] [app.common.schema :as sm]
[app.db :as db] [app.db :as db]
[app.db.sql :as-alias sql] [app.db.sql :as-alias sql]
[app.http.session :as session] [app.http.session :as session]
@ -23,21 +23,19 @@
[app.tokens :as tokens] [app.tokens :as tokens]
[app.tokens.spec.team-invitation :as-alias spec.team-invitation] [app.tokens.spec.team-invitation :as-alias spec.team-invitation]
[app.util.services :as sv] [app.util.services :as sv]
[clojure.spec.alpha :as s])) [app.util.time :as dt]))
(s/def ::iss keyword?)
(s/def ::exp ::us/inst)
(defmulti process-token (fn [_ _ claims] (:iss claims))) (defmulti process-token (fn [_ _ claims] (:iss claims)))
(s/def ::verify-token (def ^:private schema:verify-token
(s/keys :req-un [::token] [:map {:title "verify-token"}
:opt [::rpc/profile-id])) [:token [:string {:max 1000}]]])
(sv/defmethod ::verify-token (sv/defmethod ::verify-token
{::rpc/auth false {::rpc/auth false
::doc/added "1.15" ::doc/added "1.15"
::doc/module :auth} ::doc/module :auth
::sm/params schema:verify-token}
[{:keys [::db/pool] :as cfg} {:keys [token] :as params}] [{:keys [::db/pool] :as cfg} {:keys [token] :as params}]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(let [claims (tokens/verify (::setup/props cfg) {:token token}) (let [claims (tokens/verify (::setup/props cfg) {:token token})
@ -131,26 +129,28 @@
(assoc member :is-active true))) (assoc member :is-active true)))
(s/def ::spec.team-invitation/profile-id ::us/uuid) (def schema:team-invitation-claims
(s/def ::spec.team-invitation/role ::us/keyword) [:map {:title "TeamInvitationClaims"}
(s/def ::spec.team-invitation/team-id ::us/uuid) [:iss :keyword]
(s/def ::spec.team-invitation/member-email ::us/email) [:exp ::dt/instant]
(s/def ::spec.team-invitation/member-id (s/nilable ::us/uuid)) [:profile-id ::sm/uuid]
[:role teams/schema:role]
[:team-id ::sm/uuid]
[:member-email ::sm/email]
[:member-id {:optional true} ::sm/uuid]])
(s/def ::team-invitation-claims (def valid-team-invitation-claims?
(s/keys :req-un [::iss ::exp (sm/lazy-validator schema:team-invitation-claims))
::spec.team-invitation/profile-id
::spec.team-invitation/role
::spec.team-invitation/team-id
::spec.team-invitation/member-email]
:opt-un [::spec.team-invitation/member-id]))
(defmethod process-token :team-invitation (defmethod process-token :team-invitation
[{:keys [conn] :as cfg} [{:keys [conn] :as cfg}
{:keys [::rpc/profile-id token] :as params} {:keys [::rpc/profile-id token] :as params}
{:keys [member-id team-id member-email] :as claims}] {:keys [member-id team-id member-email] :as claims}]
(us/verify! ::team-invitation-claims claims) (when-not (valid-team-invitation-claims? claims)
(ex/raise :type :validation
:code :invalid-invitation-token
:hint "invitation token contains unexpected data"))
(let [invitation (db/get* conn :team-invitation (let [invitation (db/get* conn :team-invitation
{:team-id team-id :email-to member-email}) {:team-id team-id :email-to member-email})

View File

@ -98,7 +98,7 @@
(assoc ::perms perms) (assoc ::perms perms)
(assoc :profile-id profile-id))] (assoc :profile-id profile-id))]
;; When we have neither profile nor share, we just return a not ;; When we have neither profile nor share, we just return a not
;; found response to the user. ;; found response to the user.
(when-not perms (when-not perms
(ex/raise :type :not-found (ex/raise :type :not-found

View File

@ -8,7 +8,7 @@
(:require (:require
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.spec :as us] [app.common.schema :as sm]
[app.common.uri :as u] [app.common.uri :as u]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.db :as db] [app.db :as db]
@ -19,7 +19,6 @@
[app.rpc.doc :as-alias doc] [app.rpc.doc :as-alias doc]
[app.util.services :as sv] [app.util.services :as sv]
[app.util.time :as dt] [app.util.time :as dt]
[clojure.spec.alpha :as s]
[cuerdas.core :as str])) [cuerdas.core :as str]))
(defn decode-row (defn decode-row
@ -29,18 +28,6 @@
;; --- Mutation: Create Webhook ;; --- Mutation: Create Webhook
(s/def ::team-id ::us/uuid)
(s/def ::uri ::us/uri)
(s/def ::is-active ::us/boolean)
(s/def ::mtype
#{"application/json"
"application/transit+json"})
(s/def ::create-webhook
(s/keys :req [::rpc/profile-id]
:req-un [::team-id ::uri ::mtype]
:opt-un [::is-active]))
;; NOTE: for now the quote is hardcoded but this need to be solved in ;; NOTE: for now the quote is hardcoded but this need to be solved in
;; a more universal way for handling properly object quotes ;; a more universal way for handling properly object quotes
(def max-hooks-for-team 8) (def max-hooks-for-team 8)
@ -99,31 +86,49 @@
{::db/return-keys true}) {::db/return-keys true})
(decode-row))) (decode-row)))
(def valid-mtypes
#{"application/json"
"application/transit+json"})
(def ^:private schema:create-webhook
[:map {:title "create-webhook"}
[:team-id ::sm/uuid]
[:uri ::sm/uri]
[:mtype [::sm/one-of {:format "string"} valid-mtypes]]])
(sv/defmethod ::create-webhook (sv/defmethod ::create-webhook
{::doc/added "1.17"} {::doc/added "1.17"
::sm/params schema:create-webhook}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id] :as params}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id] :as params}]
(check-edition-permissions! pool profile-id team-id) (check-edition-permissions! pool profile-id team-id)
(validate-quotes! cfg params) (validate-quotes! cfg params)
(validate-webhook! cfg nil params) (validate-webhook! cfg nil params)
(insert-webhook! cfg params)) (insert-webhook! cfg params))
(s/def ::update-webhook (def ^:private schema:update-webhook
(s/keys :req-un [::id ::uri ::mtype ::is-active])) [:map {:title "update-webhook"}
[:id ::sm/uuid]
[:uri ::sm/uri]
[:mtype [::sm/one-of {:format "string"} valid-mtypes]]
[:is-active :boolean]])
(sv/defmethod ::update-webhook (sv/defmethod ::update-webhook
{::doc/added "1.17"} {::doc/added "1.17"
::sm/params schema:update-webhook}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id] :as params}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id] :as params}]
(let [whook (-> (db/get pool :webhook {:id id}) (decode-row))] (let [whook (-> (db/get pool :webhook {:id id}) (decode-row))]
(check-edition-permissions! pool profile-id (:team-id whook)) (check-edition-permissions! pool profile-id (:team-id whook))
(validate-webhook! cfg whook params) (validate-webhook! cfg whook params)
(update-webhook! cfg whook params))) (update-webhook! cfg whook params)))
(s/def ::delete-webhook (def ^:private schema:delete-webhook
(s/keys :req [::rpc/profile-id] [:map {:title "delete-webhook"}
:req-un [::id])) [:id ::sm/uuid]])
(sv/defmethod ::delete-webhook (sv/defmethod ::delete-webhook
{::doc/added "1.17"} {::doc/added "1.17"
::sm/params schema:delete-webhook}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id]}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id id]}]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(let [whook (-> (db/get conn :webhook {:id id}) decode-row)] (let [whook (-> (db/get conn :webhook {:id id}) decode-row)]
@ -133,16 +138,17 @@
;; --- Query: Webhooks ;; --- Query: Webhooks
(s/def ::team-id ::us/uuid)
(s/def ::get-webhooks
(s/keys :req [::rpc/profile-id]
:req-un [::team-id]))
(def sql:get-webhooks (def sql:get-webhooks
"select id, uri, mtype, is_active, error_code, error_count "select id, uri, mtype, is_active, error_code, error_count
from webhook where team_id = ? order by uri") from webhook where team_id = ? order by uri")
(def ^:private schema:get-webhooks
[:map {:title "get-webhooks"}
[:team-id ::sm/uuid]])
(sv/defmethod ::get-webhooks (sv/defmethod ::get-webhooks
{::doc/added "1.17"
::sm/params schema:get-webhooks}
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id]}] [{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id team-id]}]
(dm/with-open [conn (db/open pool)] (dm/with-open [conn (db/open pool)]
(check-read-permissions! conn profile-id team-id) (check-read-permissions! conn profile-id team-id)

View File

@ -12,7 +12,7 @@
[app.common.spec :as us] [app.common.spec :as us]
[clojure.spec.alpha :as s])) [clojure.spec.alpha :as s]))
(sm/def! ::permissions (sm/register! ::permissions
[:map {:title "Permissions"} [:map {:title "Permissions"}
[:type {:gen/elements [:membership :share-link]} :keyword] [:type {:gen/elements [:membership :share-link]} :keyword]
[:is-owner :boolean] [:is-owner :boolean]

View File

@ -368,7 +368,7 @@
(let [p1 (System/nanoTime)] (let [p1 (System/nanoTime)]
#(duration {:nanos (- (System/nanoTime) p1)}))) #(duration {:nanos (- (System/nanoTime) p1)})))
(sm/def! ::instant (sm/register! ::instant
{:type ::instant {:type ::instant
:pred instant? :pred instant?
:type-properties :type-properties
@ -379,7 +379,7 @@
::oapi/type "string" ::oapi/type "string"
::oapi/format "iso"}}) ::oapi/format "iso"}})
(sm/def! ::duration (sm/register! ::duration
{:type :durations {:type :durations
:pred duration? :pred duration?
:type-properties :type-properties

View File

@ -104,10 +104,10 @@
(dissoc :app.srepl/server (dissoc :app.srepl/server
:app.http/server :app.http/server
:app.http/router :app.http/router
:app.auth.oidc/google-provider :app.auth.oidc.providers/google
:app.auth.oidc/gitlab-provider :app.auth.oidc.providers/gitlab
:app.auth.oidc/github-provider :app.auth.oidc.providers/github
:app.auth.oidc/generic-provider :app.auth.oidc.providers/generic
:app.setup/templates :app.setup/templates
:app.auth.oidc/routes :app.auth.oidc/routes
:app.worker/monitor :app.worker/monitor

View File

@ -39,6 +39,8 @@
(t/is (nil? (:error out))) (t/is (nil? (:error out)))
(t/is (= 1 (:call-count @http-mock))) (t/is (= 1 (:call-count @http-mock)))
;; (th/print-result! out)
(let [result (:result out)] (let [result (:result out)]
(t/is (contains? result :id)) (t/is (contains? result :id))
(t/is (contains? result :team-id)) (t/is (contains? result :team-id))

View File

@ -84,7 +84,7 @@
"plugins/runtime"} "plugins/runtime"}
(into frontend-only-features))) (into frontend-only-features)))
(sm/def! ::features (sm/register! ::features
[:schema [:schema
{:title "FileFeatures" {:title "FileFeatures"
::smdj/inline true ::smdj/inline true

View File

@ -33,25 +33,24 @@
(def ^:private (def ^:private
schema:operation schema:operation
(sm/define [:multi {:dispatch :type :title "Operation" ::smd/simplified true}
[:multi {:dispatch :type :title "Operation" ::smd/simplified true} [:set
[:set [:map {:title "SetOperation"}
[:map {:title "SetOperation"} [:type [:= :set]]
[:type [:= :set]] [:attr :keyword]
[:attr :keyword] [:val :any]
[:val :any] [:ignore-touched {:optional true} :boolean]
[:ignore-touched {:optional true} :boolean] [:ignore-geometry {:optional true} :boolean]]]
[:ignore-geometry {:optional true} :boolean]]] [:set-touched
[:set-touched [:map {:title "SetTouchedOperation"}
[:map {:title "SetTouchedOperation"} [:type [:= :set-touched]]
[:type [:= :set-touched]] [:touched [:maybe [:set :keyword]]]]]
[:touched [:maybe [:set :keyword]]]]] [:set-remote-synced
[:set-remote-synced [:map {:title "SetRemoteSyncedOperation"}
[:map {:title "SetRemoteSyncedOperation"} [:type [:= :set-remote-synced]]
[:type [:= :set-remote-synced]] [:remote-synced {:optional true} [:maybe :boolean]]]]])
[:remote-synced {:optional true} [:maybe :boolean]]]]]))
(sm/define! ::change (sm/register! ::change
[:schema [:schema
[:multi {:dispatch :type :title "Change" ::smd/simplified true} [:multi {:dispatch :type :title "Change" ::smd/simplified true}
[:set-option [:set-option
@ -246,7 +245,7 @@
[:type [:= :del-typography]] [:type [:= :del-typography]]
[:id ::sm/uuid]]]]]) [:id ::sm/uuid]]]]])
(sm/define! ::changes (sm/register! ::changes
[:sequential {:gen/max 2} ::change]) [:sequential {:gen/max 2} ::change])
(def check-change! (def check-change!

View File

@ -24,7 +24,7 @@
;; Auxiliary functions to help create a set of changes (undo + redo) ;; Auxiliary functions to help create a set of changes (undo + redo)
(sm/define! ::changes (sm/register! ::changes
[:map {:title "changes"} [:map {:title "changes"}
[:redo-changes vector?] [:redo-changes vector?]
[:undo-changes seq?] [:undo-changes seq?]

View File

@ -90,7 +90,7 @@
(sm/lazy-validator (sm/lazy-validator
[:and [:fn matrix?] schema:matrix-attrs])) [:and [:fn matrix?] schema:matrix-attrs]))
(sm/def! ::matrix (sm/register! ::matrix
(letfn [(decode [o] (letfn [(decode [o]
(if (map? o) (if (map? o)
(map->Matrix o) (map->Matrix o)

View File

@ -61,7 +61,7 @@
(sm/lazy-validator (sm/lazy-validator
[:and [:fn point?] schema:point-attrs])) [:and [:fn point?] schema:point-attrs]))
(sm/def! ::point (sm/register! ::point
(letfn [(decode [p] (letfn [(decode [p]
(if (map? p) (if (map? p)
(map->Point p) (map->Point p)

View File

@ -80,7 +80,7 @@
[:x2 ::sm/safe-number] [:x2 ::sm/safe-number]
[:y2 ::sm/safe-number]]) [:y2 ::sm/safe-number]])
(sm/define! ::rect (sm/register! ::rect
[:and [:and
{:gen/gen (->> (sg/tuple (sg/small-double) {:gen/gen (->> (sg/tuple (sg/small-double)
(sg/small-double) (sg/small-double)

View File

@ -75,7 +75,8 @@
(-explain s value) (-explain s value)
(m/explain s value default-options))) (m/explain s value default-options)))
(defn humanize (defn simplify
"Given an explain data structure, return a simplified version of it"
[exp] [exp]
(me/humanize exp)) (me/humanize exp))
@ -86,10 +87,12 @@
(mg/generate (schema s) o))) (mg/generate (schema s) o)))
(defn form (defn form
"Returns a readable form of the schema"
[s] [s]
(m/form s default-options)) (m/form s default-options))
(defn merge (defn merge
"Merge two schemas"
[& items] [& items]
(apply mu/merge (map schema items))) (apply mu/merge (map schema items)))
@ -102,6 +105,7 @@
(m/deref s)) (m/deref s))
(defn error-values (defn error-values
"Get error values form explain data structure"
[exp] [exp]
(malli.error/error-value exp {:malli.error/mask-valid-values '...})) (malli.error/error-value exp {:malli.error/mask-valid-values '...}))
@ -138,18 +142,6 @@
:decoders coders :decoders coders
:encoders coders}))) :encoders coders})))
(defn validator
[s]
(if (lazy-schema? s)
(-get-validator s)
(-> s schema m/validator)))
(defn explainer
[s]
(if (lazy-schema? s)
(-get-explainer s)
(-> s schema m/explainer)))
(defn encode (defn encode
([s val transformer] ([s val transformer]
(m/encode s val default-options transformer)) (m/encode s val default-options transformer))
@ -164,6 +156,18 @@
([s val options transformer] ([s val options transformer]
(m/decode s val options transformer))) (m/decode s val options transformer)))
(defn validator
[s]
(if (lazy-schema? s)
(-get-validator s)
(-> s schema m/validator)))
(defn explainer
[s]
(if (lazy-schema? s)
(-get-explainer s)
(-> s schema m/explainer)))
(defn encoder (defn encoder
([s] ([s]
(if (lazy-schema? s) (if (lazy-schema? s)
@ -201,6 +205,7 @@
(fn [v] (@vfn v))))) (fn [v] (@vfn v)))))
(defn humanize-explain (defn humanize-explain
"Returns a string representation of the explain data structure"
[{:keys [schema errors value]} & {:keys [length level]}] [{:keys [schema errors value]} & {:keys [length level]}]
(let [errors (mapv #(update % :schema form) errors)] (let [errors (mapv #(update % :schema form) errors)]
(with-out-str (with-out-str
@ -213,7 +218,6 @@
:level (d/nilv level 8) :level (d/nilv level 8)
:length (d/nilv length 12)}))))) :length (d/nilv length 12)})))))
(defmethod v/-format ::schemaless-explain (defmethod v/-format ::schemaless-explain
[_ {:keys [schema] :as explanation} printer] [_ {:keys [schema] :as explanation} printer]
{:body [:group {:body [:group
@ -353,15 +357,8 @@
(defn register! [type s] (defn register! [type s]
(let [s (if (map? s) (simple-schema s) s)] (let [s (if (map? s) (simple-schema s) s)]
(swap! sr/registry assoc type s))) (swap! sr/registry assoc type s)
nil))
(defn def! [type s]
(register! type s)
nil)
(defn define! [id s]
(register! id s)
nil)
(defn define (defn define
"Create ans instance of ILazySchema" "Create ans instance of ILazySchema"
@ -435,8 +432,8 @@
;; --- BUILTIN SCHEMAS ;; --- BUILTIN SCHEMAS
(define! :merge (mu/-merge)) (register! :merge (mu/-merge))
(define! :union (mu/-union)) (register! :union (mu/-union))
(def uuid-rx (def uuid-rx
#"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$") #"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$")
@ -447,7 +444,7 @@
(some->> (re-matches uuid-rx s) uuid/uuid) (some->> (re-matches uuid-rx s) uuid/uuid)
s)) s))
(define! ::uuid (register! ::uuid
{:type ::uuid {:type ::uuid
:pred uuid? :pred uuid?
:type-properties :type-properties
@ -472,7 +469,7 @@
(and (string? s) (and (string? s)
(re-seq email-re s))) (re-seq email-re s)))
(define! ::email (register! ::email
{:type :string {:type :string
:pred email-string? :pred email-string?
:property-pred :property-pred
@ -501,7 +498,7 @@
;; NOTE: this is general purpose set spec and should be used over the other ;; NOTE: this is general purpose set spec and should be used over the other
(define! ::set (register! ::set
{:type :set {:type :set
:min 0 :min 0
:max 1 :max 1
@ -557,7 +554,7 @@
(into #{} xform v)))}}))}) (into #{} xform v)))}}))})
(define! ::vec (register! ::vec
{:type :vector {:type :vector
:min 0 :min 0
:max 1 :max 1
@ -614,7 +611,7 @@
(into [] xform v)))}}))}) (into [] xform v)))}}))})
(define! ::set-of-strings (register! ::set-of-strings
{:type ::set-of-strings {:type ::set-of-strings
:pred #(and (set? %) (every? string? %)) :pred #(and (set? %) (every? string? %))
:type-properties :type-properties
@ -630,7 +627,7 @@
(let [v (if (string? v) (str/split v #"[\s,]+") v)] (let [v (if (string? v) (str/split v #"[\s,]+") v)]
(into #{} non-empty-strings-xf v)))}}) (into #{} non-empty-strings-xf v)))}})
(define! ::set-of-keywords (register! ::set-of-keywords
{:type ::set-of-keywords {:type ::set-of-keywords
:pred #(and (set? %) (every? keyword? %)) :pred #(and (set? %) (every? keyword? %))
:type-properties :type-properties
@ -646,7 +643,7 @@
(let [v (if (string? v) (str/split v #"[\s,]+") v)] (let [v (if (string? v) (str/split v #"[\s,]+") v)]
(into #{} (comp non-empty-strings-xf (map keyword)) v)))}}) (into #{} (comp non-empty-strings-xf (map keyword)) v)))}})
(define! ::set-of-emails (register! ::set-of-emails
{:type ::set-of-emails {:type ::set-of-emails
:pred #(and (set? %) (every? string? %)) :pred #(and (set? %) (every? string? %))
:type-properties :type-properties
@ -662,7 +659,7 @@
(let [v (if (string? v) (str/split v #"[\s,]+") v)] (let [v (if (string? v) (str/split v #"[\s,]+") v)]
(into #{} (keep parse-email) v)))}}) (into #{} (keep parse-email) v)))}})
(define! ::set-of-uuid (register! ::set-of-uuid
{:type ::set-of-uuid {:type ::set-of-uuid
:pred #(and (set? %) (every? uuid? %)) :pred #(and (set? %) (every? uuid? %))
:type-properties :type-properties
@ -678,7 +675,7 @@
(let [v (if (string? v) (str/split v #"[\s,]+") v)] (let [v (if (string? v) (str/split v #"[\s,]+") v)]
(into #{} (keep parse-uuid) v)))}}) (into #{} (keep parse-uuid) v)))}})
(define! ::coll-of-uuid (register! ::coll-of-uuid
{:type ::set-of-uuid {:type ::set-of-uuid
:pred (partial every? uuid?) :pred (partial every? uuid?)
:type-properties :type-properties
@ -694,7 +691,7 @@
(let [v (if (string? v) (str/split v #"[\s,]+") v)] (let [v (if (string? v) (str/split v #"[\s,]+") v)]
(into [] (keep parse-uuid) v)))}}) (into [] (keep parse-uuid) v)))}})
(define! ::one-of (register! ::one-of
{:type ::one-of {:type ::one-of
:min 1 :min 1
:max 1 :max 1
@ -717,7 +714,7 @@
;; Integer/MIN_VALUE ;; Integer/MIN_VALUE
(def min-safe-int -2147483648) (def min-safe-int -2147483648)
(define! ::safe-int (register! ::safe-int
{:type ::safe-int {:type ::safe-int
:pred #(and (int? %) (>= max-safe-int %) (>= % min-safe-int)) :pred #(and (int? %) (>= max-safe-int %) (>= % min-safe-int))
:type-properties :type-properties
@ -732,7 +729,7 @@
(parse-long s) (parse-long s)
s))}}) s))}})
(define! ::safe-number (register! ::safe-number
{:type ::safe-number {:type ::safe-number
:pred #(and (number? %) (>= max-safe-int %) (>= % min-safe-int)) :pred #(and (number? %) (>= max-safe-int %) (>= % min-safe-int))
:type-properties :type-properties
@ -748,7 +745,7 @@
(parse-double s) (parse-double s)
s))}}) s))}})
(define! ::safe-double (register! ::safe-double
{:type ::safe-double {:type ::safe-double
:pred #(and (double? %) (>= max-safe-int %) (>= % min-safe-int)) :pred #(and (double? %) (>= max-safe-int %) (>= % min-safe-int))
:type-properties :type-properties
@ -763,7 +760,7 @@
(parse-double s) (parse-double s)
s))}}) s))}})
(define! ::contains-any (register! ::contains-any
{:type ::contains-any {:type ::contains-any
:min 1 :min 1
:max 1 :max 1
@ -781,7 +778,7 @@
{:title "contains" {:title "contains"
:description "contains predicate"}}))}) :description "contains predicate"}}))})
(define! ::inst (register! ::inst
{:type ::inst {:type ::inst
:pred inst? :pred inst?
:type-properties :type-properties
@ -793,12 +790,12 @@
::oapi/type "number" ::oapi/type "number"
::oapi/format "int64"}}) ::oapi/format "int64"}})
(define! ::fn (register! ::fn
[:schema fn?]) [:schema fn?])
;; FIXME: deprecated, replace with ::text ;; FIXME: deprecated, replace with ::text
(define! ::word-string (register! ::word-string
{:type ::word-string {:type ::word-string
:pred #(and (string? %) (not (str/blank? %))) :pred #(and (string? %) (not (str/blank? %)))
:property-pred (m/-min-max-pred count) :property-pred (m/-min-max-pred count)
@ -810,7 +807,7 @@
::oapi/type "string" ::oapi/type "string"
::oapi/format "string"}}) ::oapi/format "string"}})
(define! ::uri (register! ::uri
{:type ::uri {:type ::uri
:pred u/uri? :pred u/uri?
:property-pred :property-pred
@ -847,9 +844,13 @@
:gen/gen (sg/uri) :gen/gen (sg/uri)
::oapi/type "string" ::oapi/type "string"
::oapi/format "uri" ::oapi/format "uri"
::oapi/decode (comp u/uri str/trim)}}) ::oapi/decode
(fn [val]
(if (u/uri? val)
val
(-> val str/trim u/uri)))}})
(define! ::text (register! ::text
{:type :string {:type :string
:pred #(and (string? %) (not (str/blank? %))) :pred #(and (string? %) (not (str/blank? %)))
:property-pred :property-pred
@ -891,7 +892,7 @@
(str/blank? value)) (str/blank? value))
"errors.field-not-all-whitespace")))}}) "errors.field-not-all-whitespace")))}})
(define! ::password (register! ::password
{:type :string {:type :string
:pred :pred
(fn [value] (fn [value]
@ -908,7 +909,7 @@
;; FIXME: this should not be here ;; FIXME: this should not be here
(define! ::plugin-data (register! ::plugin-data
[:map-of {:gen/max 5} :string :string]) [:map-of {:gen/max 5} :string :string])
;; ---- PREDICATES ;; ---- PREDICATES

View File

@ -37,7 +37,7 @@
(.. g (toString 16) (padStart 2 "0")) (.. g (toString 16) (padStart 2 "0"))
(.. b (toString 16) (padStart 2 "0")))))) (.. b (toString 16) (padStart 2 "0"))))))
(sm/define! ::rgb-color (sm/register! ::rgb-color
{:type ::rgb-color {:type ::rgb-color
:pred #(and (string? %) (some? (re-matches rgb-color-re %))) :pred #(and (string? %) (some? (re-matches rgb-color-re %)))
:type-properties :type-properties
@ -49,7 +49,7 @@
::oapi/type "integer" ::oapi/type "integer"
::oapi/format "int64"}}) ::oapi/format "int64"}})
(sm/define! ::image-color (sm/register! ::image-color
[:map {:title "ImageColor"} [:map {:title "ImageColor"}
[:name {:optional true} :string] [:name {:optional true} :string]
[:width :int] [:width :int]
@ -58,7 +58,7 @@
[:id ::sm/uuid] [:id ::sm/uuid]
[:keep-aspect-ratio {:optional true} :boolean]]) [:keep-aspect-ratio {:optional true} :boolean]])
(sm/define! ::gradient (sm/register! ::gradient
[:map {:title "Gradient"} [:map {:title "Gradient"}
[:type [::sm/one-of #{:linear :radial}]] [:type [::sm/one-of #{:linear :radial}]]
[:start-x ::sm/safe-number] [:start-x ::sm/safe-number]
@ -73,7 +73,7 @@
[:opacity {:optional true} [:maybe ::sm/safe-number]] [:opacity {:optional true} [:maybe ::sm/safe-number]]
[:offset ::sm/safe-number]]]]]) [:offset ::sm/safe-number]]]]])
(sm/define! ::color (sm/register! ::color
[:and [:and
[:map {:title "Color"} [:map {:title "Color"}
[:id {:optional true} ::sm/uuid] [:id {:optional true} ::sm/uuid]
@ -91,7 +91,7 @@
[:map-of {:gen/max 5} :keyword ::sm/plugin-data]]] [:map-of {:gen/max 5} :keyword ::sm/plugin-data]]]
[::sm/contains-any {:strict true} [:color :gradient :image]]]) [::sm/contains-any {:strict true} [:color :gradient :image]]])
(sm/define! ::recent-color (sm/register! ::recent-color
[:and [:and
[:map {:title "RecentColor"} [:map {:title "RecentColor"}
[:opacity {:optional true} [:maybe ::sm/safe-number]] [:opacity {:optional true} [:maybe ::sm/safe-number]]

View File

@ -26,7 +26,7 @@
(def valid-container-types (def valid-container-types
#{:page :component}) #{:page :component})
(sm/define! ::container (sm/register! ::container
[:map [:map
[:id ::sm/uuid] [:id ::sm/uuid]
[:type {:optional true} [:type {:optional true}

View File

@ -34,7 +34,7 @@
;; SCHEMA ;; SCHEMA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(sm/define! ::media-object (sm/register! ::media-object
[:map {:title "FileMediaObject"} [:map {:title "FileMediaObject"}
[:id ::sm/uuid] [:id ::sm/uuid]
[:name :string] [:name :string]
@ -43,7 +43,7 @@
[:mtype :string] [:mtype :string]
[:path {:optional true} [:maybe :string]]]) [:path {:optional true} [:maybe :string]]])
(sm/define! ::data (sm/register! ::data
[:map {:title "FileData"} [:map {:title "FileData"}
[:pages [:vector ::sm/uuid]] [:pages [:vector ::sm/uuid]]
[:pages-index [:pages-index

View File

@ -13,12 +13,12 @@
;; SCHEMA ;; SCHEMA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(sm/def! ::grid-color (sm/register! ::grid-color
[:map {:title "PageGridColor"} [:map {:title "PageGridColor"}
[:color ::ctc/rgb-color] [:color ::ctc/rgb-color]
[:opacity ::sm/safe-number]]) [:opacity ::sm/safe-number]])
(sm/def! ::column-params (sm/register! ::column-params
[:map [:map
[:color ::grid-color] [:color ::grid-color]
[:type {:optional true} [::sm/one-of #{:stretch :left :center :right}]] [:type {:optional true} [::sm/one-of #{:stretch :left :center :right}]]
@ -27,12 +27,12 @@
[:item-length {:optional true} [:maybe ::sm/safe-number]] [:item-length {:optional true} [:maybe ::sm/safe-number]]
[:gutter {:optional true} [:maybe ::sm/safe-number]]]) [:gutter {:optional true} [:maybe ::sm/safe-number]]])
(sm/def! ::square-params (sm/register! ::square-params
[:map [:map
[:size {:optional true} [:maybe ::sm/safe-number]] [:size {:optional true} [:maybe ::sm/safe-number]]
[:color ::grid-color]]) [:color ::grid-color]])
(sm/def! ::grid (sm/register! ::grid
[:multi {:dispatch :type} [:multi {:dispatch :type}
[:column [:column
[:map [:map
@ -52,7 +52,7 @@
[:display :boolean] [:display :boolean]
[:params ::square-params]]]]) [:params ::square-params]]]])
(sm/def! ::saved-grids (sm/register! ::saved-grids
[:map {:title "PageGrid"} [:map {:title "PageGrid"}
[:square {:optional true} ::square-params] [:square {:optional true} ::square-params]
[:row {:optional true} ::column-params] [:row {:optional true} ::column-params]

View File

@ -17,20 +17,20 @@
;; SCHEMAS ;; SCHEMAS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(sm/define! ::flow (sm/register! ::flow
[:map {:title "PageFlow"} [:map {:title "PageFlow"}
[:id ::sm/uuid] [:id ::sm/uuid]
[:name :string] [:name :string]
[:starting-frame ::sm/uuid]]) [:starting-frame ::sm/uuid]])
(sm/define! ::guide (sm/register! ::guide
[:map {:title "PageGuide"} [:map {:title "PageGuide"}
[:id ::sm/uuid] [:id ::sm/uuid]
[:axis [::sm/one-of #{:x :y}]] [:axis [::sm/one-of #{:x :y}]]
[:position ::sm/safe-number] [:position ::sm/safe-number]
[:frame-id {:optional true} [:maybe ::sm/uuid]]]) [:frame-id {:optional true} [:maybe ::sm/uuid]]])
(sm/define! ::page (sm/register! ::page
[:map {:title "FilePage"} [:map {:title "FilePage"}
[:id ::sm/uuid] [:id ::sm/uuid]
[:name :string] [:name :string]

View File

@ -85,10 +85,10 @@
:exclude :exclude
:intersection}) :intersection})
(sm/define! ::points (sm/register! ::points
[:vector {:gen/max 4 :gen/min 4} ::gpt/point]) [:vector {:gen/max 4 :gen/min 4} ::gpt/point])
(sm/define! ::fill (sm/register! ::fill
[:map {:title "Fill"} [:map {:title "Fill"}
[:fill-color {:optional true} ::ctc/rgb-color] [:fill-color {:optional true} ::ctc/rgb-color]
[:fill-opacity {:optional true} ::sm/safe-number] [:fill-opacity {:optional true} ::sm/safe-number]
@ -97,7 +97,7 @@
[:fill-color-ref-id {:optional true} [:maybe ::sm/uuid]] [:fill-color-ref-id {:optional true} [:maybe ::sm/uuid]]
[:fill-image {:optional true} ::ctc/image-color]]) [:fill-image {:optional true} ::ctc/image-color]])
(sm/define! ::stroke (sm/register! ::stroke
[:map {:title "Stroke"} [:map {:title "Stroke"}
[:stroke-color {:optional true} :string] [:stroke-color {:optional true} :string]
[:stroke-color-ref-file {:optional true} ::sm/uuid] [:stroke-color-ref-file {:optional true} ::sm/uuid]
@ -115,7 +115,7 @@
[:stroke-color-gradient {:optional true} ::ctc/gradient] [:stroke-color-gradient {:optional true} ::ctc/gradient]
[:stroke-image {:optional true} ::ctc/image-color]]) [:stroke-image {:optional true} ::ctc/image-color]])
(sm/define! ::shape-base-attrs (sm/register! ::shape-base-attrs
[:map {:title "ShapeMinimalRecord"} [:map {:title "ShapeMinimalRecord"}
[:id ::sm/uuid] [:id ::sm/uuid]
[:name :string] [:name :string]
@ -127,14 +127,14 @@
[:parent-id ::sm/uuid] [:parent-id ::sm/uuid]
[:frame-id ::sm/uuid]]) [:frame-id ::sm/uuid]])
(sm/define! ::shape-geom-attrs (sm/register! ::shape-geom-attrs
[:map {:title "ShapeGeometryAttrs"} [:map {:title "ShapeGeometryAttrs"}
[:x ::sm/safe-number] [:x ::sm/safe-number]
[:y ::sm/safe-number] [:y ::sm/safe-number]
[:width ::sm/safe-number] [:width ::sm/safe-number]
[:height ::sm/safe-number]]) [:height ::sm/safe-number]])
(sm/define! ::shape-attrs (sm/register! ::shape-attrs
[:map {:title "ShapeAttrs"} [:map {:title "ShapeAttrs"}
[:name {:optional true} :string] [:name {:optional true} :string]
[:component-id {:optional true} ::sm/uuid] [:component-id {:optional true} ::sm/uuid]
@ -190,12 +190,12 @@
[:plugin-data {:optional true} [:plugin-data {:optional true}
[:map-of {:gen/max 5} :keyword ::sm/plugin-data]]]) [:map-of {:gen/max 5} :keyword ::sm/plugin-data]]])
(sm/define! ::group-attrs (sm/register! ::group-attrs
[:map {:title "GroupAttrs"} [:map {:title "GroupAttrs"}
[:type [:= :group]] [:type [:= :group]]
[:shapes [:vector {:gen/max 10 :gen/min 1} ::sm/uuid]]]) [:shapes [:vector {:gen/max 10 :gen/min 1} ::sm/uuid]]])
(sm/define! ::frame-attrs (sm/register! ::frame-attrs
[:map {:title "FrameAttrs"} [:map {:title "FrameAttrs"}
[:type [:= :frame]] [:type [:= :frame]]
[:shapes [:vector {:gen/max 10 :gen/min 1} ::sm/uuid]] [:shapes [:vector {:gen/max 10 :gen/min 1} ::sm/uuid]]
@ -203,7 +203,7 @@
[:show-content {:optional true} :boolean] [:show-content {:optional true} :boolean]
[:hide-in-viewer {:optional true} :boolean]]) [:hide-in-viewer {:optional true} :boolean]])
(sm/define! ::bool-attrs (sm/register! ::bool-attrs
[:map {:title "BoolAttrs"} [:map {:title "BoolAttrs"}
[:type [:= :bool]] [:type [:= :bool]]
[:shapes [:vector {:gen/max 10 :gen/min 1} ::sm/uuid]] [:shapes [:vector {:gen/max 10 :gen/min 1} ::sm/uuid]]
@ -223,19 +223,19 @@
[:maybe [:maybe
[:map-of {:gen/max 5} :keyword ::sm/safe-number]]]]]]]) [:map-of {:gen/max 5} :keyword ::sm/safe-number]]]]]]])
(sm/define! ::rect-attrs (sm/register! ::rect-attrs
[:map {:title "RectAttrs"} [:map {:title "RectAttrs"}
[:type [:= :rect]]]) [:type [:= :rect]]])
(sm/define! ::circle-attrs (sm/register! ::circle-attrs
[:map {:title "CircleAttrs"} [:map {:title "CircleAttrs"}
[:type [:= :circle]]]) [:type [:= :circle]]])
(sm/define! ::svg-raw-attrs (sm/register! ::svg-raw-attrs
[:map {:title "SvgRawAttrs"} [:map {:title "SvgRawAttrs"}
[:type [:= :svg-raw]]]) [:type [:= :svg-raw]]])
(sm/define! ::image-attrs (sm/register! ::image-attrs
[:map {:title "ImageAttrs"} [:map {:title "ImageAttrs"}
[:type [:= :image]] [:type [:= :image]]
[:metadata [:metadata
@ -245,17 +245,17 @@
[:mtype {:optional true} [:maybe :string]] [:mtype {:optional true} [:maybe :string]]
[:id ::sm/uuid]]]]) [:id ::sm/uuid]]]])
(sm/define! ::path-attrs (sm/register! ::path-attrs
[:map {:title "PathAttrs"} [:map {:title "PathAttrs"}
[:type [:= :path]] [:type [:= :path]]
[:content ::ctsp/content]]) [:content ::ctsp/content]])
(sm/define! ::text-attrs (sm/register! ::text-attrs
[:map {:title "TextAttrs"} [:map {:title "TextAttrs"}
[:type [:= :text]] [:type [:= :text]]
[:content {:optional true} [:maybe ::ctsx/content]]]) [:content {:optional true} [:maybe ::ctsx/content]]])
(sm/define! ::shape-map (sm/register! ::shape-map
[:multi {:dispatch :type :title "Shape"} [:multi {:dispatch :type :title "Shape"}
[:group [:group
[:and {:title "GroupShape"} [:and {:title "GroupShape"}
@ -327,7 +327,7 @@
::text-attrs ::text-attrs
::ctsl/layout-child-attrs]]]) ::ctsl/layout-child-attrs]]])
(sm/define! ::shape (sm/register! ::shape
[:and [:and
{:title "Shape" {:title "Shape"
:gen/gen (->> (sg/generator ::shape-base-attrs) :gen/gen (->> (sg/generator ::shape-base-attrs)

View File

@ -26,7 +26,7 @@
;; SCHEMA ;; SCHEMA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(sm/def! ::blur (sm/register! ::blur
[:map {:title "Blur"} [:map {:title "Blur"}
[:id ::sm/uuid] [:id ::sm/uuid]
[:type [:= :layer-blur]] [:type [:= :layer-blur]]

View File

@ -10,8 +10,8 @@
(def export-types #{:png :jpeg :svg :pdf}) (def export-types #{:png :jpeg :svg :pdf})
(sm/def! ::export (sm/register! ::export
[:map {:title "ShapeExport"} [:map {:title "ShapeExport"}
[:type :keyword] [:type [::sm/one-of export-types]]
[:scale ::sm/safe-number] [:scale ::sm/safe-number]
[:suffix :string]]) [:suffix :string]])

View File

@ -71,7 +71,7 @@
(def animation-types (def animation-types
#{:dissolve :slide :push}) #{:dissolve :slide :push})
(sm/define! ::animation (sm/register! ::animation
[:multi {:dispatch :animation-type :title "Animation"} [:multi {:dispatch :animation-type :title "Animation"}
[:dissolve [:dissolve
[:map {:title "AnimationDisolve"} [:map {:title "AnimationDisolve"}
@ -96,7 +96,7 @@
(def check-animation! (def check-animation!
(sm/check-fn ::animation)) (sm/check-fn ::animation))
(sm/define! ::interaction (sm/register! ::interaction
[:multi {:dispatch :action-type} [:multi {:dispatch :action-type}
[:navigate [:navigate
[:map [:map

View File

@ -87,7 +87,7 @@
:layout-item-absolute :layout-item-absolute
:layout-item-z-index]) :layout-item-z-index])
(sm/def! ::layout-attrs (sm/register! ::layout-attrs
[:map {:title "LayoutAttrs"} [:map {:title "LayoutAttrs"}
[:layout {:optional true} [::sm/one-of layout-types]] [:layout {:optional true} [::sm/one-of layout-types]]
[:layout-flex-dir {:optional true} [::sm/one-of flex-direction-types]] [:layout-flex-dir {:optional true} [::sm/one-of flex-direction-types]]
@ -130,7 +130,7 @@
(def grid-cell-justify-self-types (def grid-cell-justify-self-types
#{:auto :start :center :end :stretch}) #{:auto :start :center :end :stretch})
(sm/def! ::grid-cell (sm/register! ::grid-cell
[:map {:title "GridCell"} [:map {:title "GridCell"}
[:id ::sm/uuid] [:id ::sm/uuid]
[:area-name {:optional true} :string] [:area-name {:optional true} :string]
@ -144,7 +144,7 @@
[:shapes [:shapes
[:vector {:gen/max 1} ::sm/uuid]]]) [:vector {:gen/max 1} ::sm/uuid]]])
(sm/def! ::grid-track (sm/register! ::grid-track
[:map {:title "GridTrack"} [:map {:title "GridTrack"}
[:type [::sm/one-of grid-track-types]] [:type [::sm/one-of grid-track-types]]
[:value {:optional true} [:maybe ::sm/safe-number]]]) [:value {:optional true} [:maybe ::sm/safe-number]]])
@ -166,7 +166,7 @@
(def item-align-self-types (def item-align-self-types
#{:start :end :center :stretch}) #{:start :end :center :stretch})
(sm/def! ::layout-child-attrs (sm/register! ::layout-child-attrs
[:map {:title "LayoutChildAttrs"} [:map {:title "LayoutChildAttrs"}
[:layout-item-margin-type {:optional true} [::sm/one-of item-margin-types]] [:layout-item-margin-type {:optional true} [::sm/one-of item-margin-types]]
[:layout-item-margin {:optional true} [:layout-item-margin {:optional true}
@ -192,7 +192,7 @@
(def valid-layouts (def valid-layouts
#{:flex :grid}) #{:flex :grid})
(sm/def! ::layout (sm/register! ::layout
[::sm/one-of valid-layouts]) [::sm/one-of valid-layouts])
(defn flex-layout? (defn flex-layout?

View File

@ -12,7 +12,7 @@
;; SCHEMA ;; SCHEMA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(sm/define! ::segment (sm/register! ::segment
[:multi {:title "PathSegment" :dispatch :command} [:multi {:title "PathSegment" :dispatch :command}
[:line-to [:line-to
[:map [:map
@ -43,5 +43,5 @@
[:c2x ::sm/safe-number] [:c2x ::sm/safe-number]
[:c2y ::sm/safe-number]]]]]]) [:c2y ::sm/safe-number]]]]]])
(sm/define! ::content (sm/register! ::content
[:vector ::segment]) [:vector ::segment])

View File

@ -11,7 +11,7 @@
(def styles #{:drop-shadow :inner-shadow}) (def styles #{:drop-shadow :inner-shadow})
(sm/def! ::shadow (sm/register! ::shadow
[:map {:title "Shadow"} [:map {:title "Shadow"}
[:id [:maybe ::sm/uuid]] [:id [:maybe ::sm/uuid]]
[:style [::sm/one-of styles]] [:style [::sm/one-of styles]]

View File

@ -16,7 +16,7 @@
(def node-types #{"root" "paragraph-set" "paragraph"}) (def node-types #{"root" "paragraph-set" "paragraph"})
(sm/def! ::content (sm/register! ::content
[:map [:map
[:type [:= "root"]] [:type [:= "root"]]
[:key {:optional true} :string] [:key {:optional true} :string]
@ -64,7 +64,7 @@
(sm/def! ::position-data (sm/register! ::position-data
[:vector {:min 1 :gen/max 2} [:vector {:min 1 :gen/max 2}
[:map [:map
[:x ::sm/safe-number] [:x ::sm/safe-number]

View File

@ -15,7 +15,7 @@
;; SCHEMA ;; SCHEMA
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(sm/def! ::typography (sm/register! ::typography
[:map {:title "Typography"} [:map {:title "Typography"}
[:id ::sm/uuid] [:id ::sm/uuid]
[:name :string] [:name :string]

View File

@ -1042,6 +1042,9 @@
{:file-id file-id {:file-id file-id
:library-id library-id})))))))))) :library-id library-id}))))))))))
;; FIXME: the data should be set on the backend for clock consistency
(def ignore-sync (def ignore-sync
"Mark the file as ignore syncs. All library changes before this moment will not "Mark the file as ignore syncs. All library changes before this moment will not
ber notified to sync." ber notified to sync."