From 8e5f4440da02213f2967c3e1054514bcc7e7d12e Mon Sep 17 00:00:00 2001 From: skanderm Date: Thu, 7 Mar 2024 18:34:14 -0800 Subject: [PATCH] Record user provenance for detections when logged in (#350) --- server/lib/orcasite/radio/detection.ex | 18 ++ .../20240227225620_add_user_to_detections.exs | 23 ++ .../repo/detections/20240227225620.json | 284 ++++++++++++++++++ 3 files changed, 325 insertions(+) create mode 100644 server/priv/repo/migrations/20240227225620_add_user_to_detections.exs create mode 100644 server/priv/resource_snapshots/repo/detections/20240227225620.json diff --git a/server/lib/orcasite/radio/detection.ex b/server/lib/orcasite/radio/detection.ex index db51f95e..65a31cc7 100644 --- a/server/lib/orcasite/radio/detection.ex +++ b/server/lib/orcasite/radio/detection.ex @@ -49,6 +49,10 @@ defmodule Orcasite.Radio.Detection do relationships do belongs_to :candidate, Candidate belongs_to :feed, Feed + + belongs_to :user, Orcasite.Accounts.User do + api Orcasite.Accounts + end end policies do @@ -181,6 +185,17 @@ defmodule Orcasite.Radio.Detection do change manage_relationship(:feed_id, :feed, type: :append) + change fn changeset, %{actor: actor} -> + case actor do + %Orcasite.Accounts.User{} -> + changeset + |> Ash.Changeset.manage_relationship(:user, actor, type: :append) + + _ -> + changeset + end + end + change fn changeset, _context -> playlist_timestamp = changeset |> Ash.Changeset.get_argument(:playlist_timestamp) player_offset = changeset |> Ash.Changeset.get_argument(:player_offset) @@ -273,6 +288,9 @@ defmodule Orcasite.Radio.Detection do graphql do type :detection + # Remove user until we want to make use of this behind + # an authenticated/authorized call + hide_fields [:user] queries do get :detection, :read diff --git a/server/priv/repo/migrations/20240227225620_add_user_to_detections.exs b/server/priv/repo/migrations/20240227225620_add_user_to_detections.exs new file mode 100644 index 00000000..baf05cbf --- /dev/null +++ b/server/priv/repo/migrations/20240227225620_add_user_to_detections.exs @@ -0,0 +1,23 @@ +defmodule Orcasite.Repo.Migrations.AddUserToDetections do + @moduledoc """ + Updates resources based on their most recent snapshots. + + This file was autogenerated with `mix ash_postgres.generate_migrations` + """ + + use Ecto.Migration + + def up do + alter table(:detections) do + add :user_id, references(:users, column: :id, name: "detections_user_id_fkey", type: :uuid) + end + end + + def down do + drop constraint(:detections, "detections_user_id_fkey") + + alter table(:detections) do + remove :user_id + end + end +end \ No newline at end of file diff --git a/server/priv/resource_snapshots/repo/detections/20240227225620.json b/server/priv/resource_snapshots/repo/detections/20240227225620.json new file mode 100644 index 00000000..36db5e5d --- /dev/null +++ b/server/priv/resource_snapshots/repo/detections/20240227225620.json @@ -0,0 +1,284 @@ +{ + "attributes": [ + { + "default": "fragment(\"uuid_generate_v7()\")", + "size": null, + "type": "uuid", + "source": "id", + "references": null, + "allow_nil?": false, + "primary_key?": true, + "generated?": false + }, + { + "default": "nil", + "size": null, + "type": "text", + "source": "source_ip", + "references": null, + "allow_nil?": true, + "primary_key?": false, + "generated?": false + }, + { + "default": "nil", + "size": null, + "type": "bigint", + "source": "playlist_timestamp", + "references": null, + "allow_nil?": false, + "primary_key?": false, + "generated?": false + }, + { + "default": "nil", + "size": null, + "type": "decimal", + "source": "player_offset", + "references": null, + "allow_nil?": false, + "primary_key?": false, + "generated?": false + }, + { + "default": "nil", + "size": null, + "type": "bigint", + "source": "listener_count", + "references": null, + "allow_nil?": true, + "primary_key?": false, + "generated?": false + }, + { + "default": "nil", + "size": null, + "type": "utc_datetime_usec", + "source": "timestamp", + "references": null, + "allow_nil?": false, + "primary_key?": false, + "generated?": false + }, + { + "default": "nil", + "size": null, + "type": "text", + "source": "description", + "references": null, + "allow_nil?": true, + "primary_key?": false, + "generated?": false + }, + { + "default": "true", + "size": null, + "type": "boolean", + "source": "visible", + "references": null, + "allow_nil?": true, + "primary_key?": false, + "generated?": false + }, + { + "default": "nil", + "size": null, + "type": "text", + "source": "category", + "references": null, + "allow_nil?": true, + "primary_key?": false, + "generated?": false + }, + { + "default": "fragment(\"now()\")", + "size": null, + "type": "utc_datetime_usec", + "source": "inserted_at", + "references": null, + "allow_nil?": false, + "primary_key?": false, + "generated?": false + }, + { + "default": "fragment(\"now()\")", + "size": null, + "type": "utc_datetime_usec", + "source": "updated_at", + "references": null, + "allow_nil?": false, + "primary_key?": false, + "generated?": false + }, + { + "default": "nil", + "size": null, + "type": "uuid", + "source": "candidate_id", + "references": { + "name": "detections_candidate_id_fkey", + "table": "candidates", + "schema": null, + "primary_key?": true, + "multitenancy": { + "global": null, + "attribute": null, + "strategy": null + }, + "destination_attribute": "id", + "on_delete": null, + "on_update": null, + "deferrable": false, + "match_with": null, + "match_type": null, + "destination_attribute_default": null, + "destination_attribute_generated": null + }, + "allow_nil?": true, + "primary_key?": false, + "generated?": false + }, + { + "default": "nil", + "size": null, + "type": "uuid", + "source": "feed_id", + "references": { + "name": "detections_feed_id_fkey", + "table": "feeds", + "schema": null, + "primary_key?": true, + "multitenancy": { + "global": null, + "attribute": null, + "strategy": null + }, + "destination_attribute": "id", + "on_delete": null, + "on_update": null, + "deferrable": false, + "match_with": null, + "match_type": null, + "destination_attribute_default": null, + "destination_attribute_generated": null + }, + "allow_nil?": true, + "primary_key?": false, + "generated?": false + }, + { + "default": "nil", + "size": null, + "type": "uuid", + "source": "user_id", + "references": { + "name": "detections_user_id_fkey", + "table": "users", + "schema": null, + "primary_key?": true, + "multitenancy": { + "global": null, + "attribute": null, + "strategy": null + }, + "destination_attribute": "id", + "on_delete": null, + "on_update": null, + "deferrable": false, + "match_with": null, + "match_type": null, + "destination_attribute_default": null, + "destination_attribute_generated": null + }, + "allow_nil?": true, + "primary_key?": false, + "generated?": false + } + ], + "table": "detections", + "hash": "40C8652202741F8E4AC96390303B2EAA7866054BDBE70BA81E5C67044821F33C", + "repo": "Elixir.Orcasite.Repo", + "identities": [], + "custom_indexes": [ + { + "message": null, + "name": null, + "table": null, + "include": null, + "prefix": null, + "fields": [ + "playlist_timestamp" + ], + "where": null, + "unique": false, + "using": null, + "concurrently": false + }, + { + "message": null, + "name": null, + "table": null, + "include": null, + "prefix": null, + "fields": [ + "player_offset" + ], + "where": null, + "unique": false, + "using": null, + "concurrently": false + }, + { + "message": null, + "name": null, + "table": null, + "include": null, + "prefix": null, + "fields": [ + "timestamp" + ], + "where": null, + "unique": false, + "using": null, + "concurrently": false + }, + { + "message": null, + "name": null, + "table": null, + "include": null, + "prefix": null, + "fields": [ + "description" + ], + "where": null, + "unique": false, + "using": null, + "concurrently": false + }, + { + "message": null, + "name": null, + "table": null, + "include": null, + "prefix": null, + "fields": [ + "inserted_at" + ], + "where": null, + "unique": false, + "using": null, + "concurrently": false + } + ], + "schema": null, + "check_constraints": [], + "multitenancy": { + "global": null, + "attribute": null, + "strategy": null + }, + "base_filter": null, + "custom_statements": [], + "has_create_action": true +} \ No newline at end of file