Skip to content

Commit

Permalink
open beta is open!!
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Nelson committed Oct 20, 2023
1 parent 45e6413 commit 47a5919
Show file tree
Hide file tree
Showing 12 changed files with 84 additions and 38 deletions.
2 changes: 1 addition & 1 deletion lib/factory.ex
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ defmodule LaunchCart.Factory do
%User{
email: Internet.email(),
hashed_password: Bcrypt.hash_pwd_salt("password"),
active?: true
confirmed_at: DateTime.utc_now()
}
end

Expand Down
2 changes: 1 addition & 1 deletion lib/launch_cart/accounts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ defmodule LaunchCart.Accounts do
"""
def get_user_by_email_and_password(email, password)
when is_binary(email) and is_binary(password) do
user = Repo.get_by(User, email: email, active?: true)
user = Repo.get_by(User, email: email)
if User.valid_password?(user, password), do: user
end

Expand Down
4 changes: 3 additions & 1 deletion lib/launch_cart/accounts/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ defmodule LaunchCart.Accounts.User do
"""
def registration_changeset(user, attrs, opts \\ []) do
user
|> cast(attrs, [:email, :notes])
|> cast(attrs, [:email, :notes, :password])
|> validate_email()
|> validate_confirmation(:password, message: "does not match password")
|> validate_password(opts)
end

defp validate_email(changeset) do
Expand Down
10 changes: 2 additions & 8 deletions lib/launch_cart/accounts/user_notifier.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,15 @@ defmodule LaunchCart.Accounts.UserNotifier do
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:
Thanks for signing for Launch Elements! You can confirm your account by visiting the URL below:
#{url}
If you didn't create an account with us, please ignore this.
==============================
""")
end

Expand All @@ -43,17 +41,13 @@ defmodule LaunchCart.Accounts.UserNotifier do
def deliver_reset_password_instructions(user, url) do
deliver(user.email, "Reset password instructions", """
==============================
Hi #{user.email},
You can reset your password by visiting the URL below:
#{url}
If you didn't request this change, please ignore this.
==============================
""")
end

Expand Down
12 changes: 8 additions & 4 deletions lib/launch_cart_web/controllers/user_registration_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@ defmodule LaunchCartWeb.UserRegistrationController do

alias LaunchCart.Accounts
alias LaunchCart.Accounts.User
alias LaunchCartWeb.UserAuth

def new(conn, _params) do
changeset = Accounts.change_user_registration(%User{})
render(conn, "new.html", changeset: changeset)
end

def create(conn, %{"user" => user_params}) do
case Accounts.register_user(user_params) do
{:ok, user} -> render(conn, "thanks.html", user: user)

with {:ok, user} <- Accounts.register_user(user_params),
{:ok, _} <-
Accounts.deliver_user_confirmation_instructions(
user,
&Routes.user_confirmation_url(conn, :edit, &1)
) do
render(conn, "thanks.html", user: user)
else
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "new.html", changeset: changeset)
end
Expand Down
18 changes: 13 additions & 5 deletions lib/launch_cart_web/controllers/user_session_controller.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule LaunchCartWeb.UserSessionController do
use LaunchCartWeb, :controller

alias LaunchCart.Accounts
alias LaunchCart.Accounts.User
alias LaunchCartWeb.UserAuth

def new(conn, _params) do
Expand All @@ -11,11 +12,18 @@ defmodule LaunchCartWeb.UserSessionController do
def create(conn, %{"user" => user_params}) do
%{"email" => email, "password" => password} = user_params

if user = Accounts.get_user_by_email_and_password(email, password) do
UserAuth.log_in_user(conn, user, user_params)
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")
case Accounts.get_user_by_email_and_password(email, password) do
%User{confirmed_at: nil} ->
render(conn, "new.html",
error_message: "Please check your email for confirmation instructions."
)

%User{} = user ->
UserAuth.log_in_user(conn, user, user_params)

nil ->
# 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")
end
end

Expand Down
20 changes: 16 additions & 4 deletions lib/launch_cart_web/templates/user_registration/new.html.heex
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="card card--contained u-centered u-push__top--xl">
<h1>Help us test Launch Elements!</h1>
<p>We are currently in beta and looking for folks to help us test out our product. Interested?
Enter your email address and some info on what you are hoping to build, and we'll get right back to you!</p>
<h1>Launch Elements enters Open Beta</h1>
<p>We are currently in open beta testing from now until the end of November, 2023. Getting started is easy!
Fill out the form below, we'll confirm your email and you are on your way.</p>

<.form let={f} for={@changeset} action={Routes.user_registration_path(@conn, :create)}>
<%= if @changeset.action do %>
Expand All @@ -17,7 +17,19 @@
</div>

<div class="input-group">
<%= label f, :notes %>
<%= label f, :password, "Password" %>
<%= password_input f, :password, required: true %>
<%= error_tag f, :password %>
</div>

<div class="input-group">
<%= label f, :password_confirmation, "Confirm password" %>
<%= password_input f, :password_confirmation, required: true %>
<%= error_tag f, :password_confirmation %>
</div>

<div class="input-group">
<%= label f, "Anything you'd like to tell us about what you're building?" %>
<%= error_tag f, :notes %>
<%= textarea f, :notes %>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<section class="card">
<h1>Thanks!</h1>
<p>Thank you for your interest in testing our product. We know that getting real user feedback is the best way to build the right thing, so we can't thank you enough. We'll be in touch soon.</p>
<p>You should receive an email shortly. Follow the confirmation instructions and you are ready to start using Launch Elements!</p>
<a class="button" href="/">Back to homepage</a>
</section>
3 changes: 2 additions & 1 deletion lib/launch_cart_web/templates/user_session/new.html.heex
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
</.form>

<p class="u-push__top--lg">
Don't have an account yet? <%= link "Register", to: Routes.user_registration_path(@conn, :new) %> for one now!
Don't have an account yet? <%= link "Register", to: Routes.user_registration_path(@conn, :new) %> for one now! <br/>
Need to confirm your email? <%= link "Resend confirmation instructions", to: Routes.user_confirmation_path(@conn, :new) %>
</p>
</div>
23 changes: 14 additions & 9 deletions test/launch_cart/accounts_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@ defmodule LaunchCart.AccountsTest do
assert %User{id: ^id} = Accounts.get_user_by_email_and_password(user.email, "password")
end

test "does not return the user if they are not active" do
user = insert(:user, active?: false)
refute Accounts.get_user_by_email_and_password(user.email, "password")
end
end

describe "get_user!/1" do
Expand All @@ -55,22 +51,29 @@ defmodule LaunchCart.AccountsTest do
end

describe "register_user/1" do
test "requires email" do
test "requires email and password" do
{:error, changeset} = Accounts.register_user(%{})

assert %{
email: ["can't be blank"]
email: ["can't be blank"],
password: ["can't be blank"]
} = errors_on(changeset)
end

test "creates a disabled user and notifies a Launch Scout" do
email = unique_user_email()

{:ok, user} =
Accounts.register_user(%{email: email, notes: "I want to build something cool"})
Accounts.register_user(%{
email: email,
notes: "I want to build something cool",
password: "Password1234",
password_confirmation: "Password1234"
})

assert user.notes =~ ~r/cool/
refute user.active?
refute user.confirmed_at
assert user.hashed_password

assert_email_sent(fn %{to: [{_name, email_address}]} ->
assert email_address =~ ~r/launchscout/
Expand All @@ -81,7 +84,9 @@ defmodule LaunchCart.AccountsTest do
test "activate_user" do
email = unique_user_email()

{:ok, %User{id: user_id} = user} = Accounts.register_user(%{email: email, notes: "I want to build something cool"})
{:ok, %User{id: user_id} = user} =
Accounts.register_user(%{email: email, notes: "I want to build something cool"})

assert {:ok, %User{id: ^user_id, active?: true}} = Accounts.activate_user(user)
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ defmodule LaunchCartWeb.UserRegistrationControllerTest do
alias ExDoc.Language
use LaunchCartWeb.ConnCase, async: true

alias LaunchCart.Repo
alias LaunchCart.Accounts.{User, UserToken}

import LaunchCart.AccountsFixtures
import LaunchCart.Factory

describe "GET /users/register" do
test "renders registration page", %{conn: conn} do
conn = get(conn, Routes.user_registration_path(conn, :new))
response = html_response(conn, 200)
assert response =~ "Help us test Launch Elements!"
assert response =~ "Launch Elements enters Open Beta"
assert response =~ "Log in</a>"
assert response =~ "Register</a>"
PallyTest.here(conn)
Expand All @@ -23,16 +26,20 @@ defmodule LaunchCartWeb.UserRegistrationControllerTest do

describe "POST /users/register" do
@tag :capture_log
test "thanks the user", %{conn: conn} do
test "thanks the user and sends confirmation email", %{conn: conn} do
email = unique_user_email()

conn =
post(conn, Routes.user_registration_path(conn, :create), %{
"user" => %{email: email}
"user" => %{email: email, password: "Password1235", password_confirmation: "Password1235"}
})

response = html_response(conn, 200)
assert response =~ "Thanks"

assert user = Repo.get_by!(User, email: email)
assert Repo.get_by!(UserToken, user_id: user.id).context == "confirm"

PallyTest.here(conn)
end
end
Expand Down
13 changes: 13 additions & 0 deletions test/launch_cart_web/controllers/user_session_controller_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,19 @@ defmodule LaunchCartWeb.UserSessionControllerTest do
assert response =~ "Invalid email or password"
PallyTest.here(conn)
end

test "Gives confirmation reminder for unconfirmed user", %{conn: conn} do
unconfirmed_user = insert(:user, confirmed_at: nil)
conn =
post(conn, Routes.user_session_path(conn, :create), %{
"user" => %{"email" => unconfirmed_user.email, "password" => "password"}
})

response = html_response(conn, 200)
assert response =~ "<h1>Log in</h1>"
assert response =~ "Please check your email for confirmation instructions."
PallyTest.here(conn)
end
end

describe "DELETE /users/log_out" do
Expand Down

0 comments on commit 47a5919

Please sign in to comment.