Skip to content

Commit

Permalink
Merge branch 'develop' into mr/check-enrollments
Browse files Browse the repository at this point in the history
  • Loading branch information
MarioRodrigues10 authored Aug 12, 2023
2 parents 2ed6035 + 36eef5f commit 1a8e48f
Show file tree
Hide file tree
Showing 13 changed files with 80 additions and 55 deletions.
25 changes: 11 additions & 14 deletions lib/atomic/accounts/user_notifier.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ defmodule Atomic.Accounts.UserNotifier do

defp base_email(to: email) do
new()
|> from({"Atomic", "noreply@atomic.cesium.pt"})
|> to(email)
|> from({"Atomic", "noreply@atomic.cesium.pt"})
end

defp deliver(recipient, subject, body) do
Expand All @@ -29,20 +29,17 @@ defmodule Atomic.Accounts.UserNotifier do
Deliver instructions to confirm account.
"""
def deliver_confirmation_instructions(user, url) do
deliver(user.email, "Confirmation instructions", """
==============================
Hi #{user.email},
You can confirm your account by visiting the URL below:
#{url}
If you didn't create an account with us, please ignore this.
email =
base_email(to: user.email)
|> subject("Confirm your Account")
|> assign(:user, user)
|> assign(:url, url)
|> render_body("user_confirmation.txt")

==============================
""")
case Mailer.deliver(email) do
{:ok, _term} -> {:ok, email}
{:error, ch} -> {:error, ch}
end
end

@doc """
Expand Down
13 changes: 13 additions & 0 deletions lib/atomic_web/controllers/user_auth.ex
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,19 @@ defmodule AtomicWeb.UserAuth do
end
end

def require_confirmed_user(conn, _opts) do
current_user = conn.assigns[:current_user]

if conn.assigns[:current_user] && not is_nil(current_user.confirmed_at) do
conn
else
conn
|> put_flash(:error, "You must confirm your account in order to access this page.")
|> redirect(to: "/404")
|> halt()
end
end

defp maybe_store_return_to(%{method: "GET"} = conn) do
put_session(conn, :user_return_to, current_path(conn))
end
Expand Down
8 changes: 4 additions & 4 deletions lib/atomic_web/controllers/user_confirmation_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defmodule AtomicWeb.UserConfirmationController do
alias Atomic.Accounts

def new(conn, _params) do
render(conn, "new.html")
render(conn, "new.html", error_message: nil)
end

def create(conn, %{"user" => %{"email" => email}}) do
Expand All @@ -25,7 +25,7 @@ defmodule AtomicWeb.UserConfirmationController do
end

def edit(conn, %{"token" => token}) do
render(conn, "edit.html", token: token)
render(conn, "edit.html", token: token, error_message: nil)
end

# Do not log in the user after confirmation to avoid a
Expand All @@ -35,7 +35,7 @@ defmodule AtomicWeb.UserConfirmationController do
{:ok, _} ->
conn
|> put_flash(:info, "User confirmed successfully.")
|> redirect(to: "/")
|> redirect(to: "/users/log_in")

:error ->
# If there is a current user and the account was already confirmed,
Expand All @@ -49,7 +49,7 @@ defmodule AtomicWeb.UserConfirmationController do
%{} ->
conn
|> put_flash(:error, "User confirmation link is invalid or it has expired.")
|> redirect(to: "/")
|> redirect(to: "/users/log_in")
end
end
end
Expand Down
5 changes: 2 additions & 3 deletions lib/atomic_web/controllers/user_registration_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ defmodule AtomicWeb.UserRegistrationController do

alias Atomic.Accounts
alias Atomic.Accounts.User
alias AtomicWeb.UserAuth

def new(conn, _params) do
changeset = Accounts.change_user_registration(%User{})
Expand All @@ -25,8 +24,8 @@ defmodule AtomicWeb.UserRegistrationController do
)

conn
|> put_flash(:info, "User created successfully.")
|> UserAuth.log_in_user(user)
|> put_flash(:info, "Registered successfully. Check your email inbox before continuing")
|> render("new.html", changeset: Accounts.change_user_registration(user))

{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "new.html", changeset: changeset)
Expand Down
9 changes: 7 additions & 2 deletions lib/atomic_web/controllers/user_session_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ defmodule AtomicWeb.UserSessionController do

def create(conn, %{"user" => user_params}) do
%{"email" => email, "password" => password} = user_params
user = Accounts.get_user_by_email_and_password(email, password)

if user = Accounts.get_user_by_email_and_password(email, password) do
UserAuth.log_in_user(conn, user, user_params)
if user do
if is_nil(user.confirmed_at) do
render(conn, "new.html", error_message: "Confirm your email before continuing")
else
UserAuth.log_in_user(conn, user, user_params)
end
else
# In order to prevent user enumeration attacks, don't disclose whether the email is registered.
render(conn, "new.html", error_message: "Invalid email or password")
Expand Down
8 changes: 4 additions & 4 deletions lib/atomic_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ defmodule AtomicWeb.Router do
end

scope "/", AtomicWeb do
pipe_through [:browser, :require_authenticated_user]
pipe_through [:browser, :require_authenticated_user, :require_confirmed_user]

get "/users/settings", UserSettingsController, :edit
put "/users/settings", UserSettingsController, :update

live_session :logged_in, on_mount: [{AtomicWeb.Hooks, :authenticated_user_state}] do
live "/", HomeLive.Index, :index
Expand Down Expand Up @@ -155,9 +158,6 @@ defmodule AtomicWeb.Router do

scope "/", AtomicWeb do
pipe_through [:browser, :require_authenticated_user]

get "/users/settings", UserSettingsController, :edit
put "/users/settings", UserSettingsController, :update
get "/users/settings/confirm_email/:token", UserSettingsController, :confirm_email
end

Expand Down
7 changes: 7 additions & 0 deletions lib/atomic_web/templates/email/user_confirmation.txt.eex
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Hi <%= @user.email %>,

You can confirm your Atomic account by visiting the URL below:

<%= @url %>

If you didn't create an account with us, please ignore this.
27 changes: 17 additions & 10 deletions lib/atomic_web/templates/user_confirmation/edit.html.heex
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
<h1>Confirm account</h1>
<div class="flex flex-col items-center w-screen h-screen justify-center bg-[url('/images/atomic.png')] bg-cover bg-[length:2000px_1400px] bg-no-repeat bg-opacity-25 bg-center">
<.form let={_f} for={:user} action={Routes.user_confirmation_path(@conn, :update, @token)} as={:user} class="flex flex-col items-center justify-center w-full h-full mx-8 mt-8 space-y-6 sm:mx-0">
<h2 class="mt-6 text-center text-5xl font-extrabold text-zinc-900">
<span><%= gettext("Confirm your Account") %></span>
</h2>
<%= if @error_message do %>
<div class="alert alert-danger">
<p><%= @error_message %></p>
</div>
<% end %>

<.form let={_f} for={:user} action={Routes.user_confirmation_path(@conn, :update, @token)}>
<div>
<%= submit("Confirm my account") %>
</div>
</.form>

<p>
<%= link("Register", to: Routes.user_registration_path(@conn, :new)) %> | <%= link("Log in", to: Routes.user_session_path(@conn, :new)) %>
</p>
<div>
<%= submit class: "w-64 border-2 rounded-md bg-orange-500 text-lg border-orange-500 py-2 px-3.5 text-sm font-medium text-white shadow-sm" do %>
<%= gettext("Confirm") %>
<% end %>
</div>
</.form>
</div>
2 changes: 1 addition & 1 deletion test/atomic/organizations_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ defmodule Atomic.OrganizationsTest do
alias Atomic.Organizations.Membership

test "list_memberships/1 returns all memberships of organization" do
membership = insert(:membership)
membership = insert(:membership, role: :member)

memberships =
Organizations.list_memberships(%{"organization_id" => membership.organization_id})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ defmodule AtomicWeb.UserConfirmationControllerTest do
test "renders the confirmation page", %{conn: conn} do
conn = get(conn, Routes.user_confirmation_path(conn, :edit, "some-token"))
response = html_response(conn, 200)
assert response =~ "<h1>Confirm account</h1>"
assert response =~ "Confirm your Account"

form_action = Routes.user_confirmation_path(conn, :update, "some-token")
assert response =~ "action=\"#{form_action}\""
Expand All @@ -74,15 +74,15 @@ defmodule AtomicWeb.UserConfirmationControllerTest do
end)

conn = post(conn, Routes.user_confirmation_path(conn, :update, token))
assert redirected_to(conn) == "/"
assert redirected_to(conn) == "/users/log_in"
assert get_flash(conn, :info) =~ "User confirmed successfully"
assert Accounts.get_user!(user.id).confirmed_at
refute get_session(conn, :user_token)
assert Repo.all(Accounts.UserToken) == []

# When not logged in
conn = post(conn, Routes.user_confirmation_path(conn, :update, token))
assert redirected_to(conn) == "/"
assert redirected_to(conn) == "/users/log_in"
assert get_flash(conn, :error) =~ "User confirmation link is invalid or it has expired"

# When logged in
Expand All @@ -97,7 +97,7 @@ defmodule AtomicWeb.UserConfirmationControllerTest do

test "does not confirm email with invalid token", %{conn: conn, user: user} do
conn = post(conn, Routes.user_confirmation_path(conn, :update, "oops"))
assert redirected_to(conn) == "/"
assert redirected_to(conn) == "/users/log_in"
assert get_flash(conn, :error) =~ "User confirmation link is invalid or it has expired"
refute Accounts.get_user!(user.id).confirmed_at
end
Expand Down
12 changes: 2 additions & 10 deletions test/atomic_web/controllers/user_registration_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ defmodule AtomicWeb.UserRegistrationControllerTest do

describe "POST /users/register" do
@tag :capture_log
test "creates account and logs the user in", %{conn: conn} do
test "creates account but doesn't log the user in", %{conn: conn} do
organization = insert(:organization)

user_attrs = %{
Expand All @@ -34,15 +34,7 @@ defmodule AtomicWeb.UserRegistrationControllerTest do
"user" => user_attrs
})

assert get_session(conn, :user_token)
assert redirected_to(conn) == "/"

# Now do a logged in request and assert on the menu
conn = get(conn, "/")

response = html_response(conn, 200)

assert response =~ "Home"
assert is_nil(get_session(conn, :user_token))
end
end
end
7 changes: 5 additions & 2 deletions test/atomic_web/controllers/user_session_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ defmodule AtomicWeb.UserSessionControllerTest do

setup do
organization = insert(:organization)
%{user: insert(:user, default_organization_id: organization.id)}

%{
user:
insert(:user, default_organization_id: organization.id, confirmed_at: DateTime.utc_now())
}
end

describe "GET /users/log_in" do
Expand Down Expand Up @@ -36,7 +40,6 @@ defmodule AtomicWeb.UserSessionControllerTest do
# Now do a logged in request and assert on the menu
conn = get(conn, "/")
response = html_response(conn, 200)
assert response =~ user.email
assert response =~ "Home"
end

Expand Down
4 changes: 3 additions & 1 deletion test/support/conn_case.ex
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ defmodule AtomicWeb.ConnCase do
"""
def register_and_log_in_user(%{conn: conn}) do
organization = insert(:organization)
user = insert(:user, %{default_organization_id: organization.id})

user =
insert(:user, %{default_organization_id: organization.id, confirmed_at: DateTime.utc_now()})

Organizations.create_membership(%{
organization_id: organization.id,
Expand Down

0 comments on commit 1a8e48f

Please sign in to comment.