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

This commit is contained in:
Alejandro Alonso 2023-01-13 14:37:06 +01:00
commit 19bac6bd10
21 changed files with 57 additions and 228 deletions

View file

@ -106,9 +106,6 @@
(s/def ::file-change-snapshot-every ::us/integer) (s/def ::file-change-snapshot-every ::us/integer)
(s/def ::file-change-snapshot-timeout ::dt/duration) (s/def ::file-change-snapshot-timeout ::dt/duration)
(s/def ::setup-admin-email ::us/email)
(s/def ::setup-admin-password ::us/not-empty-string)
(s/def ::default-executor-parallelism ::us/integer) (s/def ::default-executor-parallelism ::us/integer)
(s/def ::scheduled-executor-parallelism ::us/integer) (s/def ::scheduled-executor-parallelism ::us/integer)
@ -314,9 +311,6 @@
::srepl-host ::srepl-host
::srepl-port ::srepl-port
::setup-admin-email
::setup-admin-password
::assets-storage-backend ::assets-storage-backend
::storage-assets-fs-directory ::storage-assets-fs-directory
::storage-assets-s3-bucket ::storage-assets-s3-bucket
@ -332,8 +326,7 @@
[:enable-backend-api-doc [:enable-backend-api-doc
:enable-backend-worker :enable-backend-worker
:enable-secure-session-cookies :enable-secure-session-cookies
:enable-email-verification :enable-email-verification])
:enable-quotes])
(defn- parse-flags (defn- parse-flags
[config] [config]

View file

@ -91,9 +91,7 @@
(let [params (:path-params match) (let [params (:path-params match)
result (:result match) result (:result match)
handler (or (:handler result) not-found-handler) handler (or (:handler result) not-found-handler)
request (-> request request (assoc request :path-params params)]
(assoc :path-params params)
(update :params merge params))]
(handler request respond raise)) (handler request respond raise))
(not-found-handler request respond raise))) (not-found-handler request respond raise)))

View file

@ -408,9 +408,6 @@
{:port (cf/get :srepl-port) {:port (cf/get :srepl-port)
:host (cf/get :srepl-host)} :host (cf/get :srepl-host)}
:app.setup/initial-profile
{::db/pool (ig/ref ::db/pool)}
:app.setup/builtin-templates :app.setup/builtin-templates
{::http.client/client (ig/ref ::http.client/client)} {::http.client/client (ig/ref ::http.client/client)}

View file

@ -299,9 +299,6 @@
{:name "0096-del-storage-pending-table" {:name "0096-del-storage-pending-table"
:fn (mg/resource "app/migrations/sql/0096-del-storage-pending-table.sql")} :fn (mg/resource "app/migrations/sql/0096-del-storage-pending-table.sql")}
{:name "0097-mod-profile-table"
:fn (mg/resource "app/migrations/sql/0097-mod-profile-table.sql")}
{:name "0098-add-quotes-table" {:name "0098-add-quotes-table"
:fn (mg/resource "app/migrations/sql/0098-add-quotes-table.sql")} :fn (mg/resource "app/migrations/sql/0098-add-quotes-table.sql")}

View file

@ -1,2 +0,0 @@
ALTER TABLE profile
ADD COLUMN is_admin boolean DEFAULT false;

View file

@ -71,8 +71,8 @@
(defn- rpc-query-handler (defn- rpc-query-handler
"Ring handler that dispatches query requests and convert between "Ring handler that dispatches query requests and convert between
internal async flow into ring async flow." internal async flow into ring async flow."
[methods {:keys [profile-id session-id params] :as request} respond raise] [methods {:keys [profile-id session-id path-params params] :as request} respond raise]
(let [type (keyword (:type params)) (let [type (keyword (:type path-params))
data (-> params data (-> params
(assoc ::request-at (dt/now)) (assoc ::request-at (dt/now))
(assoc ::http/request request)) (assoc ::http/request request))
@ -94,8 +94,8 @@
(defn- rpc-mutation-handler (defn- rpc-mutation-handler
"Ring handler that dispatches mutation requests and convert between "Ring handler that dispatches mutation requests and convert between
internal async flow into ring async flow." internal async flow into ring async flow."
[methods {:keys [profile-id session-id params] :as request} respond raise] [methods {:keys [profile-id session-id path-params params] :as request} respond raise]
(let [type (keyword (:type params)) (let [type (keyword (:type path-params))
data (-> params data (-> params
(assoc ::request-at (dt/now)) (assoc ::request-at (dt/now))
(assoc ::http/request request)) (assoc ::http/request request))
@ -116,8 +116,8 @@
(defn- rpc-command-handler (defn- rpc-command-handler
"Ring handler that dispatches cmd requests and convert between "Ring handler that dispatches cmd requests and convert between
internal async flow into ring async flow." internal async flow into ring async flow."
[methods {:keys [profile-id session-id params] :as request} respond raise] [methods {:keys [profile-id session-id path-params params] :as request} respond raise]
(let [cmd (keyword (:type params)) (let [cmd (keyword (:type path-params))
etag (yrq/get-header request "if-none-match") etag (yrq/get-header request "if-none-match")
data (-> params data (-> params
@ -290,7 +290,6 @@
(let [cfg (assoc cfg ::type "command" ::metrics-id :rpc-command-timing)] (let [cfg (assoc cfg ::type "command" ::metrics-id :rpc-command-timing)]
(->> (sv/scan-ns 'app.rpc.commands.binfile (->> (sv/scan-ns 'app.rpc.commands.binfile
'app.rpc.commands.comments 'app.rpc.commands.comments
'app.rpc.commands.profile
'app.rpc.commands.management 'app.rpc.commands.management
'app.rpc.commands.verify-token 'app.rpc.commands.verify-token
'app.rpc.commands.search 'app.rpc.commands.search

View file

@ -69,7 +69,7 @@
;; ---- COMMAND: login with password ;; ---- COMMAND: login with password
(defn login-with-password (defn login-with-password
[{:keys [::db/pool session] :as cfg} {:keys [email password scope] :as params}] [{:keys [::db/pool session] :as cfg} {:keys [email password] :as params}]
(when-not (or (contains? cf/flags :login) (when-not (or (contains? cf/flags :login)
(contains? cf/flags :login-with-password)) (contains? cf/flags :login-with-password))
@ -119,17 +119,8 @@
;; accept invitation with other email ;; accept invitation with other email
response (if (and (some? invitation) (= (:id profile) (:member-id invitation))) response (if (and (some? invitation) (= (:id profile) (:member-id invitation)))
{:invitation-token (:invitation-token params)} {:invitation-token (:invitation-token params)}
(update profile :is-admin (fn [admin?] (assoc profile :is-admin (let [admins (cf/get :admins)]
(or admin? (contains? admins (:email profile)))))]
(let [admins (cf/get :admins)]
(contains? admins (:email profile)))))))]
(when (and (nil? (:default-team-id profile))
(not= scope "admin"))
(ex/raise :type :restriction
:code :admin-only-profile
:hint "can't login with admin-only profile"))
(-> response (-> response
(rph/with-transform (session/create-fn session (:id profile))) (rph/with-transform (session/create-fn session (:id profile)))
(rph/with-meta {::audit/props (audit/profile->props profile) (rph/with-meta {::audit/props (audit/profile->props profile)

View file

@ -1,75 +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) KALEIDOS INC
(ns app.rpc.commands.profile
(:require
[app.auth :as auth]
[app.common.exceptions :as ex]
[app.common.spec :as us]
[app.config :as cf]
[app.db :as db]
[app.rpc :as-alias rpc]
[app.rpc.climit :as-alias climit]
[app.rpc.doc :as-alias doc]
[app.util.services :as sv]
[clojure.spec.alpha :as s]))
;; --- MUTATION: Set profile password
(declare update-profile-password!)
(s/def ::profile-id ::us/uuid)
(s/def ::password ::us/not-empty-string)
(s/def ::get-derived-password
(s/keys :req [::rpc/profile-id]
:req-un [::password]))
(sv/defmethod ::get-derived-password
"Get derived password, only ADMINS allowed to call this RPC
methods. Designed for administration pannel integration."
{::climit/queue :auth
::climit/key-fn ::rpc/profile-id
::doc/added "1.18"}
[{:keys [::db/pool]} {:keys [::rpc/profile-id password]}]
(db/with-atomic [conn pool]
(let [admins (cf/get :admins)
profile (db/get-by-id conn :profile profile-id)]
(if (or (:is-admin profile)
(contains? admins (:email profile)))
{:password (auth/derive-password password)}
(ex/raise :type :authentication
:code :only-admins-allowed
:hint "only admins allowed to call this RPC method")))))
;; --- MUTATION: Check profile password
(s/def ::attempt ::us/not-empty-string)
(s/def ::check-profile-password
(s/keys :req [::rpc/profile-id]
:req-un [::profile-id ::password]))
(sv/defmethod ::check-profile-password
"Check profile password, only ADMINS allowed to call this RPC
methods. Designed for administration pannel integration."
{::climit/queue :auth
::climit/key-fn ::rpc/profile-id
::doc/added "1.18"}
[{:keys [::db/pool]} {:keys [profile-id password] :as params}]
(db/with-atomic [conn pool]
(let [admins (cf/get :admins)
profile (db/get-by-id pool :profile (::rpc/profile-id params))]
(if (or (:is-admin profile)
(contains? admins (:email profile)))
(let [profile (if (not= (::rpc/profile-id params) profile-id)
(db/get-by-id conn :profile profile-id)
profile)]
(auth/verify-password password (:password profile)))
(ex/raise :type :authentication
:code :only-admins-allowed
:hint "only admins allowed to call this RPC method")))))

View file

@ -29,7 +29,6 @@
(s/def ::is-active ::us/boolean) (s/def ::is-active ::us/boolean)
(s/def ::mtype (s/def ::mtype
#{"application/json" #{"application/json"
"application/x-www-form-urlencoded"
"application/transit+json"}) "application/transit+json"})
(s/def ::create-webhook (s/def ::create-webhook

View file

@ -13,7 +13,6 @@
[app.db :as db] [app.db :as db]
[app.main :as-alias main] [app.main :as-alias main]
[app.setup.builtin-templates] [app.setup.builtin-templates]
[app.setup.initial-user]
[app.setup.keys :as keys] [app.setup.keys :as keys]
[buddy.core.codecs :as bc] [buddy.core.codecs :as bc]
[buddy.core.nonce :as bn] [buddy.core.nonce :as bn]
@ -69,5 +68,5 @@
(let [secret (or key (generate-random-key))] (let [secret (or key (generate-random-key))]
(-> (retrieve-all conn) (-> (retrieve-all conn)
(assoc :secret-key secret) (assoc :secret-key secret)
(assoc :tokens-key (keys/derive secret :salt "tokens" :size 32)) (assoc :tokens-key (keys/derive secret :salt "tokens"))
(update :instance-id handle-instance-id conn (db/read-only? pool)))))) (update :instance-id handle-instance-id conn (db/read-only? pool))))))

View file

@ -1,40 +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) KALEIDOS INC
(ns app.setup.initial-user
"Initial data setup of instance."
(:require
[app.auth :as auth]
[app.common.logging :as l]
[app.config :as cf]
[app.db :as db]
[app.setup :as-alias setup]
[clojure.spec.alpha :as s]
[integrant.core :as ig]))
(def ^:private sql:insert-profile
"insert into profile (id, fullname, email, password, is_active, is_admin, created_at, modified_at)
values ('00000000-0000-0000-0000-000000000000', 'Admin', ?, ?, true, true, now(), now())
on conflict (id)
do update set email = ?, password = ?")
(defmethod ig/pre-init-spec ::setup/initial-profile [_]
(s/keys :req [::db/pool]))
(defmethod ig/init-key ::setup/initial-profile
[_ {:keys [::db/pool]}]
(let [email (cf/get :setup-admin-email)
password (cf/get :setup-admin-password)]
(when (and email password)
(db/with-atomic [conn pool]
(let [pwd (auth/derive-password password)]
(db/exec-one! conn [sql:insert-profile email pwd email pwd])
(l/info :hint "setting initial user (admin)"
:email email
:password "********"))))
nil))

View file

@ -11,9 +11,10 @@
[app.common.spec :as us] [app.common.spec :as us]
[buddy.core.kdf :as bk])) [buddy.core.kdf :as bk]))
(defn derive (defn derive
"Derive a key from secret-key" "Derive a key from secret-key"
[secret-key & {:keys [salt size]}] [secret-key & {:keys [salt size] :or {size 32}}]
(us/assert! ::us/not-empty-string secret-key) (us/assert! ::us/not-empty-string secret-key)
(let [engine (bk/engine {:key secret-key (let [engine (bk/engine {:key secret-key
:salt salt :salt salt

View file

@ -27,23 +27,13 @@
^double f] ^double f]
Object Object
(toString [_] (toString [_]
#?(:clj
(dm/fmt "matrix(%, %, %, %, %, %)" (dm/fmt "matrix(%, %, %, %, %, %)"
(mth/precision a precision) (mth/to-fixed a precision)
(mth/precision b precision) (mth/to-fixed b precision)
(mth/precision c precision) (mth/to-fixed c precision)
(mth/precision d precision) (mth/to-fixed d precision)
(mth/precision e precision) (mth/to-fixed e precision)
(mth/precision f precision)) (mth/to-fixed f precision))))
:cljs
(dm/fmt "matrix(%, %, %, %, %, %)"
(.toFixed a precision)
(.toFixed b precision)
(.toFixed c precision)
(.toFixed d precision)
(.toFixed e precision)
(.toFixed f precision)))))
(defn matrix? (defn matrix?
"Return true if `v` is Matrix instance." "Return true if `v` is Matrix instance."

View file

@ -175,14 +175,15 @@
#?(:clj #?(:clj
(defn get-error-context (defn get-error-context
[error] [error]
(merge
{:hint (ex-message error)}
(when-let [data (ex-data error)] (when-let [data (ex-data error)]
(merge (merge
{:hint (ex-message error) {:spec-problems (some->> data ::s/problems (take 10) seq vec)
:spec-problems (some->> data ::s/problems (take 10) seq vec)
:spec-value (some->> data ::s/value) :spec-value (some->> data ::s/value)
:data (some-> data (dissoc ::s/problems ::s/value ::s/spec))} :data (some-> data (dissoc ::s/problems ::s/value ::s/spec))}
(when-let [explain (ex/explain data)] (when-let [explain (ex/explain data)]
{:spec-explain explain}))))) {:spec-explain explain}))))))
(defmacro log (defmacro log
[& props] [& props]

View file

@ -127,6 +127,12 @@
(let [d (pow 10 n)] (let [d (pow 10 n)]
(/ (round (* v d)) d)))) (/ (round (* v d)) d))))
(defn to-fixed
"Returns a string representing the given number, using fixed precision."
[v n]
#?(:cljs (.toFixed ^js v n)
:clj (str (precision v n))))
(defn radians (defn radians
"Converts degrees to radians." "Converts degrees to radians."
[degrees] [degrees]

View file

@ -137,15 +137,6 @@ services:
environment: environment:
- PENPOT_FLAGS=enable-registration enable-login disable-email-verification enable-smtp - PENPOT_FLAGS=enable-registration enable-login disable-email-verification enable-smtp
## Setup initial administration user, uncommit only if you are
## going to use the penpot-admin; Once uncommented, the special
## user will be created on application start. This user can only
## be used for access admin, you will not be able to login with
## it on penpot application.
# - PENPOT_SETUP_ADMIN_EMAIL=admin@example.com
# - PENPOT_SETUP_ADMIN_PASSWORD=password
## Public URI. If you are going to expose this instance to the ## Public URI. If you are going to expose this instance to the
## internet, or use it under different domain than 'localhost' ## internet, or use it under different domain than 'localhost'
## consider using traefik and set the ## consider using traefik and set the
@ -240,32 +231,6 @@ services:
networks: networks:
- penpot - penpot
## An optional admin application for pentpot. It allows manage
## users, teams and inspect some parts of the database. You can read
## more about it on: https://github.com/penpot/penpot-admin
##
## Status: EXPERIMENTAL
# penpot-admin:
# image: "penpotapp/admin:alpha"
# networks:
# - penpot
#
# depends_on:
# - penpot-postgres
# - penpot-backend
#
# environment:
# - PENPOT_PUBLIC_URI=http://localhost:9001
# - PENPOT_API_URI=http://penpot-frontend/
#
# - PENPOT_DATABASE_HOST=penpot-postgres
# - PENPOT_DATABASE_NAME=penpot
# - PENPOT_DATABASE_USERNAME=penpot
# - PENPOT_DATABASE_PASSWORD=penpot
# - PENPOT_REDIS_URI=redis://penpot-redis/0
# - PENPOT_DEBUG="false"
## A mailcatch service, used as temporal SMTP server. You can access ## A mailcatch service, used as temporal SMTP server. You can access
## via HTTP to the port 1080 for read all emails the penpot platform ## via HTTP to the port 1080 for read all emails the penpot platform
## has sent. Should be only used as a temporal solution meanwhile ## has sent. Should be only used as a temporal solution meanwhile

View file

@ -693,8 +693,8 @@
.section-list-item { .section-list-item {
padding: $size-4 0; padding: $size-4 0;
border-bottom: 1px solid $color-gray-20; border-bottom: 1px solid $color-gray-20;
position: relative;
display: flex; display: flex;
align-items: center;
justify-content: space-between; justify-content: space-between;
.item-name { .item-name {
@ -711,7 +711,6 @@
.item-button { .item-button {
cursor: pointer; cursor: pointer;
position: absolute;
top: $size-4; top: $size-4;
right: 0; right: 0;
border: 1px solid $color-primary; border: 1px solid $color-primary;
@ -720,6 +719,7 @@
background: $color-primary; background: $color-primary;
color: $color-black; color: $color-black;
padding: $size-2; padding: $size-2;
margin-bottom: 0;
&:hover { &:hover {
color: $color-primary; color: $color-primary;
@ -770,6 +770,11 @@
margin: 0; margin: 0;
padding: 0; padding: 0;
flex-grow: 1; flex-grow: 1;
&:hover,
&:focus {
outline: none;
}
} }
& .search-icon { & .search-icon {

View file

@ -85,7 +85,7 @@
} }
& .viewer-go-next.right-bar { & .viewer-go-next.right-bar {
right: 256px; right: 264px;
} }
& .viewer-go-prev { & .viewer-go-prev {

View file

@ -476,9 +476,14 @@
component-id component-id
position position
page page
libraries)] libraries)
(rx/of (dch/commit-changes changes) undo-id (js/Symbol)]
(dws/select-shapes (d/ordered-set (:id new-shape)))))))) (rx/of (dwu/start-undo-transaction undo-id)
(dch/commit-changes changes)
(ptk/data-event :layout/update [(:id new-shape)])
(dws/select-shapes (d/ordered-set (:id new-shape)))
(dwu/commit-undo-transaction undo-id))))))
(defn detach-component (defn detach-component
"Remove all references to components in the shape with the given id, "Remove all references to components in the shape with the given id,

View file

@ -280,10 +280,11 @@
(let [{:keys [backend family variants]} (get @fontsdb font-id)] (let [{:keys [backend family variants]} (get @fontsdb font-id)]
(cond (cond
(= :google backend) (= :google backend)
(let [variant (d/seek #(= (:id %) font-variant-id) variants)]
(-> (generate-gfonts-url (-> (generate-gfonts-url
{:family family {:family family
:variants [{:id font-variant-id}]}) :variants [{:id variant}]})
(http/fetch-text)) (http/fetch-text)))
(= :custom backend) (= :custom backend)
(let [variant (d/seek #(= (:id %) font-variant-id) variants) (let [variant (d/seek #(= (:id %) font-variant-id) variants)

View file

@ -626,7 +626,6 @@
(def valid-webhook-mtypes (def valid-webhook-mtypes
[{:label "application/json" :value "application/json"} [{:label "application/json" :value "application/json"}
{:label "application/x-www-form-urlencoded" :value "application/x-www-form-urlencoded"}
{:label "application/transit+json" :value "application/transit+json"}]) {:label "application/transit+json" :value "application/transit+json"}])
(defn- extract-status (defn- extract-status