Skip to content

Commit

Permalink
Add audit log
Browse files Browse the repository at this point in the history
  • Loading branch information
tspenov committed Oct 30, 2024
1 parent 4405447 commit c217fb6
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 1 deletion.
8 changes: 8 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,14 @@ config :nostrum,
:message_content
]

config :ex_audit,
ecto_repos: [Sanbase.Repo],
version_schema: Sanbase.Version,
tracked_schemas: [
Sanbase.Accounts.User
],
primitive_structs: [DateTime, NaiveDateTime, Date]

# Import configs
import_config "ueberauth_config.exs"
import_config "scrapers_config.exs"
Expand Down
1 change: 1 addition & 0 deletions lib/sanbase/repo.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule Sanbase.Repo do
use Ecto.Repo, otp_app: :sanbase, adapter: Ecto.Adapters.Postgres
use ExAudit.Repo

alias Sanbase.Utils.Config

Expand Down
34 changes: 34 additions & 0 deletions lib/sanbase/version.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
defmodule Sanbase.Version do
use Ecto.Schema
import Ecto.Changeset

schema "versions" do
# The patch in Erlang External Term Format
field(:patch, ExAudit.Type.Patch)

# supports UUID and other types as well
field(:entity_id, :integer)

# name of the table the entity is in
field(:entity_schema, ExAudit.Type.Schema)

# type of the action that has happened to the entity (created, updated, deleted)
field(:action, ExAudit.Type.Action)

# when has this happened
field(:recorded_at, :utc_datetime)

# was this change part of a rollback?
field(:rollback, :boolean, default: false)

# custom fields
belongs_to(:user, Sanbase.Accounts.User)
end

def changeset(struct, params \\ %{}) do
struct
|> cast(params, [:patch, :entity_id, :entity_schema, :action, :recorded_at, :rollback])
# custom fields
|> cast(params, [:user_id])
end
end
47 changes: 47 additions & 0 deletions lib/sanbase_web/generic_admin/version.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
defmodule SanbaseWeb.GenericAdmin.Version do
import Ecto.Query
def schema_module, do: Sanbase.Version

def resource() do
%{
actions: [:show],
preloads: [:user],
index_fields: [
:id,
:entity_id,
:entity_schema,
:action,
:recorded_at,
:rollback
],
fields_override: %{
patch: %{
value_modifier: &format_patch/1
}
}
}
end

defp format_patch(%{patch: patch}) when is_map(patch) do
patch
|> Enum.map_join("\n", fn {field, change} ->
format_change(field, change)
end)
end

defp format_patch(_), do: ""

defp format_change(field, {:changed, {:primitive_change, old_val, new_val}}) do
"#{field}: #{inspect(old_val)}#{inspect(new_val)}"
end

defp format_change(field, {:changed, nested}) when is_map(nested) do
nested_changes =
nested
|> Enum.map_join(", ", fn {k, v} -> format_change(k, v) end)

"#{field}: {#{nested_changes}}"
end

defp format_change(field, other), do: "#{field}: #{inspect(other)}"
end
3 changes: 2 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ defmodule Sanbase.Mixfile do
{:vex, "~> 0.9", override: true},
{:waffle, "~> 1.1"},
{:websockex, "~> 0.4.3"},
{:mox, "~> 1.2"}
{:mox, "~> 1.2"},
{:ex_audit, "~> 0.10.0"}
]
end

Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"ethereumex": {:hex, :ethereumex, "0.10.6", "6d75cac39b5b7a720b064fe48563f205d3d9784e5bde25f983dd07cf306c2a6d", [:make, :mix], [{:finch, "~> 0.16", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "58cf926239dabf8bd1fc6cf50a37b926274240b7f58ba5b235a20b5500a9a7e1"},
"event_bus": {:hex, :event_bus, "1.7.0", "29a36fc09e8c4463c82206b6a300fa1d61cf4baf9a7b4e7cf0c3efb99c73998e", [:mix], [], "hexpm", "e556470f49f53060a0696c4bad81341252685011afc69eda25032c8a3a86eb2e"},
"ex_abi": {:hex, :ex_abi, "0.8.0", "bb08827bd8d71dbb311c69ac55a008669dfabe2ce5b58d65f97c08c0aba60ec6", [:mix], [{:ex_keccak, "~> 0.7.5", [hex: :ex_keccak, repo: "hexpm", optional: true]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "bbdae12c186aeeb4c53dd7c7c57f457923602db315aa1f66d7427467c8ad77af"},
"ex_audit": {:hex, :ex_audit, "0.10.0", "98625c2c3a54950cac85eb1f69caa919638c68fb65f8d4951d3d145ab52782e4", [:mix], [{:ecto, ">= 3.8.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:ecto_sql, ">= 3.8.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}], "hexpm", "9ec37f6a9ed986aea37eb311e1dd0b0c9dd855f0dd9a107837276db864e4c69b"},
"ex_aws": {:hex, :ex_aws, "2.5.4", "86c5bb870a49e0ab6f5aa5dd58cf505f09d2624ebe17530db3c1b61c88a673af", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8 or ~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e82bd0091bb9a5bb190139599f922ff3fc7aebcca4374d65c99c4e23aa6d1625"},
"ex_aws_s3": {:hex, :ex_aws_s3, "2.5.3", "422468e5c3e1a4da5298e66c3468b465cfd354b842e512cb1f6fbbe4e2f5bdaf", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "4f09dd372cc386550e484808c5ac5027766c8d0cd8271ccc578b82ee6ef4f3b8"},
"ex_json_schema": {:hex, :ex_json_schema, "0.10.2", "7c4b8c1481fdeb1741e2ce66223976edfb9bccebc8014f6aec35d4efe964fb71", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "37f43be60f8407659d4d0155a7e45e7f406dab1f827051d3d35858a709baf6a6"},
Expand Down
32 changes: 32 additions & 0 deletions priv/repo/migrations/20241030141825_add_ex_audit_versions.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule Sanbase.Repo.Migrations.AddExAuditVersions do
use Ecto.Migration

def change do
create table(:versions) do
# The patch in Erlang External Term Format
add(:patch, :binary)

# supports UUID and other types as well
add(:entity_id, :integer)

# name of the table the entity is in
add(:entity_schema, :string)

# type of the action that has happened to the entity (created, updated, deleted)
add(:action, :string)

# when has this happened
add(:recorded_at, :utc_datetime)

# was this change part of a rollback?
add(:rollback, :boolean, default: false)

# optional fields that you can define yourself
# for example, it's a good idea to track who did the change
add(:user_id, references(:users, on_update: :update_all, on_delete: :nilify_all))
end

# create this if you are going to have more than a hundred of thousands of versions
create(index(:versions, [:entity_schema, :entity_id]))
end
end
66 changes: 66 additions & 0 deletions priv/repo/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4528,6 +4528,41 @@ CREATE SEQUENCE public.users_id_seq
ALTER SEQUENCE public.users_id_seq OWNED BY public.users.id;


--
-- Name: versions; Type: TABLE; Schema: public; Owner: -
--

CREATE TABLE public.versions (
id bigint NOT NULL,
patch bytea,
entity_id integer,
entity_schema character varying(255),
action character varying(255),
recorded_at timestamp(0) without time zone,
rollback boolean DEFAULT false,
user_id bigint
);


--
-- Name: versions_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--

CREATE SEQUENCE public.versions_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;


--
-- Name: versions_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
--

ALTER SEQUENCE public.versions_id_seq OWNED BY public.versions.id;


--
-- Name: votes_id_seq; Type: SEQUENCE; Schema: public; Owner: -
--
Expand Down Expand Up @@ -5589,6 +5624,13 @@ ALTER TABLE ONLY public.user_uniswap_staking ALTER COLUMN id SET DEFAULT nextval
ALTER TABLE ONLY public.users ALTER COLUMN id SET DEFAULT nextval('public.users_id_seq'::regclass);


--
-- Name: versions id; Type: DEFAULT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.versions ALTER COLUMN id SET DEFAULT nextval('public.versions_id_seq'::regclass);


--
-- Name: votes id; Type: DEFAULT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -6620,6 +6662,14 @@ ALTER TABLE ONLY public.users
ADD CONSTRAINT users_pkey PRIMARY KEY (id);


--
-- Name: versions versions_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.versions
ADD CONSTRAINT versions_pkey PRIMARY KEY (id);


--
-- Name: votes votes_pkey; Type: CONSTRAINT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -7708,6 +7758,13 @@ CREATE UNIQUE INDEX users_twitter_id_index ON public.users USING btree (twitter_
CREATE UNIQUE INDEX users_username_index ON public.users USING btree (username);


--
-- Name: versions_entity_schema_entity_id_index; Type: INDEX; Schema: public; Owner: -
--

CREATE INDEX versions_entity_schema_entity_id_index ON public.versions USING btree (entity_schema, entity_id);


--
-- Name: votes_chart_configuration_id_user_id_index; Type: INDEX; Schema: public; Owner: -
--
Expand Down Expand Up @@ -8918,6 +8975,14 @@ ALTER TABLE ONLY public.user_uniswap_staking
ADD CONSTRAINT user_uniswap_staking_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON DELETE CASCADE;


--
-- Name: versions versions_user_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--

ALTER TABLE ONLY public.versions
ADD CONSTRAINT versions_user_id_fkey FOREIGN KEY (user_id) REFERENCES public.users(id) ON UPDATE CASCADE ON DELETE SET NULL;


--
-- Name: votes votes_chart_configuration_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
--
Expand Down Expand Up @@ -9539,3 +9604,4 @@ INSERT INTO public."schema_migrations" (version) VALUES (20241018075640);
INSERT INTO public."schema_migrations" (version) VALUES (20241029080754);
INSERT INTO public."schema_migrations" (version) VALUES (20241029082533);
INSERT INTO public."schema_migrations" (version) VALUES (20241029151959);
INSERT INTO public."schema_migrations" (version) VALUES (20241030141825);

0 comments on commit c217fb6

Please sign in to comment.