refactored for new project name

This commit is contained in:
Adam Piontek 2021-03-05 19:23:32 -05:00
commit 82ab1d1ea5
113 changed files with 417 additions and 412 deletions

View file

@ -0,0 +1,16 @@
defmodule Shift73kWeb.OtherController do
use Shift73kWeb, :controller
def index(conn, _params) do
conn
|> put_flash(:success, "Log in was a success. Good for you.")
|> put_flash(:error, "Lorem ipsum dolor sit amet consectetur adipisicing elit.")
|> put_flash(
:info,
"Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptatibus dolore sunt quia aperiam sint id reprehenderit? Dolore incidunt alias inventore accusantium nulla optio, ducimus eius aliquam hic, pariatur voluptate distinctio."
)
|> put_flash(:warning, "Oh no, there's nothing to worry about!")
|> put_flash(:primary, "Something in the brand color.")
|> render("index.html")
end
end

View file

@ -0,0 +1,171 @@
defmodule Shift73kWeb.UserAuth do
import Plug.Conn
import Phoenix.Controller
alias Shift73k.Accounts
alias Shift73kWeb.Router.Helpers, as: Routes
@pubsub_topic "user_updates"
# Make the remember me cookie valid for 60 days.
# If you want bump or reduce this value, also change
# the token expiry itself in UserToken.
@max_age 60 * 60 * 24 * 60
@remember_me_cookie "user_remember_me"
@remember_me_options [sign: true, max_age: @max_age, same_site: "Lax"]
@doc """
Logs the user in.
It renews the session ID and clears the whole session
to avoid fixation attacks. See the renew_session
function to customize this behaviour.
It also sets a `:live_socket_id` key in the session,
so LiveView sessions are identified and automatically
disconnected on log out. The line can be safely removed
if you are not using LiveView.
"""
def log_in_user(conn, user, params \\ %{}) do
token = Accounts.generate_user_session_token(user)
conn
|> renew_session()
|> put_session(:user_token, token)
|> put_session(:live_socket_id, "users_sessions:#{Base.url_encode64(token)}")
|> maybe_write_remember_me_cookie(token, params)
|> redirect(to: get_session(conn, :user_return_to) || signed_in_path(conn))
end
defp maybe_write_remember_me_cookie(conn, token, %{"remember_me" => "true"}) do
put_resp_cookie(conn, @remember_me_cookie, token, @remember_me_options)
end
defp maybe_write_remember_me_cookie(conn, _token, _params) do
conn
end
# This function renews the session ID and erases the whole
# session to avoid fixation attacks. If there is any data
# in the session you may want to preserve after log in/log out,
# you must explicitly fetch the session data before clearing
# and then immediately set it after clearing, for example:
#
# defp renew_session(conn) do
# preferred_locale = get_session(conn, :preferred_locale)
#
# conn
# |> configure_session(renew: true)
# |> clear_session()
# |> put_session(:preferred_locale, preferred_locale)
# end
#
defp renew_session(conn) do
conn
|> configure_session(renew: true)
|> clear_session()
end
@doc """
Logs the user out.
It clears all session data for safety. See renew_session.
"""
def log_out_user(conn) do
user_token = get_session(conn, :user_token)
user_token && Accounts.delete_session_token(user_token)
if live_socket_id = get_session(conn, :live_socket_id) do
Shift73kWeb.Endpoint.broadcast(live_socket_id, "disconnect", %{})
end
conn
|> renew_session()
|> delete_resp_cookie(@remember_me_cookie)
|> redirect(to: "/")
end
@doc """
Authenticates the user by looking into the session
and remember me token.
"""
def fetch_current_user(conn, _opts) do
{user_token, conn} = ensure_user_token(conn)
user = user_token && Accounts.get_user_by_session_token(user_token)
assign(conn, :current_user, user)
end
defp ensure_user_token(conn) do
if user_token = get_session(conn, :user_token) do
{user_token, conn}
else
conn = fetch_cookies(conn, signed: [@remember_me_cookie])
if user_token = conn.cookies[@remember_me_cookie] do
{user_token, put_session(conn, :user_token, user_token)}
else
{nil, conn}
end
end
end
@doc """
Used for routes that require the user to not be authenticated.
"""
def redirect_if_user_is_authenticated(conn, _opts) do
if conn.assigns[:current_user] do
conn
|> redirect(to: signed_in_path(conn))
|> halt()
else
conn
end
end
@doc """
Used for routes that require the user to be authenticated.
If you want to enforce the user email is confirmed before
they use the application at all, here would be a good place.
"""
def require_authenticated_user(conn, _opts) do
if conn.assigns[:current_user] do
conn
else
conn
|> put_flash(:error, "You must log in to access this page.")
|> maybe_store_return_to()
|> redirect(to: Routes.user_session_path(conn, :new))
|> halt()
end
end
@doc """
Used for routes that require the user's email to be confirmed.
"""
def require_email_confirmed(conn, _opts) do
if conn.assigns[:current_user] |> Map.get(:confirmed_at) do
conn
else
conn
|> put_flash(:error, "You must confirm your email to access this page.")
|> redirect(to: Routes.user_confirmation_path(conn, :new))
|> halt()
end
end
@doc """
Returns the pubsub topic name for receiving notifications when a user updated
"""
def pubsub_topic, do: @pubsub_topic
defp maybe_store_return_to(%{method: "GET"} = conn) do
%{request_path: request_path, query_string: query_string} = conn
return_to = if query_string == "", do: request_path, else: request_path <> "?" <> query_string
put_session(conn, :user_return_to, return_to)
end
defp maybe_store_return_to(conn), do: conn
defp signed_in_path(_conn), do: "/"
end

View file

@ -0,0 +1,43 @@
defmodule Shift73kWeb.UserConfirmationController do
use Shift73kWeb, :controller
alias Shift73k.Accounts
def new(conn, _params) do
render(conn, "new.html")
end
def create(conn, %{"user" => %{"email" => email}}) do
if user = Accounts.get_user_by_email(email) do
Accounts.deliver_user_confirmation_instructions(
user,
&Routes.user_confirmation_url(conn, :confirm, &1)
)
end
# Regardless of the outcome, show an impartial success/error message.
conn
|> put_flash(
:info,
"If your email is in our system and it has not been confirmed yet, " <>
"you will receive an email with instructions shortly."
)
|> redirect(to: "/")
end
# Do not log in the user after confirmation to avoid a
# leaked token giving the user access to the account.
def confirm(conn, %{"token" => token}) do
case Accounts.confirm_user(token) do
{:ok, _} ->
conn
|> put_flash(:info, "Account confirmed successfully.")
|> redirect(to: "/")
:error ->
conn
|> put_flash(:error, "Confirmation link is invalid or it has expired.")
|> redirect(to: "/")
end
end
end

View file

@ -0,0 +1,8 @@
defmodule Shift73kWeb.UserRegistrationController do
use Shift73kWeb, :controller
import Phoenix.LiveView.Controller
def new(conn, _params) do
live_render(conn, Shift73kWeb.UserLive.Registration)
end
end

View file

@ -0,0 +1,46 @@
defmodule Shift73kWeb.UserResetPasswordController do
use Shift73kWeb, :controller
import Phoenix.LiveView.Controller
alias Shift73k.Accounts
plug(:get_user_by_reset_password_token when action in [:edit])
def new(conn, _params) do
render(conn, "new.html")
end
def create(conn, %{"user" => %{"email" => email}}) do
if user = Accounts.get_user_by_email(email) do
Accounts.deliver_user_reset_password_instructions(
user,
&Routes.user_reset_password_url(conn, :edit, &1)
)
end
# Regardless of the outcome, show an impartial success/error message.
conn
|> put_flash(
:info,
"If your email is in our system, you'll receive instructions to reset your password shortly."
)
|> redirect(to: "/")
end
def edit(conn, _params) do
live_render(conn, Shift73kWeb.UserLive.ResetPassword)
end
defp get_user_by_reset_password_token(conn, _opts) do
%{"token" => token} = conn.params
if user = Accounts.get_user_by_reset_password_token(token) do
put_session(conn, "user_id", user.id)
else
conn
|> put_flash(:error, "Reset password link is invalid or it has expired.")
|> redirect(to: "/")
|> halt()
end
end
end

View file

@ -0,0 +1,56 @@
defmodule Shift73kWeb.UserSessionController do
use Shift73kWeb, :controller
alias Phoenix.HTML
alias Shift73k.Accounts
alias Shift73k.Accounts.User
alias Shift73kWeb.UserAuth
def new(conn, _params) do
render(conn, "new.html", error_message: nil)
end
def create(conn, %{"user" => %{"email" => email, "password" => password} = user_params}) do
if user = Accounts.get_user_by_email_and_password(email, password) do
conn
|> put_flash(
:info,
HTML.raw("Welcome back, #{user.email} &mdash; you were logged in successfuly.")
)
|> UserAuth.log_in_user(user, user_params)
else
render(conn, "new.html", error_message: "Invalid email or password")
end
end
def create(conn, %{"user" => %{"params_token" => token} = user_params}) do
with {:ok, params} <- Phoenix.Token.decrypt(Shift73kWeb.Endpoint, "login_params", token),
%User{} = user <- Accounts.get_user(params.user_id) do
conn
|> collect_messages(params.messages)
|> put_session(:user_return_to, params.user_return_to)
|> UserAuth.log_in_user(user, Map.put_new(user_params, "remember_me", "false"))
else
_ -> render(conn, "new.html", error_message: "Invalid email or password")
end
end
defp collect_messages(conn, messages) do
Enum.reduce(messages, conn, fn {type, msg}, acc -> put_flash(acc, type, msg) end)
end
def delete(conn, _params) do
conn
|> put_flash(:info, "Logged out successfully.")
|> UserAuth.log_out_user()
end
def force_logout(conn, _params) do
conn
|> put_flash(
:info,
"You were logged out. Please login again to continue using our application."
)
|> UserAuth.log_out_user()
end
end

View file

@ -0,0 +1,19 @@
defmodule Shift73kWeb.UserSettingsController do
use Shift73kWeb, :controller
alias Shift73k.Accounts
def confirm_email(conn, %{"token" => token}) do
case Accounts.update_user_email(conn.assigns.current_user, token) do
:ok ->
conn
|> put_flash(:info, "Email changed successfully.")
|> redirect(to: Routes.user_settings_path(conn, :edit))
:error ->
conn
|> put_flash(:error, "Email change link is invalid or it has expired.")
|> redirect(to: Routes.user_settings_path(conn, :edit))
end
end
end