🐛 Fixed security action history entries#29012
Conversation
|
| Command | Status | Duration | Result |
|---|---|---|---|
nx run @tryghost/admin-x-settings:test:acceptance |
✅ Succeeded | 9m 56s | View ↗ |
nx run-many --target=build --projects=tag:publi... |
✅ Succeeded | <1s | View ↗ |
nx run ghost:test:ci:integration |
✅ Succeeded | 2m 28s | View ↗ |
nx run-many -t test:unit -p @tryghost/admin-x-f... |
✅ Succeeded | 7m 10s | View ↗ |
nx run ghost:test:integration |
✅ Succeeded | 2m 47s | View ↗ |
nx run @tryghost/admin:build |
✅ Succeeded | 3m 52s | View ↗ |
nx run ghost:test:legacy |
✅ Succeeded | 2m 58s | View ↗ |
nx run ghost:test:e2e |
✅ Succeeded | 2m 26s | View ↗ |
Additional runs (5) |
✅ Succeeded | ... | View ↗ |
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗
☁️ Nx Cloud last updated this comment at 2026-07-01 14:29:55 UTC
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #29012 +/- ##
=======================================
Coverage 74.37% 74.38%
=======================================
Files 1565 1565
Lines 135730 135749 +19
Branches 16501 16509 +8
=======================================
+ Hits 100949 100972 +23
+ Misses 33785 33749 -36
- Partials 996 1028 +32
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
ref #28222 Reset all authentication records audit entries with resource_type=security_action. Those entries are not backed by a Bookshelf model, so including resource in the actions API caused History to fail while eager-loading the polymorphic relation. This keeps the audit resource type intact, teaches the resource relation to accept it, and formats the History label without snake_case.
f52548c to
e42dcda
Compare
WalkthroughThis PR adds support for a new Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (2)
ghost/core/core/server/models/action.js (1)
13-22: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winDocument/enforce the
resource_id === nullinvariant forsecurity_action.Mapping
security_actiontoUseronly avoids the "unknown polymorphic type" error safely becauseresource_idis always null for this type —morphTogroups by stored type and querieswhereIn id [...ids], which yields no match on null, soresourcecorrectly resolves as absent. But if a future code path ever writes a non-nullresource_idforsecurity_action, this mapping would silently fetch and expose an unrelatedUserrecord asresource.Consider adding a comment explaining this constraint, since nothing in the model enforces it.
📝 Suggested comment
resourceCandidates() { const candidates = this.candidates(); const User = ghostBookshelf.registry.models.User; if (User) { + // NOTE: 'security_action' rows always have a null resource_id. + // This candidate exists only so morphTo doesn't throw an + // "unknown polymorphic type" error; it must never resolve to + // an actual User record. candidates.push([User, 'security_action']); } return candidates; },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ghost/core/core/server/models/action.js` around lines 13 - 22, Add an inline comment in action.js around resourceCandidates() explaining that mapping security_action to User is only safe because resource_id must always remain null for this type, and that morphTo would otherwise resolve an unrelated User record if a non-null resource_id were ever persisted. Reference resourceCandidates(), candidates(), and the security_action/User mapping so the invariant is clear for future maintainers.apps/admin-x-framework/test/unit/api/actions.test.ts (1)
24-29: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTest doesn't isolate null resource_id equality.
This case returns
falsepurely due to theresource_typemismatch (security_actionvssetting); it doesn't actually exercise thenull === nullresource_id comparison. Consider adding a positive case where two actions shareresource_id: null, sameresource_type,event, andaction_nameto confirm they do group.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/admin-x-framework/test/unit/api/actions.test.ts` around lines 24 - 29, The current test in actionsAreGroupable only proves different resource_type values do not group, so it never validates null resource_id handling. Update the unit coverage in actions.test.ts by adding a positive case for actions with resource_id: null, matching resource_type, event, and context.action_name so the actionsAreGroupable behavior for null === null is explicitly exercised.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@apps/admin-x-framework/test/unit/api/actions.test.ts`:
- Around line 24-29: The current test in actionsAreGroupable only proves
different resource_type values do not group, so it never validates null
resource_id handling. Update the unit coverage in actions.test.ts by adding a
positive case for actions with resource_id: null, matching resource_type, event,
and context.action_name so the actionsAreGroupable behavior for null === null is
explicitly exercised.
In `@ghost/core/core/server/models/action.js`:
- Around line 13-22: Add an inline comment in action.js around
resourceCandidates() explaining that mapping security_action to User is only
safe because resource_id must always remain null for this type, and that morphTo
would otherwise resolve an unrelated User record if a non-null resource_id were
ever persisted. Reference resourceCandidates(), candidates(), and the
security_action/User mapping so the invariant is clear for future maintainers.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2da01201-66f0-4e6a-8c00-059d77ebd6c7
📒 Files selected for processing (6)
apps/admin-x-framework/src/api/actions.tsapps/admin-x-framework/test/unit/api/actions.test.tsapps/admin-x-settings/src/components/settings/advanced/history-modal.tsxapps/admin-x-settings/test/acceptance/advanced/history.test.tsghost/core/core/server/models/action.jsghost/core/test/e2e-api/admin/actions.test.js

ref #28222
Summary
include=resourceforsecurity_actionaudit rows without throwing Bookshelf's unknown polymorphic type errorsecurity_actionaudit category intact so existing installs are fixed without a data migration(unknown)include=actor,resourcepath and the History display/grouping helpersReview follow-up
Incorporated review-agent findings for the History
: (unknown)fallback and null-resource grouping edge case before internal review.Testing
pnpm --dir ghost/core test:single test/e2e-api/admin/actions.test.jspnpm exec eslint core/server/models/action.js test/e2e-api/admin/actions.test.jsfromghost/corepnpm --filter @tryghost/admin-x-framework test:unit -- test/unit/api/actions.test.tspnpm --filter @tryghost/admin-x-framework lint:codepnpm --filter @tryghost/admin-x-framework lint:testpnpm --filter @tryghost/admin-x-framework test:typespnpm --filter @tryghost/admin-x-settings lintpnpm nx run @tryghost/admin-x-framework:buildpnpm --filter @tryghost/admin-x-settings test:acceptance -- test/acceptance/advanced/history.test.ts