0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-13 18:48:37 -05:00

Merge branch 'niwinz-auditlog-fixes' into develop

This commit is contained in:
Andrey Antukh 2021-05-20 10:51:06 +02:00
commit f57fb5006d
8 changed files with 154 additions and 90 deletions

View file

@ -6,7 +6,6 @@
(ns app.http.oauth (ns app.http.oauth
(:require (:require
[app.common.data :as d]
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.uri :as u] [app.common.uri :as u]
@ -99,10 +98,11 @@
res (http/send! req)] res (http/send! req)]
(when (= 200 (:status res)) (when (= 200 (:status res))
(let [{:keys [name] :as data} (json/read-str (:body res) :key-fn keyword)] (let [info (json/read-str (:body res) :key-fn keyword)]
(-> data {:backend (:name provider)
(assoc :backend (:name provider)) :email (:email info)
(assoc :fullname name))))) :fullname (:name info)
:props (dissoc info :name :email)})))
(catch Exception e (catch Exception e
(l/error :hint "unexpected exception on retrieve-user-info" (l/error :hint "unexpected exception on retrieve-user-info"
@ -118,7 +118,8 @@
(retrieve-user-info cfg))] (retrieve-user-info cfg))]
(when-not info (when-not info
(ex/raise :type :internal (ex/raise :type :internal
:code :unable-to-auth)) :code :unable-to-auth
:hint "no user info"))
;; If the provider is OIDC, we can proceed to check ;; If the provider is OIDC, we can proceed to check
;; roles if they are defined. ;; roles if they are defined.
@ -141,8 +142,10 @@
(some? (:invitation-token state)) (some? (:invitation-token state))
(assoc :invitation-token (:invitation-token state)) (assoc :invitation-token (:invitation-token state))
;; If state token comes with props, merge them. The state token
;; props can contain pm_ and utm_ prefixed query params.
(map? (:props state)) (map? (:props state))
(d/merge (:props state))))) (update :props merge (:props state)))))
;; --- HTTP HANDLERS ;; --- HTTP HANDLERS
@ -152,7 +155,8 @@
(let [sk (name k)] (let [sk (name k)]
(cond-> params (cond-> params
(or (str/starts-with? sk "pm_") (or (str/starts-with? sk "pm_")
(str/starts-with? sk "pm-")) (str/starts-with? sk "pm-")
(str/starts-with? sk "utm_"))
(assoc (-> sk str/kebab keyword) v)))) (assoc (-> sk str/kebab keyword) v))))
{} {}
params)) params))
@ -254,9 +258,7 @@
[cfg] [cfg]
(let [opts {:client-id (cf/get :google-client-id) (let [opts {:client-id (cf/get :google-client-id)
:client-secret (cf/get :google-client-secret) :client-secret (cf/get :google-client-secret)
:scopes #{"email" "profile" "openid" :scopes #{"openid" "email" "profile"}
"https://www.googleapis.com/auth/userinfo.email"
"https://www.googleapis.com/auth/userinfo.profile"}
:auth-uri "https://accounts.google.com/o/oauth2/v2/auth" :auth-uri "https://accounts.google.com/o/oauth2/v2/auth"
:token-uri "https://oauth2.googleapis.com/token" :token-uri "https://oauth2.googleapis.com/token"
:user-uri "https://openidconnect.googleapis.com/v1/userinfo" :user-uri "https://openidconnect.googleapis.com/v1/userinfo"
@ -272,8 +274,7 @@
[cfg] [cfg]
(let [opts {:client-id (cf/get :github-client-id) (let [opts {:client-id (cf/get :github-client-id)
:client-secret (cf/get :github-client-secret) :client-secret (cf/get :github-client-secret)
:scopes #{"read:user" :scopes #{"read:user" "user:email"}
"user:email"}
:auth-uri "https://github.com/login/oauth/authorize" :auth-uri "https://github.com/login/oauth/authorize"
:token-uri "https://github.com/login/oauth/access_token" :token-uri "https://github.com/login/oauth/access_token"
:user-uri "https://api.github.com/user" :user-uri "https://api.github.com/user"

View file

@ -24,19 +24,33 @@
[lambdaisland.uri :as u])) [lambdaisland.uri :as u]))
(defn clean-props (defn clean-props
"Cleans the params from complex data, only accept strings, numbers and [{:keys [profile-id] :as event}]
uuids and removing sensitive data such as :password and related (letfn [(clean-common [props]
props." (-> props
[params] (dissoc :session-id)
(let [params (dissoc params :session-id :password :old-password :token)] (dissoc :password)
(reduce-kv (fn [params k v] (dissoc :old-password)
(cond-> params (dissoc :token)))
(or (string? v)
(uuid? v) (clean-profile-id [props]
(number? v)) (cond-> props
(assoc k v))) (= profile-id (:profile-id props))
{} (dissoc :profile-id)))
params)))
(clean-complex-data [props]
(reduce-kv (fn [props k v]
(cond-> props
(or (string? v)
(uuid? v)
(boolean? v)
(number? v))
(assoc k v)
(keyword? v)
(assoc k (name v))))
{}
props))]
(update event :props #(-> % clean-common clean-profile-id clean-complex-data))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Collector ;; Collector
@ -52,11 +66,16 @@
(defmethod ig/pre-init-spec ::collector [_] (defmethod ig/pre-init-spec ::collector [_]
(s/keys :req-un [::db/pool ::wrk/executor ::enabled])) (s/keys :req-un [::db/pool ::wrk/executor ::enabled]))
(def event-xform
(comp
(filter :profile-id)
(map clean-props)))
(defmethod ig/init-key ::collector (defmethod ig/init-key ::collector
[_ {:keys [enabled] :as cfg}] [_ {:keys [enabled] :as cfg}]
(when enabled (when enabled
(l/info :msg "intializing audit collector") (l/info :msg "intializing audit collector")
(let [input (a/chan) (let [input (a/chan 1 event-xform)
buffer (aa/batch input {:max-batch-size 100 buffer (aa/batch input {:max-batch-size 100
:max-batch-age (* 5 1000) :max-batch-age (* 5 1000)
:init []})] :init []})]
@ -65,14 +84,17 @@
(l/debug :action "persist-events (batch)" (l/debug :action "persist-events (batch)"
:reason (name type) :reason (name type)
:count (count events)) :count (count events))
(a/<! (persist-events cfg events)) (let [res (a/<! (persist-events cfg events))]
(when (ex/exception? res)
(l/error :hint "error on persiting events"
:cause res)))
(recur))) (recur)))
(fn [& [cmd & params]] (fn [& [cmd & params]]
(case cmd (case cmd
:stop (a/close! input) :stop (a/close! input)
:submit (when-not (a/offer! input (first params)) :submit (when-not (a/offer! input (first params))
(l/warn :msg "activity channel is full"))))))) (l/warn :msg "activity channel is full")))))))
(defn- persist-events (defn- persist-events
@ -113,7 +135,6 @@
(ex/raise :type :internal (ex/raise :type :internal
:code :task-not-configured :code :task-not-configured
:hint "archive task not configured, missing uri")) :hint "archive task not configured, missing uri"))
(l/debug :msg "start archiver" :uri uri)
(loop [] (loop []
(let [res (archive-events cfg)] (let [res (archive-events cfg)]
(when (= res :continue) (when (= res :continue)
@ -204,7 +225,6 @@
(defn- clean-archived (defn- clean-archived
[{:keys [pool max-age]}] [{:keys [pool max-age]}]
(prn "clean-archived" max-age)
(let [interval (db/interval max-age) (let [interval (db/interval max-age)
result (db/exec-one! pool [sql:clean-archived interval]) result (db/exec-one! pool [sql:clean-archived interval])
result (:next.jdbc/update-count result)] result (:next.jdbc/update-count result)]

View file

@ -99,7 +99,6 @@
(ex/raise :type :authentication (ex/raise :type :authentication
:code :authentication-required :code :authentication-required
:hint "authentication required for this endpoint")) :hint "authentication required for this endpoint"))
(let [params (us/conform spec params) (let [params (us/conform spec params)
result (f cfg params) result (f cfg params)
resultm (meta result)] resultm (meta result)]
@ -109,9 +108,10 @@
(::audit/profile-id resultm)) (::audit/profile-id resultm))
props (d/merge params (::audit/props resultm))] props (d/merge params (::audit/props resultm))]
(audit :submit {:type (::type cfg) (audit :submit {:type (::type cfg)
:name (::sv/name mdata) :name (or (::audit/name resultm)
(::sv/name mdata))
:profile-id profile-id :profile-id profile-id
:props (audit/clean-props props)}))) :props props})))
result)))) result))))
(defn- process-method (defn- process-method

View file

@ -11,6 +11,7 @@
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
[app.config :as cfg] [app.config :as cfg]
[app.db :as db] [app.db :as db]
[app.loggers.audit :as audit]
[app.rpc.mutations.profile :as profile] [app.rpc.mutations.profile :as profile]
[app.setup.initial-data :as sid] [app.setup.initial-data :as sid]
[app.util.services :as sv] [app.util.services :as sv]
@ -53,5 +54,6 @@
::wrk/conn conn ::wrk/conn conn
:profile-id id}) :profile-id id})
{:email email (with-meta {:email email
:password password}))) :password password}
{::audit/profile-id id}))))

View file

@ -6,7 +6,6 @@
(ns app.rpc.mutations.profile (ns app.rpc.mutations.profile
(:require (:require
[app.common.data :as d]
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.uuid :as uuid] [app.common.uuid :as uuid]
@ -277,10 +276,12 @@
:member-email (:email profile)) :member-email (:email profile))
token (tokens :generate claims)] token (tokens :generate claims)]
(with-meta {:invitation-token token} (with-meta {:invitation-token token}
{:transform-response ((:create session) (:id profile))})) {:transform-response ((:create session) (:id profile))
::audit/profile-id (:id profile)}))
(with-meta profile (with-meta profile
{:transform-response ((:create session) (:id profile))})))))) {:transform-response ((:create session) (:id profile))
::audit/profile-id (:id profile)}))))))
;; --- Mutation: Logout ;; --- Mutation: Logout
@ -305,35 +306,39 @@
[{:keys [pool metrics] :as cfg} params] [{:keys [pool metrics] :as cfg} params]
(db/with-atomic [conn pool] (db/with-atomic [conn pool]
(let [profile (-> (assoc cfg :conn conn) (let [profile (-> (assoc cfg :conn conn)
(login-or-register params))] (login-or-register params))
props (merge
(select-keys profile [:backend :fullname :email])
(:props profile))]
(with-meta profile (with-meta profile
{:before-complete (annotate-profile-register metrics profile)})))) {:before-complete (annotate-profile-register metrics profile)
::audit/name (if (::created profile) "register" "login")
::audit/props props
::audit/profile-id (:id profile)}))))
(defn login-or-register (defn login-or-register
[{:keys [conn] :as cfg} {:keys [email backend] :as params}] [{:keys [conn] :as cfg} {:keys [email] :as params}]
(letfn [(info->props [info] (letfn [(info->lang [{:keys [locale] :as info}]
(dissoc info :name :fullname :email :backend))
(info->lang [{:keys [locale] :as info}]
(when (and (string? locale) (when (and (string? locale)
(not (str/blank? locale))) (not (str/blank? locale)))
locale)) locale))
(create-profile [conn {:keys [email] :as info}] (create-profile [conn {:keys [fullname backend email props] :as info}]
(db/insert! conn :profile (let [params {:id (uuid/next)
{:id (uuid/next) :fullname fullname
:fullname (:fullname info) :email (str/lower email)
:email (str/lower email) :lang (info->lang props)
:lang (info->lang info) :auth-backend backend
:auth-backend backend :is-active true
:is-active true :password "!"
:password "!" :props (db/tjson props)
:props (db/tjson (info->props info)) :is-demo false}]
:is-demo false})) (-> (db/insert! conn :profile params)
(update :props db/decode-transit-pgobject))))
(update-profile [conn info profile] (update-profile [conn info profile]
(let [props (d/merge (:props profile) (let [props (merge (:props profile)
(info->props info))] (:props info))]
(db/update! conn :profile (db/update! conn :profile
{:props (db/tjson props) {:props (db/tjson props)
:modified-at (dt/now)} :modified-at (dt/now)}
@ -614,7 +619,7 @@
;; Schedule a complete deletion of profile ;; Schedule a complete deletion of profile
(wrk/submit! {::wrk/task :delete-profile (wrk/submit! {::wrk/task :delete-profile
::wrk/dalay cfg/deletion-delay ::wrk/delay cfg/deletion-delay
::wrk/conn conn ::wrk/conn conn
:profile-id profile-id}) :profile-id profile-id})

View file

@ -379,9 +379,11 @@
on-success identity}} (meta params)] on-success identity}} (meta params)]
(->> (rp/mutation :delete-profile {}) (->> (rp/mutation :delete-profile {})
(rx/tap on-success) (rx/tap on-success)
(rx/delay-at-least 300)
(rx/catch (constantly (rx/of 1)))
(rx/map logged-out)
(rx/catch on-error)))))) (rx/catch on-error))))))
;; --- EVENT: request-profile-recovery ;; --- EVENT: request-profile-recovery
(s/def ::request-profile-recovery (s/def ::request-profile-recovery

View file

@ -12,7 +12,7 @@
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.main.ui.messages :as msgs] [app.main.ui.messages :as msgs]
[app.util.i18n :as i18n :refer [tr t]] [app.util.i18n :as i18n :refer [tr]]
[app.util.router :as rt] [app.util.router :as rt]
[beicon.core :as rx] [beicon.core :as rx]
[cljs.spec.alpha :as s] [cljs.spec.alpha :as s]
@ -25,42 +25,36 @@
(rx/of (dm/error msg))) (rx/of (dm/error msg)))
(rx/throw error))) (rx/throw error)))
(defn on-success
[x]
(st/emit! (rt/nav :auth-login)))
(mf/defc delete-account-modal (mf/defc delete-account-modal
{::mf/register modal/components {::mf/register modal/components
::mf/register-as :delete-account} ::mf/register-as :delete-account}
[props] [props]
(let [locale (mf/deref i18n/locale) (let [on-close
on-close
(mf/use-callback (st/emitf (modal/hide))) (mf/use-callback (st/emitf (modal/hide)))
on-accept on-accept
(mf/use-callback (mf/use-callback
(st/emitf (modal/hide) (st/emitf (modal/hide)
(du/request-account-deletion (du/request-account-deletion
(with-meta {} {:on-error on-error (with-meta {} {:on-error on-error}))))]
:on-success on-success}))))]
[:div.modal-overlay [:div.modal-overlay
[:div.modal-container.change-email-modal [:div.modal-container.change-email-modal
[:div.modal-header [:div.modal-header
[:div.modal-header-title [:div.modal-header-title
[:h2 (t locale "modals.delete-account.title")]] [:h2 (tr "modals.delete-account.title")]]
[:div.modal-close-button [:div.modal-close-button
{:on-click on-close} i/close]] {:on-click on-close} i/close]]
[:div.modal-content [:div.modal-content
[:& msgs/inline-banner [:& msgs/inline-banner
{:type :warning {:type :warning
:content (t locale "modals.delete-account.info")}]] :content (tr "modals.delete-account.info")}]]
[:div.modal-footer [:div.modal-footer
[:div.action-buttons [:div.action-buttons
[:button.btn-warning.btn-large {:on-click on-accept} [:button.btn-warning.btn-large {:on-click on-accept}
(t locale "modals.delete-account.confirm")] (tr "modals.delete-account.confirm")]
[:button.btn-secondary.btn-large {:on-click on-close} [:button.btn-secondary.btn-large {:on-click on-close}
(t locale "modals.delete-account.cancel")]]]]])) (tr "modals.delete-account.cancel")]]]]]))

View file

@ -98,6 +98,54 @@ Copyright (c) UXBOX Labs SL
EOF EOF
} }
function build-frontend-bundle {
echo ">> bundle frontend start";
local version=$(print-current-version);
local bundle_dir="./bundle-frontend";
build "frontend";
rm -rf $bundle_dir;
mv ./frontend/target/dist $bundle_dir;
echo $version > $bundle_dir/version.txt;
put-license-file $bundle_dir;
echo ">> bundle frontend end";
}
function build-backend-bundle {
echo ">> bundle backend start";
local version=$(print-current-version);
local bundle_dir="./bundle-backend";
build "backend";
rm -rf $bundle_dir;
mv ./backend/target/dist $bundle_dir;
echo $version > $bundle_dir/version.txt;
put-license-file $bundle_dir;
echo ">> bundle frontend end";
}
function build-exporter-bundle {
echo ">> bundle exporter start";
local version=$(print-current-version);
local bundle_dir="./bundle-exporter";
build "exporter";
rm -rf $bundle_dir;
mv ./exporter/target $bundle_dir;
echo $version > $bundle_dir/version.txt
put-license-file $bundle_dir;
echo ">> bundle exporter end";
}
# DEPRECATED: temporary mantained for backward compatibilty.
function build-app-bundle { function build-app-bundle {
echo ">> bundle app start"; echo ">> bundle app start";
@ -117,22 +165,6 @@ function build-app-bundle {
echo ">> bundle app end"; echo ">> bundle app end";
} }
function build-exporter-bundle {
echo ">> bundle exporter start";
local version=$(print-current-version);
local bundle_dir="./bundle-exporter";
build "exporter";
rm -rf $bundle_dir;
mv ./exporter/target $bundle_dir;
echo $version > $bundle_dir/version.txt
put-license-file $bundle_dir;
echo ">> bundle exporter end";
}
function usage { function usage {
echo "PENPOT build & release manager" echo "PENPOT build & release manager"
echo "USAGE: $0 OPTION" echo "USAGE: $0 OPTION"
@ -182,6 +214,14 @@ case $1 in
build-app-bundle; build-app-bundle;
;; ;;
build-frontend-bundle)
build-frontend-bundle;
;;
build-backend-bundle)
build-backend-bundle;
;;
build-exporter-bundle) build-exporter-bundle)
build-exporter-bundle; build-exporter-bundle;
;; ;;