In a host application, every list screen of some tables showed a red error: "Resource not found POST /qqq/v1/qbit/collaboration/recents (HTTP 404)". The Next UI sends POST /recents with targetType: TABLE on every list screen (and with RECORD on every record screen) whenever the collaboration extension is installed. The person could read those tables: the list under the error was filled.
Core hands a table's custom permission checker the action input and does not say which permission is asked. A checker for a read-only table therefore tells a read from a write by the input's type: a query, a get or a count reads, anything else is refused. An untyped AbstractActionInput is none of those, so the checker refused, canReadTable answered false and TargetResolver.require threw QNotFoundException("Not found"): no recent and no favorite for that table, for anyone.
ParentRecordAccess in this repository already asks the same question with new GetInput(tableName).
Change
canReadTable asks with new QueryInput(table), the read it stands for. One line. Who may read a table does not change: the table's checker still decides, and a person it refuses is still answered "Not found".
Test
RecentsServiceTest.tableWithAnInputTypedPermissionCheckerIsATarget: a table whose checker reads the input's type; a person holding its permission records the table and one of its records as recent and lists both; a person without it is answered "Not found" for both. Before the change it failed on the first call with QNotFoundException: Not found.
./mvnw -B verify on this head: BUILD SUCCESS, 345 tests, 0 failures, 0 errors, 26 skipped (MySqlUploadJournalTest and PostgresUploadJournalTest, which run only with their system property set, as on develop), Checkstyle, the architecture guardrails and the JaCoCo gate passed.
Not in this change
The released line hosts consume is release/1.2 (1.2.0-RC.3). This fix needs a port there to reach an RC.
The UI shows a failed POST /recents as a page-level error although it is a background call nobody asked for; that belongs to the frontend.
## What was seen
In a host application, every list screen of some tables showed a red error: "Resource not found POST /qqq/v1/qbit/collaboration/recents (HTTP 404)". The Next UI sends `POST /recents` with `targetType: TABLE` on every list screen (and with `RECORD` on every record screen) whenever the collaboration extension is installed. The person could read those tables: the list under the error was filled.
## Cause
`TargetResolver.canReadTable` asked `PermissionsHelper.hasTablePermission(new AbstractActionInput(), table, READ)`.
Core hands a table's custom permission checker the action input and does not say which permission is asked. A checker for a read-only table therefore tells a read from a write by the input's type: a query, a get or a count reads, anything else is refused. An untyped `AbstractActionInput` is none of those, so the checker refused, `canReadTable` answered false and `TargetResolver.require` threw `QNotFoundException("Not found")`: no recent and no favorite for that table, for anyone.
`ParentRecordAccess` in this repository already asks the same question with `new GetInput(tableName)`.
## Change
`canReadTable` asks with `new QueryInput(table)`, the read it stands for. One line. Who may read a table does not change: the table's checker still decides, and a person it refuses is still answered "Not found".
## Test
`RecentsServiceTest.tableWithAnInputTypedPermissionCheckerIsATarget`: a table whose checker reads the input's type; a person holding its permission records the table and one of its records as recent and lists both; a person without it is answered "Not found" for both. Before the change it failed on the first call with `QNotFoundException: Not found`.
`./mvnw -B verify` on this head: BUILD SUCCESS, 345 tests, 0 failures, 0 errors, 26 skipped (`MySqlUploadJournalTest` and `PostgresUploadJournalTest`, which run only with their system property set, as on `develop`), Checkstyle, the architecture guardrails and the JaCoCo gate passed.
## Not in this change
- The released line hosts consume is `release/1.2` (1.2.0-RC.3). This fix needs a port there to reach an RC.
- The UI shows a failed `POST /recents` as a page-level error although it is a background call nobody asked for; that belongs to the frontend.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
TargetResolver.canReadTable asked PermissionsHelper.hasTablePermission with a
bare AbstractActionInput. Core hands a table's custom permission checker the
action input and not the permission asked, so a checker that tells a read
from a write by the input's type (a query, a get or a count reads; anything
else is refused) refused the question. For such a table every recents and
favorites call answered "Not found" for people the checker lets read it:
the UI sends POST /recents on every list and record screen, so each of them
showed "Resource not found POST /qqq/v1/qbit/collaboration/recents (HTTP
404)".
The read is now asked with a QueryInput for the table, the read it stands
for; ParentRecordAccess already asks with a GetInput. Who may read a table
does not change: the checker still decides, and a person it refuses is
still answered "Not found" (RecentsServiceTest
.tableWithAnInputTypedPermissionCheckerIsATarget, which failed before with
QNotFoundException on the first call).
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
What was seen
In a host application, every list screen of some tables showed a red error: "Resource not found POST /qqq/v1/qbit/collaboration/recents (HTTP 404)". The Next UI sends
POST /recentswithtargetType: TABLEon every list screen (and withRECORDon every record screen) whenever the collaboration extension is installed. The person could read those tables: the list under the error was filled.Cause
TargetResolver.canReadTableaskedPermissionsHelper.hasTablePermission(new AbstractActionInput(), table, READ).Core hands a table's custom permission checker the action input and does not say which permission is asked. A checker for a read-only table therefore tells a read from a write by the input's type: a query, a get or a count reads, anything else is refused. An untyped
AbstractActionInputis none of those, so the checker refused,canReadTableanswered false andTargetResolver.requirethrewQNotFoundException("Not found"): no recent and no favorite for that table, for anyone.ParentRecordAccessin this repository already asks the same question withnew GetInput(tableName).Change
canReadTableasks withnew QueryInput(table), the read it stands for. One line. Who may read a table does not change: the table's checker still decides, and a person it refuses is still answered "Not found".Test
RecentsServiceTest.tableWithAnInputTypedPermissionCheckerIsATarget: a table whose checker reads the input's type; a person holding its permission records the table and one of its records as recent and lists both; a person without it is answered "Not found" for both. Before the change it failed on the first call withQNotFoundException: Not found../mvnw -B verifyon this head: BUILD SUCCESS, 345 tests, 0 failures, 0 errors, 26 skipped (MySqlUploadJournalTestandPostgresUploadJournalTest, which run only with their system property set, as ondevelop), Checkstyle, the architecture guardrails and the JaCoCo gate passed.Not in this change
release/1.2(1.2.0-RC.3). This fix needs a port there to reach an RC.POST /recentsas a page-level error although it is a background call nobody asked for; that belongs to the frontend.🤖 Generated with Claude Code