-
Notifications
You must be signed in to change notification settings - Fork 13k
feat: Added pending invitation state to rooms #37612
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
Looks like this PR is ready to merge! 🎉 |
🦋 Changeset detectedLatest commit: e4a3790 The changes in this PR will be included in the next version bump. This PR includes changesets to release 42 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Caution Review failedThe pull request is closed. WalkthroughThis pull request introduces invitation request support for federated rooms. It adds client-side UI components for displaying and responding to room invitations (RoomInviteHeader, RoomInviteBody), a hook for handling invitation accept/reject actions, type guards for detecting invite subscriptions, server-side authorization validation, and supporting infrastructure including query keys, i18n strings, and comprehensive test coverage. Changes
Sequence DiagramsequenceDiagram
actor User
participant Room View as Room View<br/>(Room.tsx)
participant Subscription as RoomContext<br/>(useRoomSubscription)
participant Invite UI as RoomInvite<br/>Component
participant Mutation as Invitation Mutation<br/>(useRoomInvitation)
participant Server as Server<br/>/v1/rooms.invite
participant Query as Query Client<br/>(React Query)
participant Router as Router
User->>Room View: Load invited room
Room View->>Subscription: Check subscription status
Subscription-->>Room View: subscription with status='INVITED'
alt Invite Subscription Detected
Room View->>Invite UI: Render RoomInvite early return
Invite UI-->>User: Display inviter info + Accept/Reject
User->>Invite UI: Click Accept/Reject
Invite UI->>Mutation: Call acceptInvite/rejectInvite
Mutation->>Server: POST /v1/rooms.invite {action}
Server-->>Mutation: Success
Mutation->>Query: Invalidate & refetch room query
Query-->>Mutation: Resolved
alt Action = 'reject'
Mutation->>Router: Navigate to /home
Router-->>User: Redirect
else Action = 'accept'
Mutation-->>User: Room ready (normal view)
end
else Regular Room
Room View->>Room View: Continue normal rendering
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~35 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro Disabled knowledge base sources:
⛔ Files ignored due to path filters (3)
📒 Files selected for processing (18)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (9)
apps/meteor/client/views/room/hooks/useOpenRoom.ts (1)
27-27: LGTM: Good refactoring to use centralized query key helper.Replacing the inline query key construction with
roomsQueryKeys.roomReferenceimproves maintainability and ensures consistency across the codebase.apps/meteor/client/views/room/body/RoomInviteBody.spec.tsx (1)
1-52: Good coverage; consider adding a loading-state interaction testThe suite nicely covers snapshots, a11y, and basic Accept/Reject interactions. Since
RoomInviteBodyexposes anisLoadingprop that changes button behavior, consider adding a test that renders withisLoadingset, asserts the buttons are disabled/“loading”, and verifies clicks don’t trigger handlers. This would lock in the async/pending UX.packages/core-typings/src/ISubscription.ts (1)
10-93: Invite type guard looks correct; consider tightening inviter typing if possible
isInviteSubscriptioncorrectly narrows tostatus: 'INVITED'and is a good fit for the new invite header logic.If the backend guarantees that invite subscriptions always include a non-empty
inviterUsername, you might consider encoding that in the guard:export const isInviteSubscription = ( subscription: ISubscription | undefined | null, ): subscription is ISubscription & { status: 'INVITED'; inviterUsername: string } => subscription?.status === 'INVITED' && !!subscription.inviterUsername;That would let downstream code treat
inviterUsernameas required whenever the guard passes.apps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsx (1)
1-42: Optionally assert toolbox absence for invite scenariosSnapshots + a11y checks are solid. Given the main behavioral guarantee of
RoomInviteHeaderis “header without toolbox for invite rooms”, you might add a focused test (e.g., on the primary story) that assertsqueryByLabelText('Toolbox_room_actions')returns null. That would more directly pin the invite-specific behavior instead of relying solely on underlyingRoomHeadertests.apps/meteor/client/views/room/HeaderV2/RoomHeader.tsx (1)
17-68: ClarifyroomToolboxnull semantics in the render conditionThe toolbox conditional
{(slots.toolbox || roomToolbox !== null) && ( ... {slots?.toolbox?.content || roomToolbox || <RoomToolbox />} )}means the toolbar is rendered whenever
slots.toolboxis truthy orroomToolboxis anything exceptnull(includingundefined), and only hidden whenroomToolbox === nulland there’s noslots.toolbox. That matches the current tests but is a bit non-obvious at a glance.For readability, consider extracting a named boolean, e.g.:
const shouldRenderToolbox = Boolean(slots.toolbox) || roomToolbox !== null; {shouldRenderToolbox && ( ... )}or documenting via prop naming/typing that “
nullexplicitly disables the toolbox,undefinedkeeps the default toolbox”.packages/i18n/src/locales/en.i18n.json (1)
3453-3453: Title casing recommended for the "Message_request" string used in heading context.The string is rendered within a
<StatesTitle>component in RoomInviteBody.tsx (line 19), which displays it as an<h3>heading. While the current sentence casing ("Message request") matches the predominant pattern in this section of the i18n file, title casing ("Message Request") would provide better UI consistency for heading text. The suggestion is valid and worth addressing.apps/meteor/client/views/room/RoomInvite.tsx (1)
9-9: Useimport typefor type-only imports.
IRoomWithFederationOriginalNameis only used as a type, so it should use a type-only import for consistency and to avoid potential bundling issues.-import { IRoomWithFederationOriginalName } from './contexts/RoomContext'; +import type { IRoomWithFederationOriginalName } from './contexts/RoomContext';apps/meteor/client/lib/queryKeys.ts (1)
16-20: Addas constfor type consistency with other query keys.Other key generators in this file use
as constto ensure readonly tuple typing. Adding it here maintains consistency and provides better type inference.roomReference: (reference: string, type: RoomType, uid?: IUser['_id'], username?: IUser['username']) => [ ...roomsQueryKeys.all, { reference, type }, { uid, username }, -], +] as const,apps/meteor/client/views/room/body/RoomInviteBody.stories.tsx (1)
4-4: Rename import for clarity:RoomInvite→RoomInviteBody.The import alias is confusing since it doesn't match the component name. This could cause confusion when reading the story file, especially since there's a separate
RoomInvitecomponent in the codebase.-import RoomInvite from './RoomInviteBody'; +import RoomInviteBody from './RoomInviteBody';Then update line 7:
- component: RoomInvite, + component: RoomInviteBody,
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (3)
apps/meteor/client/views/room/Header/__snapshots__/RoomInviteHeader.spec.tsx.snapis excluded by!**/*.snapapps/meteor/client/views/room/HeaderV2/__snapshots__/RoomInviteHeader.spec.tsx.snapis excluded by!**/*.snapapps/meteor/client/views/room/body/__snapshots__/RoomInviteBody.spec.tsx.snapis excluded by!**/*.snap
📒 Files selected for processing (27)
.changeset/chatty-roses-help.md(1 hunks)apps/meteor/client/lib/queryKeys.ts(1 hunks)apps/meteor/client/views/room/Header/Header.tsx(3 hunks)apps/meteor/client/views/room/Header/RoomHeader.spec.tsx(1 hunks)apps/meteor/client/views/room/Header/RoomHeader.tsx(2 hunks)apps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsx(1 hunks)apps/meteor/client/views/room/Header/RoomInviteHeader.stories.tsx(1 hunks)apps/meteor/client/views/room/Header/RoomInviteHeader.tsx(1 hunks)apps/meteor/client/views/room/HeaderV2/Header.tsx(2 hunks)apps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsx(1 hunks)apps/meteor/client/views/room/HeaderV2/RoomHeader.tsx(2 hunks)apps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsx(1 hunks)apps/meteor/client/views/room/HeaderV2/RoomInviteHeader.stories.tsx(1 hunks)apps/meteor/client/views/room/HeaderV2/RoomInviteHeader.tsx(1 hunks)apps/meteor/client/views/room/Room.tsx(3 hunks)apps/meteor/client/views/room/RoomHeader.tsx(1 hunks)apps/meteor/client/views/room/RoomInvite.tsx(1 hunks)apps/meteor/client/views/room/body/RoomInviteBody.spec.tsx(1 hunks)apps/meteor/client/views/room/body/RoomInviteBody.stories.tsx(1 hunks)apps/meteor/client/views/room/body/RoomInviteBody.tsx(1 hunks)apps/meteor/client/views/room/hooks/useOpenRoom.ts(1 hunks)apps/meteor/client/views/room/hooks/useRoomInvitation.spec.tsx(1 hunks)apps/meteor/client/views/room/hooks/useRoomInvitation.tsx(1 hunks)apps/meteor/server/services/authorization/canAccessRoom.ts(2 hunks)apps/meteor/tests/mocks/utils/createDeferredMockFn.ts(1 hunks)packages/core-typings/src/ISubscription.ts(1 hunks)packages/i18n/src/locales/en.i18n.json(3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (.cursor/rules/playwright.mdc)
**/*.{ts,tsx,js}: Write concise, technical TypeScript/JavaScript with accurate typing in Playwright tests
Avoid code comments in the implementation
Files:
apps/meteor/client/views/room/body/RoomInviteBody.spec.tsxpackages/core-typings/src/ISubscription.tsapps/meteor/client/views/room/Header/RoomHeader.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomHeader.tsxapps/meteor/client/views/room/body/RoomInviteBody.tsxapps/meteor/client/views/room/Header/RoomHeader.tsxapps/meteor/client/views/room/Header/RoomInviteHeader.tsxapps/meteor/server/services/authorization/canAccessRoom.tsapps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomInviteHeader.stories.tsxapps/meteor/client/views/room/hooks/useRoomInvitation.spec.tsxapps/meteor/client/views/room/hooks/useOpenRoom.tsapps/meteor/client/lib/queryKeys.tsapps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsxapps/meteor/client/views/room/hooks/useRoomInvitation.tsxapps/meteor/client/views/room/RoomHeader.tsxapps/meteor/client/views/room/RoomInvite.tsxapps/meteor/client/views/room/body/RoomInviteBody.stories.tsxapps/meteor/client/views/room/HeaderV2/RoomInviteHeader.tsxapps/meteor/client/views/room/Header/RoomInviteHeader.stories.tsxapps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsxapps/meteor/client/views/room/Room.tsxapps/meteor/tests/mocks/utils/createDeferredMockFn.tsapps/meteor/client/views/room/Header/Header.tsxapps/meteor/client/views/room/HeaderV2/Header.tsx
🧠 Learnings (20)
📓 Common learnings
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Utilize Playwright fixtures (`test`, `page`, `expect`) for consistency in test files
Applied to files:
apps/meteor/client/views/room/body/RoomInviteBody.spec.tsxapps/meteor/client/views/room/Header/RoomHeader.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsxapps/meteor/client/views/room/hooks/useRoomInvitation.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsxapps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Prefer web-first assertions (`toBeVisible`, `toHaveText`, etc.) in Playwright tests
Applied to files:
apps/meteor/client/views/room/body/RoomInviteBody.spec.tsxapps/meteor/client/views/room/Header/RoomHeader.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsxapps/meteor/client/views/room/hooks/useRoomInvitation.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsxapps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `expect` matchers for assertions (`toEqual`, `toContain`, `toBeTruthy`, `toHaveLength`, etc.) instead of `assert` statements in Playwright tests
Applied to files:
apps/meteor/client/views/room/body/RoomInviteBody.spec.tsxapps/meteor/client/views/room/Header/RoomHeader.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsxapps/meteor/client/views/room/hooks/useRoomInvitation.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsxapps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Group related tests in the same file
Applied to files:
apps/meteor/client/views/room/body/RoomInviteBody.spec.tsxapps/meteor/client/views/room/Header/RoomHeader.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsxapps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.{ts,spec.ts} : Follow Page Object Model pattern consistently in Playwright tests
Applied to files:
apps/meteor/client/views/room/body/RoomInviteBody.spec.tsxapps/meteor/client/views/room/Header/RoomHeader.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsxapps/meteor/client/views/room/hooks/useRoomInvitation.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsxapps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Maintain test isolation between test cases in Playwright tests
Applied to files:
apps/meteor/client/views/room/body/RoomInviteBody.spec.tsxapps/meteor/client/views/room/Header/RoomHeader.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsxapps/meteor/client/views/room/hooks/useRoomInvitation.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsxapps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Use `test.step()` for complex test scenarios to improve organization in Playwright tests
Applied to files:
apps/meteor/client/views/room/body/RoomInviteBody.spec.tsxapps/meteor/client/views/room/hooks/useRoomInvitation.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsxapps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : All test files must be created in `apps/meteor/tests/e2e/` directory
Applied to files:
apps/meteor/client/views/room/body/RoomInviteBody.spec.tsxapps/meteor/client/views/room/Header/RoomHeader.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsxapps/meteor/client/views/room/hooks/useRoomInvitation.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsxapps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/page-objects/**/*.ts : Utilize existing page objects pattern from `apps/meteor/tests/e2e/page-objects/`
Applied to files:
apps/meteor/client/views/room/body/RoomInviteBody.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsxapps/meteor/client/views/room/hooks/useRoomInvitation.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsxapps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to **/*.spec.ts : Use descriptive test names that clearly communicate expected behavior in Playwright tests
Applied to files:
apps/meteor/client/views/room/body/RoomInviteBody.spec.tsxapps/meteor/client/views/room/Header/RoomHeader.spec.tsx
📚 Learning: 2025-10-06T20:32:23.658Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37152
File: packages/apps-engine/tests/test-data/utilities.ts:557-573
Timestamp: 2025-10-06T20:32:23.658Z
Learning: In packages/apps-engine/tests/test-data/utilities.ts, the field name `isSubscripbedViaBundle` in the `IMarketplaceSubscriptionInfo` type should not be flagged as a typo, as it may match the upstream API's field name.
Applied to files:
packages/core-typings/src/ISubscription.ts
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure tests run reliably in parallel without shared state conflicts
Applied to files:
apps/meteor/client/views/room/Header/RoomHeader.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsxapps/meteor/client/views/room/hooks/useRoomInvitation.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsxapps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsx
📚 Learning: 2025-11-24T17:08:17.065Z
Learnt from: CR
Repo: RocketChat/Rocket.Chat PR: 0
File: .cursor/rules/playwright.mdc:0-0
Timestamp: 2025-11-24T17:08:17.065Z
Learning: Applies to apps/meteor/tests/e2e/**/*.spec.ts : Ensure clean state for each test execution in Playwright tests
Applied to files:
apps/meteor/client/views/room/Header/RoomHeader.spec.tsxapps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsxapps/meteor/client/views/room/hooks/useRoomInvitation.spec.tsx
📚 Learning: 2025-10-28T16:53:42.761Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37205
File: ee/packages/federation-matrix/src/FederationMatrix.ts:296-301
Timestamp: 2025-10-28T16:53:42.761Z
Learning: In the Rocket.Chat federation-matrix integration (ee/packages/federation-matrix/), the createRoom method from rocket.chat/federation-sdk will support a 4-argument signature (userId, roomName, visibility, displayName) in newer versions. Code using this 4-argument call is forward-compatible with planned library updates and should not be flagged as an error.
Applied to files:
apps/meteor/client/views/room/body/RoomInviteBody.tsxapps/meteor/server/services/authorization/canAccessRoom.tsapps/meteor/client/views/room/hooks/useOpenRoom.tsapps/meteor/client/lib/queryKeys.tsapps/meteor/client/views/room/hooks/useRoomInvitation.tsxapps/meteor/client/views/room/RoomInvite.tsxapps/meteor/client/views/room/Room.tsxapps/meteor/client/views/room/Header/Header.tsx.changeset/chatty-roses-help.mdapps/meteor/client/views/room/HeaderV2/Header.tsx
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings (mapping subscription documents to room IDs), never undefined, even when user has no room subscriptions.
Applied to files:
apps/meteor/server/services/authorization/canAccessRoom.tsapps/meteor/client/views/room/hooks/useOpenRoom.tsapps/meteor/client/lib/queryKeys.tsapps/meteor/client/views/room/Room.tsxapps/meteor/client/views/room/Header/Header.tsx
📚 Learning: 2025-09-25T09:59:26.461Z
Learnt from: Dnouv
Repo: RocketChat/Rocket.Chat PR: 37057
File: packages/apps-engine/src/definition/accessors/IUserRead.ts:23-27
Timestamp: 2025-09-25T09:59:26.461Z
Learning: AppUserBridge.getUserRoomIds in apps/meteor/app/apps/server/bridges/users.ts always returns an array of strings by mapping subscription documents to room IDs, never undefined, even when user has no room subscriptions.
Applied to files:
apps/meteor/server/services/authorization/canAccessRoom.tsapps/meteor/client/views/room/hooks/useOpenRoom.tsapps/meteor/client/lib/queryKeys.tsapps/meteor/client/views/room/Room.tsxapps/meteor/client/views/room/Header/Header.tsx
📚 Learning: 2025-11-04T16:49:19.107Z
Learnt from: ricardogarim
Repo: RocketChat/Rocket.Chat PR: 37377
File: apps/meteor/ee/server/hooks/federation/index.ts:86-88
Timestamp: 2025-11-04T16:49:19.107Z
Learning: In Rocket.Chat's federation system (apps/meteor/ee/server/hooks/federation/), permission checks follow two distinct patterns: (1) User-initiated federation actions (creating rooms, adding users to federated rooms, joining from invites) should throw MeteorError to inform users they lack 'access-federation' permission. (2) Remote server-initiated federation events should silently skip/ignore when users lack permission. The beforeAddUserToRoom hook only executes for local user-initiated actions, so throwing an error there is correct. Remote federation events are handled separately by the federation Matrix package with silent skipping logic.
Applied to files:
apps/meteor/server/services/authorization/canAccessRoom.tsapps/meteor/client/views/room/hooks/useRoomInvitation.tsx.changeset/chatty-roses-help.md
📚 Learning: 2025-11-19T12:32:29.696Z
Learnt from: d-gubert
Repo: RocketChat/Rocket.Chat PR: 37547
File: packages/i18n/src/locales/en.i18n.json:634-634
Timestamp: 2025-11-19T12:32:29.696Z
Learning: Repo: RocketChat/Rocket.Chat
Context: i18n workflow
Learning: In this repository, new translation keys should be added to packages/i18n/src/locales/en.i18n.json only; other locale files are populated via the external translation pipeline and/or fall back to English. Do not request adding the same key to all locale files in future reviews.
Applied to files:
.changeset/chatty-roses-help.mdpackages/i18n/src/locales/en.i18n.json
📚 Learning: 2025-11-19T18:20:07.720Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37419
File: packages/i18n/src/locales/en.i18n.json:918-921
Timestamp: 2025-11-19T18:20:07.720Z
Learning: Repo: RocketChat/Rocket.Chat — i18n/formatting
Learning: This repository uses a custom message formatting parser in UI blocks/messages; do not assume standard Markdown rules. For keys like Call_ended_bold, Call_not_answered_bold, Call_failed_bold, and Call_transferred_bold in packages/i18n/src/locales/en.i18n.json, retain the existing single-asterisk emphasis unless maintainers request otherwise.
Applied to files:
.changeset/chatty-roses-help.mdpackages/i18n/src/locales/en.i18n.json
🧬 Code graph analysis (15)
apps/meteor/client/views/room/body/RoomInviteBody.spec.tsx (2)
packages/mock-providers/src/index.ts (1)
mockAppRoot(3-3)apps/meteor/client/lib/appLayout.tsx (1)
render(26-28)
apps/meteor/client/views/room/body/RoomInviteBody.tsx (1)
packages/livechat/src/components/Button/index.tsx (1)
Button(34-99)
apps/meteor/server/services/authorization/canAccessRoom.ts (1)
packages/core-typings/src/ISubscription.ts (1)
isInviteSubscription(89-93)
apps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsx (3)
apps/meteor/tests/mocks/data.ts (1)
createFakeRoom(46-61)packages/mock-providers/src/index.ts (1)
mockAppRoot(3-3)apps/meteor/client/lib/appLayout.tsx (1)
render(26-28)
apps/meteor/client/views/room/HeaderV2/RoomInviteHeader.stories.tsx (1)
apps/meteor/tests/mocks/data.ts (1)
createFakeRoom(46-61)
apps/meteor/client/lib/queryKeys.ts (2)
packages/core-typings/src/IRoom.ts (1)
IRoom(21-95)packages/core-typings/src/IUser.ts (1)
IUser(186-255)
apps/meteor/client/views/room/HeaderV2/RoomInviteHeader.spec.tsx (2)
packages/mock-providers/src/index.ts (1)
mockAppRoot(3-3)apps/meteor/client/lib/appLayout.tsx (1)
render(26-28)
apps/meteor/client/views/room/hooks/useRoomInvitation.tsx (4)
apps/meteor/client/startup/iframeCommands.ts (1)
user(80-89)packages/ui-contexts/src/index.ts (2)
useUser(80-80)useRouter(60-60)apps/meteor/client/hooks/useEndpointMutation.ts (1)
useEndpointMutation(23-43)apps/meteor/client/lib/queryKeys.ts (1)
roomsQueryKeys(13-28)
apps/meteor/client/views/room/RoomHeader.tsx (2)
packages/core-typings/src/IRoom.ts (1)
IRoom(21-95)packages/core-typings/src/ISubscription.ts (1)
ISubscription(11-79)
apps/meteor/client/views/room/RoomInvite.tsx (3)
packages/core-typings/src/ISubscription.ts (1)
ISubscription(11-79)apps/meteor/client/views/room/hooks/useRoomInvitation.tsx (1)
useRoomInvitation(8-36)ee/packages/federation-matrix/src/api/_matrix/invite.ts (1)
acceptInvite(136-172)
apps/meteor/client/views/room/Header/RoomInviteHeader.stories.tsx (1)
apps/meteor/tests/mocks/data.ts (1)
createFakeRoom(46-61)
apps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsx (2)
packages/mock-providers/src/index.ts (1)
mockAppRoot(3-3)apps/meteor/client/lib/appLayout.tsx (1)
render(26-28)
apps/meteor/client/views/room/Room.tsx (2)
apps/meteor/client/views/room/contexts/RoomToolboxContext.ts (1)
useRoomToolbox(47-47)packages/core-typings/src/ISubscription.ts (1)
isInviteSubscription(89-93)
apps/meteor/client/views/room/Header/Header.tsx (1)
packages/core-typings/src/ISubscription.ts (2)
ISubscription(11-79)isInviteSubscription(89-93)
apps/meteor/client/views/room/HeaderV2/Header.tsx (1)
packages/core-typings/src/ISubscription.ts (2)
ISubscription(11-79)isInviteSubscription(89-93)
🔇 Additional comments (32)
apps/meteor/tests/mocks/utils/createDeferredMockFn.ts (1)
1-1: ExportingcreateDeferredPromiseas a named utility looks goodMaking
createDeferredPromisea named export is a safe, non-breaking change that improves reusability in tests while preserving the existing default export forcreateDeferredMockFn..changeset/chatty-roses-help.md (1)
1-7: Changeset structure looks good.The YAML frontmatter format is correct, and the three packages listed align with the PR scope: @rocket.chat/meteor for new components, @rocket.chat/core-typings for type additions, and @rocket.chat/i18n for translation keys. The patch-level version bump is appropriate for feature additions without breaking changes.
Please verify that all modified packages are captured in this changeset. The PR mentions server-side authorization validation for invite-based room access—confirm whether this involves packages beyond the three listed here (e.g., server-side hooks or authorization packages).
apps/meteor/client/views/room/Header/RoomHeader.tsx (2)
34-34: LGTM: Type change enables conditional toolbox rendering.The addition of
| nullto theroomToolboxtype enables explicit suppression of the toolbox, which aligns with the invite header flow where no toolbox should be displayed.
68-76: LGTM: Conditional rendering preserves backward compatibility.The conditional
(slots.toolbox || roomToolbox !== null)correctly handles three scenarios:
- When
roomToolboxis undefined (not passed): renders default toolbox for backward compatibility- When
roomToolboxis explicitlynull: suppresses toolbox rendering- When
roomToolboxis a JSX element: renders the custom toolboxapps/meteor/client/views/room/hooks/useRoomInvitation.spec.tsx (5)
1-26: LGTM: Clean test setup with proper isolation.The test setup follows Jest best practices with proper mocking of dependencies and cleanup between tests.
27-33: LGTM: Proper async testing of acceptInvite.The test correctly validates that
acceptInvitetriggers the endpoint mutation with theacceptaction.
35-41: LGTM: Proper testing of rejectInvite action.
43-57: LGTM: Excellent async state testing.The use of
createDeferredPromiseenables precise control over the mutation lifecycle, allowing accurate validation of theisPendingstate transitions.
59-73: LGTM: Comprehensive navigation behavior coverage.Both navigation scenarios (redirect on reject, no redirect on accept) are properly validated.
apps/meteor/client/views/room/hooks/useRoomInvitation.tsx (3)
1-12: LGTM: Clean hook setup.
13-29: LGTM: Well-structured mutation with proper query management.The
onSuccesshandler correctly:
- Falls back to
room.namewhenfederationOriginalNameis unavailable- Refetches room reference queries for immediate updates
- Invalidates room queries to trigger re-validation
- Navigates to
/homeonly when rejecting invitations
31-36: LGTM: Clean API design with convenient methods.The hook exposes both the underlying mutation state and convenient
acceptInvite/rejectInvitemethods, providing a good developer experience.apps/meteor/client/views/room/Header/RoomInviteHeader.tsx (1)
4-6: LGTM: Clean component implementation.The component correctly wraps
RoomHeaderwithroomToolbox={null}to suppress toolbox rendering for invite scenarios, while properly forwarding bothroomandslotsprops.apps/meteor/server/services/authorization/canAccessRoom.ts (2)
4-4: LGTM: Import added for new validator.
87-96: Remove federation permission check suggestion; validate invite workflow security concerns.The
_validateAccessToInvitedRoomsvalidator grants room access to users with pending invitations (subscription.status === 'INVITED'), allowing them to see room details before accepting or rejecting. This aligns with the stated PR goal of displaying invitations in the UI.The TODO comment reflecting uncertainty about this approach is valid and should be resolved. However, verify these specific concerns:
- Invited users should have read-only access before accepting (to preview room details)
- Subscription status correctly transitions through the accept/reject/expiration workflow
- Timeout or expiration mechanisms exist for stale invitations
- No unintended access grants occur (e.g., to rejected or expired invitations)
The suggestion about federation permission checks in the original review is not applicable here. The
canAccessRoomvalidator is a room access control check, not a federation action. Federation permissions (like 'access-federation') apply to user-initiated federation operations (creating federated rooms, adding users to federated rooms), which are handled separately in federation hooks.apps/meteor/client/views/room/Header/RoomInviteHeader.spec.tsx (4)
1-10: LGTM: Good use of Storybook integration.Using
composeStoriesto generate test cases from Storybook stories ensures consistency between documentation and tests.
12-29: LGTM: Appropriate mocking strategy.The mocks isolate the component under test from its dependencies, ensuring reliable test execution.
31-39: LGTM: Proper snapshot testing with isolation.The snapshot tests provide regression detection for visual changes, with proper cleanup between tests.
41-46: LGTM: Excellent inclusion of accessibility testing.Using
jest-axeto validate accessibility for each story helps ensure an inclusive user experience.apps/meteor/client/views/room/HeaderV2/RoomHeader.spec.tsx (1)
1-72: Comprehensive toolbox rendering coverageThe toolbox behavior matrix (default, null override, slot-provided, custom prop, and precedence) aligns well with the new conditional logic in
RoomHeader. This should prevent regressions around hiding the toolbox for invite flows while still supporting overrides.apps/meteor/client/views/room/RoomHeader.tsx (1)
1-25: Feature-flagged header wrapper looks correctThe
RoomHeaderwrapper cleanly delegates toHeaderV2vsHeaderV1based onnewNavigationand passesroom/subscriptionconsistently. This should make it easy to roll out the new header/invite path safely.packages/i18n/src/locales/en.i18n.json (2)
3024-3025: LGTM — invite and federation strings added correctly.Naming matches existing patterns (Learn_more_about_*). No issues.
5410-5410: The standalone "unknown" key appears unused and the line reference is off by one.The actual
"unknown": "unknown"key is at line 5409 (not 5410). Verification shows this key has no direct usages in the codebase—no code callst("unknown"). However, the casing concern is valid: related keys like"App_status_unknown": "Unknown"(line 518) use capitalized values. If this key is intentionally kept for future use or as a fallback, it should be"Unknown"to maintain consistency with similar status keys. No duplicate "Unknown" key exists. Consider clarifying the key's purpose or removing it if truly orphaned.apps/meteor/client/views/room/Header/RoomHeader.spec.tsx (1)
1-73: LGTM! Comprehensive test coverage for toolbox rendering logic.The test suite effectively covers the key scenarios for toolbox rendering: default behavior, hiding when null, slot-based rendering, custom content, and precedence rules. The mocking strategy appropriately isolates the RoomHeader component.
apps/meteor/client/views/room/HeaderV2/RoomInviteHeader.stories.tsx (1)
1-21: LGTM! Story setup is well-structured.The Storybook configuration follows the established patterns with proper component wrapping, mock data, and type-safe meta definition.
apps/meteor/client/views/room/HeaderV2/Header.tsx (1)
1-47: LGTM! Clean implementation of invite subscription handling.The conditional branch for invite subscriptions is correctly placed before other room-type checks, ensuring invite states are properly intercepted. The lazy loading pattern is consistent with existing headers.
apps/meteor/client/views/room/Header/Header.tsx (1)
1-66: LGTM! Consistent invite subscription handling with proper slots forwarding.The implementation correctly adds invite subscription support while maintaining the existing slots pattern used by other headers in this folder. The conditional placement before room-type checks ensures proper invite interception.
apps/meteor/client/views/room/Header/RoomInviteHeader.stories.tsx (1)
1-21: LGTM! Consistent story structure with HeaderV2 variant.The story configuration properly mirrors the HeaderV2 version, maintaining consistency across header component stories.
apps/meteor/client/views/room/Room.tsx (4)
1-23: LGTM!The imports are well-organized and align with the new invite subscription handling functionality being introduced.
28-37: LGTM!The
roomLabelcomputation provides appropriate accessibility context for both direct messages and channels, with correct translation key interpolation.
39-45: LGTM!The early return for invite subscriptions correctly prevents access to the full chat UI and maintains consistency with the main rendering path in terms of
FocusScopewrapping and accessibility attributes. The type guard safely handles undefined/null subscriptions.
52-55: LGTM!The
RoomHeadernow receives bothroomandsubscriptionprops, with thearia-labelproviding proper accessibility context. Thesubscriptioncan be undefined for users viewing rooms they have access to but aren't subscribed to (e.g., public channels), so ensureRoomHeaderhandles this case appropriately.
138fc79 to
47cba1f
Compare
a575a7a to
5a0d940
Compare
bcbb48d to
066cda3
Compare
02ef424 to
432d3b1
Compare
9efc603 to
5a4af29
Compare
432d3b1 to
2b81d46
Compare
b2cc5c0 to
0d14b19
Compare
3f2fbe8 to
7c4a439
Compare
7c4a439 to
1e4499e
Compare
dba8733 to
85183c9
Compare
1e4499e to
ca5ee32
Compare
d25851f to
c205233
Compare
c205233 to
e4a3790
Compare
Proposed changes (including videos or screenshots)
This pull request adds support for invitation requests to rooms.
INVITED.RoomInviteHeader,RoomInviteBody,RoomInvite.RoomLayoutroomReferencequery key toqueryKeys.tsIssue(s)
FB-65
Steps to test or reproduce
ℹ️ Currently invitation requests are only available for federated rooms.
ℹ️ You'll need two workspaces with federation enabled (I'll refer to them as
ws-aandws-b)ws-a)ws-bto the room (ws-a)ws-bthe room invitation should become visible in the sidebar (ws-b)Scenario A
ws-b)ws-b)Scenario B
ws-b)ws-b)Further comments
Summary by CodeRabbit
Release Notes
New Features
Tests
✏️ Tip: You can customize this high-level summary in your review settings.