Skip to content

[1.x] Add first-party Audit extension#4704

Draft
imorland wants to merge 7 commits into
1.xfrom
im/audit-extension
Draft

[1.x] Add first-party Audit extension#4704
imorland wants to merge 7 commits into
1.xfrom
im/audit-extension

Conversation

@imorland

Copy link
Copy Markdown
Member

Adds flarum/audit, a first-party audit log extension, to the monorepo. It records moderation and administration actions and exposes a log browser in both the admin panel and the forum for users with the relevant permissions.

What it logs

Actions are stored in a flarum_audit_log table with the actor, client type, IP address, action string and a JSON payload. Core coverage includes user lifecycle (created, deleted, activated, renamed, email/password/group changes, logins), discussions, posts, settings, permissions, extension enable/disable/uninstall, and cache clears. First-party integrations add coverage for approval, flags, lock, sticky, suspend, nicknames and tags.

Extender API

A public Flarum\Audit\Extend\Audit extender lets any extension declare its own audit integrations — registering action strings, listening to events, and returning a payload to store. Core and first-party integrations use this extender internally. Third-party integrations (FoF, ClarkWinkelmann) are gated behind Extend\Conditional and kept in extend.thirdparty.php, which is excluded from PHPStan since it references packages outside the monorepo.

Search

The browser supports gambits for action, actor, client, discussion, ip and user. Registered gambits and the known action vocabulary are exposed to the frontend (permission-aware) to drive clickable filter chips, a syntax help panel, and autocomplete for action: and client: values.

GeoIP

IP-to-country display is optional and provided through fof/geoip via core's IPAddress component. The extension bundles no geo database and adds no extra runtime dependency for it.

Password reset logging

Password reset requests are logged at the HTTP layer (/api/forgot), capturing the request IP and recording attempts even when the email matches no account. The queued worker continues to log the issued-token event separately.

Upgrade path

The table-creation migration renames an existing kilowhat_audit_log table in place when upgrading from the kilowhat audit extension, preserving existing data and the primary key sequence. Composer replace removes the superseded kilowhat/flarum-ext-audit, -pro and -free packages.

Notes

  • Targets the 1.x branch.
  • js/dist and js/dist-typings are intentionally not committed; they are generated at merge time.
  • Includes unit and integration test suites and a per-extension backend CI workflow.

imorland and others added 2 commits June 11, 2026 14:07
Adds flarum/audit, a first-party audit log extension, to the monorepo.

It records moderation and administration actions (user, discussion, post,
setting, permission, extension lifecycle and cache events) to a
flarum_audit_log table, and exposes a browser in both the admin panel and
the forum for users with the relevant permissions.

Notable points:

- Public Flarum\Audit\Extend\Audit extender lets any extension declare its
  own audit integrations (register actions, listen to events and produce a
  payload). Core and first-party integrations use this extender internally;
  third-party (FoF, ClarkWinkelmann) integrations are gated behind
  Extend\Conditional and isolated in extend.thirdparty.php.
- Search gambits (action, actor, client, discussion, ip, user) with a
  registry exposed to the frontend for clickable filter chips, a syntax help
  panel, and action/client value autocomplete.
- Optional IP-to-country display via fof/geoip through core's IPAddress
  component; no bundled geo database or extra runtime dependency.
- Password reset requests are logged at the HTTP layer (with the request IP),
  including attempts for emails with no matching account.
- Migration renames an existing kilowhat_audit_log table in place when
  upgrading from the kilowhat audit extension; composer replace removes the
  superseded packages.
@imorland imorland added this to the 1.8.17 milestone Jun 11, 2026
imorland added 5 commits June 11, 2026 14:16
Replace arrow functions with closures throughout the extension's extenders
and tests, as arrow functions require PHP 7.4 and the 1.x branch supports
PHP 7.3. Reconcile the audit log table name to audit_log across the console
command and tests to match the migration and model.
The integration classes hooked Eloquent model events via the static
Model::event(Closure) API (User::saving, PasswordToken::created,
Tag::created, etc.). That binds closures to the model classes' static
dispatcher, which cannot be serialized under PHPUnit process isolation on
PHP 7.x, causing "Serialization of 'Closure' is not allowed" errors.

Register the same listeners on the events dispatcher instead, using the
"eloquent.<event>: <Model>" keys those static helpers dispatch under, with
named handler methods rather than closures. Behaviour is unchanged.

The flarum/flags HasMany::macro is left as a closure: it relies on $this
being rebound to the HasMany instance and is registered on the relation
class rather than a model instance.
The integration tests POST to guest routes (register, login, logout,
confirm, reset, forgot, cache clear). The previous GET-token-then-POST
CSRF helper was unreliable in CI. Exempt those routes from CSRF via
Extend\Csrf in the base TestCase, which is the standard approach, and
simplify sendForumCsrfRequest to a plain request.
The /api/cache controller also runs assets:publish, which returns a
non-zero exit code (409) in CI where asset publishing isn't available.
Dispatch the ClearingCache event directly and assert the log entry, which
tests the listener without depending on that environment-specific step.
@imorland

Copy link
Copy Markdown
Member Author

Documentation: flarum/docs#535

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants