mirror of
https://github.com/penpot/penpot.git
synced 2025-07-25 22:07:20 +02:00
♻️ Refactor services (for add the project-file concept.
And fix many tests.
This commit is contained in:
parent
af62d949d8
commit
183f0a5400
40 changed files with 1279 additions and 1006 deletions
|
@ -1,92 +0,0 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) 2019 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.services.queries.pages
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[promesa.core :as p]
|
||||
[uxbox.db :as db]
|
||||
[uxbox.services.queries :as sq]
|
||||
[uxbox.util.blob :as blob]
|
||||
[uxbox.util.spec :as us]
|
||||
[uxbox.util.sql :as sql]))
|
||||
|
||||
;; --- Helpers & Specs
|
||||
|
||||
(declare decode-row)
|
||||
|
||||
(s/def ::id ::us/uuid)
|
||||
(s/def ::user ::us/uuid)
|
||||
(s/def ::project-id ::us/uuid)
|
||||
|
||||
;; --- Query: Pages by Project
|
||||
|
||||
(s/def ::pages-by-project
|
||||
(s/keys :req-un [::user ::project-id]))
|
||||
|
||||
(sq/defquery ::pages-by-project
|
||||
[{:keys [user project-id] :as params}]
|
||||
(let [sql "select pg.*,
|
||||
pg.data,
|
||||
pg.metadata
|
||||
from pages as pg
|
||||
where pg.user_id = $2
|
||||
and pg.project_id = $1
|
||||
and pg.deleted_at is null
|
||||
order by pg.created_at asc;"]
|
||||
(-> (db/query db/pool [sql project-id user])
|
||||
(p/then #(mapv decode-row %)))))
|
||||
|
||||
;; --- Query: Page by Id
|
||||
|
||||
(s/def ::page
|
||||
(s/keys :req-un [::user ::id]))
|
||||
|
||||
(sq/defquery ::page
|
||||
[{:keys [user id] :as params}]
|
||||
(let [sql "select pg.*,
|
||||
pg.data,
|
||||
pg.metadata
|
||||
from pages as pg
|
||||
where pg.user_id = $2
|
||||
and pg.id = $1
|
||||
and pg.deleted_at is null"]
|
||||
(-> (db/query-one db/pool [sql id user])
|
||||
(p/then' decode-row))))
|
||||
|
||||
;; --- Query: Page History
|
||||
|
||||
(s/def ::page-id ::us/uuid)
|
||||
(s/def ::max ::us/integer)
|
||||
(s/def ::pinned ::us/boolean)
|
||||
(s/def ::since ::us/integer)
|
||||
|
||||
(s/def ::page-history
|
||||
(s/keys :req-un [::page-id ::user]
|
||||
:opt-un [::max ::pinned ::since]))
|
||||
|
||||
(sq/defquery ::page-history
|
||||
[{:keys [page-id user since max pinned] :or {since Long/MAX_VALUE max 10}}]
|
||||
(let [sql (-> (sql/from ["pages_history" "ph"])
|
||||
(sql/select "ph.*")
|
||||
(sql/where ["ph.user_id = ?" user]
|
||||
["ph.page_id = ?" page-id]
|
||||
["ph.version < ?" since]
|
||||
(when pinned
|
||||
["ph.pinned = ?" true]))
|
||||
(sql/order "ph.version desc")
|
||||
(sql/limit max))]
|
||||
(-> (db/query db/pool (sql/fmt sql))
|
||||
(p/then (partial mapv decode-row)))))
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
(defn decode-row
|
||||
[{:keys [data metadata] :as row}]
|
||||
(when row
|
||||
(cond-> row
|
||||
data (assoc :data (blob/decode data))
|
||||
metadata (assoc :metadata (blob/decode metadata)))))
|
55
backend/src/uxbox/services/queries/project_files.clj
Normal file
55
backend/src/uxbox/services/queries/project_files.clj
Normal file
|
@ -0,0 +1,55 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) 2019 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.services.queries.project-files
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[promesa.core :as p]
|
||||
[uxbox.db :as db]
|
||||
[uxbox.services.queries :as sq]
|
||||
[uxbox.util.blob :as blob]
|
||||
[uxbox.util.spec :as us]))
|
||||
|
||||
(declare decode-row)
|
||||
|
||||
;; --- Helpers & Specs
|
||||
|
||||
(s/def ::id ::us/uuid)
|
||||
(s/def ::name ::us/string)
|
||||
(s/def ::project-id ::us/uuid)
|
||||
(s/def ::user ::us/uuid)
|
||||
|
||||
;; --- Query: Project Files
|
||||
|
||||
(def ^:private sql:project-files
|
||||
"select pf.*,
|
||||
array_agg(pp.id) as pages
|
||||
from project_files as pf
|
||||
inner join projects as p on (pf.project_id = p.id)
|
||||
inner join project_users as pu on (p.id = pu.project_id)
|
||||
left join project_pages as pp on (pf.id = pp.file_id)
|
||||
where pu.user_id = $1
|
||||
and pu.project_id = $2
|
||||
and pu.can_edit = true
|
||||
group by pf.id
|
||||
order by pf.created_at asc;")
|
||||
|
||||
(s/def ::project-files
|
||||
(s/keys :req-un [::user ::project-id]))
|
||||
|
||||
(sq/defquery ::project-files
|
||||
[{:keys [user project-id] :as params}]
|
||||
(-> (db/query db/pool [sql:project-files user project-id])
|
||||
(p/then' (partial mapv decode-row))))
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
(defn decode-row
|
||||
[{:keys [metadata pages] :as row}]
|
||||
(when row
|
||||
(cond-> row
|
||||
pages (assoc :pages (vec (remove nil? pages)))
|
||||
metadata (assoc :metadata (blob/decode metadata)))))
|
145
backend/src/uxbox/services/queries/project_pages.clj
Normal file
145
backend/src/uxbox/services/queries/project_pages.clj
Normal file
|
@ -0,0 +1,145 @@
|
|||
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
;;
|
||||
;; Copyright (c) 2019 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.services.queries.project-pages
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[promesa.core :as p]
|
||||
[uxbox.db :as db]
|
||||
[uxbox.services.queries :as sq]
|
||||
[uxbox.services.util :as su]
|
||||
[uxbox.util.blob :as blob]
|
||||
[uxbox.util.spec :as us]
|
||||
[uxbox.util.sql :as sql]))
|
||||
|
||||
;; --- Helpers & Specs
|
||||
|
||||
(declare decode-row)
|
||||
|
||||
(s/def ::id ::us/uuid)
|
||||
(s/def ::user ::us/uuid)
|
||||
(s/def ::project-id ::us/uuid)
|
||||
(s/def ::file-id ::us/uuid)
|
||||
|
||||
(def ^:private sql:generic-project-pages
|
||||
"select pp.*
|
||||
from project_pages as pp
|
||||
inner join project_files as pf on (pf.id = pp.file_id)
|
||||
inner join projects as p on (p.id = pf.project_id)
|
||||
left join project_users as pu on (pu.project_id = p.id)
|
||||
left join project_file_users as pfu on (pfu.file_id = pf.id)
|
||||
where ((pfu.user_id = $1 and pfu.can_edit = true) or
|
||||
(pu.user_id = $1 and pu.can_edit = true))
|
||||
order by pp.created_at")
|
||||
|
||||
;; --- Query: Project Pages (By File ID)
|
||||
|
||||
(def ^:private sql:project-pages
|
||||
(str "with pages as (" sql:generic-project-pages ")"
|
||||
" select * from pages where file_id = $2"))
|
||||
|
||||
;; (defn project-pages-sql
|
||||
;; [user]
|
||||
;; (-> (sql/from ["project_pages" "pp"])
|
||||
;; (sql/join ["project_files" "pf"] "pf.id = pp.file_id")
|
||||
;; (sql/join ["projects" "p"] "p.id = pf.project_id")
|
||||
;; (sql/ljoin ["project_users", "pu"] "pu.project_id = p.id")
|
||||
;; (sql/ljoin ["project_file_users", "pfu"] "pfu.file_id = pf.id")
|
||||
;; (sql/select "pp.*")
|
||||
;; (sql/where ["((pfu.user_id = ? and pfu.can_edit = true) or
|
||||
;; (pu.user_id = ? and pu.can_edit = true))" user user])
|
||||
;; (sql/order "pp.created_at")))
|
||||
|
||||
;; (let [sql (-> (project-pages-sql user)
|
||||
;; (sql/where ["pp.file_id = ?" file-id])
|
||||
;; (sql/fmt))]
|
||||
;; (-> (db/query db/pool sql)
|
||||
;; (p/then #(mapv decode-row %)))))
|
||||
|
||||
(s/def ::project-pages
|
||||
(s/keys :req-un [::user ::file-id]))
|
||||
|
||||
(sq/defquery ::project-pages
|
||||
[{:keys [user file-id] :as params}]
|
||||
(let [sql sql:project-pages]
|
||||
(-> (db/query db/pool [sql user file-id])
|
||||
(p/then #(mapv decode-row %)))))
|
||||
|
||||
;; --- Query: Project Page (By ID)
|
||||
|
||||
(def ^:private sql:project-page
|
||||
(str "with pages as (" sql:generic-project-pages ")"
|
||||
" select * from pages where id = $2"))
|
||||
|
||||
(defn retrieve-page
|
||||
[conn {:keys [user id] :as params}]
|
||||
(let [sql sql:project-page]
|
||||
(-> (db/query-one conn [sql user id])
|
||||
(p/then' su/raise-not-found-if-nil)
|
||||
(p/then' decode-row))))
|
||||
|
||||
(s/def ::project-page
|
||||
(s/keys :req-un [::user ::id]))
|
||||
|
||||
(sq/defquery ::project-page
|
||||
[{:keys [user id] :as params}]
|
||||
(retrieve-page db/pool params))
|
||||
|
||||
;; --- Query: Project Page History (by Page ID)
|
||||
|
||||
;; (def ^:private sql:generic-page-history
|
||||
;; "select pph.*
|
||||
;; from project_page_history as pph
|
||||
;; where pph.page_id = $2
|
||||
;; and pph.version < $3
|
||||
;; order by pph.version < desc")
|
||||
|
||||
;; (def ^:private sql:page-history
|
||||
;; (str "with history as (" sql:generic-page-history ")"
|
||||
;; " select * from history limit $4"))
|
||||
|
||||
;; (def ^:private sql:pinned-page-history
|
||||
;; (str "with history as (" sql:generic-page-history ")"
|
||||
;; " select * from history where pinned = true limit $4"))
|
||||
|
||||
(s/def ::page-id ::us/uuid)
|
||||
(s/def ::max ::us/integer)
|
||||
(s/def ::pinned ::us/boolean)
|
||||
(s/def ::since ::us/integer)
|
||||
|
||||
(s/def ::page-history
|
||||
(s/keys :req-un [::page-id ::user]
|
||||
:opt-un [::max ::pinned ::since]))
|
||||
|
||||
(defn retrieve-page-history
|
||||
[{:keys [page-id user since max pinned] :or {since Long/MAX_VALUE max 10}}]
|
||||
(let [sql (-> (sql/from ["pages_history" "ph"])
|
||||
(sql/select "ph.*")
|
||||
(sql/where ["ph.user_id = ?" user]
|
||||
["ph.page_id = ?" page-id]
|
||||
["ph.version < ?" since]
|
||||
(when pinned
|
||||
["ph.pinned = ?" true]))
|
||||
(sql/order "ph.version desc")
|
||||
(sql/limit max))]
|
||||
(-> (db/query db/pool (sql/fmt sql))
|
||||
(p/then (partial mapv decode-row)))))
|
||||
|
||||
(sq/defquery ::page-history
|
||||
[{:keys [page-id user] :as params}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(p/do! (retrieve-page conn {:id page-id :user user})
|
||||
(retrieve-page-history conn params))))
|
||||
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
(defn decode-row
|
||||
[{:keys [data metadata] :as row}]
|
||||
(when row
|
||||
(cond-> row
|
||||
data (assoc :data (blob/decode data))
|
||||
metadata (assoc :metadata (blob/decode metadata)))))
|
|
@ -13,6 +13,8 @@
|
|||
[uxbox.util.blob :as blob]
|
||||
[uxbox.util.spec :as us]))
|
||||
|
||||
(declare decode-row)
|
||||
|
||||
;; --- Helpers & Specs
|
||||
|
||||
(s/def ::id ::us/uuid)
|
||||
|
@ -22,19 +24,26 @@
|
|||
|
||||
;; --- Query: Projects
|
||||
|
||||
;; (def ^:private projects-sql
|
||||
;; "select distinct on (p.id, p.created_at)
|
||||
;; p.*,
|
||||
;; array_agg(pg.id) over (
|
||||
;; partition by p.id
|
||||
;; order by pg.created_at
|
||||
;; range between unbounded preceding and unbounded following
|
||||
;; ) as pages
|
||||
;; from projects as p
|
||||
;; left join pages as pg
|
||||
;; on (pg.project_id = p.id)
|
||||
;; where p.user_id = $1
|
||||
;; order by p.created_at asc")
|
||||
|
||||
(def ^:private projects-sql
|
||||
"select distinct on (p.id, p.created_at)
|
||||
p.*,
|
||||
array_agg(pg.id) over (
|
||||
partition by p.id
|
||||
order by pg.created_at
|
||||
range between unbounded preceding and unbounded following
|
||||
) as pages
|
||||
from projects as p
|
||||
left join pages as pg
|
||||
on (pg.project_id = p.id)
|
||||
where p.user_id = $1
|
||||
order by p.created_at asc")
|
||||
"select p.*
|
||||
from project_users as pu
|
||||
inner join projects as p on (p.id = pu.project_id)
|
||||
where pu.can_edit = true
|
||||
and pu.user_id = $1;")
|
||||
|
||||
(s/def ::projects
|
||||
(s/keys :req-un [::user]))
|
||||
|
@ -42,5 +51,12 @@
|
|||
(sq/defquery ::projects
|
||||
[{:keys [user] :as params}]
|
||||
(-> (db/query db/pool [projects-sql user])
|
||||
(p/then (fn [rows]
|
||||
(mapv #(update % :pages vec) rows)))))
|
||||
(p/then' (partial mapv decode-row))))
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
(defn decode-row
|
||||
[{:keys [metadata] :as row}]
|
||||
(when row
|
||||
(cond-> row
|
||||
metadata (assoc :metadata (blob/decode metadata)))))
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
;;
|
||||
;; Copyright (c) 2019 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.services.queries.user-storage
|
||||
(ns uxbox.services.queries.user-attrs
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[promesa.core :as p]
|
||||
|
@ -20,13 +20,13 @@
|
|||
(cond-> row
|
||||
val (assoc :val (blob/decode val)))))
|
||||
|
||||
(s/def ::user-storage-entry
|
||||
(s/def ::user-attr
|
||||
(s/keys :req-un [::key ::user]))
|
||||
|
||||
(sq/defquery ::user-storage-entry
|
||||
(sq/defquery ::user-attr
|
||||
[{:keys [key user]}]
|
||||
(let [sql "select kv.*
|
||||
from user_storage as kv
|
||||
from user_attrs as kv
|
||||
where kv.user_id = $2
|
||||
and kv.key = $1"]
|
||||
(-> (db/query-one db/pool [sql key user])
|
|
@ -4,7 +4,7 @@
|
|||
;;
|
||||
;; Copyright (c) 2016 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.services.queries.profiles
|
||||
(ns uxbox.services.queries.users
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[promesa.core :as p]
|
||||
|
@ -51,9 +51,7 @@
|
|||
(s/def ::profile
|
||||
(s/keys :req-un [::user]))
|
||||
|
||||
(sq/defquery :profile
|
||||
{:doc "Retrieve the user profile."
|
||||
:spec ::profile}
|
||||
(sq/defquery ::profile
|
||||
[{:keys [user] :as params}]
|
||||
(-> (get-profile db/pool user)
|
||||
(p/then' strip-private-attrs)))
|
Loading…
Add table
Add a link
Reference in a new issue