Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Alejandro Alonso 2022-06-27 09:28:54 +02:00
commit 07881eed65
18 changed files with 92 additions and 84 deletions

View file

@ -11,6 +11,7 @@ jobs:
- image: cimg/redis:6.2.6 - image: cimg/redis:6.2.6
working_directory: ~/repo working_directory: ~/repo
resource_class: large
environment: environment:
# Customize the JVM maximum heap limit # Customize the JVM maximum heap limit

View file

@ -38,6 +38,9 @@
:single-key-in :single-key-in
{:level :warning} {:level :warning}
:non-arg-vec-return-type-hint
{:level :off}
:redundant-do :redundant-do
{:level :off} {:level :off}

View file

@ -15,6 +15,8 @@
### :bug: Bugs fixed ### :bug: Bugs fixed
- Fix shortcut access in main menu [Taiga #3672](https://tree.taiga.io/project/penpot/issue/3672)
- Fix modify colors in a row in selected colors [Taiga #3653](https://tree.taiga.io/project/penpot/issue/3653)
- Fix crash when double click on viewer assets [Taiga #3625](https://tree.taiga.io/project/penpot/issue/3625) - Fix crash when double click on viewer assets [Taiga #3625](https://tree.taiga.io/project/penpot/issue/3625)
- Fix right click on typographies assets [Taiga #3638](https://tree.taiga.io/project/penpot/issue/3638) - Fix right click on typographies assets [Taiga #3638](https://tree.taiga.io/project/penpot/issue/3638)

View file

@ -51,7 +51,7 @@
(defn profile->props (defn profile->props
[profile] [profile]
(-> profile (-> profile
(select-keys [:is-active :is-muted :auth-backend :email :default-team-id :default-project-id :fullname :lang]) (select-keys [:id :is-active :is-muted :auth-backend :email :default-team-id :default-project-id :fullname :lang])
(merge (:props profile)) (merge (:props profile))
(d/without-nils))) (d/without-nils)))

View file

@ -6,7 +6,6 @@
(ns app.rpc (ns app.rpc
(:require (:require
[app.common.data :as d]
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.logging :as l] [app.common.logging :as l]
[app.common.spec :as us] [app.common.spec :as us]
@ -132,10 +131,13 @@
(fn [result _] (fn [result _]
(when result (when result
(let [resultm (meta result) (let [resultm (meta result)
profile-id (or (:profile-id params) profile-id (or (::audit/profile-id resultm)
(:profile-id result) (:profile-id result)
(::audit/profile-id resultm)) (:profile-id params))
props (d/merge params (::audit/props resultm))] props (or (::audit/replace-props resultm)
(-> params
(merge (::audit/props resultm))
(dissoc :type)))]
(audit :cmd :submit (audit :cmd :submit
:type (or (::audit/type resultm) :type (or (::audit/type resultm)
(::type cfg)) (::type cfg))

View file

@ -137,7 +137,8 @@
:exp (dt/in-future "48h")} :exp (dt/in-future "48h")}
token (tokens :generate params)] token (tokens :generate params)]
{:token token})) (with-meta {:token token}
{::audit/profile-id uuid/zero})))
;; --- MUTATION: Register Profile ;; --- MUTATION: Register Profile
@ -175,7 +176,7 @@
resp {:invitation-token token}] resp {:invitation-token token}]
(with-meta resp (with-meta resp
{:transform-response ((:create session) (:id profile)) {:transform-response ((:create session) (:id profile))
::audit/props (audit/profile->props profile) ::audit/replace-props (audit/profile->props profile)
::audit/profile-id (:id profile)})) ::audit/profile-id (:id profile)}))
;; If auth backend is different from "penpot" means user is ;; If auth backend is different from "penpot" means user is
@ -184,7 +185,7 @@
(not= "penpot" (:auth-backend profile)) (not= "penpot" (:auth-backend profile))
(with-meta (profile/strip-private-attrs profile) (with-meta (profile/strip-private-attrs profile)
{:transform-response ((:create session) (:id profile)) {:transform-response ((:create session) (:id profile))
::audit/props (audit/profile->props profile) ::audit/replace-props (audit/profile->props profile)
::audit/profile-id (:id profile)}) ::audit/profile-id (:id profile)})
;; If the `:enable-insecure-register` flag is set, we proceed ;; If the `:enable-insecure-register` flag is set, we proceed
@ -192,7 +193,7 @@
(true? is-active) (true? is-active)
(with-meta (profile/strip-private-attrs profile) (with-meta (profile/strip-private-attrs profile)
{:transform-response ((:create session) (:id profile)) {:transform-response ((:create session) (:id profile))
::audit/props (audit/profile->props profile) ::audit/replace-props (audit/profile->props profile)
::audit/profile-id (:id profile)}) ::audit/profile-id (:id profile)})
;; In all other cases, send a verification email. ;; In all other cases, send a verification email.
@ -214,7 +215,7 @@
:extra-data ptoken}) :extra-data ptoken})
(with-meta profile (with-meta profile
{::audit/props (audit/profile->props profile) {::audit/replace-props (audit/profile->props profile)
::audit/profile-id (:id profile)})))))) ::audit/profile-id (:id profile)}))))))
(defn create-profile (defn create-profile

View file

@ -199,6 +199,7 @@
"taiga" "taiga"
(cf/get :telemetry-referer))] (cf/get :telemetry-referer))]
(-> {:referer referer (-> {:referer referer
:public-uri (cf/get :public-uri)
:total-teams (retrieve-num-teams conn) :total-teams (retrieve-num-teams conn)
:total-projects (retrieve-num-projects conn) :total-projects (retrieve-num-projects conn)
:total-files (retrieve-num-files conn) :total-files (retrieve-num-files conn)

View file

@ -1,34 +1,48 @@
# Should be set to the public domain where penpot is going to be served. ## Should be set to the public domain where penpot is going to be served.
##
## NOTE: If you are going to serve it under different domain than
## 'localhost' without HTTPS, consider setting the
## `disable-secure-session-cookies' flag on the 'PENPOT_FLAGS'
## setting.
PENPOT_PUBLIC_URI=http://localhost:9001 PENPOT_PUBLIC_URI=http://localhost:9001
PENPOT_TENANT=pro PENPOT_TENANT=pro
# Temporal workaround because of bad builtin default ## Feature flags.
PENPOT_FLAGS="enable-registration enable-login"
## Temporal workaround because of bad builtin default
PENPOT_HTTP_SERVER_HOST=0.0.0.0 PENPOT_HTTP_SERVER_HOST=0.0.0.0
# Standard database connection parameters (only postgresql is supported): ## Standard database connection parameters (only postgresql is supported):
PENPOT_DATABASE_URI=postgresql://penpot-postgres/penpot PENPOT_DATABASE_URI=postgresql://penpot-postgres/penpot
PENPOT_DATABASE_USERNAME=penpot PENPOT_DATABASE_USERNAME=penpot
PENPOT_DATABASE_PASSWORD=penpot PENPOT_DATABASE_PASSWORD=penpot
# Redis is used for the websockets notifications. ## Redis is used for the websockets notifications.
PENPOT_REDIS_URI=redis://penpot-redis/0 PENPOT_REDIS_URI=redis://penpot-redis/0
# By default, files uploaded by users are stored in local filesystem. But it ## By default, files uploaded by users are stored in local
# can be configured to store in AWS S3 or completely in de the database. ## filesystem. But it can be configured to store in AWS S3.
# Storing in the database makes the backups more easy but will make access to
# media less performant.
PENPOT_ASSETS_STORAGE_BACKEND=assets-fs PENPOT_ASSETS_STORAGE_BACKEND=assets-fs
PENPOT_STORAGE_ASSETS_FS_DIRECTORY=/opt/data/assets PENPOT_STORAGE_ASSETS_FS_DIRECTORY=/opt/data/assets
# Telemetry. When enabled, a periodical process will send anonymous data about ## Telemetry. When enabled, a periodical process will send anonymous
# this instance. Telemetry data will enable us to learn on how the application ## data about this instance. Telemetry data will enable us to learn on
# is used, based on real scenarios. If you want to help us, please leave it ## how the application is used, based on real scenarios. If you want
# enabled. ## to help us, please leave it enabled.
PENPOT_TELEMETRY_ENABLED=true PENPOT_TELEMETRY_ENABLED=true
# Email sending configuration. By default, emails are printed in the console, ## Email sending configuration. By default, emails are printed in the
# but for production usage is recommended to setup a real SMTP provider. Emails ## console, but for production usage is recommended to setup a real
# are used to confirm user registrations. ## SMTP provider. Emails are used to confirm user registrations.
PENPOT_SMTP_ENABLED=false PENPOT_SMTP_ENABLED=false
PENPOT_SMTP_DEFAULT_FROM=no-reply@example.com PENPOT_SMTP_DEFAULT_FROM=no-reply@example.com
PENPOT_SMTP_DEFAULT_REPLY_TO=no-reply@example.com PENPOT_SMTP_DEFAULT_REPLY_TO=no-reply@example.com
@ -39,34 +53,40 @@ PENPOT_SMTP_DEFAULT_REPLY_TO=no-reply@example.com
# PENPOT_SMTP_TLS=true # PENPOT_SMTP_TLS=true
# PENPOT_SMTP_SSL=false # PENPOT_SMTP_SSL=false
# Feature flags. Right now they are only affect frontend, but in ## Comma separated list of allowed domains to register. Empty to allow
# future release they will affect to both backend and frontend. ## all.
PENPOT_FLAGS="enable-registration"
# Comma separated list of allowed domains to register. Empty to allow all.
# PENPOT_REGISTRATION_DOMAIN_WHITELIST="" # PENPOT_REGISTRATION_DOMAIN_WHITELIST=""
## Authentication providers ## Authentication providers
# Google ## Google
# PENPOT_GOOGLE_CLIENT_ID= # PENPOT_GOOGLE_CLIENT_ID=
# PENPOT_GOOGLE_CLIENT_SECRET= # PENPOT_GOOGLE_CLIENT_SECRET=
# GitHub ## GitHub
# PENPOT_GITHUB_CLIENT_ID= # PENPOT_GITHUB_CLIENT_ID=
# PENPOT_GITHUB_CLIENT_SECRET= # PENPOT_GITHUB_CLIENT_SECRET=
# GitLab ## GitLab
# PENPOT_GITLAB_BASE_URI=https://gitlab.com # PENPOT_GITLAB_BASE_URI=https://gitlab.com
# PENPOT_GITLAB_CLIENT_ID= # PENPOT_GITLAB_CLIENT_ID=
# PENPOT_GITLAB_CLIENT_SECRET= # PENPOT_GITLAB_CLIENT_SECRET=
# OpenID Connect (since 1.5.0) ## OpenID Connect (since 1.5.0)
# PENPOT_OIDC_BASE_URI= # PENPOT_OIDC_BASE_URI=
# PENPOT_OIDC_CLIENT_ID= # PENPOT_OIDC_CLIENT_ID=
# PENPOT_OIDC_CLIENT_SECRET= # PENPOT_OIDC_CLIENT_SECRET=
# LDAP ## LDAP
##
## NOTE: to enable ldap, you will need to put 'enable-login-with-ldap'
## on the 'PENPOT_FLAGS' environment variable.
# PENPOT_LDAP_HOST=ldap # PENPOT_LDAP_HOST=ldap
# PENPOT_LDAP_PORT=10389 # PENPOT_LDAP_PORT=10389
# PENPOT_LDAP_SSL=false # PENPOT_LDAP_SSL=false
@ -78,7 +98,3 @@ PENPOT_FLAGS="enable-registration"
# PENPOT_LDAP_ATTRS_EMAIL=mail # PENPOT_LDAP_ATTRS_EMAIL=mail
# PENPOT_LDAP_ATTRS_FULLNAME=cn # PENPOT_LDAP_ATTRS_FULLNAME=cn
# PENPOT_LDAP_ATTRS_PHOTO=jpegPhoto # PENPOT_LDAP_ATTRS_PHOTO=jpegPhoto
# PENPOT_LOGIN_WITH_LDAP=true
# Exporter
PENPOT_DOMAIN_WHITE_LIST=localhost:9001

View file

@ -25,15 +25,13 @@
:host "devenv" :host "devenv"
:http-server-port 6061 :http-server-port 6061
:http-server-host "localhost" :http-server-host "localhost"
:redis-uri "redis://redis/0" :redis-uri "redis://redis/0"})
:domain-white-list #{"localhost:3449"}})
(s/def ::http-server-port ::us/integer) (s/def ::http-server-port ::us/integer)
(s/def ::http-server-host ::us/string) (s/def ::http-server-host ::us/string)
(s/def ::public-uri ::us/uri) (s/def ::public-uri ::us/uri)
(s/def ::tenant ::us/string) (s/def ::tenant ::us/string)
(s/def ::host ::us/string) (s/def ::host ::us/string)
(s/def ::domain-white-list ::us/set-of-str)
(s/def ::browser-pool-max ::us/integer) (s/def ::browser-pool-max ::us/integer)
(s/def ::browser-pool-min ::us/integer) (s/def ::browser-pool-min ::us/integer)
@ -44,8 +42,7 @@
::http-server-port ::http-server-port
::http-server-host ::http-server-host
::browser-pool-max ::browser-pool-max
::browser-pool-min ::browser-pool-min]))
::domain-white-list]))
(defn- read-env (defn- read-env
[prefix] [prefix]

View file

@ -70,7 +70,6 @@
(defmulti command-spec :cmd) (defmulti command-spec :cmd)
(s/def ::id ::us/string) (s/def ::id ::us/string)
(s/def ::uri ::us/uri)
(s/def ::wait ::us/boolean) (s/def ::wait ::us/boolean)
(s/def ::cmd ::us/keyword) (s/def ::cmd ::us/keyword)
@ -80,24 +79,13 @@
(s/def ::params (s/def ::params
(s/and (s/keys :req-un [::cmd] (s/and (s/keys :req-un [::cmd]
:opt-un [::wait ::uri]) :opt-un [::wait])
(s/multi-spec command-spec :cmd))) (s/multi-spec command-spec :cmd)))
(defn validate-uri!
[uri]
(let [white-list (cf/get :domain-white-list #{})
default (cf/get :public-uri)]
(when-not (or (contains? white-list (u/get-domain uri))
(= (u/get-domain default) (u/get-domain uri)))
(ex/raise :type :validation
:code :domain-not-allowed
:hint "looks like the uri provided is not part of the white list"))))
(defn handler (defn handler
[{:keys [:request/params] :as exchange}] [{:keys [:request/params] :as exchange}]
(let [{:keys [cmd uri] :as params} (us/conform ::params params)] (let [{:keys [cmd] :as params} (us/conform ::params params)]
(l/debug :hint "process-request" :cmd cmd) (l/debug :hint "process-request" :cmd cmd)
(some-> uri validate-uri!)
(case cmd (case cmd
:get-resource (resources/handler exchange) :get-resource (resources/handler exchange)
:export-shapes (export-shapes/handler exchange params) :export-shapes (export-shapes/handler exchange params)

View file

@ -29,7 +29,6 @@
(s/def ::file-id ::us/uuid) (s/def ::file-id ::us/uuid)
(s/def ::page-id ::us/uuid) (s/def ::page-id ::us/uuid)
(s/def ::object-id ::us/uuid) (s/def ::object-id ::us/uuid)
(s/def ::uri ::us/uri)
(s/def ::export (s/def ::export
(s/keys :req-un [::file-id ::page-id ::object-id ::name])) (s/keys :req-un [::file-id ::page-id ::object-id ::name]))
@ -39,18 +38,18 @@
(s/def ::params (s/def ::params
(s/keys :req-un [::exports] (s/keys :req-un [::exports]
:opt-un [::uri ::name])) :opt-un [::name]))
(defn handler (defn handler
[{:keys [:request/auth-token] :as exchange} {:keys [exports uri profile-id] :as params}] [{:keys [:request/auth-token] :as exchange} {:keys [exports profile-id] :as params}]
;; NOTE: we need to have the `:type` prop because the exports ;; NOTE: we need to have the `:type` prop because the exports
;; datastructure preparation uses it for creating the groups. ;; datastructure preparation uses it for creating the groups.
(let [exports (-> (map #(assoc % :type :pdf :scale 1 :suffix "") exports) (let [exports (-> (map #(assoc % :type :pdf :scale 1 :suffix "") exports)
(prepare-exports auth-token uri))] (prepare-exports auth-token))]
(handle-export exchange (assoc params :exports exports)))) (handle-export exchange (assoc params :exports exports))))
(defn handle-export (defn handle-export
[exchange {:keys [exports wait uri name profile-id] :as params}] [exchange {:keys [exports wait name profile-id] :as params}]
(let [total (count exports) (let [total (count exports)
topic (str profile-id) topic (str profile-id)
resource (rsc/create :pdf (or name (-> exports first :name))) resource (rsc/create :pdf (or name (-> exports first :name)))

View file

@ -34,7 +34,6 @@
(s/def ::scale ::us/number) (s/def ::scale ::us/number)
(s/def ::suffix ::us/string) (s/def ::suffix ::us/string)
(s/def ::type ::us/keyword) (s/def ::type ::us/keyword)
(s/def ::uri ::us/uri)
(s/def ::wait ::us/boolean) (s/def ::wait ::us/boolean)
(s/def ::export (s/def ::export
@ -45,11 +44,11 @@
(s/def ::params (s/def ::params
(s/keys :req-un [::exports ::profile-id] (s/keys :req-un [::exports ::profile-id]
:opt-un [::uri ::wait ::name])) :opt-un [::wait ::name]))
(defn handler (defn handler
[{:keys [:request/auth-token] :as exchange} {:keys [exports uri] :as params}] [{:keys [:request/auth-token] :as exchange} {:keys [exports] :as params}]
(let [exports (prepare-exports exports auth-token uri)] (let [exports (prepare-exports exports auth-token)]
(if (and (= 1 (count exports)) (if (and (= 1 (count exports))
(= 1 (count (-> exports first :objects)))) (= 1 (count (-> exports first :objects))))
(handle-single-export exchange (-> params (handle-single-export exchange (-> params
@ -58,7 +57,7 @@
(handle-multiple-export exchange (assoc params :exports exports))))) (handle-multiple-export exchange (assoc params :exports exports)))))
(defn- handle-single-export (defn- handle-single-export
[exchange {:keys [export wait uri profile-id name] :as params}] [exchange {:keys [export wait profile-id name] :as params}]
(let [topic (str profile-id) (let [topic (str profile-id)
resource (rsc/create (:type export) (or name (:name export))) resource (rsc/create (:type export) (or name (:name export)))
@ -98,7 +97,7 @@
(assoc exchange :response/body (dissoc resource :path))))) (assoc exchange :response/body (dissoc resource :path)))))
(defn- handle-multiple-export (defn- handle-multiple-export
[exchange {:keys [exports wait uri profile-id name] :as params}] [exchange {:keys [exports wait profile-id name] :as params}]
(let [resource (rsc/create :zip (or name (-> exports first :name))) (let [resource (rsc/create :zip (or name (-> exports first :name)))
total (count exports) total (count exports)
topic (str profile-id) topic (str profile-id)
@ -185,7 +184,7 @@
default-partition-size 50) default-partition-size 50)
(defn prepare-exports (defn prepare-exports
[exports token uri] [exports token]
(letfn [(process-group [group] (letfn [(process-group [group]
(sequence (comp (partition-all default-partition-size) (sequence (comp (partition-all default-partition-size)
(map process-partition)) (map process-partition))
@ -196,7 +195,6 @@
:page-id (:page-id part1) :page-id (:page-id part1)
:name (:name part1) :name (:name part1)
:token token :token token
:uri uri
:type (:type part1) :type (:type part1)
:scale (:scale part1) :scale (:scale part1)
:objects (mapv part-entry->object part)}) :objects (mapv part-entry->object part)})

View file

@ -20,7 +20,6 @@
(s/def ::file-id ::us/uuid) (s/def ::file-id ::us/uuid)
(s/def ::scale ::us/number) (s/def ::scale ::us/number)
(s/def ::token ::us/string) (s/def ::token ::us/string)
(s/def ::uri ::us/uri)
(s/def ::filename ::us/string) (s/def ::filename ::us/string)
(s/def ::object (s/def ::object
@ -30,8 +29,7 @@
(s/coll-of ::object :min-count 1)) (s/coll-of ::object :min-count 1))
(s/def ::render-params (s/def ::render-params
(s/keys :req-un [::file-id ::page-id ::scale ::token ::type ::objects] (s/keys :req-un [::file-id ::page-id ::scale ::token ::type ::objects]))
:opt-un [::uri]))
(defn- render (defn- render
[{:keys [type] :as params} on-object] [{:keys [type] :as params} on-object]

View file

@ -130,9 +130,7 @@
(defmethod query :exporter (defmethod query :exporter
[_ params] [_ params]
(let [default {:wait false (let [default {:wait false :blob? false}]
:blob? false
:uri (str base-uri)}]
(send-export (merge default params)))) (send-export (merge default params))))
(derive :upload-file-media-object ::multipart-upload) (derive :upload-file-media-object ::multipart-upload)

View file

@ -398,7 +398,9 @@
[:span (tr "labels.github-repo")]] [:span (tr "labels.github-repo")]]
[:li {:on-click #(dom/open-new-window "https://penpot.app/terms.html")} [:li {:on-click #(dom/open-new-window "https://penpot.app/terms.html")}
[:span (tr "auth.terms-of-service")]] [:span (tr "auth.terms-of-service")]]
[:li.separator {:on-click #(st/emit! (rt/nav-new-window* {:rname :settings-feedback}))} [:li.separator {:on-click #(st/emit! (when (contains? layout :collapse-left-sidebar) (dw/toggle-layout-flag :collapse-left-sidebar))
(-> (dw/toggle-layout-flag :shortcuts)
(vary-meta assoc ::ev/origin "workspace-header")))}
[:span (tr "label.shortcuts")] [:span (tr "label.shortcuts")]
[:span.shortcut (sc/get-tooltip :show-shortcuts)]] [:span.shortcut (sc/get-tooltip :show-shortcuts)]]

View file

@ -125,12 +125,11 @@
on-change on-change
(mf/use-fn (mf/use-fn
(fn [new-color old-color] (fn [new-color old-color]
(let [old-color (-> (or @prev-color* old-color) (let [old-color (-> old-color
(dissoc :name) (dissoc :name)
(dissoc :path) (dissoc :path)
(d/without-nils)) (d/without-nils))
shapes-by-color (get @grouped-colors* old-color)] shapes-by-color (get @grouped-colors* old-color)]
(reset! prev-color* new-color)
(st/emit! (dc/change-color-in-selected new-color shapes-by-color old-color))))) (st/emit! (dc/change-color-in-selected new-color shapes-by-color old-color)))))
on-open (mf/use-fn on-open (mf/use-fn

View file

@ -69,6 +69,8 @@
shared-libs (mf/deref refs/workspace-libraries) shared-libs (mf/deref refs/workspace-libraries)
hover-detach (mf/use-state false) hover-detach (mf/use-state false)
on-change-var (h/use-update-var {:fn on-change})
src-colors (if (= (:file-id color) current-file-id) src-colors (if (= (:file-id color) current-file-id)
file-colors file-colors
(get-in shared-libs [(:file-id color) :data :colors])) (get-in shared-libs [(:file-id color) :data :colors]))
@ -83,18 +85,18 @@
(when on-detach (on-detach color))) (when on-detach (on-detach color)))
change-value (fn [new-value] change-value (fn [new-value]
(when on-change (on-change (-> color (when (:fn @on-change-var) ((:fn @on-change-var) (-> color
(assoc :color new-value) (assoc :color new-value)
(dissoc :gradient))))) (dissoc :gradient)))))
change-opacity (fn [new-opacity] change-opacity (fn [new-opacity]
(when on-change (on-change (assoc color (when (:fn @on-change-var) ((:fn @on-change-var) (assoc color
:opacity new-opacity :opacity new-opacity
:id nil :id nil
:file-id nil)))) :file-id nil))))
handle-pick-color (fn [color] handle-pick-color (fn [color]
(when on-change (on-change (merge uc/empty-color color)))) (when (:fn @on-change-var) ((:fn @on-change-var) (merge uc/empty-color color))))
handle-select (fn [] handle-select (fn []
(select-only color)) (select-only color))

View file

@ -43,6 +43,7 @@
(rest keys) (rest keys)
(unchecked-get res key)))))) (unchecked-get res key))))))
#_:clj-kondo/ignore
(defn without (defn without
[obj keys] [obj keys]
(let [keys (cond (let [keys (cond