Skip to content

Allow punishment-type reads for roles with punishment permissions - #33

Merged
byteful merged 1 commit into
mainfrom
fix/punishment-type-read-permissions
Aug 10, 2026
Merged

Allow punishment-type reads for roles with punishment permissions#33
byteful merged 1 commit into
mainfrom
fix/punishment-type-read-permissions

Conversation

@theobong

@theobong theobong commented Aug 10, 2026

Copy link
Copy Markdown
Member

Problem

The panel player window showed no punishment types for moderator-style roles, making it impossible to apply punishments through the panel. The window fetches types from GET /v1/panel/settings/punishment-types, which was class-gated behind admin.settings.view.punishments — a permission the seeded Moderator role (and custom moderation roles) don't hold. The fetch 403'd, so the window had nothing to render, even though PunishmentLifecycleService.validatePunishmentPermission would have authorized the actual create.

The permission strings themselves were consistent on both sides (punishment.apply.<name>); the read gate was the only break.

Fix

  • New PunishmentTypeAccessPolicy: reads permitted for admin.settings.view.punishments, punishment.view, punishment.modify, or any punishment.apply.* permission; writes still require admin.settings.modify.punishments (mutation behavior unchanged).
  • PanelPunishmentTypeController now uses PanelAccessRule.PUNISHMENT_TYPE_ACCESS.
  • Extracted shared permission-id constants into PermissionService (reused by PlayerAccessPolicy and the new policy).
  • Added a PanelAuthorizationMatrixTest row documenting that punishment.view grants the GET; all pre-existing rows still pass.

Testing

compileJava compileTestJava clean; PanelAuthorizationMatrixTest and role service tests pass.

🤖 Generated with Claude Code

Confidence Score: 4/5

Safe to merge functionally, but the new apply-only moderation access path lacks direct regression coverage.

There is one non-security P2 finding. Under the scoring policy, a review containing only P2 findings receives a score of 4.

Files Needing Attention: src/test/java/gg/modl/backend/infrastructure/filter/PanelAuthorizationMatrixTest.java needs a matrix case for a principal with only punishment.apply..

Fix All in Claude Code

Prompt To Fix All With AI
### Issue 1
src/test/java/gg/modl/backend/infrastructure/filter/PanelAuthorizationMatrixTest.java:101
**Apply-only access remains untested**

The new `Row.playerRead` case grants `punishment.view`, so it never exercises the `hasAnyWithPrefix` branch intended for roles holding only `punishment.apply.<type>`. A regression in that branch would restore the moderator-facing 403 while this authorization matrix continues to pass.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "Allow punishment-type reads for roles wi..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Context used:

  • Context used - Ensure all code meets SOLID, DRY, and KISS softwar... (source)

The panel player window fetches punishment types from
GET /v1/panel/settings/punishment-types, which was gated behind
admin.settings.view.punishments. Moderator-style roles holding only
punishment.view / punishment.apply.* got a 403, leaving the window
empty even though the create endpoint would have authorized them.

Adds PunishmentTypeAccessPolicy: reads permitted for
admin.settings.view.punishments, punishment.view, punishment.modify,
or any punishment.apply.* permission; writes still require
admin.settings.modify.punishments.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Row.permission("POST", "/v1/panel/settings/ai-dismiss-suggestion/t1", "admin.settings.modify.punishments"),
Row.permission("GET", "/v1/panel/settings/punishment-types", "admin.settings.view.punishments"),
Row.permission("POST", "/v1/panel/settings/punishment-types", "admin.settings.modify.punishments"),
Row.playerRead("/v1/panel/settings/punishment-types"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Apply-only access remains untested

The new Row.playerRead case grants punishment.view, so it never exercises the hasAnyWithPrefix branch intended for roles holding only punishment.apply.<type>. A regression in that branch would restore the moderator-facing 403 while this authorization matrix continues to pass.

Context Used: Ensure all code meets SOLID, DRY, and KISS softwar... (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/test/java/gg/modl/backend/infrastructure/filter/PanelAuthorizationMatrixTest.java
Line: 101

Comment:
**Apply-only access remains untested**

The new `Row.playerRead` case grants `punishment.view`, so it never exercises the `hasAnyWithPrefix` branch intended for roles holding only `punishment.apply.<type>`. A regression in that branch would restore the moderator-facing 403 while this authorization matrix continues to pass.

**Context Used:** Ensure all code meets SOLID, DRY, and KISS softwar... ([source](https://app.greptile.com/review/custom-context?memory=instruction-0))

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code

@byteful byteful left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice LLM slop lil bro

@byteful
byteful merged commit ede1926 into main Aug 10, 2026
2 checks passed
@byteful
byteful deleted the fix/punishment-type-read-permissions branch August 10, 2026 23:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants