Packages
blossom
0.21.4
0.29.3
0.29.2
0.29.1
0.29.0
0.28.0
0.27.3
0.27.2
0.27.1
0.27.0
0.26.3
0.26.2
0.26.1
0.26.0
0.25.3
0.25.2
0.25.1
0.25.0
0.24.1
0.24.0
0.23.5
0.23.4
0.23.3
0.23.2
0.23.1
0.23.0
0.22.1
0.22.0
0.21.8
0.21.7
0.21.6
0.21.5
0.21.4
0.21.3
0.21.2
0.21.1
0.21.0
0.20.4
0.20.3
0.20.2
0.20.1
0.20.0
0.19.5
0.19.4
0.19.3
0.19.2
0.19.1
0.19.0
0.18.1
0.18.0
0.17.4
0.17.3
0.17.2
0.17.1
0.17.0
0.16.0
0.15.2
0.15.1
0.15.0
0.14.0
0.13.0
0.12.2
0.12.1
0.12.0
0.11.0
0.10.1
0.10.0
0.9.2
0.9.1
0.9.0
0.8.0
0.7.0
0.6.2
0.6.1
0.6.0
0.5.1
0.5.0
0.4.0
0.3.0
0.2.0
0.1.0
Easy identity for easy authentication
Current section
Files
Jump to
Current section
Files
lib/blossom/controllers/otp_codes.ex
defmodule Blossom.Controllers.OtpCodes do
alias Blossom.Controllers.OtpCodes
alias Blossom.Utils
def random_code(opts) do
symbols = Enum.to_list(Enum.concat(?A..?Z, ?0..?9))
count = Enum.count(symbols)
for _ <- 1..opts[:codes_length],
into: "",
do: <<Enum.at(symbols, :crypto.strong_rand_range(count))>>
end
def put_expiration(params, opts) do
kind = String.to_atom(Map.get(params, "kind", ""))
expiration = Keyword.get(opts[:expiration], kind, 3600)
Map.put(params, "expiration", System.os_time(:second) + expiration)
end
def codes_length(config, opts) do
Utils.option_or_key_config(config, opts, :codes_length, 6)
end
def expiration(config, opts) do
defaults = [email_verification: 43200]
Utils.option_or_key_config(config, opts, :codes_expiration, defaults)
end
def codes_opts(opts, otp_app) do
config = Application.get_env(otp_app, Blossom, [])
[
codes_length: OtpCodes.codes_length(config, opts),
expiration: OtpCodes.expiration(config, opts)
]
end
def new(params, user, opts, ctx) do
params
|> Map.put("code", OtpCodes.random_code(opts))
|> OtpCodes.put_expiration(opts)
|> ctx[:model].new(user)
end
def check_expiration(outcome) do
case outcome do
[code] ->
if code.expiration >= System.os_time(:second) do
{:ok, code}
else
{:error, :expired_code}
end
[] ->
{:error, :invalid_code}
end
end
def clean_code(outcome, code, model) do
case outcome do
{:ok, otp_code} ->
model.delete(otp_code.code, :system)
{:ok, otp_code}
{:error, _} = error ->
model.delete(code, :system)
error
end
end
def verify(params, ctx) do
case params do
%{"code" => code} ->
params
|> ctx[:model].get(:system)
|> OtpCodes.check_expiration()
|> OtpCodes.clean_code(code, ctx[:model])
_ ->
{:error, :missing_fields}
end
end
defmacro __using__(opts \\ []) do
quote do
use KilnCore.Controller, unquote(opts)
@opts unquote(opts)
@otp_app KilnCore.Utils.atom_name(@caller)
@ctx [model: @model]
def new(params, user, _opts) do
codes_opts = OtpCodes.codes_opts(@opts, @otp_app)
OtpCodes.new(params, user, codes_opts, @ctx)
end
def verify(params, _user) do
OtpCodes.verify(params, @ctx)
end
end
end
end