0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-26 00:19:07 -05:00

♻️ Move comments mutations to commands

This commit is contained in:
Andrey Antukh 2022-08-08 10:36:15 +02:00
parent 0b3d25a890
commit aceefc0485
5 changed files with 353 additions and 230 deletions

View file

@ -6,14 +6,23 @@
(ns app.rpc.commands.comments (ns app.rpc.commands.comments
(:require (:require
[app.common.exceptions :as ex]
[app.common.geom.point :as gpt]
[app.common.spec :as us] [app.common.spec :as us]
[app.db :as db] [app.db :as db]
[app.rpc.doc :as-alias doc] [app.rpc.doc :as-alias doc]
[app.rpc.queries.files :as files] [app.rpc.queries.files :as files]
[app.rpc.queries.teams :as teams] [app.rpc.queries.teams :as teams]
[app.rpc.retry :as retry]
[app.util.blob :as blob]
[app.util.services :as sv] [app.util.services :as sv]
[app.util.time :as dt]
[clojure.spec.alpha :as s])) [clojure.spec.alpha :as s]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; QUERY COMMANDS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn decode-row (defn decode-row
[{:keys [participants position] :as row}] [{:keys [participants position] :as row}]
(cond-> row (cond-> row
@ -131,7 +140,7 @@
(decode-row))))) (decode-row)))))
(defn get-comment-thread (defn get-comment-thread
[conn {:keys [profile-id file-id id share-id] :as params}] [conn {:keys [profile-id file-id id] :as params}]
(let [sql (str "with threads as (" sql:comment-threads ")" (let [sql (str "with threads as (" sql:comment-threads ")"
"select * from threads where id = ?")] "select * from threads where id = ?")]
(-> (db/exec-one! conn [sql profile-id file-id id]) (-> (db/exec-one! conn [sql profile-id file-id id])
@ -209,3 +218,317 @@
(defn get-file-comments-users (defn get-file-comments-users
[conn file-id profile-id] [conn file-id profile-id]
(db/exec! conn [sql:file-comment-users file-id profile-id])) (db/exec! conn [sql:file-comment-users file-id profile-id]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; MUTATION COMMANDS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; --- COMMAND: Create Comment Thread
(declare upsert-comment-thread-status!)
(declare create-comment-thread)
(declare retrieve-page-name)
(s/def ::page-id ::us/uuid)
(s/def ::file-id ::us/uuid)
(s/def ::share-id (s/nilable ::us/uuid))
(s/def ::profile-id ::us/uuid)
(s/def ::position ::gpt/point)
(s/def ::content ::us/string)
(s/def ::frame-id ::us/uuid)
(s/def ::create-comment-thread
(s/keys :req-un [::profile-id ::file-id ::position ::content ::page-id ::frame-id]
:opt-un [::share-id]))
(sv/defmethod ::create-comment-thread
{::retry/max-retries 3
::retry/matches retry/conflict-db-insert?
::doc/added "1.15"}
[{:keys [pool] :as cfg} {:keys [profile-id file-id share-id] :as params}]
(db/with-atomic [conn pool]
(files/check-comment-permissions! conn profile-id file-id share-id)
(create-comment-thread conn params)))
(defn- retrieve-next-seqn
[conn file-id]
(let [sql "select (f.comment_thread_seqn + 1) as next_seqn from file as f where f.id = ?"
res (db/exec-one! conn [sql file-id])]
(:next-seqn res)))
(defn create-comment-thread
[conn {:keys [profile-id file-id page-id position content frame-id] :as params}]
(let [seqn (retrieve-next-seqn conn file-id)
now (dt/now)
pname (retrieve-page-name conn params)
thread (db/insert! conn :comment-thread
{:file-id file-id
:owner-id profile-id
:participants (db/tjson #{profile-id})
:page-name pname
:page-id page-id
:created-at now
:modified-at now
:seqn seqn
:position (db/pgpoint position)
:frame-id frame-id})]
;; Create a comment entry
(db/insert! conn :comment
{:thread-id (:id thread)
:owner-id profile-id
:created-at now
:modified-at now
:content content})
;; Make the current thread as read.
(upsert-comment-thread-status! conn profile-id (:id thread))
;; Optimistic update of current seq number on file.
(db/update! conn :file
{:comment-thread-seqn seqn}
{:id file-id})
(select-keys thread [:id :file-id :page-id])))
(defn- retrieve-page-name
[conn {:keys [file-id page-id]}]
(let [{:keys [data]} (db/get-by-id conn :file file-id)
data (blob/decode data)]
(get-in data [:pages-index page-id :name])))
;; --- COMMAND: Update Comment Thread Status
(s/def ::id ::us/uuid)
(s/def ::share-id (s/nilable ::us/uuid))
(s/def ::update-comment-thread-status
(s/keys :req-un [::profile-id ::id]
:opt-un [::share-id]))
(sv/defmethod ::update-comment-thread-status
{::doc/added "1.15"}
[{:keys [pool] :as cfg} {:keys [profile-id id share-id] :as params}]
(db/with-atomic [conn pool]
(let [cthr (db/get-by-id conn :comment-thread id {:for-update true})]
(when-not cthr
(ex/raise :type :not-found))
(files/check-comment-permissions! conn profile-id (:file-id cthr) share-id)
(upsert-comment-thread-status! conn profile-id (:id cthr)))))
(def sql:upsert-comment-thread-status
"insert into comment_thread_status (thread_id, profile_id)
values (?, ?)
on conflict (thread_id, profile_id)
do update set modified_at = clock_timestamp()
returning modified_at;")
(defn upsert-comment-thread-status!
[conn profile-id thread-id]
(db/exec-one! conn [sql:upsert-comment-thread-status thread-id profile-id]))
;; --- COMMAND: Update Comment Thread
(s/def ::is-resolved ::us/boolean)
(s/def ::update-comment-thread
(s/keys :req-un [::profile-id ::id ::is-resolved]
:opt-un [::share-id]))
(sv/defmethod ::update-comment-thread
{::doc/added "1.15"}
[{:keys [pool] :as cfg} {:keys [profile-id id is-resolved share-id] :as params}]
(db/with-atomic [conn pool]
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
(when-not thread
(ex/raise :type :not-found))
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
(db/update! conn :comment-thread
{:is-resolved is-resolved}
{:id id})
nil)))
;; --- COMMAND: Add Comment
(declare create-comment)
(s/def ::create-comment
(s/keys :req-un [::profile-id ::thread-id ::content]
:opt-un [::share-id]))
(sv/defmethod ::create-comment
{::doc/added "1.15"}
[{:keys [pool] :as cfg} params]
(db/with-atomic [conn pool]
(create-comment conn params)))
(defn create-comment
[conn {:keys [profile-id thread-id content share-id] :as params}]
(let [thread (-> (db/get-by-id conn :comment-thread thread-id {:for-update true})
(decode-row))
pname (retrieve-page-name conn thread)]
;; Standard Checks
(when-not thread (ex/raise :type :not-found))
;; Permission Checks
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
;; Update the page-name cachedattribute on comment thread table.
(when (not= pname (:page-name thread))
(db/update! conn :comment-thread
{:page-name pname}
{:id thread-id}))
;; NOTE: is important that all timestamptz related fields are
;; created or updated on the database level for avoid clock
;; inconsistencies (some user sees something read that is not
;; read, etc...)
(let [ppants (:participants thread #{})
comment (db/insert! conn :comment
{:thread-id thread-id
:owner-id profile-id
:content content})]
;; NOTE: this is done in SQL instead of using db/update!
;; helper because currently the helper does not allow pass raw
;; function call parameters to the underlying prepared
;; statement; in a future when we fix/improve it, this can be
;; changed to use the helper.
;; Update thread modified-at attribute and assoc the current
;; profile to the participant set.
(let [ppants (conj ppants profile-id)
sql "update comment_thread
set modified_at = clock_timestamp(),
participants = ?
where id = ?"]
(db/exec-one! conn [sql (db/tjson ppants) thread-id]))
;; Update the current profile status in relation to the
;; current thread.
(upsert-comment-thread-status! conn profile-id thread-id)
;; Return the created comment object.
comment)))
;; --- COMMAND: Update Comment
(declare update-comment)
(s/def ::update-comment
(s/keys :req-un [::profile-id ::id ::content]
:opt-un [::share-id]))
(sv/defmethod ::update-comment
{::doc/added "1.15"}
[{:keys [pool] :as cfg} params]
(db/with-atomic [conn pool]
(update-comment conn params)))
(defn update-comment
[conn {:keys [profile-id id content share-id] :as params}]
(let [comment (db/get-by-id conn :comment id {:for-update true})
_ (when-not comment (ex/raise :type :not-found))
thread (db/get-by-id conn :comment-thread (:thread-id comment) {:for-update true})
_ (when-not thread (ex/raise :type :not-found))
pname (retrieve-page-name conn thread)]
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
;; Don't allow edit comments to not owners
(when-not (= (:owner-id thread) profile-id)
(ex/raise :type :validation
:code :not-allowed))
(db/update! conn :comment
{:content content
:modified-at (dt/now)}
{:id (:id comment)})
(db/update! conn :comment-thread
{:modified-at (dt/now)
:page-name pname}
{:id (:id thread)})
nil))
;; --- COMMAND: Delete Comment Thread
(s/def ::delete-comment-thread
(s/keys :req-un [::profile-id ::id]))
(sv/defmethod ::delete-comment-thread
{::doc/added "1.15"}
[{:keys [pool] :as cfg} {:keys [profile-id id] :as params}]
(db/with-atomic [conn pool]
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
(when-not (= (:owner-id thread) profile-id)
(ex/raise :type :validation
:code :not-allowed))
(db/delete! conn :comment-thread {:id id})
nil)))
;; --- COMMAND: Delete comment
(s/def ::delete-comment
(s/keys :req-un [::profile-id ::id]))
(sv/defmethod ::delete-comment
{::doc/added "1.15"}
[{:keys [pool] :as cfg} {:keys [profile-id id] :as params}]
(db/with-atomic [conn pool]
(let [comment (db/get-by-id conn :comment id {:for-update true})]
(when-not (= (:owner-id comment) profile-id)
(ex/raise :type :validation
:code :not-allowed))
(db/delete! conn :comment {:id id}))))
;; --- COMMAND: Update comment thread position
(s/def ::update-comment-thread-position
(s/keys :req-un [::profile-id ::id ::position ::frame-id]))
(sv/defmethod ::update-comment-thread-position
{::doc/added "1.15"}
[{:keys [pool] :as cfg} {:keys [profile-id id position frame-id] :as params}]
(db/with-atomic [conn pool]
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
(when-not (= (:owner-id thread) profile-id)
(ex/raise :type :validation
:code :not-allowed))
(db/update! conn :comment-thread
{:modified-at (dt/now)
:position (db/pgpoint position)
:frame-id frame-id}
{:id (:id thread)})
nil)))
;; --- COMMAND: Update comment frame
(s/def ::update-comment-thread-frame
(s/keys :req-un [::profile-id ::id ::frame-id]))
(sv/defmethod ::update-comment-thread-frame
{::doc/added "1.15"}
[{:keys [pool] :as cfg} {:keys [profile-id id frame-id] :as params}]
(db/with-atomic [conn pool]
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
(when-not (= (:owner-id thread) profile-id)
(ex/raise :type :validation
:code :not-allowed))
(db/update! conn :comment-thread
{:modified-at (dt/now)
:frame-id frame-id}
{:id (:id thread)})
nil)))

View file

@ -7,35 +7,18 @@
(ns app.rpc.mutations.comments (ns app.rpc.mutations.comments
(:require (:require
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.geom.point :as gpt]
[app.common.spec :as us] [app.common.spec :as us]
[app.db :as db] [app.db :as db]
[app.rpc.commands.comments :as cmd.comments]
[app.rpc.doc :as-alias doc] [app.rpc.doc :as-alias doc]
[app.rpc.queries.comments :as comments]
[app.rpc.queries.files :as files] [app.rpc.queries.files :as files]
[app.rpc.retry :as retry] [app.rpc.retry :as retry]
[app.util.blob :as blob]
[app.util.services :as sv] [app.util.services :as sv]
[app.util.time :as dt]
[clojure.spec.alpha :as s])) [clojure.spec.alpha :as s]))
;; --- Mutation: Create Comment Thread ;; --- Mutation: Create Comment Thread
(declare upsert-comment-thread-status!) (s/def ::create-comment-thread ::cmd.comments/create-comment-thread)
(declare create-comment-thread)
(declare retrieve-page-name)
(s/def ::page-id ::us/uuid)
(s/def ::file-id ::us/uuid)
(s/def ::share-id (s/nilable ::us/uuid))
(s/def ::profile-id ::us/uuid)
(s/def ::position ::gpt/point)
(s/def ::content ::us/string)
(s/def ::frame-id ::us/uuid)
(s/def ::create-comment-thread
(s/keys :req-un [::profile-id ::file-id ::position ::content ::page-id ::frame-id]
:opt-un [::share-id]))
(sv/defmethod ::create-comment-thread (sv/defmethod ::create-comment-thread
{::retry/max-retries 3 {::retry/max-retries 3
@ -45,65 +28,14 @@
[{:keys [pool] :as cfg} {:keys [profile-id file-id share-id] :as params}] [{:keys [pool] :as cfg} {:keys [profile-id file-id share-id] :as params}]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(files/check-comment-permissions! conn profile-id file-id share-id) (files/check-comment-permissions! conn profile-id file-id share-id)
(create-comment-thread conn params))) (cmd.comments/create-comment-thread conn params)))
(defn- retrieve-next-seqn
[conn file-id]
(let [sql "select (f.comment_thread_seqn + 1) as next_seqn from file as f where f.id = ?"
res (db/exec-one! conn [sql file-id])]
(:next-seqn res)))
(defn- create-comment-thread
[conn {:keys [profile-id file-id page-id position content frame-id] :as params}]
(let [seqn (retrieve-next-seqn conn file-id)
now (dt/now)
pname (retrieve-page-name conn params)
thread (db/insert! conn :comment-thread
{:file-id file-id
:owner-id profile-id
:participants (db/tjson #{profile-id})
:page-name pname
:page-id page-id
:created-at now
:modified-at now
:seqn seqn
:position (db/pgpoint position)
:frame-id frame-id})]
;; Create a comment entry
(db/insert! conn :comment
{:thread-id (:id thread)
:owner-id profile-id
:created-at now
:modified-at now
:content content})
;; Make the current thread as read.
(upsert-comment-thread-status! conn profile-id (:id thread))
;; Optimistic update of current seq number on file.
(db/update! conn :file
{:comment-thread-seqn seqn}
{:id file-id})
(select-keys thread [:id :file-id :page-id])))
(defn- retrieve-page-name
[conn {:keys [file-id page-id]}]
(let [{:keys [data]} (db/get-by-id conn :file file-id)
data (blob/decode data)]
(get-in data [:pages-index page-id :name])))
;; --- Mutation: Update Comment Thread Status ;; --- Mutation: Update Comment Thread Status
(s/def ::id ::us/uuid) (s/def ::id ::us/uuid)
(s/def ::share-id (s/nilable ::us/uuid)) (s/def ::share-id (s/nilable ::us/uuid))
(s/def ::update-comment-thread-status (s/def ::update-comment-thread-status ::cmd.comments/update-comment-thread-status)
(s/keys :req-un [::profile-id ::id]
:opt-un [::share-id]))
(sv/defmethod ::update-comment-thread-status (sv/defmethod ::update-comment-thread-status
{::doc/added "1.0" {::doc/added "1.0"
@ -111,30 +43,14 @@
[{:keys [pool] :as cfg} {:keys [profile-id id share-id] :as params}] [{:keys [pool] :as cfg} {:keys [profile-id id share-id] :as params}]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(let [cthr (db/get-by-id conn :comment-thread id {:for-update true})] (let [cthr (db/get-by-id conn :comment-thread id {:for-update true})]
(when-not cthr (when-not cthr (ex/raise :type :not-found))
(ex/raise :type :not-found))
(files/check-comment-permissions! conn profile-id (:file-id cthr) share-id) (files/check-comment-permissions! conn profile-id (:file-id cthr) share-id)
(upsert-comment-thread-status! conn profile-id (:id cthr))))) (cmd.comments/upsert-comment-thread-status! conn profile-id (:id cthr)))))
(def sql:upsert-comment-thread-status
"insert into comment_thread_status (thread_id, profile_id)
values (?, ?)
on conflict (thread_id, profile_id)
do update set modified_at = clock_timestamp()
returning modified_at;")
(defn- upsert-comment-thread-status!
[conn profile-id thread-id]
(db/exec-one! conn [sql:upsert-comment-thread-status thread-id profile-id]))
;; --- Mutation: Update Comment Thread ;; --- Mutation: Update Comment Thread
(s/def ::is-resolved ::us/boolean) (s/def ::update-comment-thread ::cmd.comments/update-comment-thread)
(s/def ::update-comment-thread
(s/keys :req-un [::profile-id ::id ::is-resolved]
:opt-un [::share-id]))
(sv/defmethod ::update-comment-thread (sv/defmethod ::update-comment-thread
{::doc/added "1.0" {::doc/added "1.0"
@ -146,7 +62,6 @@
(ex/raise :type :not-found)) (ex/raise :type :not-found))
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id) (files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
(db/update! conn :comment-thread (db/update! conn :comment-thread
{:is-resolved is-resolved} {:is-resolved is-resolved}
{:id id}) {:id id})
@ -155,104 +70,31 @@
;; --- Mutation: Add Comment ;; --- Mutation: Add Comment
(s/def ::add-comment (s/def ::add-comment ::cmd.comments/create-comment)
(s/keys :req-un [::profile-id ::thread-id ::content]
:opt-un [::share-id]))
(sv/defmethod ::add-comment (sv/defmethod ::add-comment
{::doc/added "1.0" {::doc/added "1.0"
::doc/deprecated "1.15"} ::doc/deprecated "1.15"}
[{:keys [pool] :as cfg} {:keys [profile-id thread-id content share-id] :as params}] [{:keys [pool] :as cfg} params]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(let [thread (-> (db/get-by-id conn :comment-thread thread-id {:for-update true}) (cmd.comments/create-comment conn params)))
(comments/decode-row))
pname (retrieve-page-name conn thread)]
;; Standard Checks
(when-not thread (ex/raise :type :not-found))
;; Permission Checks
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
;; Update the page-name cachedattribute on comment thread table.
(when (not= pname (:page-name thread))
(db/update! conn :comment-thread
{:page-name pname}
{:id thread-id}))
;; NOTE: is important that all timestamptz related fields are
;; created or updated on the database level for avoid clock
;; inconsistencies (some user sees something read that is not
;; read, etc...)
(let [ppants (:participants thread #{})
comment (db/insert! conn :comment
{:thread-id thread-id
:owner-id profile-id
:content content})]
;; NOTE: this is done in SQL instead of using db/update!
;; helper because currently the helper does not allow pass raw
;; function call parameters to the underlying prepared
;; statement; in a future when we fix/improve it, this can be
;; changed to use the helper.
;; Update thread modified-at attribute and assoc the current
;; profile to the participant set.
(let [ppants (conj ppants profile-id)
sql "update comment_thread
set modified_at = clock_timestamp(),
participants = ?
where id = ?"]
(db/exec-one! conn [sql (db/tjson ppants) thread-id]))
;; Update the current profile status in relation to the
;; current thread.
(upsert-comment-thread-status! conn profile-id thread-id)
;; Return the created comment object.
comment))))
;; --- Mutation: Update Comment ;; --- Mutation: Update Comment
(s/def ::update-comment (s/def ::update-comment ::cmd.comments/update-comment)
(s/keys :req-un [::profile-id ::id ::content]
:opt-un [::share-id]))
(sv/defmethod ::update-comment (sv/defmethod ::update-comment
{::doc/added "1.0" {::doc/added "1.0"
::doc/deprecated "1.15"} ::doc/deprecated "1.15"}
[{:keys [pool] :as cfg} {:keys [profile-id id content share-id] :as params}] [{:keys [pool] :as cfg} params]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(let [comment (db/get-by-id conn :comment id {:for-update true}) (cmd.comments/update-comment conn params)))
_ (when-not comment (ex/raise :type :not-found))
thread (db/get-by-id conn :comment-thread (:thread-id comment) {:for-update true})
_ (when-not thread (ex/raise :type :not-found))
pname (retrieve-page-name conn thread)]
(files/check-comment-permissions! conn profile-id (:file-id thread) share-id)
;; Don't allow edit comments to not owners
(when-not (= (:owner-id thread) profile-id)
(ex/raise :type :validation
:code :not-allowed))
(db/update! conn :comment
{:content content
:modified-at (dt/now)}
{:id (:id comment)})
(db/update! conn :comment-thread
{:modified-at (dt/now)
:page-name pname}
{:id (:id thread)})
nil)))
;; --- Mutation: Delete Comment Thread ;; --- Mutation: Delete Comment Thread
(s/def ::delete-comment-thread (s/def ::delete-comment-thread ::cmd.comments/delete-comment-thread)
(s/keys :req-un [::profile-id ::id]))
(sv/defmethod ::delete-comment-thread (sv/defmethod ::delete-comment-thread
{::doc/added "1.0" {::doc/added "1.0"
@ -261,16 +103,14 @@
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})] (let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
(when-not (= (:owner-id thread) profile-id) (when-not (= (:owner-id thread) profile-id)
(ex/raise :type :validation (ex/raise :type :validation :code :not-allowed))
:code :not-allowed))
(db/delete! conn :comment-thread {:id id}) (db/delete! conn :comment-thread {:id id})
nil))) nil)))
;; --- Mutation: Delete comment ;; --- Mutation: Delete comment
(s/def ::delete-comment (s/def ::delete-comment ::cmd.comments/delete-comment)
(s/keys :req-un [::profile-id ::id]))
(sv/defmethod ::delete-comment (sv/defmethod ::delete-comment
{::doc/added "1.0" {::doc/added "1.0"
@ -279,44 +119,5 @@
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(let [comment (db/get-by-id conn :comment id {:for-update true})] (let [comment (db/get-by-id conn :comment id {:for-update true})]
(when-not (= (:owner-id comment) profile-id) (when-not (= (:owner-id comment) profile-id)
(ex/raise :type :validation (ex/raise :type :validation :code :not-allowed))
:code :not-allowed))
(db/delete! conn :comment {:id id})))) (db/delete! conn :comment {:id id}))))
;; --- Mutation: Update comment thread position
(s/def ::update-comment-thread-position
(s/keys :req-un [::profile-id ::id ::position ::frame-id]))
(sv/defmethod ::update-comment-thread-position
[{:keys [pool] :as cfg} {:keys [profile-id id position frame-id] :as params}]
(db/with-atomic [conn pool]
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
(when-not (= (:owner-id thread) profile-id)
(ex/raise :type :validation
:code :not-allowed))
(db/update! conn :comment-thread
{:modified-at (dt/now)
:position (db/pgpoint position)
:frame-id frame-id}
{:id (:id thread)})
nil)))
;; --- Mutation: Update comment frame
(s/def ::update-comment-thread-frame
(s/keys :req-un [::profile-id ::id ::frame-id]))
(sv/defmethod ::update-comment-thread-frame
[{:keys [pool] :as cfg} {:keys [profile-id id frame-id] :as params}]
(db/with-atomic [conn pool]
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
(when-not (= (:owner-id thread) profile-id)
(ex/raise :type :validation
:code :not-allowed))
(db/update! conn :comment-thread
{:modified-at (dt/now)
:frame-id frame-id}
{:id (:id thread)})
nil)))

View file

@ -6,7 +6,6 @@
(ns app.rpc.queries.comments (ns app.rpc.queries.comments
(:require (:require
[app.common.spec :as us]
[app.db :as db] [app.db :as db]
[app.rpc.commands.comments :as cmd.comments] [app.rpc.commands.comments :as cmd.comments]
[app.rpc.doc :as-alias doc] [app.rpc.doc :as-alias doc]
@ -51,7 +50,7 @@
(sv/defmethod ::comment-thread (sv/defmethod ::comment-thread
{::doc/added "1.0" {::doc/added "1.0"
::doc/deprecated "1.15"} ::doc/deprecated "1.15"}
[{:keys [pool] :as cfg} {:keys [profile-id file-id id share-id] :as params}] [{:keys [pool] :as cfg} {:keys [profile-id file-id share-id] :as params}]
(with-open [conn (db/open pool)] (with-open [conn (db/open pool)]
(files/check-comment-permissions! conn profile-id file-id share-id) (files/check-comment-permissions! conn profile-id file-id share-id)
(cmd.comments/get-comment-thread conn params))) (cmd.comments/get-comment-thread conn params)))

View file

@ -93,7 +93,7 @@
objects (wsh/lookup-page-objects state page-id) objects (wsh/lookup-page-objects state page-id)
frame-id (cph/frame-id-by-position objects (:position params)) frame-id (cph/frame-id-by-position objects (:position params))
params (assoc params :frame-id frame-id)] params (assoc params :frame-id frame-id)]
(->> (rp/mutation! :create-comment-thread params) (->> (rp/cmd! :create-comment-thread params)
(rx/mapcat #(rp/cmd! :get-comment-thread {:file-id (:file-id %) :id (:id %)})) (rx/mapcat #(rp/cmd! :get-comment-thread {:file-id (:file-id %) :id (:id %)}))
(rx/map created-thread-on-workspace) (rx/map created-thread-on-workspace)
(rx/catch #(rx/throw {:type :comment-error}))))))) (rx/catch #(rx/throw {:type :comment-error})))))))
@ -122,7 +122,7 @@
(let [share-id (-> state :viewer-local :share-id) (let [share-id (-> state :viewer-local :share-id)
frame-id (:frame-id params) frame-id (:frame-id params)
params (assoc params :share-id share-id :frame-id frame-id)] params (assoc params :share-id share-id :frame-id frame-id)]
(->> (rp/mutation! :create-comment-thread params) (->> (rp/cmd! :create-comment-thread params)
(rx/mapcat #(rp/cmd! :get-comment-thread {:file-id (:file-id %) :id (:id %) :share-id share-id})) (rx/mapcat #(rp/cmd! :get-comment-thread {:file-id (:file-id %) :id (:id %) :share-id share-id}))
(rx/map created-thread-on-viewer) (rx/map created-thread-on-viewer)
(rx/catch #(rx/throw {:type :comment-error}))))))) (rx/catch #(rx/throw {:type :comment-error})))))))
@ -135,7 +135,7 @@
(watch [_ state _] (watch [_ state _]
(let [done #(d/update-in-when % [:comment-threads id] assoc :count-unread-comments 0) (let [done #(d/update-in-when % [:comment-threads id] assoc :count-unread-comments 0)
share-id (-> state :viewer-local :share-id)] share-id (-> state :viewer-local :share-id)]
(->> (rp/mutation! :update-comment-thread-status {:id id :share-id share-id}) (->> (rp/cmd! :update-comment-thread-status {:id id :share-id share-id})
(rx/map (constantly done)) (rx/map (constantly done))
(rx/catch #(rx/throw {:type :comment-error}))))))) (rx/catch #(rx/throw {:type :comment-error})))))))
@ -153,7 +153,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [share-id (-> state :viewer-local :share-id)] (let [share-id (-> state :viewer-local :share-id)]
(->> (rp/mutation! :update-comment-thread {:id id :is-resolved is-resolved :share-id share-id}) (->> (rp/cmd! :update-comment-thread {:id id :is-resolved is-resolved :share-id share-id})
(rx/catch #(rx/throw {:type :comment-error})) (rx/catch #(rx/throw {:type :comment-error}))
(rx/ignore)))))) (rx/ignore))))))
@ -168,7 +168,7 @@
(watch [_ state _] (watch [_ state _]
(let [share-id (-> state :viewer-local :share-id)] (let [share-id (-> state :viewer-local :share-id)]
(rx/concat (rx/concat
(->> (rp/mutation! :add-comment {:thread-id (:id thread) :content content :share-id share-id}) (->> (rp/cmd! :create-comment {:thread-id (:id thread) :content content :share-id share-id})
(rx/map #(partial created %)) (rx/map #(partial created %))
(rx/catch #(rx/throw {:type :comment-error}))) (rx/catch #(rx/throw {:type :comment-error})))
(rx/of (refresh-comment-thread thread)))))))) (rx/of (refresh-comment-thread thread))))))))
@ -184,7 +184,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [share-id (-> state :viewer-local :share-id)] (let [share-id (-> state :viewer-local :share-id)]
(->> (rp/mutation! :update-comment {:id id :content content :share-id share-id}) (->> (rp/cmd! :update-comment {:id id :content content :share-id share-id})
(rx/catch #(rx/throw {:type :comment-error})) (rx/catch #(rx/throw {:type :comment-error}))
(rx/ignore)))))) (rx/ignore))))))
@ -202,7 +202,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ _ _] (watch [_ _ _]
(->> (rp/mutation! :delete-comment-thread {:id id}) (->> (rp/cmd! :delete-comment-thread {:id id})
(rx/catch #(rx/throw {:type :comment-error})) (rx/catch #(rx/throw {:type :comment-error}))
(rx/ignore))))) (rx/ignore)))))
@ -221,7 +221,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [share-id (-> state :viewer-local :share-id)] (let [share-id (-> state :viewer-local :share-id)]
(->> (rp/mutation! :delete-comment-thread {:id id :share-id share-id}) (->> (rp/cmd! :delete-comment-thread {:id id :share-id share-id})
(rx/catch #(rx/throw {:type :comment-error})) (rx/catch #(rx/throw {:type :comment-error}))
(rx/ignore)))))) (rx/ignore))))))
@ -236,7 +236,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [share-id (-> state :viewer-local :share-id)] (let [share-id (-> state :viewer-local :share-id)]
(->> (rp/mutation! :delete-comment {:id id :share-id share-id}) (->> (rp/cmd! :delete-comment {:id id :share-id share-id})
(rx/catch #(rx/throw {:type :comment-error})) (rx/catch #(rx/throw {:type :comment-error}))
(rx/ignore)))))) (rx/ignore))))))
@ -426,7 +426,7 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ _ _] (watch [_ _ _]
(let [thread-id (:id thread)] (let [thread-id (:id thread)]
(->> (rp/mutation! :update-comment-thread-frame {:id thread-id :frame-id frame-id}) (->> (rp/cmd! :update-comment-thread-frame {:id thread-id :frame-id frame-id})
(rx/catch #(rx/throw {:type :comment-error :code :update-comment-thread-frame})) (rx/catch #(rx/throw {:type :comment-error :code :update-comment-thread-frame}))
(rx/ignore))))))) (rx/ignore)))))))

View file

@ -136,7 +136,7 @@
(rx/merge (rx/merge
(rx/of (dwc/commit-changes changes)) (rx/of (dwc/commit-changes changes))
(->> (rp/mutation :update-comment-thread-position thread) (->> (rp/cmd! :update-comment-thread-position thread)
(rx/catch #(rx/throw {:type :update-comment-thread-position})) (rx/catch #(rx/throw {:type :update-comment-thread-position}))
(rx/ignore)))))))) (rx/ignore))))))))