diff --git a/lib/mix/tasks/papertrail/install.ex b/lib/mix/tasks/papertrail/install.ex index bc249964..036cdc38 100644 --- a/lib/mix/tasks/papertrail/install.ex +++ b/lib/mix/tasks/papertrail/install.ex @@ -22,7 +22,7 @@ defmodule Mix.Tasks.Papertrail.Install do add :item_type, :string, null: false add :item_id, :integer add :item_changes, :map, null: false - add :setter_id, :integer + add :setter_id, references(:users) # you can change :users to your own foreign key constraint #{set_by_field()} add :meta, :map @@ -41,7 +41,7 @@ defmodule Mix.Tasks.Papertrail.Install do defp set_by_field do case @strict_mode do - true -> "add :set_by, :string, size: 50, null: false, default: 'unknown'" + true -> "add :set_by, :string, size: 50, null: false, default: \"unknown\"" _ -> "add :set_by, :string, size: 50" end end diff --git a/lib/paper_trail.ex b/lib/paper_trail.ex index 2fb5e968..366a2f3b 100644 --- a/lib/paper_trail.ex +++ b/lib/paper_trail.ex @@ -47,7 +47,7 @@ defmodule PaperTrail do @doc """ Inserts a record to the database with a related version insertion in one transaction """ - def insert(changeset, options \\ [set_by: nil, meta: nil]) do + def insert(changeset, options \\ [set_by: nil, meta: nil, setter_id: nil]) do case @client.strict_mode() do true -> transaction = Multi.new @@ -98,7 +98,7 @@ defmodule PaperTrail do @doc """ Updates a record from the database with a related version insertion in one transaction """ - def update(changeset, options \\ [set_by: nil, meta: nil]) do + def update(changeset, options \\ [set_by: nil, meta: nil, setter_id: nil]) do case @client.strict_mode() do true -> transaction = Multi.new @@ -145,7 +145,7 @@ defmodule PaperTrail do @doc """ Deletes a record from the database with a related version insertion in one transaction """ - def delete(struct, options \\ [set_by: nil, meta: nil]) do + def delete(struct, options \\ [set_by: nil, meta: nil, setter_id: nil]) do transaction = Multi.new |> Multi.delete(:model, struct) |> Multi.run(:version, fn %{} -> @@ -167,6 +167,7 @@ defmodule PaperTrail do item_type: model.__struct__ |> Module.split |> List.last, item_id: model.id, item_changes: serialize(model), + setter_id: options[:setter_id], set_by: options[:set_by], meta: options[:meta] } @@ -177,6 +178,7 @@ defmodule PaperTrail do item_type: changeset.data.__struct__ |> Module.split |> List.last, item_id: changeset.data.id, item_changes: changeset.changes, + setter_id: options[:setter_id], set_by: options[:set_by], meta: options[:meta] } @@ -187,6 +189,7 @@ defmodule PaperTrail do item_type: model.__struct__ |> Module.split |> List.last, item_id: model.id, item_changes: serialize(model), + setter_id: options[:setter_id], set_by: options[:set_by], meta: options[:meta] } diff --git a/lib/version.ex b/lib/version.ex index 110bb016..3cb55f26 100644 --- a/lib/version.ex +++ b/lib/version.ex @@ -4,7 +4,7 @@ defmodule PaperTrail.Version do import Ecto.Changeset import Ecto.Query - @setter PaperTrail.OriginatorClient.setter + @setter PaperTrail.RepoClient.setter schema "versions" do field :event, :string @@ -16,7 +16,7 @@ defmodule PaperTrail.Version do field :setter_id, :integer if @setter do - belongs_to @setter[:name], @setter[:model], foreign_key: :originator_id, define_field: false + belongs_to @setter[:name], @setter[:model], define_field: false, foreign_key: :originator_id end timestamps(updated_at: false) diff --git a/priv/repo/migrations/20160619190935_add_users.exs b/priv/repo/migrations/20160619190935_add_users.exs new file mode 100644 index 00000000..db42cc0c --- /dev/null +++ b/priv/repo/migrations/20160619190935_add_users.exs @@ -0,0 +1,14 @@ +defmodule Repo.Migrations.AddVersions do + use Ecto.Migration + + def change do + create table(:users) do + add :token, :string, null: false + add :username, :string, null: false + + timestamps() + end + + create index(:users, [:token]) + end +end diff --git a/priv/repo/migrations/20160619190936_add_versions.exs b/priv/repo/migrations/20160619190936_add_versions.exs index 05270c51..93ed5374 100644 --- a/priv/repo/migrations/20160619190936_add_versions.exs +++ b/priv/repo/migrations/20160619190936_add_versions.exs @@ -7,15 +7,16 @@ defmodule Repo.Migrations.AddVersions do add :item_type, :string, null: false add :item_id, :integer, null: false add :item_changes, :map, null: false - # add :owner_id # in future - add :set_by, :string, size: 50 + add :setter_id, references(:users) # you can change users to your own foreign key constraint + add :set_by, :string, size: 50, read_after_writes: true add :meta, :map add :inserted_at, :utc_datetime, null: false end + create index(:versions, [:setter_id]) create index(:versions, [:item_type, :item_id]) - create index(:versions, [:event, :item_type]) create index(:versions, [:item_type, :inserted_at]) + # create index(:versions, [:event, :item_type]) end end diff --git a/test/paper_trail_strict_mode_test.exs b/test/paper_trail_strict_mode_test.exs index 555028d0..5e13004a 100644 --- a/test/paper_trail_strict_mode_test.exs +++ b/test/paper_trail_strict_mode_test.exs @@ -8,6 +8,8 @@ defmodule PaperTrailStrictModeTest do alias StrictPerson, as: Person @repo PaperTrail.RepoClient.repo + @create_company_params %{name: "Acme LLC", is_active: true, city: "Greenwich"} + @update_company_params %{city: "Hong Kong", website: "http://www.acme.com", facebook: "acme.llc"} doctest PaperTrail @@ -29,7 +31,8 @@ defmodule PaperTrailStrictModeTest do end test "creating a company creates a company version with correct attributes" do - {:ok, result} = create_company_with_version() + user = create_user() + {:ok, result} = create_company_with_version(@create_company_params, setter_id: user.id) company_count = Company.count() version_count = Version.count() @@ -57,6 +60,7 @@ defmodule PaperTrailStrictModeTest do item_type: "StrictCompany", item_id: company.id, item_changes: company, + setter_id: user.id, set_by: nil, meta: nil } @@ -71,8 +75,11 @@ defmodule PaperTrailStrictModeTest do end test "updating a company creates a company version with correct item_changes" do + user = create_user() {:ok, insert_company_result} = create_company_with_version() - {:ok, result} = update_company_with_version(insert_company_result[:model]) + {:ok, result} = update_company_with_version( + insert_company_result[:model], @update_company_params, setter_id: user.id + ) company_count = Company.count() version_count = Version.count() @@ -105,6 +112,7 @@ defmodule PaperTrailStrictModeTest do facebook: "acme.llc", current_version_id: version.id }, + setter_id: user.id, set_by: nil, meta: nil } @@ -125,10 +133,11 @@ defmodule PaperTrailStrictModeTest do end test "deleting a company creates a company version with correct attributes" do + user = create_user() {:ok, insert_company_result} = create_company_with_version() {:ok, update_company_result} = update_company_with_version(insert_company_result[:model]) company_before_deletion = first(Company, :id) |> @repo.one |> serialize - {:ok, result} = PaperTrail.delete(update_company_result[:model]) + {:ok, result} = PaperTrail.delete(update_company_result[:model], setter_id: user.id) company_count = Company.count() version_count = Version.count() @@ -170,6 +179,7 @@ defmodule PaperTrailStrictModeTest do first_version_id: insert_company_result[:version].id, current_version_id: update_company_result[:version].id }, + setter_id: user.id, set_by: nil, meta: nil } @@ -202,7 +212,7 @@ defmodule PaperTrailStrictModeTest do last_name: "Nakri", gender: true, company_id: insert_company_result[:model].id - }) |> PaperTrail.insert(set_by: "admin") + }) |> PaperTrail.insert(set_by: "admin", meta: %{linkname: "izelnakri"}) person_count = Person.count() version_count = Version.count() @@ -228,8 +238,9 @@ defmodule PaperTrailStrictModeTest do item_type: "StrictPerson", item_id: person.id, item_changes: person, + setter_id: nil, set_by: "admin", - meta: nil + meta: %{linkname: "izelnakri"} } assert person == first(Person, :id) |> @repo.one |> serialize end @@ -284,10 +295,9 @@ defmodule PaperTrailStrictModeTest do current_version_id: version.id, company_id: insert_company_result[:model].id }, + setter_id: nil, set_by: "scraper", - meta: %{ - linkname: "izelnakri" - } + meta: %{linkname: "izelnakri"} } assert person == first(Person, :id) |> @repo.one |> serialize end @@ -309,7 +319,9 @@ defmodule PaperTrailStrictModeTest do birthdate: ~D[1992-04-01] }) |> PaperTrail.update(set_by: "scraper", meta: %{linkname: "izelnakri"}) person_before_deletion = first(Person, :id) |> @repo.one |> serialize - {:ok, result} = PaperTrail.delete(update_person_result[:model]) + {:ok, result} = PaperTrail.delete( + update_person_result[:model], set_by: "admin", meta: %{linkname: "izelnakri"} + ) person_count = Person.count() version_count = Version.count() @@ -337,21 +349,22 @@ defmodule PaperTrailStrictModeTest do first_version_id: insert_person_result[:version].id, current_version_id: update_person_result[:version].id }, - set_by: nil, - meta: nil + setter_id: nil, + set_by: "admin", + meta: %{linkname: "izelnakri"} } assert old_person == person_before_deletion end - defp create_company_with_version(params \\ %{ - name: "Acme LLC", is_active: true, city: "Greenwich" - }, options \\ nil) do + defp create_user do + User.changeset(%User{}, %{token: "fake-token", username: "izelnakri"}) |> @repo.insert! + end + + defp create_company_with_version(params \\ @create_company_params, options \\ nil) do Company.changeset(%Company{}, params) |> PaperTrail.insert(options) end - defp update_company_with_version(company, params \\ %{ - city: "Hong Kong", website: "http://www.acme.com", facebook: "acme.llc" - }, options \\ nil) do + defp update_company_with_version(company, params \\ @update_company_params , options \\ nil) do Company.changeset(company, params) |> PaperTrail.update(options) end diff --git a/test/paper_trail_test.exs b/test/paper_trail_test.exs index 32509e06..0b6880f7 100644 --- a/test/paper_trail_test.exs +++ b/test/paper_trail_test.exs @@ -8,6 +8,8 @@ defmodule PaperTrailTest do alias SimplePerson, as: Person @repo PaperTrail.RepoClient.repo + @create_company_params %{name: "Acme LLC", is_active: true, city: "Greenwich"} + @update_company_params %{city: "Hong Kong", website: "http://www.acme.com", facebook: "acme.llc"} doctest PaperTrail @@ -29,7 +31,8 @@ defmodule PaperTrailTest do end test "creating a company creates a company version with correct attributes" do - {:ok, result} = create_company_with_version() + user = create_user() + {:ok, result} = create_company_with_version(@create_company_params, setter_id: user.id) company_count = Company.count() version_count = Version.count() @@ -55,6 +58,7 @@ defmodule PaperTrailTest do item_type: "SimpleCompany", item_id: company.id, item_changes: company, + setter_id: user.id, set_by: nil, meta: nil } @@ -69,8 +73,11 @@ defmodule PaperTrailTest do end test "updating a company creates a company version with correct item_changes" do + user = create_user() {:ok, insert_result} = create_company_with_version() - {:ok, result} = update_company_with_version(insert_result[:model]) + {:ok, result} = update_company_with_version( + insert_result[:model], @update_company_params, setter_id: user.id + ) company_count = Company.count() version_count = Version.count() @@ -96,6 +103,7 @@ defmodule PaperTrailTest do item_type: "SimpleCompany", item_id: company.id, item_changes: %{city: "Hong Kong", website: "http://www.acme.com", facebook: "acme.llc"}, + setter_id: user.id, set_by: nil, meta: nil } @@ -116,10 +124,11 @@ defmodule PaperTrailTest do end test "deleting a company creates a company version with correct attributes" do + user = create_user() {:ok, insert_result} = create_company_with_version() {:ok, update_result} = update_company_with_version(insert_result[:model]) company_before_deletion = first(Company, :id) |> @repo.one |> serialize - {:ok, result} = PaperTrail.delete(update_result[:model]) + {:ok, result} = PaperTrail.delete(update_result[:model], setter_id: user.id) company_count = Company.count() version_count = Version.count() @@ -157,6 +166,7 @@ defmodule PaperTrailTest do twitter: nil, founded_in: nil }, + setter_id: user.id, set_by: nil, meta: nil } @@ -189,7 +199,7 @@ defmodule PaperTrailTest do last_name: "Nakri", gender: true, company_id: new_company_result[:model].id - }) |> PaperTrail.insert(set_by: "admin") + }) |> PaperTrail.insert(set_by: "admin", meta: %{linkname: "izelnakri"}) person_count = Person.count() version_count = Version.count() @@ -213,8 +223,9 @@ defmodule PaperTrailTest do item_type: "SimplePerson", item_id: person.id, item_changes: person, + setter_id: nil, set_by: "admin", - meta: nil + meta: %{linkname: "izelnakri"} } assert person == first(Person, :id) |> @repo.one |> serialize end @@ -266,10 +277,9 @@ defmodule PaperTrailTest do birthdate: elem(Ecto.Date.cast(~D[1992-04-01]), 1), company_id: initial_company_insertion[:model].id }, + setter_id: nil, set_by: "scraper", - meta: %{ - linkname: "izelnakri" - } + meta: %{linkname: "izelnakri"} } assert person == first(Person, :id) |> @repo.one |> serialize end @@ -292,7 +302,9 @@ defmodule PaperTrailTest do company_id: target_company_insertion[:model].id }) |> PaperTrail.update(set_by: "scraper", meta: %{linkname: "izelnakri"}) person_before_deletion = first(Person, :id) |> @repo.one |> serialize - {:ok, result} = PaperTrail.delete(update_result[:model]) + {:ok, result} = PaperTrail.delete( + update_result[:model], set_by: "admin", meta: %{linkname: "izelnakri"} + ) person_count = Person.count() version_count = Version.count() @@ -318,21 +330,22 @@ defmodule PaperTrailTest do birthdate: elem(Ecto.Date.cast(~D[1992-04-01]), 1), company_id: target_company_insertion[:model].id }, - set_by: nil, - meta: nil + setter_id: nil, + set_by: "admin", + meta: %{linkname: "izelnakri"} } assert old_person == person_before_deletion end - defp create_company_with_version(params \\ %{ - name: "Acme LLC", is_active: true, city: "Greenwich" - }, options \\ nil) do + defp create_user do + User.changeset(%User{}, %{token: "fake-token", username: "izelnakri"}) |> @repo.insert! + end + + defp create_company_with_version(params \\ @create_company_params, options \\ nil) do Company.changeset(%Company{}, params) |> PaperTrail.insert(options) end - defp update_company_with_version(company, params \\ %{ - city: "Hong Kong", website: "http://www.acme.com", facebook: "acme.llc" - }, options \\ nil) do + defp update_company_with_version(company, params \\ @update_company_params, options \\ nil) do Company.changeset(company, params) |> PaperTrail.update(options) end diff --git a/test/test_helper.exs b/test/test_helper.exs index ce6eb625..16d97f5b 100644 --- a/test/test_helper.exs +++ b/test/test_helper.exs @@ -4,6 +4,26 @@ defmodule PaperTrail.Repo do use Ecto.Repo, otp_app: :paper_trail end +defmodule User do + use Ecto.Schema + + import Ecto.Changeset + import Ecto.Query + + schema "users" do + field :token, :string + field :username, :string + + timestamps() + end + + def changeset(model, params \\ %{}) do + model + |> cast(params, [:token, :username]) + |> validate_required([:token, :username]) + end +end + Mix.Task.run "ecto.create", ~w(-r PaperTrail.Repo) Mix.Task.run "ecto.migrate", ~w(-r PaperTrail.Repo)