-
Notifications
You must be signed in to change notification settings - Fork 222
/
config.ex
326 lines (286 loc) · 10.2 KB
/
config.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
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.
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:
* :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)
* :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_hashing_alg (Comeonin.Bcrypt) - Password hashing algorithm to use.
* :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)
* :router: the module name of your Router (`router: MyProject.Router`)
* :schema_key
* :session_key ("session_auth")
* :session_permitted_attributes - List of allowed session attributes as strings
* :site_name - The site name used for email
* :title - Layout page title
* :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
* :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.
* :user_active_field - Include the user active feature
* :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
alias Coherence.Config
Config.module
"""
defmacro __using__(_) do
quote do
alias unquote(__MODULE__)
end
end
require Logger
[
{: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_from_name,
:email_reply_to_email,
:email_reply_to_name,
{:forwarded_invitation_fields, [:email, :name]},
:invitation_permitted_attributes,
:layout,
:log_emails,
:logged_in_url,
:logged_out_url,
{:login_cookie, "coherence_login"},
{:login_field, :email},
{:max_failed_login_attempts, 5},
:messages_backend,
{:minimum_password_length, 4},
:module,
{:opts, []},
{:password_hash_field, :password_hash},
{:password_hashing_alg, Comeonin.Bcrypt},
:password_reset_permitted_attributes,
:registration_permitted_attributes,
{:rememberable_cookie_expire_hours, 48},
:repo,
{:require_current_password, true},
{:reset_token_expire_days, 2},
: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},
{:update_login, :update_login},
:use_binary_id,
:user_active_field,
:user_schema,
:user_token,
{:verify_user_token, &Coherence.SessionService.verify_user_token/2},
:web_module
]
|> Enum.each(fn
{key, default} ->
def unquote(key)(opts \\ unquote(default)) do
get_application_env(unquote(key), opts)
end
key ->
def unquote(key)(opts \\ nil) do
get_application_env(unquote(key), opts)
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
nil ->
{get_application_env(:email_from_name), get_application_env(:email_from_email)}
email ->
Logger.info(
"email_from config is deprecated. Use email_from_name and email_from_email instead"
)
email
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
nil ->
case {get_application_env(:email_reply_to_name),
get_application_env(:email_reply_to_email)} do
{nil, nil} -> nil
email -> email
end
true ->
true
email ->
Logger.info(
"email_reply_to {name, email} config is deprecated. Use email_reply_to_name and email_reply_to_email instead"
)
email
end
end
@doc """
Get title
"""
@spec title() :: String.t() | nil
def title, do: get_application_env(:title, get(:module))
@doc """
Get a configuration item.
"""
@spec get(atom, any) :: any
def get(key, default \\ nil) do
get_application_env(key, default)
end
@doc """
Test if an options is configured.
"""
@spec has_option(atom) :: boolean
def has_option(option) do
has_any_option?(fn {name, _actions} -> name == option end)
end
@doc """
Test if an option is configured and accepts a specific action
"""
@spec has_action?(atom, atom) :: boolean
def has_action?(option, action) do
has_any_option?(fn {name, actions} ->
name == option and (actions == :all or action in actions)
end)
end
@doc """
Test if Phoenix is configured to use binary ids by default
"""
@spec use_binary_id?() :: boolean
def use_binary_id? do
!!Application.get_env(:phoenix, :generators, [])[:binary_id] ||
Application.get_env(:coherence, :use_binary_id)
end
defp has_any_option?(fun) do
if opts() == :all do
true
else
Enum.any?(opts(), &fun.(standardize_option(&1)))
end
end
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)
end
defp get_application_env(key, default \\ nil) do
case Application.get_env(:coherence, key, default) do
{:system, env_var} -> System.get_env(env_var)
value -> value
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 ->
%{
registrations_new: "/registrations/new",
registrations: "/registrations",
passwords: "/passwords",
confirmations: "/confirmations",
unlocks: "/unlocks",
invitations: "/invitations",
invitations_create: "/invitations/create",
invitations_resend: "/invitations/:id/resend",
sessions: "/sessions",
registrations_edit: "/registrations/edit"
}
%{} = config ->
config
true ->
Logger.info("The configuration for default_routes must be a map")
nil
end
end
end