Skip to content

Commit

Permalink
add email logging
Browse files Browse the repository at this point in the history
  • Loading branch information
smpallen99 committed Oct 13, 2018
1 parent c71df24 commit 8e9cd03
Show file tree
Hide file tree
Showing 3 changed files with 235 additions and 103 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -9,6 +9,8 @@ See these [0.5.x to 0.6.x upgrade instructions](https://gist.github.com/smpallen
* Add configurable salt and max_age for tokens
* Add default opts for token functions
* Add support for application configurable confirmable
* Support code formatter formatter
* Add logging to the mailer template

* Bug Fixes
* Fixed detection of remember me checkbox on session new page
Expand Down
222 changes: 134 additions & 88 deletions lib/coherence/config.ex
Expand Up @@ -2,66 +2,71 @@ defmodule Coherence.Config do
@moduledoc """
Coherence Configuration Module.
Provides a small wrapper around `Application.get_env :coherence`, providing an accessor function for each configuration items.
Provides a small wrapper around `Application.get_env :coherence`, providing an
accessor function for each configuration items.
Configuration items can be defined as either a single atom or {name, default} tuple. Each of the items can be included in your `config/config.exs` file.
Configuration items can be defined as either a single atom or {name, default}
tuple. Each of the items can be included in your `config/config.exs` file.
The following items are supported:
* :module - the name of project module (`module: MyProject`)
* :web_module - the name of the project's web module (`web_module: MyProjectWeb`)
* :repo: the module name of your Repo (`repo: MyProject.Repo`)
* :user_schema
* :schema_key
* :logged_out_url
* :logged_in_url
* :email_from - Deprecated. Use `email_from_name` and `email_from_email` instead
* :email_from_name
* :email_from_email
* :email_reply_to - Set to true to add email_from_name and email_from_email
* :email_reply_to_name
* :email_reply_to_email
* :site_name - The site name used for email
* :login_cookie ("coherence_login") - The name of the login cookie
* :allow_silent_password_recovery_for_unknown_user (false)
* :allow_unconfirmed_access_for (0) - default 0 days
* :assigns_key (:current_user)
* :async_rememberable? (false) - Don't update rememberable seq_no for ajax requests
* :auth_module (Coherence.Authentication.Session)
* :changeset - Custom user changeset
* :confirm_email_updates (false) - All email updates should be confirmed by email (using the unconfirmed_email field)
* :confirmation_token_expire_days (5)
* :create_login (:create_login)
* :update_login (:update_login)
* :credential_store - override the credential store module
* :delete_login (:delete_login)
* :email_from - Deprecated. Use `email_from_name` and `email_from_email` instead
* :email_from_email
* :email_from_name
* :email_reply_to - Set to true to add email_from_name and email_from_email
* :email_reply_to_email
* :email_reply_to_name
* :invitation_permitted_attributes - List of allowed invitation parameter attribues as strings
* :layout - Customize the layout template e.g. {MyApp.LayoutView, "app.html"}
* :log_emails - Set to true to log each rendered email.
* :logged_in_url
* :logged_out_url
* :login_cookie ("coherence_login") - The name of the login cookie
* :login_field (:email) - The user model field used to login
* :max_failed_login_attempts (5)
* :messages_backend - (MyApp.Coherence.Messages)
* :minimum_password_length The minimum password length to be accepted. Default value is 4.
* :module - the name of project module (`module: MyProject`)
* :opts ([])
* :password_hash_field (:password_hash) - The field used to save the hashed password
* :password_reset_permitted_attributes - List of allowed password reset atributes as stings,
* :registration_permitted_attributes - List of allowed registration parameter attributes as strings
* :repo: the module name of your Repo (`repo: MyProject.Repo`)
* :rememberable_cookie_expire_hours (2*24)
* :reset_token_expire_days (2)
* :confirmation_token_expire_days (5)
* :allow_unconfirmed_access_for (0) - default 0 days
* :max_failed_login_attempts (5)
* :unlock_timeout_minutes (20)
* :unlock_token_expire_minutes (5)
* :router: the module name of your Router (`router: MyProject.Router`)
* :schema_key
* :session_key ("session_auth")
* :rememberable_cookie_expire_hours (2*24)
* :password_hash_field (:password_hash) - The field used to save the hashed password
* :login_field (:email) - The user model field used to login
* :changeset - Custom user changeset
* :session_permitted_attributes - List of allowed session attributes as strings
* :site_name - The site name used for email
* :title - Layout page title
* :layout - Customize the layout template e.g. {MyApp.LayoutView, "app.html"}
* :async_rememberable? (false) - Don't update rememberable seq_no for ajax requests
* :user_token (false) - generate tokens for channel authentication
* :token_salt ("user socket") - Phoenix.Token salt
* :token_max_age (2 * 7 * 24 * 60 * 60) - Phoenix.Token max_age
* :token_assigns_key (:user_token) - key used to access the channel_token in the conn.assigns map
* :token_generator (fn conn, user -> Phoenix.Token.sign(conn, "user socket", user.id) end) - override the default
* may also provide an arity 3 function as a tuple {Module, :function, args}
* where apply(Module, function, args) will be used
* :verify_user_token (fn socket, token -> Phoenix.Token.verify(socket, "user socket", token, max_age: 2 * 7 * 24 * 60 * 60) end
* can also be a 3 element tuple as described above for :token_generator
may also provide an arity 3 function as a tuple {Module, :function, args}
where apply(Module, function, args) will be used
* :token_max_age (2 * 7 * 24 * 60 * 60) - Phoenix.Token max_age
* :token_salt ("user socket") - Phoenix.Token salt
* :update_login (:update_login)
* :unlock_timeout_minutes (20)
* :unlock_token_expire_minutes (5)
* :use_binary_id (false) - Use binary ids.
* :minimum_password_length The minimum password length to be accepted. Default value is 4.
* :messages_backend - (MyApp.Coherence.Messages)
* :router: the module name of your Router (`router: MyProject.Router`)
* :user_active_field - Include the user active feature
* :registration_permitted_attributes - List of allowed registration parameter attributes as strings
* :invitation_permitted_attributes - List of allowed invitation parameter attribues as strings
* :password_reset_permitted_attributes - List of allowed password reset atributes as stings,
* :session_permitted_attributes - List of allowed session attributes as strings
* :credential_store - override the credential store module
* :confirm_email_updates - All email updates should be confirmed by email (using the unconfirmed_email field)
* :user_token (false) - generate tokens for channel authentication
* :user_schema
* :verify_user_token (fn socket, token -> Phoenix.Token.verify(socket, "user socket", token, max_age: 2 * 7 * 24 * 60 * 60) end
can also be a 3 element tuple as described above for :token_generator
* :web_module - the name of the project's web module (`web_module: MyProjectWeb`)
## Examples
Expand All @@ -79,60 +84,60 @@ defmodule Coherence.Config do

require Logger

# opts: :all || [:trackable, :lockable, :rememberable, :confirmable]
[
:module,
:web_module,
:repo,
:user_schema,
:schema_key,
:logged_out_url,
:logged_in_url,
:email_from_name,
{:allow_silent_password_recovery_for_unknown_user, false},
{:allow_unconfirmed_access_for, 0},
{:assigns_key, :current_user},
{:async_rememberable?, false},
{:auth_module, Coherence.Authentication.Session},
:changeset,
{:confirm_email_updates, false},
{:confirmation_token_expire_days, 5},
{:create_login, :create_login},
:credential_store,
{:delete_login, :delete_login},
:email_from_email,
:email_reply_to_name,
:email_from_name,
:email_reply_to_email,
:site_name,
:changeset,
:email_reply_to_name,
{:forwarded_invitation_fields, [:email, :name]},
:invitation_permitted_attributes,
:layout,
:user_token,
:use_binary_id,
{:token_salt, "user socket"},
{:token_max_age, 2 * 7 * 24 * 60 * 60},
{:token_assigns_key, :user_token},
{:token_generator, &Coherence.SessionService.sign_user_token/2},
{:verify_user_token, &Coherence.SessionService.verify_user_token/2},
{:password_hash_field, :password_hash},
{:login_field, :email},
:log_emails,
:logged_in_url,
:logged_out_url,
{:login_cookie, "coherence_login"},
{:auth_module, Coherence.Authentication.Session},
{:create_login, :create_login},
{:update_login, :update_login},
{:delete_login, :delete_login},
{:login_field, :email},
{:max_failed_login_attempts, 5},
:messages_backend,
{:minimum_password_length, 4},
:module,
{:opts, []},
{:assigns_key, :current_user},
{:password_hash_field, :password_hash},
:password_reset_permitted_attributes,
:registration_permitted_attributes,
{:rememberable_cookie_expire_hours, 48},
:repo,
{:require_current_password, true},
{:reset_token_expire_days, 2},
{:confirmation_token_expire_days, 5},
{:allow_unconfirmed_access_for, 0},
{:max_failed_login_attempts, 5},
:router,
:schema_key,
{:session_key, "session_auth"},
:session_permitted_attributes,
:site_name,
{:token_assigns_key, :user_token},
{:token_generator, &Coherence.SessionService.sign_user_token/2},
{:token_max_age, 1_209_600},
{:token_salt, "user socket"},
{:unlock_timeout_minutes, 20},
{:unlock_token_expire_minutes, 5},
{:session_key, "session_auth"},
{:rememberable_cookie_expire_hours, 2 * 24},
{:forwarded_invitation_fields, [:email, :name]},
{:allow_silent_password_recovery_for_unknown_user, false},
{:async_rememberable?, false},
{:minimum_password_length, 4},
:messages_backend,
:router,
{:update_login, :update_login},
:use_binary_id,
:user_active_field,
:registration_permitted_attributes,
:invitation_permitted_attributes,
:password_reset_permitted_attributes,
:session_permitted_attributes,
:credential_store,
{:confirm_email_updates, false}
:user_schema,
:user_token,
{:verify_user_token, &Coherence.SessionService.verify_user_token/2},
:web_module
]
|> Enum.each(fn
{key, default} ->
Expand All @@ -146,6 +151,9 @@ defmodule Coherence.Config do
end
end)

@doc """
Get the email_from configuration
"""
@spec email_from() :: {nil, nil} | {String.t(), String.t()} | String.t()
def email_from do
case get_application_env(:email_from) do
Expand All @@ -161,6 +169,15 @@ defmodule Coherence.Config do
end
end

@doc """
Get the email_reply_to value.
Fetches `:email_reply_to` from coherence configuration
* if nil, returns {config[:email_reply_to_name], config[:email_reply_to_email]}
* if true, returns true
* if email, returns email with a deprecation logged
"""
@spec email_reply_to() :: nil | true | {String.t(), String.t()} | String.t()
def email_reply_to do
case get_application_env(:email_reply_to) do
Expand Down Expand Up @@ -235,6 +252,11 @@ defmodule Coherence.Config do
defp standardize_option(option) when is_atom(option), do: {option, :all}
defp standardize_option(option), do: option

@doc """
Macro to fetch the password_hash field.
Use a macro here to optimize performance.
"""
defmacro password_hash do
field = Application.get_env(:coherence, :password_hash_field, :password_hash)
quote do: unquote(field)
Expand All @@ -247,10 +269,34 @@ defmodule Coherence.Config do
end
end

@doc """
Get the configured mailer adapter
"""
def mailer? do
!!Application.get_env(:coherence, Module.concat(web_module(), Coherence.Mailer))
end

@doc """
Get the configured routes.
If config[:default_routes] is nil, return the default routes, otherwise, return
the the configured map.
## Examples
iex Application.put_env(:coherence, :default_routes, %{
passwords: "/passwords",
sessions: "/sessions",
})
:ok
iex Coherence.Config.default_routes()
%{
passwords: "/passwords",
sessions: "/sessions",
})
"""
def default_routes do
case Application.get_env(:coherence, :default_routes) do
nil ->
Expand Down

0 comments on commit 8e9cd03

Please sign in to comment.