Conversation
dd332da to
5d8c47b
Compare
|
Thanks @raulrpearson , For the Flop lib adoption, I agree that existing admin views (events, users) would benefit from the same approach in the future. Here are some concerns, you already talked about them but I think we have to be strict on security and data integrity. BugsB1.
|
| Item | Location | Note |
|---|---|---|
list_action_types/0 full table scan |
audit.ex:76-83 |
SELECT DISTINCT action will degrade on large tables. Consider caching. |
log_resource_action/5 has no nil-user clause |
audit.ex:49-63 |
Inconsistent with log_action/3 which handles nil users. |
get_log!/1 uses two queries |
audit.ex:99-103 |
Repo.get! + Repo.preload could be a single query. |
| Test coverage gaps | audit_test.exs |
No tests for filtering/pagination params, LiveView rendering, or access control enforcement. |
@impl Phoenix.LiveView vs @impl true |
audit_log_live.ex |
Inconsistent with existing admin LiveViews which use @impl true. |
Dep version pins ~> 0.26.3 |
mix.exs |
More restrictive than typical ~> 0.26 — may miss bugfix releases. |
| Nav active state | admin.html.heex:236 |
Sidebar highlight doesn't persist on /admin/audit_logs/:id (existing pattern). |
SVG icons missing aria-hidden="true" |
icons.ex |
Decorative icons should be hidden from screen readers. |
No on_mount hook for admin live_session |
router.ex |
Existing gap — admin role revocation not enforced on active LiveView sessions. Not new to this PR. |
Verdict
Must fix before merge: B1, B2, S1, S2
Strongly recommended: S3, CB1, I1, UX1, and the Nav active state
Nice to have: Everything else
Finally, the suggested prevent_update_delete() trigger is a good idea. Could be added in a follow-up migration.
|
Thanks, @alxlion, pretty epic review, I like it. I'll work on amendments and ping back for re-review when ready. |
Summary
Audit.Log model
The PR adds a new
Auditcontext,Logschema and associated migration. The model for the new log includes:action: a tag like"user.login","user.logout"or"system.restart". This name was picked to avoid a clash with "event", which we already use for the user generated ones.resource_typeandresource_id: an optional string tag referencing and entity like an event, quiz, etc. and its associated ID. This is implemented like this rather than a foreign key to keep things simple and open, as we're not sure what type of entity "actions" we'll want to track. Let me know if there's some easy way to create some kind of polymorphic association, I don't know how, which is why I'm suggesting a loose string and ID.metadata: the general purpose map/jsonb blob.user: association to user. Nullable in case we want logs not associated to a user (system).updated_at: as this is supposed to be an audit log, I suppose we're not supposed to edit entries, so no update timestamp necessary.If we want to actually enforce no updates or deletes we could do something like this vibecoded snippet:
Flop and Flop Phoenix
I ended up going with Flop for filtering, sorting and pagination because adding filtering and sorting on top of our
Repo.paginate/2was requiring a lot of wiring. I like how it turned out with the URL query string holding the current filtering parameters, so navigation and update is more robust. You can refresh or share the URL with a given query.IMO could be good to rework existing live views with this approach. Right now admin events and users are not paginated, for example. Taking that a step further, is it wise to ever have a context module listing function not be parametrised with filtering, ordering and pagination? We currently have some complexity around this in the
Eventsmodule, for example.Phoenix components
In order to make Flop Phoenix components work out-of-the-box, I copy-pasted (with a couple small tweaks) the
CoreComponentsmodule generated with the latestmix phx.new. This duplicates approaches with our currentClaperWeb.Component.Inputmodule. I'd be inclined to choose getting closer to theCoreComponentsimplementation.I also created an
Iconsmodule just to reuse some SVG markup. I've been meaning to suggest a better alternative using Iconify, but something to discuss in the future, I think.Client IP
The
ClaperWeb.Helpers.ConnUtilsmodule is an AI creation. It gives preference to thex-forwarded-forheader. Do we want to use a more robust approach?Review
Feel free to question any of the choices I made. Available to discuss on a call if you want. The default page size for the logs view is 50. If you want to test pagination, maybe populate the database programmatically or you can add the
default_limit: 5keyword to the Flop segment inClaper.Audit.Logso you don't need as many.