changeset changes

This commit is contained in:
byte[] 2019-11-15 10:15:21 -05:00
parent 187051d56c
commit 32d3098da4
7 changed files with 96 additions and 27 deletions

View file

@ -20,6 +20,7 @@ config :philomena, :pow,
user: Philomena.Users.User, user: Philomena.Users.User,
repo: Philomena.Repo, repo: Philomena.Repo,
web_module: PhilomenaWeb, web_module: PhilomenaWeb,
users_context: Philomena.Users,
extensions: [PowResetPassword, PowLockout, PowPersistentSession], extensions: [PowResetPassword, PowLockout, PowPersistentSession],
controller_callbacks: Pow.Extension.Phoenix.ControllerCallbacks, controller_callbacks: Pow.Extension.Phoenix.ControllerCallbacks,
mailer_backend: PhilomenaWeb.PowMailer mailer_backend: PhilomenaWeb.PowMailer

15
lib/philomena/slug.ex Normal file
View file

@ -0,0 +1,15 @@
defmodule Philomena.Slug do
def slug(string) when is_binary(string) do
string
|> String.replace("-", "-dash-")
|> String.replace("/", "-fwslash-")
|> String.replace("\\", "-bwslash-")
|> String.replace(":", "-colon-")
|> String.replace(".", "-dot-")
|> String.replace("+", "-plus-")
|> URI.encode()
|> String.replace("%20", "+")
end
def slug(_string), do: ""
end

View file

@ -77,22 +77,6 @@ defmodule Philomena.Users do
|> Repo.update() |> Repo.update()
end end
@doc """
Deletes a User.
## Examples
iex> delete_user(user)
{:ok, %User{}}
iex> delete_user(user)
{:error, %Ecto.Changeset{}}
"""
def delete_user(%User{} = user) do
Repo.delete(user)
end
@doc """ @doc """
Returns an `%Ecto.Changeset{}` for tracking user changes. Returns an `%Ecto.Changeset{}` for tracking user changes.
@ -105,4 +89,16 @@ defmodule Philomena.Users do
def change_user(%User{} = user) do def change_user(%User{} = user) do
User.changeset(user, %{}) User.changeset(user, %{})
end end
@impl Pow.Ecto.Context
def delete(user) do
{:error, User.changeset(user, %{})}
end
@impl Pow.Ecto.Context
def create(params) do
%User{}
|> User.creation_changeset(params)
|> Repo.insert()
end
end end

View file

@ -1,5 +1,6 @@
defmodule Philomena.Users.User do defmodule Philomena.Users.User do
alias Philomena.Users.Password alias Philomena.Users.Password
alias Philomena.Slug
use Ecto.Schema use Ecto.Schema
@ -117,6 +118,20 @@ defmodule Philomena.Users.User do
|> validate_required([]) |> validate_required([])
end end
def creation_changeset(user, attrs) do
user
|> pow_changeset(attrs)
|> pow_extension_changeset(attrs)
|> cast(attrs, [:name])
|> validate_required([:name])
|> put_api_key()
|> put_slug()
|> unique_constraint(:name, name: :index_users_on_name)
|> unique_constraint(:slug, name: :index_users_on_slug)
|> unique_constraint(:email, name: :index_users_on_email)
|> unique_constraint(:authentication_token, name: :index_users_on_authentication_token)
end
def filter_changeset(user, filter) do def filter_changeset(user, filter) do
change(user) change(user)
|> put_change(:current_filter_id, filter.id) |> put_change(:current_filter_id, filter.id)
@ -157,21 +172,20 @@ defmodule Philomena.Users.User do
def totp_changeset(changeset, params, backup_codes) do def totp_changeset(changeset, params, backup_codes) do
changeset = change(changeset, %{}) changeset = change(changeset, %{})
user = changeset.data user = changeset.data
token = extract_token(params)
case user.otp_required_for_login do case user.otp_required_for_login do
true -> true ->
# User wants to disable TOTP # User wants to disable TOTP
changeset changeset
|> pow_password_changeset(params) |> pow_password_changeset(params)
|> consume_totp_token_changeset(token) |> consume_totp_token_changeset(params)
|> disable_totp_changeset() |> disable_totp_changeset()
_falsy -> _falsy ->
# User wants to enable TOTP # User wants to enable TOTP
changeset changeset
|> pow_password_changeset(params) |> pow_password_changeset(params)
|> consume_totp_token_changeset(token) |> consume_totp_token_changeset(params)
|> enable_totp_changeset(backup_codes) |> enable_totp_changeset(backup_codes)
end end
end end
@ -227,7 +241,10 @@ defmodule Philomena.Users.User do
user user
|> change(%{ |> change(%{
otp_required_for_login: false, otp_required_for_login: false,
otp_backup_codes: [] otp_backup_codes: [],
encrypted_otp_secret: nil,
encrypted_otp_secret_iv: nil,
encrypted_otp_secret_salt: nil
}) })
end end
@ -237,6 +254,19 @@ defmodule Philomena.Users.User do
defp extract_token(_params), defp extract_token(_params),
do: "" do: ""
defp put_api_key(changeset) do
key = :crypto.strong_rand_bytes(15) |> Base.url_encode64()
change(changeset, authentication_token: key)
end
defp put_slug(changeset) do
name = get_field(changeset, :name)
changeset
|> put_change(:slug, Slug.slug(name))
end
defp totp_valid?(user, token), defp totp_valid?(user, token),
do: :pot.valid_totp(token, totp_secret(user), window: 1) do: :pot.valid_totp(token, totp_secret(user), window: 1)

View file

@ -30,15 +30,10 @@ defmodule PhilomenaWeb.Router do
scope "/" do scope "/" do
pipe_through [:browser, :ensure_totp] pipe_through [:browser, :ensure_totp]
pow_session_routes() pow_routes()
pow_extension_routes() pow_extension_routes()
end end
scope "/", Pow.Phoenix, as: "pow" do
pipe_through [:browser, :protected, :ensure_totp]
resources "/registration", RegistrationController, singleton: true, only: [:edit, :update]
end
scope "/", PhilomenaWeb do scope "/", PhilomenaWeb do
pipe_through [:browser, :protected] pipe_through [:browser, :protected]

View file

@ -6,6 +6,38 @@ h1 Two Factor Authentication
p Oops, something went wrong! Please check the errors below. p Oops, something went wrong! Please check the errors below.
= if @current_user.otp_required_for_login do = if @current_user.otp_required_for_login do
= if !@changeset.action and get_flash(@conn, :totp_backup_codes) do
.dnp-warning
h4 Important - Save The Below Codes
p
' The backup codes shown in the green box below are necessary to
' regain access to your account in the event of you losing access
' to your authenticator app (such as loss, theft, or damage to your
' phone). It is extremely important that you write them down and
' store them in a safe, secure place. If you lose access to you
' authenticator app and do not have one or more of the above codes,
' we will be unable to help you regain access to your account.
br
.block.block--fixed.block--success.layout--narrow
h2 Two Factor Authentication Enabled
p
' You've sucessfully enabled two-factor authentication on your
' account. From now on you'll be asked for the 6 digit code each
' time you log in.
p
' In case you lose your device or uninstall the application, you
' will need one of the following backup codes to access to your
' account:
ul
= for code <- get_flash(@conn, :totp_backup_codes) do
li = code
br
p
' Make sure to write these down (preferably on paper) and store them
' in a safe location, otherwise you may
strong<> permanently lose access
' to your account.
p p
' Two factor authentication is currently ' Two factor authentication is currently
strong> enabled strong> enabled

View file

@ -67,7 +67,7 @@ defmodule PhilomenaWeb.AppView do
end end
end end
def button_to(text, route, args) do def button_to(text, route, args \\ []) do
method = Keyword.get(args, :method, "get") method = Keyword.get(args, :method, "get")
class = Keyword.get(args, :class, nil) class = Keyword.get(args, :class, nil)
data = Keyword.get(args, :data, []) data = Keyword.get(args, :data, [])