mirror of
https://github.com/penpot/penpot.git
synced 2025-08-06 13:08:28 +02:00
♻️ Rename collections to libraries.
And make them team dependent.
This commit is contained in:
parent
0ad2b13d76
commit
3ce9c8820f
19 changed files with 1068 additions and 766 deletions
|
@ -17,6 +17,7 @@
|
|||
[uxbox.db :as db]
|
||||
[uxbox.media :as media]
|
||||
[uxbox.images :as images]
|
||||
[uxbox.services.queries.teams :as teams]
|
||||
[uxbox.services.queries :as sq]
|
||||
[uxbox.services.util :as su]
|
||||
[uxbox.util.blob :as blob]
|
||||
|
@ -28,55 +29,85 @@
|
|||
|
||||
(s/def ::id ::us/uuid)
|
||||
(s/def ::profile-id ::us/uuid)
|
||||
(s/def ::collection-id (s/nilable ::us/uuid))
|
||||
|
||||
(defn decode-row
|
||||
[{:keys [metadata] :as row}]
|
||||
(when row
|
||||
(cond-> row
|
||||
metadata (assoc :metadata (blob/decode metadata)))))
|
||||
(s/def ::team-id ::us/uuid)
|
||||
(s/def ::library-id (s/nilable ::us/uuid))
|
||||
|
||||
|
||||
|
||||
;; --- Query: Collections
|
||||
;; --- Query: Colors Librarys
|
||||
|
||||
(def ^:private sql:collections
|
||||
"select *,
|
||||
(select count(*) from color where collection_id = ic.id) as num_colors
|
||||
from color_collection as ic
|
||||
where (ic.profile_id = $1 or
|
||||
ic.profile_id = '00000000-0000-0000-0000-000000000000'::uuid)
|
||||
and ic.deleted_at is null
|
||||
order by ic.created_at desc")
|
||||
(def ^:private sql:libraries
|
||||
"select lib.*,
|
||||
(select count(*) from color where library_id = lib.id) as num_colors
|
||||
from color_library as lib
|
||||
where lib.team_id = $1
|
||||
and lib.deleted_at is null
|
||||
order by lib.created_at desc")
|
||||
|
||||
(s/def ::color-collections
|
||||
(s/keys :req-un [::profile-id]))
|
||||
(s/def ::color-libraries
|
||||
(s/keys :req-un [::profile-id ::team-id]))
|
||||
|
||||
(sq/defquery ::color-collections
|
||||
[{:keys [profile-id] :as params}]
|
||||
(let [sqlv [sql:collections profile-id]]
|
||||
(db/query db/pool sqlv)))
|
||||
(sq/defquery ::color-libraries
|
||||
[{:keys [profile-id team-id]}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(teams/check-edition-permissions! conn profile-id team-id)
|
||||
(db/query conn [sql:libraries team-id])))
|
||||
|
||||
|
||||
|
||||
;; --- Colors By Collection ID
|
||||
;; --- Query: Color Library
|
||||
|
||||
(def ^:private sql:colors
|
||||
"select *
|
||||
from color as i
|
||||
where (i.profile_id = $1 or
|
||||
i.profile_id = '00000000-0000-0000-0000-000000000000'::uuid)
|
||||
and i.deleted_at is null
|
||||
and i.collection_id = $2
|
||||
order by i.created_at desc")
|
||||
(declare retrieve-library)
|
||||
|
||||
(s/def ::color-library
|
||||
(s/keys :req-un [::profile-id ::id]))
|
||||
|
||||
(sq/defquery ::color-library
|
||||
[{:keys [profile-id id]}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(p/let [lib (retrieve-library conn id)]
|
||||
(teams/check-edition-permissions! conn profile-id (:team-id lib))
|
||||
lib)))
|
||||
|
||||
(def ^:private sql:single-library
|
||||
"select lib.*,
|
||||
(select count(*) from color where library_id = lib.id) as num_colors
|
||||
from color_library as lib
|
||||
where lib.deleted_at is null
|
||||
and lib.id = $1")
|
||||
|
||||
(defn- retrieve-library
|
||||
[conn id]
|
||||
(-> (db/query-one conn [sql:single-library id])
|
||||
(p/then' su/raise-not-found-if-nil)))
|
||||
|
||||
|
||||
|
||||
;; --- Query: Colors (by library)
|
||||
|
||||
(declare retrieve-colors)
|
||||
|
||||
(s/def ::colors
|
||||
(s/keys :req-un [::profile-id ::collection-id]))
|
||||
(s/keys :req-un [::profile-id ::library-id]))
|
||||
|
||||
(sq/defquery ::colors
|
||||
[{:keys [profile-id collection-id] :as params}]
|
||||
(-> (db/query db/pool [sql:colors profile-id collection-id])
|
||||
(p/then' #(mapv decode-row %))))
|
||||
[{:keys [profile-id library-id] :as params}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(p/let [lib (retrieve-library conn library-id)]
|
||||
(teams/check-edition-permissions! conn profile-id (:team-id lib))
|
||||
(retrieve-colors conn library-id))))
|
||||
|
||||
(def ^:private sql:colors
|
||||
"select color.*
|
||||
from color as color
|
||||
inner join color_library as lib on (lib.id = color.library_id)
|
||||
where color.deleted_at is null
|
||||
and color.library_id = $1
|
||||
order by created_at desc")
|
||||
|
||||
(defn- retrieve-colors
|
||||
[conn library-id]
|
||||
(db/query conn [sql:colors library-id]))
|
||||
|
||||
|
||||
|
||||
|
@ -89,14 +120,22 @@
|
|||
(s/keys :req-un [::profile-id ::id]))
|
||||
|
||||
(sq/defquery ::color
|
||||
[{:keys [id] :as params}]
|
||||
(-> (retrieve-color db/pool id)
|
||||
(p/then' su/raise-not-found-if-nil)))
|
||||
[{:keys [profile-id id] :as params}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(p/let [color (retrieve-color conn id)]
|
||||
(teams/check-edition-permissions! conn profile-id (:team-id color))
|
||||
color)))
|
||||
|
||||
(def ^:private sql:single-color
|
||||
"select color.*,
|
||||
lib.team_id as team_id
|
||||
from color as color
|
||||
inner join color_library as lib on (lib.id = color.library_id)
|
||||
where color.deleted_at is null
|
||||
and color.id = $1
|
||||
order by created_at desc")
|
||||
|
||||
(defn retrieve-color
|
||||
[conn id]
|
||||
(let [sql "select * from color
|
||||
where id = $1
|
||||
and deleted_at is null;"]
|
||||
(-> (db/query-one conn [sql id])
|
||||
(p/then' su/raise-not-found-if-nil))))
|
||||
(-> (db/query-one conn [sql:single-color id])
|
||||
(p/then' su/raise-not-found-if-nil)))
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
[uxbox.db :as db]
|
||||
[uxbox.media :as media]
|
||||
[uxbox.images :as images]
|
||||
[uxbox.services.queries.teams :as teams]
|
||||
[uxbox.services.queries :as sq]
|
||||
[uxbox.services.util :as su]
|
||||
[uxbox.util.blob :as blob]
|
||||
|
@ -27,8 +28,9 @@
|
|||
;; --- Helpers & Specs
|
||||
|
||||
(s/def ::id ::us/uuid)
|
||||
(s/def ::name ::us/string)
|
||||
(s/def ::profile-id ::us/uuid)
|
||||
(s/def ::collection-id (s/nilable ::us/uuid))
|
||||
(s/def ::library-id ::us/uuid)
|
||||
|
||||
(defn decode-row
|
||||
[{:keys [metadata] :as row}]
|
||||
|
@ -38,45 +40,82 @@
|
|||
|
||||
|
||||
|
||||
;; --- Query: Collections
|
||||
;; --- Query: Icons Librarys
|
||||
|
||||
(def ^:private sql:collections
|
||||
"select *,
|
||||
(select count(*) from icon where collection_id = ic.id) as num_icons
|
||||
from icon_collection as ic
|
||||
where (ic.profile_id = $1 or
|
||||
ic.profile_id = '00000000-0000-0000-0000-000000000000'::uuid)
|
||||
and ic.deleted_at is null
|
||||
order by ic.created_at desc")
|
||||
(def ^:private sql:libraries
|
||||
"select lib.*,
|
||||
(select count(*) from icon where library_id = lib.id) as num_icons
|
||||
from icon_library as lib
|
||||
where lib.team_id = $1
|
||||
and lib.deleted_at is null
|
||||
order by lib.created_at desc")
|
||||
|
||||
(s/def ::icon-collections
|
||||
(s/keys :req-un [::profile-id]))
|
||||
(s/def ::icon-libraries
|
||||
(s/keys :req-un [::profile-id ::team-id]))
|
||||
|
||||
(sq/defquery ::icon-collections
|
||||
[{:keys [profile-id] :as params}]
|
||||
(let [sqlv [sql:collections profile-id]]
|
||||
(db/query db/pool sqlv)))
|
||||
(sq/defquery ::icon-libraries
|
||||
[{:keys [profile-id team-id]}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(teams/check-edition-permissions! conn profile-id team-id)
|
||||
(db/query conn [sql:libraries team-id])))
|
||||
|
||||
|
||||
|
||||
;; --- Icons By Collection ID
|
||||
;; --- Query: Icon Library
|
||||
|
||||
(def ^:private sql:icons
|
||||
"select *
|
||||
from icon as i
|
||||
where (i.profile_id = $1 or
|
||||
i.profile_id = '00000000-0000-0000-0000-000000000000'::uuid)
|
||||
and i.deleted_at is null
|
||||
and i.collection_id = $2
|
||||
order by i.created_at desc")
|
||||
(declare retrieve-library)
|
||||
|
||||
(s/def ::icon-library
|
||||
(s/keys :req-un [::profile-id ::id]))
|
||||
|
||||
(sq/defquery ::icon-library
|
||||
[{:keys [profile-id id]}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(p/let [lib (retrieve-library conn id)]
|
||||
(teams/check-edition-permissions! conn profile-id (:team-id lib))
|
||||
lib)))
|
||||
|
||||
(def ^:private sql:single-library
|
||||
"select lib.*,
|
||||
(select count(*) from icon where library_id = lib.id) as num_icons
|
||||
from icon_library as lib
|
||||
where lib.deleted_at is null
|
||||
and lib.id = $1")
|
||||
|
||||
(defn- retrieve-library
|
||||
[conn id]
|
||||
(-> (db/query-one conn [sql:single-library id])
|
||||
(p/then' su/raise-not-found-if-nil)))
|
||||
|
||||
|
||||
|
||||
;; --- Query: Icons (by library)
|
||||
|
||||
(declare retrieve-icons)
|
||||
|
||||
(s/def ::icons
|
||||
(s/keys :req-un [::profile-id ::collection-id]))
|
||||
(s/keys :req-un [::profile-id ::library-id]))
|
||||
|
||||
(sq/defquery ::icons
|
||||
[{:keys [profile-id collection-id] :as params}]
|
||||
(-> (db/query db/pool [sql:icons profile-id collection-id])
|
||||
(p/then' #(mapv decode-row %))))
|
||||
[{:keys [profile-id library-id] :as params}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(p/let [lib (retrieve-library conn library-id)]
|
||||
(teams/check-edition-permissions! conn profile-id (:team-id lib))
|
||||
(-> (retrieve-icons conn library-id)
|
||||
(p/then' (fn [rows] (mapv decode-row rows)))))))
|
||||
|
||||
(def ^:private sql:icons
|
||||
"select icon.*
|
||||
from icon as icon
|
||||
inner join icon_library as lib on (lib.id = icon.library_id)
|
||||
where icon.deleted_at is null
|
||||
and icon.library_id = $1
|
||||
order by created_at desc")
|
||||
|
||||
(defn- retrieve-icons
|
||||
[conn library-id]
|
||||
(db/query conn [sql:icons library-id]))
|
||||
|
||||
|
||||
|
||||
;; --- Query: Icon (by ID)
|
||||
|
@ -88,15 +127,23 @@
|
|||
(s/keys :req-un [::profile-id ::id]))
|
||||
|
||||
(sq/defquery ::icon
|
||||
[{:keys [id] :as params}]
|
||||
(-> (retrieve-icon db/pool id)
|
||||
(p/then' su/raise-not-found-if-nil)))
|
||||
[{:keys [profile-id id] :as params}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(p/let [icon (retrieve-icon conn id)]
|
||||
(teams/check-edition-permissions! conn profile-id (:team-id icon))
|
||||
(decode-row icon))))
|
||||
|
||||
(def ^:private sql:single-icon
|
||||
"select icon.*,
|
||||
lib.team_id as team_id
|
||||
from icon as icon
|
||||
inner join icon_library as lib on (lib.id = icon.library_id)
|
||||
where icon.deleted_at is null
|
||||
and icon.id = $1
|
||||
order by created_at desc")
|
||||
|
||||
(defn retrieve-icon
|
||||
[conn id]
|
||||
(let [sql "select * from icon
|
||||
where id = $1
|
||||
and deleted_at is null;"]
|
||||
(-> (db/query-one conn [sql id])
|
||||
(p/then' su/raise-not-found-if-nil))))
|
||||
(-> (db/query-one conn [sql:single-icon id])
|
||||
(p/then' su/raise-not-found-if-nil)))
|
||||
|
||||
|
|
|
@ -5,47 +5,105 @@
|
|||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2019 Andrey Antukh <niwi@niwi.nz>
|
||||
;; Copyright (c) 2019-2020 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.services.queries.images
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[promesa.core :as p]
|
||||
[promesa.exec :as px]
|
||||
[uxbox.common.exceptions :as ex]
|
||||
[uxbox.common.spec :as us]
|
||||
[uxbox.db :as db]
|
||||
[uxbox.media :as media]
|
||||
[uxbox.images :as images]
|
||||
[uxbox.services.queries.teams :as teams]
|
||||
[uxbox.services.queries :as sq]
|
||||
[uxbox.services.util :as su]
|
||||
[uxbox.util.blob :as blob]
|
||||
[uxbox.util.data :as data]
|
||||
[uxbox.util.uuid :as uuid]
|
||||
[vertx.core :as vc]))
|
||||
[uxbox.services.util :as su]))
|
||||
|
||||
(s/def ::id ::us/uuid)
|
||||
(s/def ::name ::us/string)
|
||||
(s/def ::profile-id ::us/uuid)
|
||||
(s/def ::collection-id (s/nilable ::us/uuid))
|
||||
(s/def ::library-id ::us/uuid)
|
||||
|
||||
;; --- Query: Image Collections
|
||||
;; --- Query: Image Librarys
|
||||
|
||||
(def ^:private sql:collections
|
||||
"select *,
|
||||
(select count(*) from image where collection_id = ic.id) as num_images
|
||||
from image_collection as ic
|
||||
where (ic.profile_id = $1 or
|
||||
ic.profile_id = '00000000-0000-0000-0000-000000000000'::uuid)
|
||||
and ic.deleted_at is null
|
||||
order by ic.created_at desc;")
|
||||
(def ^:private sql:libraries
|
||||
"select lib.*,
|
||||
(select count(*) from image where library_id = lib.id) as num_images
|
||||
from image_library as lib
|
||||
where lib.team_id = $1
|
||||
and lib.deleted_at is null
|
||||
order by lib.created_at desc")
|
||||
|
||||
(s/def ::image-collections
|
||||
(s/keys :req-un [::profile-id]))
|
||||
(s/def ::image-libraries
|
||||
(s/keys :req-un [::profile-id ::team-id]))
|
||||
|
||||
(sq/defquery ::image-collections
|
||||
[{:keys [profile-id] :as params}]
|
||||
(db/query db/pool [sql:collections profile-id]))
|
||||
(sq/defquery ::image-libraries
|
||||
[{:keys [profile-id team-id]}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(teams/check-edition-permissions! conn profile-id team-id)
|
||||
(db/query conn [sql:libraries team-id])))
|
||||
|
||||
|
||||
;; --- Query: Image Library
|
||||
|
||||
(declare retrieve-library)
|
||||
|
||||
(s/def ::image-library
|
||||
(s/keys :req-un [::profile-id ::id]))
|
||||
|
||||
(sq/defquery ::image-library
|
||||
[{:keys [profile-id id]}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(p/let [lib (retrieve-library conn id)]
|
||||
(teams/check-edition-permissions! conn profile-id (:team-id lib))
|
||||
lib)))
|
||||
|
||||
(def ^:private sql:single-library
|
||||
"select lib.*,
|
||||
(select count(*) from image where library_id = lib.id) as num_images
|
||||
from image_library as lib
|
||||
where lib.deleted_at is null
|
||||
and lib.id = $1")
|
||||
|
||||
(defn- retrieve-library
|
||||
[conn id]
|
||||
(-> (db/query-one conn [sql:single-library id])
|
||||
(p/then' su/raise-not-found-if-nil)))
|
||||
|
||||
|
||||
|
||||
;; --- Query: Images (by library)
|
||||
|
||||
(declare retrieve-images)
|
||||
|
||||
(s/def ::images
|
||||
(s/keys :req-un [::profile-id ::library-id]))
|
||||
|
||||
;; TODO: check if we can resolve url with transducer for reduce
|
||||
;; garbage generation for each request
|
||||
|
||||
(sq/defquery ::images
|
||||
[{:keys [profile-id library-id] :as params}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(p/let [lib (retrieve-library conn library-id)]
|
||||
(teams/check-edition-permissions! conn profile-id (:team-id lib))
|
||||
(-> (retrieve-images conn library-id)
|
||||
(p/then' (fn [rows]
|
||||
(->> rows
|
||||
(mapv #(images/resolve-urls % :path :uri))
|
||||
(mapv #(images/resolve-urls % :thumb-path :thumb-uri)))))))))
|
||||
|
||||
|
||||
(def ^:private sql:images
|
||||
"select img.*
|
||||
from image as img
|
||||
inner join image_library as lib on (lib.id = img.library_id)
|
||||
where img.deleted_at is null
|
||||
and img.library_id = $1
|
||||
order by created_at desc")
|
||||
|
||||
(defn- retrieve-images
|
||||
[conn library-id]
|
||||
(db/query conn [sql:images library-id]))
|
||||
|
||||
|
||||
|
||||
|
@ -58,42 +116,27 @@
|
|||
(s/keys :req-un [::profile-id ::id]))
|
||||
|
||||
(sq/defquery ::image
|
||||
[{:keys [id] :as params}]
|
||||
(-> (retrieve-image db/pool id)
|
||||
(p/then' #(images/resolve-urls % :path :uri))
|
||||
(p/then' #(images/resolve-urls % :thumb-path :thumb-uri))))
|
||||
[{:keys [profile-id id] :as params}]
|
||||
(db/with-atomic [conn db/pool]
|
||||
(p/let [img (retrieve-image conn id)]
|
||||
(teams/check-edition-permissions! conn profile-id (:team-id img))
|
||||
(-> img
|
||||
(images/resolve-urls :path :uri)
|
||||
(images/resolve-urls :thumb-path :thumb-uri)))))
|
||||
|
||||
(def ^:private sql:single-image
|
||||
"select img.*,
|
||||
lib.team_id as team_id
|
||||
from image as img
|
||||
inner join image_library as lib on (lib.id = img.library_id)
|
||||
where img.deleted_at is null
|
||||
and img.id = $1
|
||||
order by created_at desc")
|
||||
|
||||
(defn retrieve-image
|
||||
[conn id]
|
||||
(let [sql "select * from image
|
||||
where id = $1
|
||||
and deleted_at is null;"]
|
||||
(-> (db/query-one conn [sql id])
|
||||
(p/then' su/raise-not-found-if-nil))))
|
||||
(-> (db/query-one conn [sql:single-image id])
|
||||
(p/then' su/raise-not-found-if-nil)))
|
||||
|
||||
|
||||
|
||||
;; --- Query: Images (by collection)
|
||||
|
||||
(def ^:private sql:images
|
||||
"select *
|
||||
from image
|
||||
where (profile_id = $1 or
|
||||
profile_id = '00000000-0000-0000-0000-000000000000'::uuid)
|
||||
and deleted_at is null
|
||||
and collection_id = $2
|
||||
order by created_at desc")
|
||||
|
||||
(s/def ::images
|
||||
(s/keys :req-un [::profile-id ::collection-id]))
|
||||
|
||||
;; TODO: check if we can resolve url with transducer for reduce
|
||||
;; garbage generation for each request
|
||||
|
||||
(sq/defquery ::images
|
||||
[{:keys [profile-id collection-id] :as params}]
|
||||
(-> (db/query db/pool [sql:images profile-id collection-id])
|
||||
(p/then' (fn [rows]
|
||||
(->> rows
|
||||
(mapv #(images/resolve-urls % :path :uri))
|
||||
(mapv #(images/resolve-urls % :thumb-path :thumb-uri)))))))
|
||||
|
|
44
backend/src/uxbox/services/queries/teams.clj
Normal file
44
backend/src/uxbox/services/queries/teams.clj
Normal file
|
@ -0,0 +1,44 @@
|
|||
;; 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/.
|
||||
;;
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2020 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.services.queries.teams
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[promesa.core :as p]
|
||||
[uxbox.db :as db]
|
||||
[uxbox.common.exceptions :as ex]
|
||||
[uxbox.common.spec :as us]
|
||||
[uxbox.services.queries :as sq]
|
||||
[uxbox.services.util :as su]
|
||||
[uxbox.util.blob :as blob]
|
||||
[uxbox.util.uuid :as uuid]))
|
||||
|
||||
|
||||
;; --- Team Edition Permissions
|
||||
|
||||
(def ^:private sql:team-permissions
|
||||
"select tpr.is_owner,
|
||||
tpr.is_admin,
|
||||
tpr.can_edit
|
||||
from team_profile_rel as tpr
|
||||
where tpr.profile_id = $1
|
||||
and tpr.team_id = $2")
|
||||
|
||||
(defn check-edition-permissions!
|
||||
[conn profile-id team-id]
|
||||
(-> (db/query-one conn [sql:team-permissions profile-id team-id])
|
||||
(p/then' (fn [row]
|
||||
(when-not (or (:can-edit row)
|
||||
(:is-admin row)
|
||||
(:is-owner row))
|
||||
(ex/raise :type :validation
|
||||
:code :not-authorized))))))
|
||||
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue