diff --git a/backend/src/app/config.clj b/backend/src/app/config.clj index 8f7f1c7ea..870ff58d5 100644 --- a/backend/src/app/config.clj +++ b/backend/src/app/config.clj @@ -106,9 +106,6 @@ (s/def ::file-change-snapshot-every ::us/integer) (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 ::scheduled-executor-parallelism ::us/integer) @@ -314,9 +311,6 @@ ::srepl-host ::srepl-port - ::setup-admin-email - ::setup-admin-password - ::assets-storage-backend ::storage-assets-fs-directory ::storage-assets-s3-bucket @@ -332,8 +326,7 @@ [:enable-backend-api-doc :enable-backend-worker :enable-secure-session-cookies - :enable-email-verification - :enable-quotes]) + :enable-email-verification]) (defn- parse-flags [config] diff --git a/backend/src/app/http.clj b/backend/src/app/http.clj index 976f42d6e..6cb6b398c 100644 --- a/backend/src/app/http.clj +++ b/backend/src/app/http.clj @@ -91,9 +91,7 @@ (let [params (:path-params match) result (:result match) handler (or (:handler result) not-found-handler) - request (-> request - (assoc :path-params params) - (update :params merge params))] + request (assoc request :path-params params)] (handler request respond raise)) (not-found-handler request respond raise))) diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj index 78250dce0..6b5141a84 100644 --- a/backend/src/app/main.clj +++ b/backend/src/app/main.clj @@ -408,9 +408,6 @@ {:port (cf/get :srepl-port) :host (cf/get :srepl-host)} - :app.setup/initial-profile - {::db/pool (ig/ref ::db/pool)} - :app.setup/builtin-templates {::http.client/client (ig/ref ::http.client/client)} diff --git a/backend/src/app/migrations.clj b/backend/src/app/migrations.clj index b50bf97c6..14c83afeb 100644 --- a/backend/src/app/migrations.clj +++ b/backend/src/app/migrations.clj @@ -299,9 +299,6 @@ {:name "0096-del-storage-pending-table" :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" :fn (mg/resource "app/migrations/sql/0098-add-quotes-table.sql")} diff --git a/backend/src/app/migrations/sql/0097-mod-profile-table.sql b/backend/src/app/migrations/sql/0097-mod-profile-table.sql deleted file mode 100644 index 9e3ab6212..000000000 --- a/backend/src/app/migrations/sql/0097-mod-profile-table.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE profile - ADD COLUMN is_admin boolean DEFAULT false; diff --git a/backend/src/app/rpc.clj b/backend/src/app/rpc.clj index 6681c13b1..cdda84a0b 100644 --- a/backend/src/app/rpc.clj +++ b/backend/src/app/rpc.clj @@ -71,8 +71,8 @@ (defn- rpc-query-handler "Ring handler that dispatches query requests and convert between internal async flow into ring async flow." - [methods {:keys [profile-id session-id params] :as request} respond raise] - (let [type (keyword (:type params)) + [methods {:keys [profile-id session-id path-params params] :as request} respond raise] + (let [type (keyword (:type path-params)) data (-> params (assoc ::request-at (dt/now)) (assoc ::http/request request)) @@ -94,8 +94,8 @@ (defn- rpc-mutation-handler "Ring handler that dispatches mutation requests and convert between internal async flow into ring async flow." - [methods {:keys [profile-id session-id params] :as request} respond raise] - (let [type (keyword (:type params)) + [methods {:keys [profile-id session-id path-params params] :as request} respond raise] + (let [type (keyword (:type path-params)) data (-> params (assoc ::request-at (dt/now)) (assoc ::http/request request)) @@ -116,8 +116,8 @@ (defn- rpc-command-handler "Ring handler that dispatches cmd requests and convert between internal async flow into ring async flow." - [methods {:keys [profile-id session-id params] :as request} respond raise] - (let [cmd (keyword (:type params)) + [methods {:keys [profile-id session-id path-params params] :as request} respond raise] + (let [cmd (keyword (:type path-params)) etag (yrq/get-header request "if-none-match") data (-> params @@ -290,7 +290,6 @@ (let [cfg (assoc cfg ::type "command" ::metrics-id :rpc-command-timing)] (->> (sv/scan-ns 'app.rpc.commands.binfile 'app.rpc.commands.comments - 'app.rpc.commands.profile 'app.rpc.commands.management 'app.rpc.commands.verify-token 'app.rpc.commands.search diff --git a/backend/src/app/rpc/commands/auth.clj b/backend/src/app/rpc/commands/auth.clj index 894e98179..dec65f571 100644 --- a/backend/src/app/rpc/commands/auth.clj +++ b/backend/src/app/rpc/commands/auth.clj @@ -69,7 +69,7 @@ ;; ---- COMMAND: 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) (contains? cf/flags :login-with-password)) @@ -119,17 +119,8 @@ ;; accept invitation with other email response (if (and (some? invitation) (= (:id profile) (:member-id invitation))) {:invitation-token (:invitation-token params)} - (update profile :is-admin (fn [admin?] - (or admin? - (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")) - + (assoc profile :is-admin (let [admins (cf/get :admins)] + (contains? admins (:email profile)))))] (-> response (rph/with-transform (session/create-fn session (:id profile))) (rph/with-meta {::audit/props (audit/profile->props profile) diff --git a/backend/src/app/rpc/commands/profile.clj b/backend/src/app/rpc/commands/profile.clj deleted file mode 100644 index 141664b8c..000000000 --- a/backend/src/app/rpc/commands/profile.clj +++ /dev/null @@ -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"))))) diff --git a/backend/src/app/rpc/commands/webhooks.clj b/backend/src/app/rpc/commands/webhooks.clj index 2786b80e6..b08b3443b 100644 --- a/backend/src/app/rpc/commands/webhooks.clj +++ b/backend/src/app/rpc/commands/webhooks.clj @@ -29,7 +29,6 @@ (s/def ::is-active ::us/boolean) (s/def ::mtype #{"application/json" - "application/x-www-form-urlencoded" "application/transit+json"}) (s/def ::create-webhook diff --git a/backend/src/app/setup.clj b/backend/src/app/setup.clj index 8ecc2696f..f8af36050 100644 --- a/backend/src/app/setup.clj +++ b/backend/src/app/setup.clj @@ -13,7 +13,6 @@ [app.db :as db] [app.main :as-alias main] [app.setup.builtin-templates] - [app.setup.initial-user] [app.setup.keys :as keys] [buddy.core.codecs :as bc] [buddy.core.nonce :as bn] @@ -69,5 +68,5 @@ (let [secret (or key (generate-random-key))] (-> (retrieve-all conn) (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)))))) diff --git a/backend/src/app/setup/initial_user.clj b/backend/src/app/setup/initial_user.clj deleted file mode 100644 index 35d254b38..000000000 --- a/backend/src/app/setup/initial_user.clj +++ /dev/null @@ -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)) - - diff --git a/backend/src/app/setup/keys.clj b/backend/src/app/setup/keys.clj index bba5ae697..3ee5153e7 100644 --- a/backend/src/app/setup/keys.clj +++ b/backend/src/app/setup/keys.clj @@ -11,9 +11,10 @@ [app.common.spec :as us] [buddy.core.kdf :as bk])) + (defn derive "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) (let [engine (bk/engine {:key secret-key :salt salt diff --git a/common/src/app/common/geom/matrix.cljc b/common/src/app/common/geom/matrix.cljc index 8ee0cc2ac..01ee53c9d 100644 --- a/common/src/app/common/geom/matrix.cljc +++ b/common/src/app/common/geom/matrix.cljc @@ -27,23 +27,13 @@ ^double f] Object (toString [_] - #?(:clj - (dm/fmt "matrix(%, %, %, %, %, %)" - (mth/precision a precision) - (mth/precision b precision) - (mth/precision c precision) - (mth/precision d precision) - (mth/precision e precision) - (mth/precision f precision)) - - :cljs - (dm/fmt "matrix(%, %, %, %, %, %)" - (.toFixed a precision) - (.toFixed b precision) - (.toFixed c precision) - (.toFixed d precision) - (.toFixed e precision) - (.toFixed f precision))))) + (dm/fmt "matrix(%, %, %, %, %, %)" + (mth/to-fixed a precision) + (mth/to-fixed b precision) + (mth/to-fixed c precision) + (mth/to-fixed d precision) + (mth/to-fixed e precision) + (mth/to-fixed f precision)))) (defn matrix? "Return true if `v` is Matrix instance." diff --git a/common/src/app/common/logging.cljc b/common/src/app/common/logging.cljc index 0796daa4b..de8501d38 100644 --- a/common/src/app/common/logging.cljc +++ b/common/src/app/common/logging.cljc @@ -175,14 +175,15 @@ #?(:clj (defn get-error-context [error] - (when-let [data (ex-data error)] - (merge - {:hint (ex-message error) - :spec-problems (some->> data ::s/problems (take 10) seq vec) - :spec-value (some->> data ::s/value) - :data (some-> data (dissoc ::s/problems ::s/value ::s/spec))} - (when-let [explain (ex/explain data)] - {:spec-explain explain}))))) + (merge + {:hint (ex-message error)} + (when-let [data (ex-data error)] + (merge + {:spec-problems (some->> data ::s/problems (take 10) seq vec) + :spec-value (some->> data ::s/value) + :data (some-> data (dissoc ::s/problems ::s/value ::s/spec))} + (when-let [explain (ex/explain data)] + {:spec-explain explain})))))) (defmacro log [& props] diff --git a/common/src/app/common/math.cljc b/common/src/app/common/math.cljc index 03525d4d3..5ed4f01f9 100644 --- a/common/src/app/common/math.cljc +++ b/common/src/app/common/math.cljc @@ -127,6 +127,12 @@ (let [d (pow 10 n)] (/ (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 "Converts degrees to radians." [degrees] diff --git a/docker/images/docker-compose.yaml b/docker/images/docker-compose.yaml index b8ae99216..15882f60c 100644 --- a/docker/images/docker-compose.yaml +++ b/docker/images/docker-compose.yaml @@ -137,15 +137,6 @@ services: environment: - 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 ## internet, or use it under different domain than 'localhost' ## consider using traefik and set the @@ -240,32 +231,6 @@ services: networks: - 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 ## via HTTP to the port 1080 for read all emails the penpot platform ## has sent. Should be only used as a temporal solution meanwhile diff --git a/frontend/resources/styles/main/partials/modal.scss b/frontend/resources/styles/main/partials/modal.scss index 37dc692e7..026deb7cf 100644 --- a/frontend/resources/styles/main/partials/modal.scss +++ b/frontend/resources/styles/main/partials/modal.scss @@ -693,8 +693,8 @@ .section-list-item { padding: $size-4 0; border-bottom: 1px solid $color-gray-20; - position: relative; display: flex; + align-items: center; justify-content: space-between; .item-name { @@ -711,7 +711,6 @@ .item-button { cursor: pointer; - position: absolute; top: $size-4; right: 0; border: 1px solid $color-primary; @@ -720,6 +719,7 @@ background: $color-primary; color: $color-black; padding: $size-2; + margin-bottom: 0; &:hover { color: $color-primary; @@ -770,6 +770,11 @@ margin: 0; padding: 0; flex-grow: 1; + + &:hover, + &:focus { + outline: none; + } } & .search-icon { diff --git a/frontend/resources/styles/main/partials/viewer.scss b/frontend/resources/styles/main/partials/viewer.scss index 97d6c77d0..6875d65b3 100644 --- a/frontend/resources/styles/main/partials/viewer.scss +++ b/frontend/resources/styles/main/partials/viewer.scss @@ -85,7 +85,7 @@ } & .viewer-go-next.right-bar { - right: 256px; + right: 264px; } & .viewer-go-prev { diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index a4ce6a4a5..9c75d03ae 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -476,9 +476,14 @@ component-id position page - libraries)] - (rx/of (dch/commit-changes changes) - (dws/select-shapes (d/ordered-set (:id new-shape)))))))) + libraries) + undo-id (js/Symbol)] + (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 "Remove all references to components in the shape with the given id, diff --git a/frontend/src/app/main/fonts.cljs b/frontend/src/app/main/fonts.cljs index bee11fe9f..e3f7d198c 100644 --- a/frontend/src/app/main/fonts.cljs +++ b/frontend/src/app/main/fonts.cljs @@ -280,10 +280,11 @@ (let [{:keys [backend family variants]} (get @fontsdb font-id)] (cond (= :google backend) - (-> (generate-gfonts-url - {:family family - :variants [{:id font-variant-id}]}) - (http/fetch-text)) + (let [variant (d/seek #(= (:id %) font-variant-id) variants)] + (-> (generate-gfonts-url + {:family family + :variants [{:id variant}]}) + (http/fetch-text))) (= :custom backend) (let [variant (d/seek #(= (:id %) font-variant-id) variants) diff --git a/frontend/src/app/main/ui/dashboard/team.cljs b/frontend/src/app/main/ui/dashboard/team.cljs index e8dc7e20e..1675b59cc 100644 --- a/frontend/src/app/main/ui/dashboard/team.cljs +++ b/frontend/src/app/main/ui/dashboard/team.cljs @@ -626,7 +626,6 @@ (def valid-webhook-mtypes [{: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"}]) (defn- extract-status