Skip to content

Commit

Permalink
Add audit log for the rest billing "write" actions (#856)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsdshcym authored and ericmj committed Oct 17, 2019
1 parent b372086 commit 6f1a27a
Show file tree
Hide file tree
Showing 6 changed files with 518 additions and 100 deletions.
25 changes: 25 additions & 0 deletions lib/hexpm/accounts/audit_log.ex
Expand Up @@ -142,6 +142,9 @@ defmodule Hexpm.Accounts.AuditLog do
defp extract_params("password.reset.finish", nil), do: %{}
defp extract_params("password.update", nil), do: %{}

defp extract_params("billing.cancel", {organization, _params}),
do: %{organization: serialize(organization)}

defp extract_params("billing.create", {organization, params}),
do: %{
organization: serialize(organization),
Expand All @@ -152,6 +155,28 @@ defmodule Hexpm.Accounts.AuditLog do
quantity: params["quantity"]
}

defp extract_params("billing.update", {organization, params}),
do: %{
organization: serialize(organization),
email: params["email"],
person: params["person"],
company: params["company"],
token: params["token"],
quantity: params["quantity"]
}

defp extract_params("billing.change_plan", {organization, params}),
do: %{
organization: serialize(organization),
plan_id: params["plan_id"]
}

defp extract_params("billing.pay_invoice", {organization, invoice_id}),
do: %{
organization: serialize(organization),
invoice_id: invoice_id
}

defp serialize(%Key{} = key) do
key
|> do_serialize()
Expand Down
38 changes: 38 additions & 0 deletions lib/hexpm/billing/billing.ex
Expand Up @@ -25,6 +25,12 @@ defmodule Hexpm.Billing do
def pay_invoice(id), do: impl().pay_invoice(id)
def report(), do: impl().report()

def cancel(params, audit: %{audit_data: audit_data, organization: organization}) do
result = impl().cancel(params)
Repo.insert!(audit(audit_data, "billing.cancel", {organization, params}))
result
end

def create(params, audit: %{audit_data: audit_data, organization: organization}) do
case impl().create(params) do
{:ok, result} ->
Expand All @@ -35,4 +41,36 @@ defmodule Hexpm.Billing do
{:error, reason}
end
end

def update(organization_name, params,
audit: %{audit_data: audit_data, organization: organization}
) do
case impl().update(organization_name, params) do
{:ok, result} ->
Repo.insert!(audit(audit_data, "billing.update", {organization, params}))
{:ok, result}

{:error, reason} ->
{:error, reason}
end
end

def change_plan(organization_name, params,
audit: %{audit_data: audit_data, organization: organization}
) do
impl().change_plan(organization_name, params)
Repo.insert!(audit(audit_data, "billing.change_plan", {organization, params}))
:ok
end

def pay_invoice(id, audit: %{audit_data: audit_data, organization: organization}) do
case impl().pay_invoice(id) do
:ok ->
Repo.insert!(audit(audit_data, "billing.pay_invoice", {organization, id}))
:ok

{:error, reason} ->
{:error, reason}
end
end
end
39 changes: 23 additions & 16 deletions lib/hexpm_web/controllers/dashboard/organization_controller.ex
Expand Up @@ -137,7 +137,9 @@ defmodule HexpmWeb.Dashboard.OrganizationController do

def cancel_billing(conn, %{"dashboard_org" => organization}) do
access_organization(conn, organization, "admin", fn organization ->
customer = Hexpm.Billing.cancel(organization.name)
audit = %{audit_data: audit_data(conn), organization: organization}
customer = Hexpm.Billing.cancel(organization.name, audit: audit)

message = cancel_message(customer["subscription"]["current_period_end"])

conn
Expand Down Expand Up @@ -170,8 +172,10 @@ defmodule HexpmWeb.Dashboard.OrganizationController do
customer = Hexpm.Billing.get(organization.name)
invoice_ids = Enum.map(customer["invoices"], & &1["id"])

audit = %{audit_data: audit_data(conn), organization: organization}

if id in invoice_ids do
case Hexpm.Billing.pay_invoice(id) do
case Hexpm.Billing.pay_invoice(id, audit: audit) do
:ok ->
conn
|> put_flash(:info, "Invoice paid.")
Expand All @@ -191,11 +195,13 @@ defmodule HexpmWeb.Dashboard.OrganizationController do

def update_billing(conn, %{"dashboard_org" => organization} = params) do
access_organization(conn, organization, "admin", fn organization ->
audit = %{audit_data: audit_data(conn), organization: organization}

update_billing(
conn,
organization,
params,
&Hexpm.Billing.update(organization.name, &1)
&Hexpm.Billing.update(organization.name, &1, audit: audit)
)
end)
end
Expand All @@ -209,16 +215,9 @@ defmodule HexpmWeb.Dashboard.OrganizationController do
|> Map.put("token", organization.name)
|> Map.put("quantity", user_count)

update_billing(
conn,
organization,
params,
# TODO: call fun.(customer_params, audit: audit_data(conn)) in
# update_billing/4 directly after Hexpm.Billing.update/2 is added
&Hexpm.Billing.create(&1,
audit: %{audit_data: audit_data(conn), organization: organization}
)
)
audit = %{audit_data: audit_data(conn), organization: organization}

update_billing(conn, organization, params, &Hexpm.Billing.create(&1, audit: audit))
end)
end

Expand All @@ -232,7 +231,10 @@ defmodule HexpmWeb.Dashboard.OrganizationController do
seats = current_seats + add_seats

if seats >= user_count do
{:ok, _customer} = Hexpm.Billing.update(organization.name, %{"quantity" => seats})
audit = %{audit_data: audit_data(conn), organization: organization}

{:ok, _customer} =
Hexpm.Billing.update(organization.name, %{"quantity" => seats}, audit: audit)

conn
|> put_flash(:info, "The number of open seats have been increased.")
Expand All @@ -252,7 +254,10 @@ defmodule HexpmWeb.Dashboard.OrganizationController do
seats = String.to_integer(params["seats"])

if seats >= user_count do
{:ok, _customer} = Hexpm.Billing.update(organization.name, %{"quantity" => seats})
audit = %{audit_data: audit_data(conn), organization: organization}

{:ok, _customer} =
Hexpm.Billing.update(organization.name, %{"quantity" => seats}, audit: audit)

conn
|> put_flash(:info, "The number of open seats have been reduced.")
Expand All @@ -268,7 +273,9 @@ defmodule HexpmWeb.Dashboard.OrganizationController do

def change_plan(conn, %{"dashboard_org" => organization} = params) do
access_organization(conn, organization, "admin", fn organization ->
Hexpm.Billing.change_plan(organization.name, %{"plan_id" => params["plan_id"]})
audit = %{audit_data: audit_data(conn), organization: organization}

Hexpm.Billing.change_plan(organization.name, %{"plan_id" => params["plan_id"]}, audit: audit)

conn
|> put_flash(:info, "You have switched to the #{plan_name(params["plan_id"])} plan.")
Expand Down
92 changes: 92 additions & 0 deletions test/hexpm/accounts/audit_log_test.exs
Expand Up @@ -43,6 +43,26 @@ defmodule Hexpm.Accounts.AuditLogTest do
assert audit.params.user.handles.github == user.handles.github
end

test "action billing.cancel", %{user: user} do
organization = build(:organization, name: "Organization Name")

audit =
AuditLog.build(
user,
"user_agent",
"billing.cancel",
{
organization,
"Organization Name"
}
)

assert audit.action == "billing.cancel"
assert audit.user_id == user.id
assert audit.user_agent == "user_agent"
assert audit.params.organization.name == "Organization Name"
end

test "action billing.create", %{user: user} do
organization = build(:organization, name: "Organization Name")

Expand Down Expand Up @@ -73,6 +93,48 @@ defmodule Hexpm.Accounts.AuditLogTest do
assert audit.params.token == "Test Token"
assert audit.params.quantity == 11
end

test "action billing.change_plan", %{user: user} do
organization = build(:organization, name: "Organization Name")

audit =
AuditLog.build(
user,
"user_agent",
"billing.change_plan",
{
organization,
%{"plan_id" => "test plan"}
}
)

assert audit.action == "billing.change_plan"
assert audit.user_id == user.id
assert audit.user_agent == "user_agent"
assert audit.params.organization.name == "Organization Name"
assert audit.params.plan_id == "test plan"
end

test "action billing.pay_invoice", %{user: user} do
organization = build(:organization, name: "Organization Name")

audit =
AuditLog.build(
user,
"user_agent",
"billing.pay_invoice",
{
organization,
897
}
)

assert audit.action == "billing.pay_invoice"
assert audit.user_id == user.id
assert audit.user_agent == "user_agent"
assert audit.params.organization.name == "Organization Name"
assert audit.params.invoice_id == 897
end
end

describe "audit/3" do
Expand All @@ -81,6 +143,36 @@ defmodule Hexpm.Accounts.AuditLogTest do

assert %AuditLog{action: "docs.revert"} = audit_log
end

test "billing.update", %{user: user} do
organization = build(:organization, name: "Organization Name")

audit =
AuditLog.audit(
{user, "user_agent"},
"billing.update",
{
organization,
%{
"email" => "test@example.com",
"person" => "Test Person",
"company" => "Test Company",
"token" => "Test Token",
"quantity" => 11
}
}
)

assert audit.action == "billing.update"
assert audit.user_id == user.id
assert audit.user_agent == "user_agent"
assert audit.params.organization.name == "Organization Name"
assert audit.params.email == "test@example.com"
assert audit.params.person == "Test Person"
assert audit.params.company == "Test Company"
assert audit.params.token == "Test Token"
assert audit.params.quantity == 11
end
end

describe "audit/4" do
Expand Down

0 comments on commit 6f1a27a

Please sign in to comment.