From 8fef6bcf82992e1be7aec399909ce1439d3a89db Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Thu, 16 Jan 2025 22:50:44 +0100 Subject: [PATCH] feat(Audit): Add 'Signatures added/removed' map audit events --- .github/workflows/build.yml | 15 +- lib/wanderer_app/api/user_activity.ex | 6 +- .../components/user_activity.ex | 16 ++ .../map_signatures_event_handler.ex | 31 ++- .../live/maps/map_audit_live.ex | 4 +- .../20250116211927.json | 198 ++++++++++++++++++ 6 files changed, 259 insertions(+), 11 deletions(-) create mode 100644 priv/resource_snapshots/repo/map_system_structures_v1/20250116211927.json diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ecefb5a5..af827743 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -78,22 +78,23 @@ jobs: fetch-depth: 0 - name: 😅 Cache deps id: cache-deps - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-elixir-deps with: - path: deps - key: ${{ runner.os }}-mix-${{ env.cache-name }}-${{ hashFiles('**/mix.lock') }} + path: | + deps + key: ${{ runner.os }}-mix-${{ matrix.elixir }}-${{ matrix.otp }}-${{ hashFiles('**/mix.lock') }} restore-keys: | - ${{ runner.os }}-mix-${{ env.cache-name }}- + ${{ runner.os }}-mix-${{ matrix.elixir }}-${{ matrix.otp }}- - name: 😅 Cache compiled build id: cache-build - uses: actions/cache@v3 + uses: actions/cache@v4 env: cache-name: cache-compiled-build with: path: | - **/_build + _build key: ${{ runner.os }}-build-${{ hashFiles('**/mix.lock') }}-${{ hashFiles( '**/lib/**/*.{ex,eex}', '**/config/*.exs', '**/mix.exs' ) }} restore-keys: | ${{ runner.os }}-build-${{ hashFiles('**/mix.lock') }}- @@ -187,6 +188,8 @@ jobs: push: true context: . file: ./Dockerfile + cache-from: type=gha + cache-to: type=gha,mode=max labels: ${{ steps.meta.outputs.labels }} platforms: ${{ matrix.platform }} outputs: type=image,"name=${{ env.REGISTRY_IMAGE }}",push-by-digest=true,name-canonical=true,push=true diff --git a/lib/wanderer_app/api/user_activity.ex b/lib/wanderer_app/api/user_activity.ex index 2ae2fd0b..5f1f4875 100644 --- a/lib/wanderer_app/api/user_activity.ex +++ b/lib/wanderer_app/api/user_activity.ex @@ -95,7 +95,9 @@ defmodule WandererApp.Api.UserActivity do :map_acl_member_updated, :map_connection_added, :map_connection_updated, - :map_connection_removed + :map_connection_removed, + :signatures_added, + :signatures_removed ] ) @@ -108,8 +110,6 @@ defmodule WandererApp.Api.UserActivity do update_timestamp(:updated_at) end - - relationships do belongs_to :character, WandererApp.Api.Character do allow_nil? true diff --git a/lib/wanderer_app_web/components/user_activity.ex b/lib/wanderer_app_web/components/user_activity.ex index 5f548e6f..05cb8e6e 100644 --- a/lib/wanderer_app_web/components/user_activity.ex +++ b/lib/wanderer_app_web/components/user_activity.ex @@ -139,6 +139,8 @@ defmodule WandererAppWeb.UserActivity do defp get_event_name(:system_added), do: "System Added" defp get_event_name(:system_updated), do: "System Updated" defp get_event_name(:systems_removed), do: "System(s) Removed" + defp get_event_name(:signatures_added), do: "Signatures Added" + defp get_event_name(:signatures_removed), do: "Signatures Removed" defp get_event_name(name), do: name defp get_event_data(:map_acl_added, %{"acl_id" => acl_id}) do @@ -204,6 +206,20 @@ defmodule WandererAppWeb.UserActivity do |> Enum.map(&_get_system_name/1) |> Enum.join(", ") + defp get_event_data(:signatures_added, %{ + "signatures" => signatures + }), + do: + signatures + |> Enum.join(", ") + + defp get_event_data(:signatures_removed, %{ + "signatures" => signatures + }), + do: + signatures + |> Enum.join(", ") + defp get_event_data(:map_connection_added, %{ "solar_system_source_id" => solar_system_source_id, "solar_system_target_id" => solar_system_target_id diff --git a/lib/wanderer_app_web/live/maps/event_handlers/map_signatures_event_handler.ex b/lib/wanderer_app_web/live/maps/event_handlers/map_signatures_event_handler.ex index 20db1ea6..3ce4ca8a 100644 --- a/lib/wanderer_app_web/live/maps/event_handlers/map_signatures_event_handler.ex +++ b/lib/wanderer_app_web/live/maps/event_handlers/map_signatures_event_handler.ex @@ -81,6 +81,7 @@ defmodule WandererAppWeb.MapSignaturesEventHandler do }, %{ assigns: %{ + current_user: current_user, map_id: map_id, map_user_settings: map_user_settings, user_characters: user_characters, @@ -161,10 +162,38 @@ defmodule WandererAppWeb.MapSignaturesEventHandler do end) added_signatures - |> Enum.map(fn s -> + |> Enum.each(fn s -> s |> WandererApp.Api.MapSystemSignature.create!() end) + added_signatures_eve_ids = + added_signatures + |> Enum.map(fn s -> s.eve_id end) + + first_tracked_character = + current_user.characters + |> Enum.find(fn c -> c.eve_id === first_character_eve_id end) + + if not is_nil(first_tracked_character) && + not (added_signatures_eve_ids |> Enum.empty?()) do + WandererApp.User.ActivityTracker.track_map_event(:signatures_added, %{ + character_id: first_tracked_character.id, + user_id: current_user.id, + map_id: map_id, + signatures: added_signatures_eve_ids + }) + end + + if not is_nil(first_tracked_character) && + not (removed_signatures_eve_ids |> Enum.empty?()) do + WandererApp.User.ActivityTracker.track_map_event(:signatures_removed, %{ + character_id: first_tracked_character.id, + user_id: current_user.id, + map_id: map_id, + signatures: removed_signatures_eve_ids + }) + end + Phoenix.PubSub.broadcast!(WandererApp.PubSub, map_id, %{ event: :signatures_updated, payload: system.solar_system_id diff --git a/lib/wanderer_app_web/live/maps/map_audit_live.ex b/lib/wanderer_app_web/live/maps/map_audit_live.ex index 033bb30b..dfadf517 100755 --- a/lib/wanderer_app_web/live/maps/map_audit_live.ex +++ b/lib/wanderer_app_web/live/maps/map_audit_live.ex @@ -171,7 +171,9 @@ defmodule WandererAppWeb.MapAuditLive do {"ACL Removed", :map_acl_removed}, {"Connection Added", :map_connection_added}, {"Connection Updated", :map_connection_updated}, - {"Connection Removed", :map_connection_removed} + {"Connection Removed", :map_connection_removed}, + {"Signatures Added", :signatures_added}, + {"Signatures Removed", :signatures_removed} ]) |> load_activity(1) end diff --git a/priv/resource_snapshots/repo/map_system_structures_v1/20250116211927.json b/priv/resource_snapshots/repo/map_system_structures_v1/20250116211927.json new file mode 100644 index 00000000..97c80cc5 --- /dev/null +++ b/priv/resource_snapshots/repo/map_system_structures_v1/20250116211927.json @@ -0,0 +1,198 @@ +{ + "attributes": [ + { + "allow_nil?": false, + "default": "fragment(\"gen_random_uuid()\")", + "generated?": false, + "primary_key?": true, + "references": null, + "size": null, + "source": "id", + "type": "uuid" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "structure_type_id", + "type": "text" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "structure_type", + "type": "text" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "character_eve_id", + "type": "text" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "solar_system_name", + "type": "text" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "solar_system_id", + "type": "bigint" + }, + { + "allow_nil?": false, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "name", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "notes", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "owner_name", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "owner_ticker", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "owner_id", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "status", + "type": "text" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "end_time", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": false, + "default": "fragment(\"(now() AT TIME ZONE 'utc')\")", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "inserted_at", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": false, + "default": "fragment(\"(now() AT TIME ZONE 'utc')\")", + "generated?": false, + "primary_key?": false, + "references": null, + "size": null, + "source": "updated_at", + "type": "utc_datetime_usec" + }, + { + "allow_nil?": true, + "default": "nil", + "generated?": false, + "primary_key?": false, + "references": { + "deferrable": false, + "destination_attribute": "id", + "destination_attribute_default": null, + "destination_attribute_generated": null, + "index?": false, + "match_type": null, + "match_with": null, + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "name": "map_system_structures_v1_system_id_fkey", + "on_delete": null, + "on_update": null, + "primary_key?": true, + "schema": "public", + "table": "map_system_v1" + }, + "size": null, + "source": "system_id", + "type": "uuid" + } + ], + "base_filter": null, + "check_constraints": [], + "custom_indexes": [], + "custom_statements": [], + "has_create_action": true, + "hash": "B9DA704034C53F0EC20C28EED99D579A34034655225EDC3BC7E57719B276F83F", + "identities": [], + "multitenancy": { + "attribute": null, + "global": null, + "strategy": null + }, + "repo": "Elixir.WandererApp.Repo", + "schema": null, + "table": "map_system_structures_v1" +} \ No newline at end of file