Skip to content

feat(permissions): Split chat and reaction permissions#16835

Closed
luflow wants to merge 23 commits intonextcloud:mainfrom
luflow:feat/split-chat-react-permissions
Closed

feat(permissions): Split chat and reaction permissions#16835
luflow wants to merge 23 commits intonextcloud:mainfrom
luflow:feat/split-chat-react-permissions

Conversation

@luflow
Copy link
Contributor

@luflow luflow commented Jan 23, 2026

☑️ Resolves

Summary

This PR separates the combined "chat" permission into two distinct permissions:

  • PERMISSIONS_CHAT (128): For posting messages
  • PERMISSIONS_REACT (256): For adding/removing reactions

This allows admins to create "announcement channels" where only moderators can post messages, but all users can still react to those messages.

Backend Changes

  • Added PERMISSIONS_REACT = 256 constant to Attendee model
  • Added REACT permission attribute in RequirePermission
  • Added REACT permission check in InjectionMiddleware
  • Updated ReactionController to use REACT permission instead of CHAT
  • Added database migration to grant REACT permission to all users who have CHAT permission
  • Fixed hardcoded 255 validation in RoomService to use PERMISSIONS_MAX_CUSTOM

Frontend Changes

  • Added REACT: 256 constant to constants.ts
  • Updated MAX_DEFAULT to 510 and MAX_CUSTOM to 511
  • Split PermissionsEditor checkbox "Can post messages and reactions" into two separate checkboxes:
    • "Can post messages" (CHAT)
    • "Can add reactions" (REACT)
  • Updated MessageItem.vue to check REACT permission for canReact

Migration Strategy

The migration ensures backward compatibility:

  • All existing records with CHAT (128) permission automatically get REACT (256) added
  • Old clients continue to work because they ignore unknown permission bits
  • No frontend fallbacks needed - the UI will work correctly after data migration

🖌️ UI Checklist

🖼️ Screenshots / Screencasts

🏚️ Before 🏡 After
Bildschirmfoto 2026-01-24 um 00 56 34 Bildschirmfoto 2026-01-24 um 00 53 41

🚧 Tasks

  • Frontend constants updated
  • Frontend UI split into two checkboxes

🏁 Checklist

  • 🌏 Tested with different browsers / clients:
    • Chromium (Chrome / Edge / Opera / Brave)
    • Firefox
    • Safari
    • Talk Desktop
    • Integrations with Files sidebar and other apps
    • Not risky to browser differences / client
  • 🖌️ Design was reviewed, approved or inspired by the design team
  • ⛑️ Tests are included or not possible
  • 📗 User documentation in https://github.com/nextcloud/documentation/tree/master/user_manual/talk has been updated or is not required

🛠️ API Checklist

🚧 Tasks

  • Backend permission constant added
  • Backend permission check implemented
  • New permission constant PERMISSIONS_REACT = 256 added
  • Migration preserves backward compatibility
  • Database migration for existing data
  • Integration tests updated

🏁 Checklist

  • ⛑️ Tests (unit and/or integration) are included or not possible
  • 📘 API documentation in docs/ has been updated or is not required
  • 🔖 Capability is added or not needed

@luflow luflow force-pushed the feat/split-chat-react-permissions branch from 7f4febd to bab47a8 Compare January 23, 2026 23:41
luflow added a commit to luflow/talk-android that referenced this pull request Jan 24, 2026
Adds compatibility with nextcloud/spreed#16835 which splits the combined
CHAT permission into separate CHAT (128) and REACT (256) permissions.

This enables "announcement channels" where only moderators can post
messages, but all users can still react.

Changes:
- Add REACT (256) permission constant to ParticipantPermissions
- Add hasReactPermission() method with backward compatibility fallback
- Update MessageActionsDialog to use react permission for emoji bar
- Add permission check in onClickReaction() for toggling reactions
- Add unit tests for new permission handling

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
Copy link
Member

@nickvergessen nickvergessen left a comment

Choose a reason for hiding this comment

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

Thanks a lot, looks pretty good.

@nickvergessen nickvergessen added this to the 🏖️ Next Major (34) milestone Jan 26, 2026
@nickvergessen nickvergessen added 2. developing enhancement feature: chat 💬 Chat and system messages feature: api 🛠️ OCS API for conversations, chats and participants feature: frontend 🖌️ "Web UI" client feature: reactions 👍 labels Jan 26, 2026
@nickvergessen

This comment was marked as resolved.

@nickvergessen

This comment was marked as resolved.

@nickvergessen
Copy link
Member

The sharing tests are unrelated and on my todo

@luflow
Copy link
Contributor Author

luflow commented Jan 26, 2026

We should add an entry to the capabilities, so clients know when to show the new permission and send it to the backend, as well as which permission should be checked when showing the reactions action.

@nickvergessen I was already wondering how we handle this breaking change - capabilities is a good solution for that :) was already tinkering with version numbers… which felt wrong.

what name would you suggest? Something like „react-permission“?

Will create/edit PRs in Android, iOS, desktop clients accordingly.

@nickvergessen
Copy link
Member

what name would you suggest? Something like „react-permission“?

Sounds good

Will create/edit PRs in Android, iOS, desktop clients accordingly.

If you can that's cool, otherwise we raise an issue on the platform.
Desktop is not needed, as it reuses the web frontend from this repo's src/ folder

@luflow luflow force-pushed the feat/split-chat-react-permissions branch from 554fd71 to 3d6d4d2 Compare January 26, 2026 12:09
@luflow

This comment was marked as resolved.

luflow added a commit to luflow/talk-android that referenced this pull request Jan 26, 2026
Adds compatibility with nextcloud/spreed#16835 which splits the combined
CHAT permission into separate CHAT (128) and REACT (256) permissions.

This enables "announcement channels" where only moderators can post
messages, but all users can still react.

Changes:
- Add REACT (256) permission constant to ParticipantPermissions
- Add hasReactPermission() method with backward compatibility fallback
- Update MessageActionsDialog to use react permission for emoji bar
- Add permission check in onClickReaction() for toggling reactions
- Add unit tests for new permission handling

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
@nickvergessen

This comment was marked as resolved.

@luflow

This comment was marked as resolved.

@nickvergessen

This comment was marked as resolved.

@nickvergessen
Copy link
Member

  • features/federation/permissions.feature:14 seems to have an error when testing against 32
  • But we can ignore this for now, I will try to find a way to solve this.

luflow and others added 6 commits January 27, 2026 13:49
This change separates the combined "chat" permission into two distinct permissions:
- PERMISSIONS_CHAT (128): For posting messages
- PERMISSIONS_REACT (256): For adding/removing reactions

This allows admins to create "announcement channels" where only moderators
can post messages, but all users can still react to those messages.

Backend changes:
- Added PERMISSIONS_REACT constant to Attendee model
- Added REACT permission check in InjectionMiddleware
- Updated ReactionController to use REACT permission instead of CHAT
- Added database migration to grant REACT permission to users with CHAT
- Fixed hardcoded 255 validation in RoomService

Frontend changes:
- Added REACT constant to constants.ts
- Split PermissionsEditor into two separate checkboxes
- Updated MessageItem to check REACT permission for canReact

Resolves: nextcloud#11329
Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
Co-authored-by: Joas Schilling <213943+nickvergessen@users.noreply.github.com>
Signed-off-by: Florian Ludwig <florian@krautnerds.de>
Add 'react-permission' to the FEATURES array and document
it in capabilities.md for Talk 24.

This allows clients to detect when the server supports the
separate REACT permission (256) for adding reactions.

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
Check for 'react-permission' capability and fall back to CHAT
permission when federating with older servers that don't support
the separate REACT permission.

Also adds 'react-permission' to mocked capabilities for tests.

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
Update expected participantPermissions from 254 to 510 to reflect
the new MAX_DEFAULT value that includes the REACT permission (256).

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
@luflow

This comment was marked as resolved.

@luflow
Copy link
Contributor Author

luflow commented Jan 28, 2026

@Antreesy found the error - don't know why it worked before in my tests, but the annotations and openai yamls were still having the old limits, thats why the middleware threw a 400 error

Not it works flawlessly. I also fixed the already existing bug that the action menu (send later, etc) and voice button were not disabled when permission "chat" was not given. Now the whole buttons and input row is correctly disabled.

The "react only" also works without issues :)

If there is already a reaction though and you click without permission on the button, the warning "reactions are not permitted" is still shown. I think thats ok? Otherwise we have to make the reactions there also "read only" - I think though its a good ux to have feedback there, when you are normally used to be able to react. Then its actionable for you "aaah, I dont have permission here, good to know"

The OpenAPI schema was validating permissions input against the old
maximum value of 255, which blocked setting the new REACT permission
(256). Updated annotations and schema to allow values up to 511
(PERMISSIONS_MAX_CUSTOM).

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
…lowed

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
Button was showing a color change on click even though button was disabled. Action Buttons (attachments + voice recording) did not have this weird behavior when disabled. Might be actually a bug in the vue components - hotfixed via :deep selector

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
@luflow luflow force-pushed the feat/split-chat-react-permissions branch from ef719f7 to bb7dc24 Compare January 28, 2026 21:34
Signed-off-by: Florian Ludwig <florian@krautnerds.de>
Copy link
Contributor

@Antreesy Antreesy left a comment

Choose a reason for hiding this comment

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

Otherwise good from my side!

Copy link
Member

@nickvergessen nickvergessen left a comment

Choose a reason for hiding this comment

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

Fine for now, but we need a follow up.


Follow up:

  • Permission check in middleware does not account for federation
  • Your instance is 34 but the host is 33
    • On update of your instance your permissions expend to add reaction permission
    • If the host changes your permission still on 33, it does not know reaction permission and will make you set your permissiions without reaction
    • Options:
      • 🐌 check in middleware if the server knows the permission via capability (very bad performance wise)
      • Do math when getting permissions update and check capabilities there (still not good, but less often)
      • Add the list of known permissions (max_custom number would be enough) to the request, so the instance can judge from there if it contains all numbers or needs to do some healing
  • Host updates from 33 to 34 after you
    • We should let instances know that the users permissions got modified, but doing that in the migration might not work:
      • Server could be "not reachable" so requests could fail, etc
      • Sending many requests during the update is also not good
      • Next join of the participant should be good enough (we just need to make sure to track and notice the changed permission and store it locally?)
  • Host updates from 33 to 34 before you
    • Currently the migration would simply change your permissions to now include the reaction permission
    • But what if the moderator took that away from you already?
    • Same as above we can/should heal the permissions when joining the room, that is most likely the most important moment and good enough

Then user "participant3" is participant of room "LOCAL::room" (v4)
| permissions | attendeePermissions |
| SJAVPM | D |
| SJAVPMR | D |
Copy link
Member

Choose a reason for hiding this comment

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

Can you add @skip33 to the test for now, similarly


That should allow CI to pass in the federation case against an older version for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

luflow and others added 4 commits January 29, 2026 12:35
- Remove disabled button CSS hotfixes (to be fixed upstream)
- Fix chatReactions logic to only set when capability exists

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
- lastMessage is used later to updated LeftSidebar with subline and unread counter
- lastMessage should only be of a list of rendered messages for that list
- this doesn't include hidden system messages like reactions

Signed-off-by: Maksim Sukharev <antreesy.web@gmail.com>
Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
Signed-off-by: Nextcloud bot <bot@nextcloud.com>
Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
Add the reactions to the original message for now,
so that when it's relayed, it shows the reaction already.
However, if we fix the sending order and the "reaction"
message is relayed after the message, a client would add
the reaction again showing 2 reactions while there is only one.
So in case we change that, we need to rever this here.

Signed-off-by: Joas Schilling <coding@schilljs.com>
Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
@luflow luflow force-pushed the feat/split-chat-react-permissions branch from da721cb to 944549f Compare January 29, 2026 11:36
Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
The new permissions config section was added but the OpenAPI specs
weren't regenerated and the PHP unit tests weren't updated with
the expected permissions values.

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
@luflow
Copy link
Contributor Author

luflow commented Jan 29, 2026

@nickvergessen open-api regenerate did not run correctly locally, now fixed! Also eslint was failing because of this. I hope now the important things are green ^^

@nickvergessen
Copy link
Member

I added you to our org and would create a guest account for you on our instance to improve the communication options. If you don't mind, send me the email address we should invite to <my github username>@nextcloud.com

The testCapabilitiesDocumentation test iterates over all config
sections from OpenAPI and checks LOCAL_CONFIGS for each. The new
permissions section was missing, causing a TypeError.

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
@luflow
Copy link
Contributor Author

luflow commented Jan 29, 2026

I added you to our org and would create a guest account for you on our instance to improve the communication options. If you don't mind, send me the email address we should invite to <my github username>@nextcloud.com

Sounds good :) Done.

@nickvergessen
Copy link
Member

I sent an invite, in case you didnt get the email, simply try a password reset on cloud.nextcloud.com with the email you sent me

@nickvergessen
Copy link
Member

Follow up moved to #16902

Since permissions has no local (user-specific) configs, its LOCAL_CONFIGS
entry is an empty array. The type must allow list<string> instead of
non-empty-list<string> to accommodate this.

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
The change from non-empty-list<string> to list<string> in
ResponseDefinitions requires removing minItems: 1 from the
config-local arrays in the OpenAPI specs.

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
@luflow
Copy link
Contributor Author

luflow commented Jan 30, 2026

Work continues in #16920

@luflow luflow closed this Jan 30, 2026
luflow added a commit to luflow/talk-android that referenced this pull request Jan 31, 2026
Adds compatibility with nextcloud/spreed#16835 which splits the combined
CHAT permission into separate CHAT (128) and REACT (256) permissions.

This enables "announcement channels" where only moderators can post
messages, but all users can still react.

Changes:
- Add REACT (256) permission constant to ParticipantPermissions
- Add hasReactPermission() method with backward compatibility fallback
- Update MessageActionsDialog to use react permission for emoji bar
- Add permission check in onClickReaction() for toggling reactions
- Add unit tests for new permission handling

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
luflow added a commit to luflow/talk-android that referenced this pull request Feb 4, 2026
Adds compatibility with nextcloud/spreed#16835 which splits the combined
CHAT permission into separate CHAT (128) and REACT (256) permissions.

This enables "announcement channels" where only moderators can post
messages, but all users can still react.

Changes:
- Add REACT (256) permission constant to ParticipantPermissions
- Add hasReactPermission() method with backward compatibility fallback
- Update MessageActionsDialog to use react permission for emoji bar
- Add permission check in onClickReaction() for toggling reactions
- Add unit tests for new permission handling

Signed-off-by: Florian Ludwig <florian.ludwig@uninow.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement feature: api 🛠️ OCS API for conversations, chats and participants feature: chat 💬 Chat and system messages feature: frontend 🖌️ "Web UI" client feature: reactions 👍

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Split "can post messages and reaction permissions"

4 participants