Skip to content

Conversation

@ricardogarim
Copy link
Contributor

@ricardogarim ricardogarim commented Oct 28, 2025

  • New Features
    • Added member profile update functionality for federated rooms. Administrators can now modify member display names, with changes automatically propagated across all connected federation servers.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 28, 2025

Walkthrough

A new public method updateMemberProfile() is added to the RoomService class, enabling updates to room member display names. The method validates membership status, constructs an m.room.member event, processes it through the state service, and broadcasts it to all federated servers.

Changes

Cohort / File(s) Summary
Member Profile Update
packages/federation-sdk/src/services/room.service.ts
Adds updateMemberProfile(roomId, userId, displayName) method that fetches room state, verifies member status, creates and broadcasts an m.room.member event with updated displayName, and returns the persisted event. Includes federation propagation with error handling.

Sequence Diagram

sequenceDiagram
    participant Client
    participant RoomService
    participant StateService
    participant Federation
    
    Client->>RoomService: updateMemberProfile(roomId, userId, displayName)
    RoomService->>RoomService: Fetch room info & state
    RoomService->>RoomService: Verify user is joined member
    alt Member verification fails
        RoomService-->>Client: Error
    else Member verified
        RoomService->>RoomService: Build m.room.member event<br/>(membership: 'join', displayName)
        RoomService->>StateService: Process event
        StateService-->>RoomService: Event processed
        RoomService->>Federation: Broadcast event to servers
        alt Federation rejected
            Federation-->>RoomService: Error
            RoomService-->>Client: Error thrown
        else Federation accepted
            Federation-->>RoomService: Acknowledged
            RoomService-->>Client: Return PersistentEvent
        end
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Focus on error handling for federation rejection scenarios
  • Verify member status validation logic is comprehensive
  • Confirm m.room.member event structure aligns with protocol specifications
  • Review federation broadcasting error propagation

Poem

🐰 A profile update hops our way,
Display names now can brightly play,
Through federation's distant halls,
The member's update swiftly calls,
Room members smile—their names shine bright! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "feat: add update member name support" accurately and concisely describes the main change in the changeset, which adds a new updateMemberProfile() method to the RoomService class that enables updating member display names with federation propagation. The title is specific and clear without vague terminology or noise, making it easy for teammates to understand the primary change when scanning history. The title directly corresponds to the core functionality being introduced.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/rename-user

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter
Copy link

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.49%. Comparing base (8bdd4f8) to head (d0c4f55).
⚠️ Report is 24 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #291      +/-   ##
==========================================
+ Coverage   60.31%   60.49%   +0.18%     
==========================================
  Files          67       67              
  Lines        6672     6675       +3     
==========================================
+ Hits         4024     4038      +14     
+ Misses       2648     2637      -11     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ricardogarim ricardogarim marked this pull request as ready for review October 28, 2025 14:53
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/federation-sdk/src/services/room.service.ts (1)

703-707: Consider adding displayName validation.

The method doesn't validate the displayName parameter (e.g., length limits, character restrictions). While validation might be handled elsewhere in the stack, adding basic validation here would provide defense in depth and fail fast on invalid input.

Consider adding validation:

 	async updateMemberProfile(
 		roomId: RoomID,
 		userId: UserID,
 		displayName: string,
 	): Promise<PersistentEventBase<RoomVersion, 'm.room.member'>> {
+		// Validate displayName
+		if (!displayName || displayName.trim().length === 0) {
+			throw new HttpException(
+				'Display name cannot be empty',
+				HttpStatus.BAD_REQUEST,
+			);
+		}
+		if (displayName.length > 256) {
+			throw new HttpException(
+				'Display name too long (max 256 characters)',
+				HttpStatus.BAD_REQUEST,
+			);
+		}
+
 		logger.info(
 			`Updating member profile for user ${userId} in room ${roomId}`,
 		);
📜 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.

📥 Commits

Reviewing files that changed from the base of the PR and between e131461 and d0c4f55.

📒 Files selected for processing (1)
  • packages/federation-sdk/src/services/room.service.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
packages/federation-sdk/src/services/room.service.ts (2)
packages/federation-sdk/src/index.ts (4)
  • RoomID (29-29)
  • UserID (28-28)
  • PersistentEventBase (25-25)
  • RoomVersion (26-26)
packages/room/src/types/_common.ts (2)
  • RoomID (16-16)
  • UserID (20-20)
🔇 Additional comments (1)
packages/federation-sdk/src/services/room.service.ts (1)

703-745: Improve error handling and logging; verify authorization when integrating this method into API endpoints.

The updateMemberProfile method is correctly implemented for updating member profile information, but requires attention in three areas:

  1. Authorization verification needed upon integration: This method is not currently called from any controller. When exposed via HTTP endpoints, verify that authorization is properly enforced to ensure only the target user (or an admin) can update their own profile, preventing impersonation.

  2. Inconsistent error handling: Throws generic Error objects instead of HttpException with proper HTTP status codes (lines 713, 737-739), inconsistent with other methods in this class like leaveRoom and kickUser.

  3. Missing logging: Other similar methods (updateRoomName, leaveRoom, kickUser) include logging statements. Add logger calls at method entry and exit for debugging and auditing.

Apply error handling and logging improvements:

 	async updateMemberProfile(
 		roomId: RoomID,
 		userId: UserID,
 		displayName: string,
 	): Promise<PersistentEventBase<RoomVersion, 'm.room.member'>> {
+		this.logger.info(
+			`Updating member profile for user ${userId} in room ${roomId}`,
+		);
+
 		const roomInfo = await this.stateService.getRoomInformation(roomId);
 		const currentState = await this.stateService.getLatestRoomState(roomId);
 
 		const currentMembership = currentState.get(`m.room.member:${userId}`);
 		if (!currentMembership || currentMembership.getMembership() !== 'join') {
-			throw new Error(`User ${userId} is not a member of room ${roomId}`);
+			throw new HttpException(
+				`User ${userId} is not a member of room ${roomId}`,
+				HttpStatus.FORBIDDEN,
+			);
 		}
 
 		const memberEvent = await this.stateService.buildEvent<'m.room.member'>(
 			{
 				type: 'm.room.member',
 				content: {
 					membership: 'join', // SAME membership (not changing)
 					displayname: displayName, // NEW displayname
 				},
 				room_id: roomId,
 				sender: userId,
 				state_key: userId,
 				auth_events: [],
 				depth: 0,
 				prev_events: [],
 				origin_server_ts: Date.now(),
 			},
 			roomInfo.room_version,
 		);
 
 		await this.stateService.handlePdu(memberEvent);
 
 		if (memberEvent.rejected) {
-			throw new Error(
-				`Member profile update rejected: ${memberEvent.rejectReason}`,
-			);
+			throw new HttpException(
+				`Member profile update rejected: ${memberEvent.rejectReason}`,
+				HttpStatus.BAD_REQUEST,
+			);
 		}
 
+		this.logger.info(
+			`Successfully updated member profile for user ${userId} in room ${roomId}`,
+		);
+
 		void this.federationService.sendEventToAllServersInRoom(memberEvent);
 
 		return memberEvent;
 	}

@ggazzo ggazzo merged commit c8ff64c into main Nov 7, 2025
3 checks passed
@ggazzo ggazzo deleted the feat/rename-user branch November 7, 2025 16:16
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.

4 participants