Improve profile props handling and audit log integration.

This commit is contained in:
Andrey Antukh 2021-05-20 10:46:45 +02:00
parent 344622b1c1
commit 6c1e13b6e5
3 changed files with 38 additions and 35 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

@ -108,7 +108,8 @@
(::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 props}))) :props props})))
result)))) result))))

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]
@ -307,37 +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/props (:props profile) ::audit/name (if (::created profile) "register" "login")
::audit/props props
::audit/profile-id (:id profile)})))) ::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)}