mirror of
https://github.com/philomena-dev/philomena.git
synced 2024-11-30 14:57:59 +01:00
changeset changes
This commit is contained in:
parent
187051d56c
commit
32d3098da4
7 changed files with 96 additions and 27 deletions
|
@ -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
15
lib/philomena/slug.ex
Normal 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
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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]
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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, [])
|
||||||
|
|
Loading…
Reference in a new issue