mirror of
https://github.com/penpot/penpot.git
synced 2026-08-19 11:19:10 +00:00
Merge remote-tracking branch 'origin/staging' into develop
This commit is contained in:
commit
296dd748bd
@ -166,8 +166,12 @@
|
||||
;; the same row/object.
|
||||
(let [profile (get-profile conn profile-id ::db/for-update true)
|
||||
fullname (d/normalize-string fullname)
|
||||
lang (d/normalize-string lang)
|
||||
theme (d/normalize-string theme)
|
||||
lang (if (contains? params :lang)
|
||||
(d/normalize-string lang)
|
||||
(:lang profile))
|
||||
theme (if (contains? params :theme)
|
||||
(d/normalize-string theme)
|
||||
(:theme profile))
|
||||
;; Update the profile map with direct params
|
||||
profile (-> profile
|
||||
(assoc :fullname fullname)
|
||||
|
||||
@ -46,6 +46,7 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.math :as mth]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uri :as uri]
|
||||
@ -180,8 +181,8 @@
|
||||
result (rds/eval rconn script)
|
||||
allowed? (boolean (nth result 0))
|
||||
remaining (nth result 1)
|
||||
reset (* (/ (inst-ms interval) rate)
|
||||
(- capacity remaining))]
|
||||
reset (long (mth/ceil (double (* (/ (inst-ms interval) rate)
|
||||
(- capacity remaining)))))]
|
||||
(l/trace :hint "limit processed"
|
||||
:method method
|
||||
:limit (name (::name limit))
|
||||
|
||||
@ -125,6 +125,17 @@
|
||||
(t/is (= "en" (:lang result)))
|
||||
(t/is (= "dark" (:theme result))))))
|
||||
|
||||
(t/testing "update profile preserves omitted optional fields"
|
||||
(let [data {::th/type :update-profile
|
||||
::rpc/profile-id (:id profile)
|
||||
:fullname "Updated Name"}
|
||||
out (th/command! data)]
|
||||
|
||||
(t/is (nil? (:error out)))
|
||||
(t/is (= "Updated Name" (get-in out [:result :fullname])))
|
||||
(t/is (= "en" (get-in out [:result :lang])))
|
||||
(t/is (= "dark" (get-in out [:result :theme])))))
|
||||
|
||||
(t/testing "update photo"
|
||||
(let [data {::th/type :update-profile-photo
|
||||
::rpc/profile-id (:id profile)
|
||||
|
||||
28
backend/test/backend_tests/rpc_rlimit_test.clj
Normal file
28
backend/test/backend_tests/rpc_rlimit_test.clj
Normal file
@ -0,0 +1,28 @@
|
||||
;; 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 Sucursal en Espana SL
|
||||
|
||||
(ns backend-tests.rpc-rlimit-test
|
||||
(:require
|
||||
[app.common.time :as ct]
|
||||
[app.redis :as rds]
|
||||
[app.rpc.rlimit :as rlimit]
|
||||
[clojure.test :as t]))
|
||||
|
||||
(t/deftest bucket-reset-supports-fractional-milliseconds
|
||||
(let [now (ct/inst 0)
|
||||
limit {::rlimit/name :test
|
||||
::rlimit/strategy :bucket
|
||||
::rlimit/key "test"
|
||||
::rlimit/method "main.test"
|
||||
::rlimit/capacity 5
|
||||
::rlimit/rate 3
|
||||
::rlimit/interval (ct/duration 1000)
|
||||
::rlimit/params [1 3 5]
|
||||
::rlimit/opts "5/3/1s"}]
|
||||
(with-redefs [rds/eval (fn [_ _] [true 4])]
|
||||
(let [result (rlimit/process-limit nil "profile" now limit)]
|
||||
(t/is (= (ct/inst 334)
|
||||
(:app.rpc.rlimit.result/reset result)))))))
|
||||
@ -161,6 +161,16 @@ http {
|
||||
location / {
|
||||
include /etc/nginx/overrides/location.d/*.conf;
|
||||
|
||||
# Regenerated from the environment on every container start
|
||||
# (see nginx-entrypoint.sh) while its URL is only versioned by
|
||||
# the build, so a flags only restart leaves the URL untouched.
|
||||
# Caching it like a build asset would keep returning users on
|
||||
# the previous PENPOT_FLAGS for up to a week.
|
||||
location = /js/config.js {
|
||||
include /etc/nginx/nginx-security-headers.conf;
|
||||
add_header Cache-Control "no-store, no-cache, max-age=0" always;
|
||||
}
|
||||
|
||||
location ~* \.(js|css|jpg|png|svg|gif|ttf|woff|woff2|wasm|map)$ {
|
||||
include /etc/nginx/nginx-security-headers.conf;
|
||||
add_header Cache-Control "public, max-age=604800" always; # 7 days
|
||||
|
||||
@ -122,6 +122,10 @@
|
||||
|
||||
;; --- Update Profile
|
||||
|
||||
(defn profile-update-params
|
||||
[profile]
|
||||
(d/without-nils (select-keys profile [:fullname :lang :theme])))
|
||||
|
||||
(defn persist-profile
|
||||
[& {:as opts}]
|
||||
(ptk/reify ::persist-profile
|
||||
@ -130,7 +134,7 @@
|
||||
(let [on-success (:on-success opts identity)
|
||||
on-error (:on-error opts rx/throw)
|
||||
profile (:profile state)
|
||||
params (select-keys profile [:fullname :lang :theme])]
|
||||
params (profile-update-params profile)]
|
||||
(->> (rp/cmd! :update-profile params)
|
||||
(rx/tap on-success)
|
||||
(rx/map set-profile)
|
||||
@ -143,7 +147,7 @@
|
||||
props"
|
||||
[profile]
|
||||
|
||||
(let [profile (check-profile profile)]
|
||||
(let [profile (check-profile (d/without-nils profile))]
|
||||
(ptk/reify ::update-profile
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
|
||||
@ -609,50 +609,56 @@
|
||||
|
||||
(defn check-and-submit-invite-members
|
||||
"Fetches fresh team data from the server to ensure up-to-date organization
|
||||
permissions, then submits member invitations or shows a restriction modal."
|
||||
permissions, then submits member invitations or shows a permission error."
|
||||
[{:keys [team-id] :as params} origin do-invite-members]
|
||||
(ptk/reify ::check-and-submit-invite-members
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(if (contains? cf/flags :admin-console)
|
||||
(with-refreshed-team team-id
|
||||
(fn [team]
|
||||
(if (not (cto/allowed? :add-anybody-to-team
|
||||
{:organization-perms (:organization team)}))
|
||||
(->> (rp/cmd! :check-organization-members {:organization-id (get-in team [:organization :id])
|
||||
:emails (vec (:emails params))})
|
||||
(rx/mapcat
|
||||
(fn [result]
|
||||
(let [blocked (into [] (comp (filter (fn [[_ v]] (not v)))
|
||||
(map first))
|
||||
result)]
|
||||
(cond
|
||||
(empty? blocked)
|
||||
(do (do-invite-members params origin) (rx/empty))
|
||||
(watch [_ state _]
|
||||
(let [profile-id (dm/get-in state [:profile :id])]
|
||||
(if (contains? cf/flags :admin-console)
|
||||
(with-refreshed-team team-id
|
||||
(fn [team]
|
||||
(if (not (cto/can-send-invitations?
|
||||
{:organization (:organization team)
|
||||
:profile-id profile-id
|
||||
:team-permissions (:permissions team)}))
|
||||
(rx/of (modal/show :no-permission-modal {:type :invite-members}))
|
||||
(if (not (cto/allowed? :add-anybody-to-team
|
||||
{:organization-perms (:organization team)}))
|
||||
(->> (rp/cmd! :check-organization-members {:organization-id (get-in team [:organization :id])
|
||||
:emails (vec (:emails params))})
|
||||
(rx/mapcat
|
||||
(fn [result]
|
||||
(let [blocked (into [] (comp (filter (fn [[_ v]] (not v)))
|
||||
(map first))
|
||||
result)]
|
||||
(cond
|
||||
(empty? blocked)
|
||||
(do (do-invite-members params origin) (rx/empty))
|
||||
|
||||
(= (count blocked) (count result))
|
||||
(rx/of
|
||||
(modal/show
|
||||
{:type :alert
|
||||
:title (tr "modals.invite-restricted-members.all-blocked-title")
|
||||
:message (tr "modals.invite-restricted-members.all-blocked")
|
||||
:accept-label (tr "labels.accept")
|
||||
:accept-style :primary}))
|
||||
(= (count blocked) (count result))
|
||||
(rx/of
|
||||
(modal/show
|
||||
{:type :alert
|
||||
:title (tr "modals.invite-restricted-members.all-blocked-title")
|
||||
:message (tr "modals.invite-restricted-members.all-blocked")
|
||||
:accept-label (tr "labels.accept")
|
||||
:accept-style :primary}))
|
||||
|
||||
:else
|
||||
(rx/of
|
||||
(modal/show
|
||||
{:type :invite-restricted-members
|
||||
:blocked-emails blocked
|
||||
:on-accept (fn []
|
||||
(let [valid-emails (into #{} (filter (fn [e] (get result e)))
|
||||
(:emails params))
|
||||
params' (assoc params :emails valid-emails)]
|
||||
(do-invite-members params' origin)))})))))))
|
||||
(do (do-invite-members params origin)
|
||||
(rx/empty)))))
|
||||
(do (do-invite-members params origin)
|
||||
(rx/empty))))))
|
||||
:else
|
||||
(rx/of
|
||||
(modal/show
|
||||
{:type :invite-restricted-members
|
||||
:blocked-emails blocked
|
||||
:on-accept (fn []
|
||||
(let [valid-emails (into #{} (filter (fn [e] (get result e)))
|
||||
(:emails params))
|
||||
params' (assoc params :emails valid-emails)]
|
||||
(do-invite-members params' origin)))})))))))
|
||||
(do (do-invite-members params origin)
|
||||
(rx/empty))))))
|
||||
(do (do-invite-members params origin)
|
||||
(rx/empty)))))))
|
||||
|
||||
(defn copy-invitation-link
|
||||
[{:keys [email team-id] :as params}]
|
||||
|
||||
@ -233,6 +233,9 @@
|
||||
(= :email-domain-is-not-allowed code))
|
||||
(st/emit! (ntf/error (tr "errors.email-domain-not-allowed"))
|
||||
(modal/hide))
|
||||
(and (= :validation type)
|
||||
(= :insufficient-permissions code))
|
||||
(st/emit! (modal/show :no-permission-modal {:type :invite-members}))
|
||||
|
||||
:else
|
||||
(st/emit! (ntf/error (tr "errors.generic"))
|
||||
|
||||
@ -152,6 +152,8 @@
|
||||
(tr "dashboard.no-permission-create-team.message" organization-name)]
|
||||
:delete-team [(tr "dashboard.delete-team")
|
||||
(tr "dashboard.no-permission-delete-team.message" organization-name)]
|
||||
:invite-members [(tr "modals.invite-team-member.title")
|
||||
(tr "dashboard.invitations.no-permission")]
|
||||
:no-organizations-create [(tr "dashboard.select-organization-modal.title")
|
||||
(tr "dashboard.no-organization-allows-create-team.message")]
|
||||
:no-organizations-change [(tr "dashboard.change-organization-modal.title")
|
||||
|
||||
30
frontend/test/frontend_tests/data/profile_test.cljs
Normal file
30
frontend/test/frontend_tests/data/profile_test.cljs
Normal file
@ -0,0 +1,30 @@
|
||||
;; 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 Sucursal en España SL
|
||||
|
||||
(ns frontend-tests.data.profile-test
|
||||
(:require
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.profile :as dprof]
|
||||
[cljs.test :as t :include-macros true]))
|
||||
|
||||
(t/deftest profile-update-params-omits-nil-values
|
||||
(t/is (= {:fullname "Updated Name"}
|
||||
(dprof/profile-update-params {:fullname "Updated Name"
|
||||
:lang nil
|
||||
:theme nil}))))
|
||||
|
||||
(t/deftest profile-update-params-preserves-present-values
|
||||
(t/is (= {:fullname "Updated Name"
|
||||
:lang "en"
|
||||
:theme "dark"}
|
||||
(dprof/profile-update-params {:fullname "Updated Name"
|
||||
:lang "en"
|
||||
:theme "dark"}))))
|
||||
|
||||
(t/deftest update-profile-accepts-nil-optional-values
|
||||
(t/is (some? (dprof/update-profile {:id uuid/zero
|
||||
:fullname "Updated Name"
|
||||
:theme nil}))))
|
||||
@ -11,6 +11,7 @@
|
||||
[frontend-tests.data.dashboard-test]
|
||||
[frontend-tests.data.exports-assets-test]
|
||||
[frontend-tests.data.nitrate-test]
|
||||
[frontend-tests.data.profile-test]
|
||||
[frontend-tests.data.repo-test]
|
||||
[frontend-tests.data.store-test]
|
||||
[frontend-tests.data.uploads-test]
|
||||
@ -107,6 +108,7 @@
|
||||
'frontend-tests.copy-as-svg-test
|
||||
'frontend-tests.data.dashboard-test
|
||||
'frontend-tests.data.nitrate-test
|
||||
'frontend-tests.data.profile-test
|
||||
'frontend-tests.data.repo-test
|
||||
'frontend-tests.data.store-test
|
||||
'frontend-tests.data.exports-assets-test
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user