Skip to content

Conversation

@jordane
Copy link
Member

@jordane jordane commented Oct 6, 2025

… management

Update project permission system to use correct NATS endpoints for user information retrieval:

  • Add USER_METADATA_READ NATS subject for lfx.auth-service.user_metadata.read
  • Fix getUserInfo to use email_to_username result for user metadata lookup
  • Maintain email_to_sub for backend storage consistency (auditors/writers)
  • Handle proper response format from user metadata service
  • Map picture field to avatar and construct names from metadata

🤖 Generated with Claude Code

… management

Update project permission system to use correct NATS endpoints for user information retrieval:
- Add USER_METADATA_READ NATS subject for lfx.auth-service.user_metadata.read
- Fix getUserInfo to use email_to_username result for user metadata lookup
- Maintain email_to_sub for backend storage consistency (auditors/writers)
- Handle proper response format from user metadata service
- Map picture field to avatar and construct names from metadata

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Jordan Evans <[email protected]>
Copilot AI review requested due to automatic review settings October 6, 2025 22:14
@coderabbitai
Copy link

coderabbitai bot commented Oct 6, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Controller no longer resolves emails; it forwards the original username/email to the service. Service now normalizes emails to backend identifier (sub), updates permission operations to use sub, adds email→sub/username helpers, adjusts NATS subjects and metadata retrieval. Shared NATS enum gains USER_METADATA_READ.

Changes

Cohort / File(s) Summary
Controller: permissions input handling
apps/lfx-one/src/server/controllers/project.controller.ts
Removed controller-side email→username resolution; forwards original input as username to service. Preserves provided manualUserInfo.username, updates success log payload to include is_email and uses input username.
Service: permissions normalization and lookups
apps/lfx-one/src/server/services/project.service.ts
updateProjectPermissions signature now accepts usernameOrEmail; resolves emails to backendIdentifier (sub) via resolveEmailToSub; operations (add/update/remove) use backendIdentifier for writers/auditors; added/modified helpers resolveEmailToSub, resolveEmailToUsername, adjusted getUserInfo to fetch user metadata via NATS and return avatar; updated NATS request subjects, logging, and error handling.
Shared: NATS subjects
packages/shared/src/enums/nats.enum.ts
Added USER_METADATA_READ = 'lfx.auth-service.user_metadata.read' to NatsSubjects.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant UI as Client
  participant C as ProjectController
  participant S as ProjectService
  participant N as NATS Bus
  participant Auth as Auth Service
  participant Store as Project Store

  UI->>C: add/update/remove permissions(usernameOrEmail, role, manualUserInfo?)
  C->>S: updateProjectPermissions(req, projectId, op, usernameOrEmail, role, manualUserInfo?)

  rect rgba(200,220,255,0.25)
  note over S: Normalize identifier
  alt Input is email
    S->>N: request resolveEmailToSub(email)
    N->>Auth: email → sub lookup
    Auth-->>N: sub (or timeout/error)
    N-->>S: sub
    S->>N: USER_METADATA_READ (by sub)
    N-->>S: user metadata
  else Username provided
    S->>N: USER_METADATA_READ (by username)
    N-->>S: user metadata
  end
  end

  note over S: Build userInfo (username := sub if email), merge manualUserInfo

  alt op == remove
    S->>Store: remove permission entries by backendIdentifier (sub)
  else op == add/update
    S->>Store: upsert writer/auditor entries by backendIdentifier (sub)
  end

  S-->>C: result (users, is_email, identifiers)
  C-->>UI: response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly summarizes the main change by indicating that the permissions feature now fixes the metadata lookup flow for email-based users, and it clearly connects to the modifications in the service and controller layers without unnecessary detail or noise.
Linked Issues Check ✅ Passed The changes introduce the USER_METADATA_READ subject, update getUserInfo to build full user objects with name, email, and avatar, and maintain backend identifiers for writers and auditors, thereby satisfying the linked issue’s requirement to treat writers and auditors as objects with additional attributes.
Out of Scope Changes Check ✅ Passed All modifications are focused on improving email-based user lookup and metadata handling within the project permissions feature, and there are no changes detected that fall outside the scope of updating writers and auditors to support richer user profiles.
Description Check ✅ Passed The pull request description outlines the relevant changes to NATS subjects, getUserInfo logic, email-to-sub consistency, and field mappings, directly reflecting the code modifications and remaining on topic with the updates to the project permission system.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ 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 jme/LFXV2-638

📜 Recent 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 8d6425e and 087906a.

📒 Files selected for processing (2)
  • apps/lfx-one/src/server/controllers/project.controller.ts (1 hunks)
  • apps/lfx-one/src/server/services/project.service.ts (8 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript interfaces instead of union types for better maintainability
When defining PrimeNG-related types, reference the official PrimeNG component interfaces

Files:

  • apps/lfx-one/src/server/controllers/project.controller.ts
  • apps/lfx-one/src/server/services/project.service.ts
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Include required license headers on all source files

Files:

  • apps/lfx-one/src/server/controllers/project.controller.ts
  • apps/lfx-one/src/server/services/project.service.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • apps/lfx-one/src/server/controllers/project.controller.ts
  • apps/lfx-one/src/server/services/project.service.ts
🧬 Code graph analysis (1)
apps/lfx-one/src/server/services/project.service.ts (3)
packages/shared/src/interfaces/project.interface.ts (1)
  • ProjectSettings (139-152)
packages/shared/src/constants/api.constants.ts (1)
  • NATS_CONFIG (28-43)
apps/lfx-one/src/server/errors/index.ts (1)
  • ResourceNotFoundError (7-7)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: E2E Tests / Playwright E2E Tests
🔇 Additional comments (3)
apps/lfx-one/src/server/services/project.service.ts (2)

147-217: LGTM! Well-structured permission update flow.

The refactored logic correctly:

  • Determines the backend identifier (sub for emails, username for usernames)
  • Filters existing entries by backend identifier
  • Handles both manual and fetched user info paths
  • Maintains backend consistency by storing sub for emails

The two-step resolution for emails (email→username for metadata lookup, email→sub for storage) aligns with the PR objectives.


505-510: Ensure email display for username-based lookups
When the lookup is by username, originalEmail is empty and email always falls back to '', so no email will appear in the UI. Confirm one of the following:

  • Enrich user metadata to include an email and change to email: userData.email || originalEmail || ''
  • Document this limitation and ensure the UI handles empty emails gracefully
  • Fetch the email in a separate step for username lookups
apps/lfx-one/src/server/controllers/project.controller.ts (1)

263-287: LGTM! Clean delegation to service layer.

The controller changes correctly:

  • Preserve the original input for manual user info
  • Delegate email/username resolution to the service layer
  • Update logging to reflect the new flow (is_email instead of resolved_from_email)

The inline comment at lines 279-280 helpfully explains that the service handles the resolution internally.


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

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Purpose: Align project permission user resolution with new auth service metadata endpoints, introducing USER_METADATA_READ, separating email-to-sub (backend identifier) from email-to-username (display), and updating permission update flow to consume user metadata (name/avatar) correctly.

  • Add new NATS subject USER_METADATA_READ and switch metadata lookup to it
  • Introduce separate resolveEmailToSub and resolveEmailToUsername flows and adjust permission update to store sub as backend identifier
  • Refactor getUserInfo to use user metadata service and map avatar from picture

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
packages/shared/src/enums/nats.enum.ts Added USER_METADATA_READ NATS subject constant to support new metadata lookup
apps/lfx-one/src/server/services/project.service.ts Refactored permission update flow, added email-to-sub + email-to-username resolution, switched to metadata read subject, updated user info shaping
apps/lfx-one/src/server/controllers/project.controller.ts Simplified controller by delegating email/username resolution to service and adjusted logging/parameter passing

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Run yarn format to ensure consistent code style across the project.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Jordan Evans <[email protected]>
Copy link

@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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/lfx-one/src/server/services/project.service.ts (1)

181-216: Prevent legacy username duplicates when normalizing to sub.

Line 181 only filters by backendIdentifier. Any existing writer/auditor stored under the old directory username (e.g., jdoe) will survive, so an add/update via email now leaves the legacy entry in place and appends a second record keyed by sub. That regresses the permissions UI with duplicate rows and breaks removal flows that rely on a single entry. Please strip out the prior identifier as well (resolve email_to_username once and filter against both values) before pushing the new object.

-    // Use backendIdentifier (sub) for comparison to ensure proper removal
-    updatedSettings.writers = updatedSettings.writers.filter((u) => u.username !== backendIdentifier);
-    updatedSettings.auditors = updatedSettings.auditors.filter((u) => u.username !== backendIdentifier);
+    const identifiersToRemove = new Set<string>([backendIdentifier]);
+    const rawIdentifier = usernameOrEmail.trim();
+    if (rawIdentifier) {
+      identifiersToRemove.add(rawIdentifier);
+    }
+    if (usernameOrEmail.includes('@')) {
+      const directoryUsername = await this.resolveEmailToUsername(req, usernameOrEmail);
+      identifiersToRemove.add(directoryUsername);
+    }
+
+    updatedSettings.writers = updatedSettings.writers.filter((user) => !identifiersToRemove.has(user.username));
+    updatedSettings.auditors = updatedSettings.auditors.filter((user) => !identifiersToRemove.has(user.username));
📜 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 6b7f43d and 8d6425e.

📒 Files selected for processing (3)
  • apps/lfx-one/src/server/controllers/project.controller.ts (1 hunks)
  • apps/lfx-one/src/server/services/project.service.ts (8 hunks)
  • packages/shared/src/enums/nats.enum.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
packages/shared/src/enums/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

Place all enums in the shared package at packages/shared/src/enums

Files:

  • packages/shared/src/enums/nats.enum.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use TypeScript interfaces instead of union types for better maintainability
When defining PrimeNG-related types, reference the official PrimeNG component interfaces

Files:

  • packages/shared/src/enums/nats.enum.ts
  • apps/lfx-one/src/server/controllers/project.controller.ts
  • apps/lfx-one/src/server/services/project.service.ts
**/*.{ts,tsx,js,jsx,mjs,cjs,html,css,scss}

📄 CodeRabbit inference engine (CLAUDE.md)

Include required license headers on all source files

Files:

  • packages/shared/src/enums/nats.enum.ts
  • apps/lfx-one/src/server/controllers/project.controller.ts
  • apps/lfx-one/src/server/services/project.service.ts
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Do not nest ternary expressions

Files:

  • packages/shared/src/enums/nats.enum.ts
  • apps/lfx-one/src/server/controllers/project.controller.ts
  • apps/lfx-one/src/server/services/project.service.ts
🧬 Code graph analysis (1)
apps/lfx-one/src/server/services/project.service.ts (3)
packages/shared/src/interfaces/project.interface.ts (1)
  • ProjectSettings (139-152)
packages/shared/src/constants/api.constants.ts (1)
  • NATS_CONFIG (28-43)
apps/lfx-one/src/server/errors/index.ts (1)
  • ResourceNotFoundError (7-7)
🪛 GitHub Actions: Quality Checks
apps/lfx-one/src/server/controllers/project.controller.ts

[warning] 1-1: Code style issues found in file. Run Prettier with --write to fix.

apps/lfx-one/src/server/services/project.service.ts

[warning] 1-1: Code style issues found in file. Run Prettier with --write to fix.

@github-actions
Copy link

github-actions bot commented Oct 6, 2025

✅ E2E Tests Passed

Browser: chromium
Status: passed

All E2E tests passed successfully.

Test Configuration

@dealako dealako merged commit 526162b into main Oct 6, 2025
8 checks passed
@dealako dealako deleted the jme/LFXV2-638 branch October 6, 2025 23:15
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.

3 participants