Skip to content

Commit

Permalink
basic plug based payment guard
Browse files Browse the repository at this point in the history
  • Loading branch information
ericdude4 committed Oct 22, 2020
1 parent 18c3ee2 commit 7bf5f29
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 5 deletions.
3 changes: 3 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use Mix.Config

import_config "#{Mix.env()}.exs"
5 changes: 5 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use Mix.Config

config :shopifex,
shop_schema: %{},
payment_guard: Shopifex.Plug.PaymentGuardTest.PaymentGuard
23 changes: 23 additions & 0 deletions lib/shopifex/payment_guard.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule Shopifex.PaymentGuard do
defmacro __using__(_opts) do
quote do
import Ecto.Query, warn: false

def payment_schema, do: Application.fetch_env!(:shopifex, :payment_schema)
def repo, do: Application.fetch_env!(:shopifex, :repo)

@doc """
Returns a payment record which grants access to the payment guard or nil
"""
def payment_for_guard(shop, identifier) do
from(s in payment_schema(),
where: s.shop_id == ^shop.id,
where: s.identifier == ^identifier
)
|> repo().one()
end

defoverridable payment_for_guard: 2
end
end
end
32 changes: 32 additions & 0 deletions lib/shopifex/plug/payment_guard.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule Shopifex.Plug.PaymentGuard do
import Plug.Conn
require Logger

def init(options) do
# initialize options
options
end

@doc """
This makes sure the shop in the session contains a payment which unlocks the guard
"""
def call(conn, guard_identifier) do
payment_guard = Application.fetch_env!(:shopifex, :payment_guard)

case payment_guard.payment_for_guard(conn.private.shop, guard_identifier) do
nil ->
Logger.info("Payment guard blocked request")

redirect_after = URI.encode_www_form("#{conn.request_path}?#{conn.query_string}")

conn
|> Phoenix.Controller.redirect(
to: "/payment?guard=#{guard_identifier}&redirect_after=#{redirect_after}"
)
|> halt()

payment_for_guard ->
Plug.Conn.put_private(conn, :payment_for_guard, payment_for_guard)
end
end
end
41 changes: 41 additions & 0 deletions test/plug/payment_guard_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
defmodule Shopifex.Plug.PaymentGuardTest do
use ExUnit.Case, async: true
use Plug.Test

defmodule PaymentGuard do
use Shopifex.PaymentGuard

def payment_for_guard(_shop, "grant"), do: %{}
def payment_for_guard(_shop, "block"), do: nil
end

setup do
shop = %{url: "shopifex.myshopify.com", scope: "orders", access_token: "asdf1234"}

{:ok, shop: shop}
end

test "payment guard blocks pay-walled function and redirects to payment route", %{shop: shop} do
conn =
conn(:get, "/premium-route?foo=bar&fizz=buzz", %{})
|> Plug.Conn.put_private(:shop, shop)
|> Shopifex.Plug.PaymentGuard.call("block")

assert conn.status == 302

assert Plug.Conn.get_resp_header(conn, "location") == [
"/payment?guard=block&redirect_after=%2Fpremium-route%3Ffoo%3Dbar%26fizz%3Dbuzz"
]
end

test "payment guard grants access pay-walled function and places guard payment in session", %{
shop: shop
} do
conn =
conn(:get, "/premium-route?foo=bar&fizz=buzz", %{})
|> Plug.Conn.put_private(:shop, shop)
|> Shopifex.Plug.PaymentGuard.call("grant")

assert conn.private.payment_for_guard == %{}
end
end
15 changes: 10 additions & 5 deletions test/plug/shopify_session_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@ defmodule Shopifex.Plug.ShopifySessionTest do
use ExUnit.Case, async: true
use Plug.Test

setup do
shop = %{url: "shopifex.myshopify.com", scope: "orders", access_token: "asdf1234"}

{:ok, shop}
end

test "redirect location preserves parameters" do
Application.put_env(:shopifex, :shop_schema, %{})
result = conn(:get, "/?shop=store", %{})
|> Map.put(:private, %{phoenix_flash: %{shop: ""}})
|> Shopifex.Plug.ShopifySession.call(%{})
result =
conn(:get, "/?shop=store", %{})
|> Map.put(:private, %{phoenix_flash: %{shop: ""}})
|> Shopifex.Plug.ShopifySession.call(%{})

assert result.halted
assert result.status == 302
assert Plug.Conn.get_resp_header(result, "location") == ["/auth?shop=store"]
end

end

0 comments on commit 7bf5f29

Please sign in to comment.