[2.x] Audit extension 2.x migration, integration split, and GDPR/core coverage#4711
Merged
Conversation
* [1.x] Add first-party Audit extension 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. * Apply fixes from StyleCI * chore: change table name * [1.x] Support PHP 7.3 in Audit extension 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. * [1.x] Register model lifecycle listeners on the events dispatcher 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. * [1.x] Exempt routes from CSRF in tests instead of the token dance 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. * [1.x] Test cache logging via the event, not the cache-clear controller 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. * chore: update extension background color, move away from Clark's brand color * chore: change color again --------- Co-authored-by: StyleCI Bot <bot@styleci.io>
…ut; add gdpr + core event coverage - Port flarum/audit to Flarum 2.x (JSON:API resources, search filters, frontend, PHPUnit 12, code-splitting) - Move first-party audit integrations (approval, flags, lock, nicknames, sticky, suspend, tags) into their own extensions behind Extend\Conditional + optional flarum/audit dependency - Add audit logging to flarum/gdpr for erasure (recording the processor, or system) and export - Add core audit actions: group created/renamed/deleted, developer token created, settings reset - Enrich core Group\Event\Renamed with the previous name
… post (PostgreSQL FK) The seeded discussion pointed first_post_id at a post id that was never created, which PostgreSQL rejects via discussions_first_post_id_foreign during the approve flow (MySQL/SQLite tolerated it). Point it at the seeded post.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR brings the first-party
flarum/auditextension to Flarum 2.x, then builds on it in three ways: it decouples audit from the other first-party extensions, adds audit logging to GDPR, and adds coverage for several core events.It targets
2.xand follows on from #4704 (which added the extension on1.x).1.
flarum/audit2.x migrationPorts the extension to the 2.x APIs:
AuditLogResource(AbstractDatabaseResource) with anIndexendpoint. The list endpoint moves from/api/audit/logsto/api/audit(resource typeaudit).Filterclasses wired throughExtend\SearchDriver; the frontend now translates thekey:valuebrowser syntax into discretefilter[...]params.ext:imports, method-style model,Avatar/Iconcomponents, theExtend.Adminregistry, LESS→CSS variables, and code-splitting (lazy modals).#[Test], model-factory seeding, schema), plus added filter coverage.match, etc.).2. First-party integrations moved into their own extensions
flarum/auditpreviously hardcoded audit logging for seven extensions. Each now owns its integration, registered via the publicFlarum\Audit\Extend\Auditextender behindExtend\Conditional()->whenExtensionEnabled('flarum-audit', …), with an optionalflarum/auditdependency — a no-op when audit isn't installed.Moved: approval, flags, lock, nicknames, sticky, suspend, tags. Action labels travel with each extension (under the
flarum-audit.lib.browser.*namespace), and integration tests live in each extension's suite via a sharedInteractsWithAuditLogtrait.flarum/auditretains only core (non-extension) logging. (lock gained a backend test suite, which it previously lacked.)3. GDPR audit logging
Adds logging for the two privacy-sensitive GDPR operations:
user.gdpr_deleted/user.gdpr_anonymized, recording who processed it (the admin, or system for the scheduled task —actor_idnull). This required a small additive change to gdpr'sErasedevent to carry the originatingErasureRequest.user.gdpr_exported, attributed to the requesting actor.4. New core event coverage
group.created/group.renamed/group.deleteddeveloper_token_created(the raw token value is never logged)settings_resetIncludes one additive core change:
Group\Event\Renamednow carries the previous name (mirroringDiscussion\Event\Renamed), so the rename log can show old → new.Documentation: flarum/docs#535