Skip to content

Commit

Permalink
Add audit logs when creating or updating script (#1815)
Browse files Browse the repository at this point in the history
Adds audit logging when a user creates or updates a script.

Adds a templates file for Product audit logging.

Adding the user as a parameter to creation and updates of scripts is
also a preparation for #1799 :)
  • Loading branch information
elinol authored Jan 23, 2025
1 parent 1b78d7d commit acfea91
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 29 deletions.
23 changes: 23 additions & 0 deletions lib/nerves_hub/audit_logs/templates/product_templates.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule NervesHub.AuditLogs.ProductTemplates do
alias NervesHub.AuditLogs
alias NervesHub.AuditLogs.AuditLog
alias NervesHub.Accounts.User
alias NervesHub.Products.Product
alias NervesHub.Scripts.Script

@spec audit_script_created(User.t(), Product.t(), Script.t()) :: AuditLog.t()
def audit_script_created(user, product, script) do
description =
"User #{user.name} created script named #{script.name} with id #{script.id} for product #{product.name}"

AuditLogs.audit!(user, product, description)
end

@spec audit_script_created(User.t(), Product.t(), Script.t()) :: AuditLog.t()
def audit_script_updated(user, product, script) do
description =
"User #{user.name} updated script named #{script.name} with id #{script.id} for product #{product.name}"

AuditLogs.audit!(user, product, description)
end
end
31 changes: 28 additions & 3 deletions lib/nerves_hub/scripts.ex
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
defmodule NervesHub.Scripts do
import Ecto.Query

alias Ecto.Changeset
alias NervesHub.Accounts.User
alias NervesHub.AuditLogs.ProductTemplates
alias NervesHub.Products
alias NervesHub.Products.Product
alias NervesHub.Scripts.Script

Expand Down Expand Up @@ -52,16 +56,37 @@ defmodule NervesHub.Scripts do
end
end

def create(product, params) do
@spec create(Product.t(), User.t(), map()) :: {:ok, Script.t()} | {:error, Changeset.t()}
def create(product, user, params) do
product
|> Ecto.build_assoc(:scripts)
|> Script.changeset(params)
|> Repo.insert()
|> case do
{:ok, script} ->
ProductTemplates.audit_script_created(user, product, script)
{:ok, script}

err ->
err
end
end

def update(command, params) do
command
@spec update(Script.t(), User.t(), map()) :: {:ok, Script.t()} | {:error, Changeset.t()}
def update(script, user, params) do
script
|> Script.changeset(params)
|> Repo.update()
|> case do
{:ok, script} ->
product = Products.get_product!(script.product_id)

ProductTemplates.audit_script_updated(user, product, script)

{:ok, script}

err ->
err
end
end
end
14 changes: 8 additions & 6 deletions lib/nerves_hub_web/live/support_scripts/edit.ex
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ defmodule NervesHubWeb.Live.SupportScripts.Edit do
end

@impl Phoenix.LiveView
def handle_event("update-script", %{"script" => script_params}, socket) do
authorized!(:"support_script:update", socket.assigns.org_user)

%{org: org, product: product} = socket.assigns
def handle_event(
"update-script",
%{"script" => script_params},
%{assigns: %{org: org, product: product, script: script, org_user: org_user}} = socket
) do
authorized!(:"support_script:update", org_user)

case Scripts.update(socket.assigns.script, script_params) do
{:ok, _command} ->
case Scripts.update(script, org_user.user, script_params) do
{:ok, _script} ->
socket
|> put_flash(:info, "Support Script updated")
|> send_toast(:info, "Support Script updated successfully.")
Expand Down
14 changes: 8 additions & 6 deletions lib/nerves_hub_web/live/support_scripts/new.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ defmodule NervesHubWeb.Live.SupportScripts.New do
end

@impl Phoenix.LiveView
def handle_event("create-script", %{"script" => script_params}, socket) do
authorized!(:"support_script:create", socket.assigns.org_user)
def handle_event(
"create-script",
%{"script" => script_params},
%{assigns: %{org_user: org_user, org: org, product: product}} = socket
) do
authorized!(:"support_script:create", org_user)

%{org: org, product: product} = socket.assigns

case Scripts.create(product, script_params) do
{:ok, _command} ->
case Scripts.create(product, org_user.user, script_params) do
{:ok, _script} ->
socket
|> put_flash(:info, "Support Script created")
|> send_toast(:info, "Support Script created successfully.")
Expand Down
10 changes: 5 additions & 5 deletions test/nerves_hub/scripts_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ defmodule NervesHub.ScriptsTest do
%{user: user, org: org, product: product}
end

describe "creating a command" do
test "successful", %{product: product} do
{:ok, command} =
Scripts.create(product, %{
describe "creating a script" do
test "successful", %{product: product, user: user} do
{:ok, script} =
Scripts.create(product, user, %{
name: "MOTD",
text: "NervesMOTD.print()"
})

assert command.product_id == product.id
assert script.product_id == product.id
end
end
end
7 changes: 4 additions & 3 deletions test/nerves_hub_web/live/devices/show_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -540,10 +540,11 @@ defmodule NervesHubWeb.Live.Devices.ShowTest do
conn: conn,
org: org,
product: product,
device: device
device: device,
user: user
} do
{:ok, _command} =
NervesHub.Scripts.create(product, %{name: "MOTD", text: "NervesMOTD.print()"})
{:ok, _script} =
NervesHub.Scripts.create(product, user, %{name: "MOTD", text: "NervesMOTD.print()"})

conn
|> visit("/org/#{org.name}/#{product.name}/devices/#{device.identifier}")
Expand Down
17 changes: 11 additions & 6 deletions test/nerves_hub_web/live/support_scripts_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ defmodule NervesHubWeb.Live.SupportScriptsTest do
|> assert_has("h3", text: "#{product.name} doesn’t have any Support Scripts yet")
end

test "shows all support scripts for a product", %{conn: conn, org: org, product: product} do
{:ok, _command} = Scripts.create(product, %{name: "MOTD", text: "NervesMOTD.print()"})
test "shows all support scripts for a product", %{
conn: conn,
org: org,
product: product,
user: user
} do
{:ok, _script} = Scripts.create(product, user, %{name: "MOTD", text: "NervesMOTD.print()"})

conn
|> visit("/org/#{org.name}/#{product.name}/scripts")
Expand All @@ -29,8 +34,8 @@ defmodule NervesHubWeb.Live.SupportScriptsTest do
end

describe "delete" do
test "removes support script", %{conn: conn, org: org, product: product} do
{:ok, _command} = Scripts.create(product, %{name: "MOTD", text: "NervesMOTD.print()"})
test "removes support script", %{conn: conn, org: org, product: product, user: user} do
{:ok, _script} = Scripts.create(product, user, %{name: "MOTD", text: "NervesMOTD.print()"})

conn
|> visit("/org/#{org.name}/#{product.name}/scripts")
Expand Down Expand Up @@ -59,8 +64,8 @@ defmodule NervesHubWeb.Live.SupportScriptsTest do
end

describe "edit" do
test "requires a name and text", %{conn: conn, org: org, product: product} do
{:ok, script} = Scripts.create(product, %{name: "MOTD", text: "NervesMOTD.print()"})
test "requires a name and text", %{conn: conn, org: org, product: product, user: user} do
{:ok, script} = Scripts.create(product, user, %{name: "MOTD", text: "NervesMOTD.print()"})

conn
|> visit("/org/#{org.name}/#{product.name}/scripts/#{script.id}/edit")
Expand Down

0 comments on commit acfea91

Please sign in to comment.