Repository navigation
Description
How to use GitHub
- Please use the 👍 reaction to show that you are affected by the same issue.
- Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
- Subscribe to receive notifications on status change and new comments.
Describe the bug
Users who have read-only access to a board (shared without edit permission) can't see card descriptions in the web UI. The description area stays empty, so checklists in the description are invisible too. Opening a card makes the frontend create a Text session (PUT /apps/text/session/deck_card/{cardId}/create), and that request fails with "Permission denied".
The cause is lib/Provider/TextContextProvider.php:
public function prepareSession(): SessionInfo {
$readonly = !$this->permissionService->checkPermission($this->cardMapper, $this->cardId, Acl::PERMISSION_EDIT, $this->userId);PermissionService::checkPermission() doesn't return false when the permission is missing. It throws NoPermissionException. So $readonly is never true: for every read-only user the exception ends the request, instead of the session being opened read-only. isReadOnly() has the same pattern. main still has this code.
The data itself is readable: the same user gets the full description from GET /index.php/apps/deck/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}, and can read and post comments.
A possible fix is to treat the exception as read-only:
public function prepareSession(): SessionInfo {
return new SessionInfo(
readOnly: $this->isReadOnly(),
lock: null,
canAttachFiles: false,
);
}
public function isReadOnly(): bool {
try {
return !$this->permissionService->checkPermission($this->cardMapper, $this->cardId, Acl::PERMISSION_EDIT, $this->userId);
} catch (NoPermissionException) {
return true;
}
}Users without read access still can't get at the content, because loadContent() goes through CardService::find(), which checks read permission.
I tried this change on the setup below. PUT /apps/text/session/deck_card/{cardId}/create then returns:
| User | Board access | Before | With the change |
|---|---|---|---|
| B | read-only | 500, NoPermissionException |
200, readOnly: true, with the description |
| C | can edit | 200, readOnly: false |
unchanged |
| D | no access | 403 | 403, unchanged |
To Reproduce
Reproduced on a fresh nextcloud:35-apache Docker container (SQLite) with Deck 1.19.2:
- As user A, create a board and a card with a description.
- Share the board with a group that user B is in. Leave "Can edit" unchecked.
- Log in as user B, open the board, and open the card.
- The description is empty.
nextcloud.logshowsOCA\Deck\NoPermissionException: Permission deniedforPUT /apps/text/session/deck_card/{cardId}/create.
Expected behavior
User B sees the description and its checklists read-only. The read-only path looks like it was intended: prepareSession() passes readOnly to SessionInfo.
Screenshots
Not needed: the card opens, but the description area is empty.
Client details:
- OS: any
- Browser: any (the error is server-side)
- Version: -
- Device: desktop
Server details
Operating system: Debian GNU/Linux 13 (trixie), official nextcloud:35-apache Docker image
Web server: Apache 2.4.69
Database: SQLite
PHP version: 8.5.12
Nextcloud version: 35.0.2
Where did you install Nextcloud from: official Docker image (nextcloud:35-apache), Deck installed with occ app:install deck
Signing status:
No errors. Reproduced on unmodified Deck files; only the test of the fix above changed TextContextProvider.php.
List of activated apps:
Stock apps of the nextcloud:35-apache image, plus:
- deck: 1.19.2
Text (shipped): 9.0.1
Nextcloud configuration:
{
"system": {
"htaccess.RewriteBase": "/",
"memcache.local": "\\OC\\Memcache\\APCu",
"apps_paths": [
{ "path": "/var/www/html/apps", "url": "/apps", "writable": false },
{ "path": "/var/www/html/custom_apps", "url": "/custom_apps", "writable": true }
],
"upgrade.disable-web": true,
"passwordsalt": "***REMOVED SENSITIVE VALUE***",
"secret": "***REMOVED SENSITIVE VALUE***",
"trusted_domains": [ "localhost" ],
"datadirectory": "***REMOVED SENSITIVE VALUE***",
"dbtype": "sqlite3",
"version": "35.0.2.2",
"overwrite.cli.url": "http://localhost",
"instanceid": "***REMOVED SENSITIVE VALUE***",
"dbname": "***REMOVED SENSITIVE VALUE***",
"installed": true
}
}
Are you using an external user-backend, if yes which one: no, local users
Logs
Nextcloud log (data/nextcloud.log)
PUT /apps/text/session/deck_card/7876/create | Permission denied
OCA\Deck\NoPermissionException: Permission denied
custom_apps/deck/lib/Provider/TextContextProvider.php:64 OCA\Deck\Service\PermissionService->checkPermission()
apps/text/lib/Service/ApiService.php:71 OCA\Deck\Provider\TextContextProvider->prepareSession()
apps/text/lib/Controller/SessionController.php:71 OCA\Text\Service\ApiService->create()
lib/private/AppFramework/Http/Dispatcher.php:198 OCA\Text\Controller\SessionController->create()
lib/private/AppFramework/Http/Dispatcher.php:86 OC\AppFramework\Http\Dispatcher->executeController()
lib/private/AppFramework/App.php:138 OC\AppFramework\Http\Dispatcher->dispatch()
lib/private/Route/Router.php:324 OC\AppFramework\App::main()
Browser log
PUT /apps/text/session/deck_card/{cardId}/create -> 500 (read-only user)
Activity
blizzz commentedon Nov 13, 2026
Fix in #8739