Skip to content

Commit

Permalink
BC Part 3 (#137)
Browse files Browse the repository at this point in the history
  • Loading branch information
macifell authored Dec 22, 2023
1 parent 0d35aa2 commit 9e390b9
Show file tree
Hide file tree
Showing 11 changed files with 163 additions and 69 deletions.
54 changes: 32 additions & 22 deletions lib/recognizer/accounts.ex
Original file line number Diff line number Diff line change
Expand Up @@ -195,15 +195,6 @@ defmodule Recognizer.Accounts do
|> maybe_send_newsletter(attrs)
end

defp maybe_send_newsletter({:ok, _user} = response, %{"newsletter" => "true"} = attrs) do
Recognizer.Hal.update_newsletter(attrs)
response
end

defp maybe_send_newsletter(response, _attrs) do
response
end

@doc """
Registers a user from a third party service. This is different from above
because it does not set a password, therefor only letting the user login with
Expand All @@ -227,6 +218,18 @@ defmodule Recognizer.Accounts do
end
end

def maybe_create_big_commerce_customer({:ok, user}) do
if BigCommerce.enabled?() do
BigCommerce.create_customer(user)
else
{:ok, user}
end
end

def maybe_create_big_commerce_customer(error) do
error
end

defp maybe_notify_new_user({:ok, user}) do
{:ok, _} = Notification.deliver_user_created_message(user)
{:ok, user}
Expand All @@ -236,6 +239,15 @@ defmodule Recognizer.Accounts do
error
end

defp maybe_send_newsletter({:ok, _user} = response, %{"newsletter" => "true"} = attrs) do
Recognizer.Hal.update_newsletter(attrs)
response
end

defp maybe_send_newsletter(response, _attrs) do
response
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking user changes.
Expand Down Expand Up @@ -281,12 +293,22 @@ defmodule Recognizer.Accounts do
if Map.has_key?(attrs, "newsletter"), do: Recognizer.Hal.update_newsletter(attrs)
changeset = User.changeset(user, attrs)

with {:ok, updated_user} <- Repo.update(changeset) do
with {:ok, updated_user} <- Repo.update(changeset),
{:ok, _} <- maybe_update_big_commerce_customer(updated_user) do
Notification.deliver_user_updated_message(updated_user)

{:ok, updated_user}
end
end

defp maybe_update_big_commerce_customer(user) do
if BigCommerce.enabled?() do
Recognizer.BigCommerce.update_customer(user)
else
{:ok, user}
end
end

@doc """
Returns an `%Ecto.Changeset{}` for changing the user password.
Expand Down Expand Up @@ -716,16 +738,4 @@ defmodule Recognizer.Accounts do

Repo.delete_all(user_codes)
end

def maybe_create_big_commerce_customer({:ok, user}) do
if BigCommerce.enabled?() do
BigCommerce.create_customer(user)
else
{:ok, user}
end
end

def maybe_create_big_commerce_customer(error) do
error
end
end
11 changes: 11 additions & 0 deletions lib/recognizer/bigcommerce.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ defmodule Recognizer.BigCommerce do
end
end

def update_customer(user) do
case Client.update_customer(Repo.preload(user, :bigcommerce_user)) do
{:ok, _} ->
{:ok, user}

{:error, e} ->
Logger.error("error creating bigcommerce customer: #{inspect(e)}")
{:error, e}
end
end

def login_redirect_uri(user) do
config(:login_uri) <> generate_login_jwt(user)
end
Expand Down
77 changes: 72 additions & 5 deletions lib/recognizer/bigcommerce/client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ defmodule Recognizer.BigCommerce.Client do

require Logger

alias Recognizer.Accounts.BCCustomerUser
alias Recognizer.Accounts.User

alias HTTPoison.Response
Expand All @@ -27,12 +28,19 @@ defmodule Recognizer.BigCommerce.Client do
end
end

defp user_as_customer_params(%User{email: email, first_name: first_name, last_name: last_name}) do
{:ok, [%{"email" => email, "first_name" => first_name, "last_name" => last_name}]}
end
def update_customer(user) do
with {:ok, customer_params} <- user_as_customer_params(user),
{:ok, customer_json} <- Jason.encode(customer_params) do
put_customer(customer_json)
else
{:error, e} ->
Logger.error("cannot update customer with error: #{inspect(e)}")
{:error, e}

defp user_as_customer_params(_user) do
{:error, :invalid_user}
e ->
Logger.error("cannot update customer with error: #{inspect(e)}")
{:error, e}
end
end

defp post_customer(customer_json) do
Expand All @@ -52,6 +60,23 @@ defmodule Recognizer.BigCommerce.Client do
end
end

defp put_customer(customer_json) do
case http_client().put(customers_uri(), customer_json, default_headers()) do
{:ok, %Response{body: response, status_code: 200}} ->
{:ok, response}

{:ok, %Response{status_code: 429, headers: headers}} ->
sleep_for_rate_limit(headers)
put_customer(customer_json)

{:error, e} ->
{:error, e}

e ->
{:error, e}
end
end

defp get_id(response) do
case Jason.decode(response) do
{:ok, %{"data" => [%{"id" => id}]}} -> {:ok, id}
Expand All @@ -60,6 +85,48 @@ defmodule Recognizer.BigCommerce.Client do
end
end

defp user_as_customer_params(%User{
email: email,
first_name: first_name,
last_name: last_name,
company_name: company,
phone_number: phone_number,
bigcommerce_user: %BCCustomerUser{bc_id: bc_id}
}) do
{:ok,
[
%{
"id" => bc_id,
"email" => email,
"first_name" => first_name,
"last_name" => last_name,
"company" => company,
"phone" => phone_number
}
]}
end

defp user_as_customer_params(%User{
email: email,
first_name: first_name,
last_name: last_name,
company_name: company
}) do
{:ok,
[
%{
"email" => email,
"first_name" => first_name,
"last_name" => last_name,
"company" => company
}
]}
end

defp user_as_customer_params(_user) do
{:error, :invalid_user}
end

defp default_headers() do
[
{"Content-Type", "application/json"},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,10 @@ defmodule RecognizerWeb.Accounts.UserSettingsController do
plug :assign_email_and_password_changesets

def edit(conn, _params) do
cond do
get_session(conn, :bc) ->
render(conn, "edit.html")

Application.get_env(:recognizer, :redirect_url) ->
redirect(conn, external: Application.get_env(:recognizer, :redirect_url))

true ->
render(conn, "edit.html")
if Application.get_env(:recognizer, :redirect_url) do
redirect(conn, external: Application.get_env(:recognizer, :redirect_url))
else
render(conn, "edit.html")
end
end

Expand Down Expand Up @@ -52,7 +47,7 @@ defmodule RecognizerWeb.Accounts.UserSettingsController do
case Accounts.update_user(user, user_params) do
{:ok, _updated_user} ->
conn
|> put_flash(:info, "Settings has been updated.")
|> put_flash(:info, "Your settings have been updated.")
|> redirect(to: Routes.user_settings_path(conn, :edit))

{:error, changeset} ->
Expand Down
11 changes: 5 additions & 6 deletions test/recognizer/accounts_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ defmodule Recognizer.AccountsTest do

import Mox
import Recognizer.AccountFactory
import Recognizer.BigCommerceTestHelpers

alias Recognizer.Accounts
alias Recognizer.Accounts.BCCustomerUser
Expand All @@ -12,12 +13,6 @@ defmodule Recognizer.AccountsTest do

setup :verify_on_exit!

defp ok_bigcommerce_response() do
body = Jason.encode!(%{data: [%{id: 1001}]})

{:ok, %HTTPoison.Response{body: body, status_code: 200}}
end

describe "get_user_by_email/1" do
test "does not return the user if the email does not exist" do
refute Accounts.get_user_by_email("[email protected]")
Expand Down Expand Up @@ -193,13 +188,17 @@ defmodule Recognizer.AccountsTest do
end

test "updates the email", %{user: user} do
expect(HTTPoisonMock, :put, 1, fn _, _, _ -> ok_bigcommerce_response() end)

assert {:ok, _user} = Accounts.update_user(user, %{email: "[email protected]"})
changed_user = Repo.get!(User, user.id)
assert changed_user.email != user.email
assert "[email protected]" == changed_user.email
end

test "clears company name for individual accounts", %{user: user} do
expect(HTTPoisonMock, :put, 1, fn _, _, _ -> ok_bigcommerce_response() end)

assert {:ok, _user} = Accounts.update_user(user, %{type: :individual, company_name: "test"})
changed_user = Repo.get!(User, user.id)
assert changed_user.type == :individual
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule RecognizerWeb.Api.UserRegistrationControllerTest do
use RecognizerWeb.ConnCase

import Mox
import Recognizer.BigCommerceTestHelpers

alias Recognizer.Accounts.BCCustomerUser
alias Recognizer.Accounts.User
Expand All @@ -12,24 +13,13 @@ defmodule RecognizerWeb.Api.UserRegistrationControllerTest do
setup :verify_on_exit!
setup :register_and_log_in_admin

defp ok_bigcommerce_response() do
body = Jason.encode!(%{data: [%{id: 1001}]})

{:ok, %HTTPoison.Response{body: body, status_code: 200}}
end

defp limit_bigcommerce_response() do
headers = [{"x-rate-limit-time-reset-ms", "1"}]

{:ok, %HTTPoison.Response{status_code: 429, headers: headers}}
end

describe "POST /api/create-account" do
test "POST /api/create-account is limited to staff only", %{conn: conn} do
user = %{
"email" => "[email protected]",
"first_name" => "Test",
"last_name" => "User"
"last_name" => "User",
"company" => ""
}

user_json = Jason.encode!([user])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ defmodule RecognizerWeb.Api.UserSettingsControllerTest do

import Mox
import Recognizer.AccountFactory
import Recognizer.BigCommerceTestHelpers

describe "GET /api/settings" do
test "two factor is reflected", %{conn: conn} do
Expand Down Expand Up @@ -36,6 +37,8 @@ defmodule RecognizerWeb.Api.UserSettingsControllerTest do
setup :verify_on_exit!

test "PUT /api/settings with `update` action", %{conn: conn, user: %{id: user_id}} do
expect(HTTPoisonMock, :put, 1, fn _, _, _ -> ok_bigcommerce_response() end)

conn = put(conn, "/api/settings", %{"action" => "update", "user" => %{"first_name" => "Updated"}})
assert %{"user" => %{"id" => ^user_id, "first_name" => "Updated"}} = json_response(conn, 200)
end
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
defmodule RecognizerWeb.Accounts.Prompt.TwoFactorControllerTest do
use RecognizerWeb.ConnCase

import Mox
import Recognizer.AccountFactory
import Recognizer.BigCommerceTestHelpers

setup :verify_on_exit!

setup %{conn: conn} do
user =
Expand Down Expand Up @@ -35,6 +39,8 @@ defmodule RecognizerWeb.Accounts.Prompt.TwoFactorControllerTest do

describe "PUT /prompt/setup-two-factor" do
test "updates the user notification settings", %{conn: conn} do
expect(HTTPoisonMock, :put, 1, fn _, _, _ -> ok_bigcommerce_response() end)

new_conn =
put(conn, Routes.prompt_two_factor_path(conn, :create), %{
"user" => %{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,14 @@ defmodule RecognizerWeb.Accounts.UserRegistrationControllerTest do

import Mox
import Recognizer.AccountFactory
import Recognizer.BigCommerceTestHelpers

alias Recognizer.Accounts.BCCustomerUser
alias Recognizer.Accounts.User
alias Recognizer.Repo

setup :verify_on_exit!

defp ok_bigcommerce_response() do
body = Jason.encode!(%{data: [%{id: 1001}]})

{:ok, %HTTPoison.Response{body: body, status_code: 200}}
end

defp bad_bigcommerce_response() do
body = Jason.encode!(%{errors: [%{failure: 1}]})

{:ok, %HTTPoison.Response{body: body, status_code: 400}}
end

describe "GET /users/register" do
test "renders registration page", %{conn: conn} do
conn = get(conn, Routes.user_registration_path(conn, :new))
Expand Down
Loading

0 comments on commit 9e390b9

Please sign in to comment.