(ns metabase.login-history.record (:require [metabase.analytics.snowplow :as snowplow] [metabase.channel.email.messages :as messages] [metabase.login-history.models.login-history :as login-history] [metabase.login-history.settings :as login-history.settings] [metabase.request.core :as request] [metabase.util :as u] [metabase.util.log :as log] [metabase.util.malli :as mu] [toucan2.connection :as t2.conn])) | |
If set to send emails on first login from new devices, that is the case, and its not the users first login, send an email from a separate thread. | (defn- maybe-send-login-from-new-device-email
[history-record]
(when (and (login-history.settings/send-email-on-first-login-from-new-device)
(login-history/first-login-on-this-device? history-record)
(not (login-history/first-login-ever? history-record)))
;; if there's an existing open connection (and there seems to be one, but I'm not 100% sure why) we can't try to use
;; it across threads since it can close at any moment! So unbind it so the future can get its own thread.
(binding [t2.conn/*current-connectable* nil]
(future
;; off thread for both IP lookup and email sending. Either one could block and slow down user login (#16169)
(try
(let [[info] (login-history/human-friendly-infos [history-record])]
(messages/send-login-from-new-device-email! info))
(catch Throwable e
(log/error e "Error sending 'login from new device' notification email"))))))) |
Record login history for a user, and send them an email if this is their first time logging in from this device. | (mu/defn record-login-history!
[session-id :- uuid?
user :- [:map
{:description ":model/User"}
[:id pos-int?]
[:last_login {:optional true} :any]]
device-info :- request/DeviceInfo]
(let [history-entry (login-history/record-login-history! session-id (u/the-id user) device-info)]
(when-not (:embedded device-info)
(maybe-send-login-from-new-device-email history-entry))
(when-not (:last_login user)
(snowplow/track-event! :snowplow/account {:event :new-user-created} (u/the-id user))))) |