-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
2601 allow non user audit actors #2638
base: main
Are you sure you want to change the base?
Conversation
* Also extra tests to cover changes
@@ -12,7 +12,16 @@ defmodule Lightning.Auditing do | |||
from(a in Audit, | |||
left_join: u in User, | |||
on: [id: a.actor_id], | |||
select_merge: %{actor: u}, | |||
select_merge: %{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The next iteration of this query is likely to be a Union - some experimentation with a union and a select merge that maps to a Struct produced issues. So, for now, I am going with a dumber version that will hopefully be more acceptable once the union is implemented.
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #2638 +/- ##
=======================================
Coverage 90.87% 90.88%
=======================================
Files 320 320
Lines 11257 11252 -5
=======================================
- Hits 10230 10226 -4
+ Misses 1027 1026 -1 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice abstraction Sir @rorymckinley ! Nit picking you again with pipes and I would like to propose keeping the existing virtual actor map unless we are sure that the View is very stable and unlikely to change according to multiple actor types available.
field :actor_display_identifier, :string, virtual: true | ||
field :actor_display_label, :string, virtual: true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Model exists to support some view at least at some point in time (internally or externally) so I guess where you're heading to but we might end up having more flexibility if we keep/preserve the actor map and use the same trick you did but assigning to the virtual map:
import Ecto.Query;
query =
from a in Lightning.Auditing.Audit,
left_join: u in Lightning.Accounts.User,
on: [id: a.actor_id],
select_merge: %{actor: u}
Repo.all(query)
Then whatever change we might have on the View, for any of the three actor types, we wouldn't need to change the model again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jyeshe My initial intent was to retain the actor map, but when I started experimenting with unions, I ran into the following error:
** (Ecto.SubQueryError) the following exception happened when compiling a subquery.
** (Ecto.QueryError) atoms, structs, maps, lists, tuples and sources are not allowed as map values in subquery, got: `%{actor: &1}` in query:
from a0 in Lightning.Auditing.Audit,
prefix: "public",
left_join: u1 in Lightning.Accounts.User,
on: u1.id == a0.actor_id,
where: a0.actor_type == "Lightning.Accounts.User",
union_all: (from a0 in Lightning.Auditing.Audit,
prefix: "public",
left_join: p1 in Lightning.VersionControl.ProjectRepoConnection,
on: p1.id == a0.actor_id,
where: a0.actor_type == "Lightning.VersionControl.ProjectRepoConnection",
select: merge(a0, %{actor: p1})),
select: merge(a0, %{actor: u1})
There are ways to correct this and still retain the actor map but I am not sure that the benefit outweighs the cost currently, as my understanding of the deliverable is that the primary intent is to ensure that the data is captured.
Therefore, my preference is to apply a less elegant and less flexible approach to satisfy the current view requirements so that I can maintain momentum on the capturing of audit events. I am more than willing to revisit this if (a) one of the new events demands it or (b) there is time to do so once the primary objectives have been met.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, in this case I would do just a single query with select: %{audit: a, user: u, trigger: t, provision: p}
It would allow keeping a generic model and use a single select on the SQL side.
To set the actor would be as clean as:
Enum.map(audits, &Map.put(&1.audit, :actor, &1.user || &1.trigger || &1.provision))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But again if we are sure of what we want on the presentation layer, if it's a stable view, I am fine with the only two virtuals.
lib/lightning/auditing/audit.ex
Outdated
@@ -173,7 +178,7 @@ defmodule Lightning.Auditing.Audit do | |||
String.t(), | |||
String.t(), | |||
Ecto.UUID.t(), | |||
Ecto.UUID.t(), | |||
struct(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if there are only 3 types we can enumerate them with a |
:
Lightning.Accounts.User.t() | Lightning.Workflows.Trigger.t() | ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, nice - fixed. Thanks @jyeshe
lib/lightning/auditing/audit.ex
Outdated
changeset( | ||
%__MODULE__{}, | ||
%{ | ||
item_type: item_type, | ||
event: event, | ||
item_id: item_id, | ||
actor_id: actor_id, | ||
actor_type: actor_struct |> extract_actor_type(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well done getting the module type mr Rory, this is nice trick. Please remember that the |>
are for chaining values and not much for simple function calls. Sometimes we do:
socket
|> assign(...)
but there is a purpose of making it easy to add other assigns. If we do piping for all function calls it produces extra work for the compiler on each compilation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @jyeshe - cleaned up.
lib/lightning/auditing/audit.ex
Outdated
struct_name | ||
|> case do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the function call above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks - cleaned up.
@@ -269,10 +269,9 @@ defmodule Lightning.Credentials do | |||
|> Multi.insert( | |||
:audit, | |||
fn %{credential: credential} -> | |||
Audit.event( | |||
Audit.user_initiated_event( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
like
@@ -24,4 +24,10 @@ defmodule Lightning.Credentials.Audit do | |||
changes | |||
end | |||
end | |||
|
|||
def user_initiated_event(event, credential, changes \\ %{}) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
Thanks for the feedback @jyeshe , I have addressed it in two follow-up commits. |
Description
This allows audit events to be created with non-user actors. This is in preparation for the auditing of snapshots, where the actor may be a
ProjectRepoConnection
or aTrigger
.There are a fair number of changes in this PR, but they mostly consist of:
I have tried to group related changes in commits to make reviewing easier.
#2601
Validation steps
As the intent of this change is to have everything remain unchanged, I would suggest the following:
main
make some retention period changes for a project.main
AI Usage
Please disclose how you've used AI in this work (it's cool, we just want to know!):
You can read more details in our Responsible AI Policy
Pre-submission checklist
:owner
,:admin
,:editor
,:viewer
)