Skip to content

refactor: Add validations by checking ecosystem details present in user's token.#1578

Merged
pranalidhanavade merged 8 commits intomainfrom
refactor/check-ecosystem-exist-from-jwt-token
Mar 6, 2026
Merged

refactor: Add validations by checking ecosystem details present in user's token.#1578
pranalidhanavade merged 8 commits intomainfrom
refactor/check-ecosystem-exist-from-jwt-token

Conversation

@pranalidhanavade
Copy link
Contributor

@pranalidhanavade pranalidhanavade commented Mar 4, 2026

What

  • refactor: Add validations by checking ecosystem details present in user's token.
  • refactor: Fetch verification templates by ecosystemId instead of orgId.

Summary by CodeRabbit

  • New Features

    • Auth tokens now carry ecosystem-level access info for per-request ecosystem selection.
  • Refactor

    • Invitation-status endpoint changed from POST to PUT; invitation handling and parameter ordering simplified.
  • API Changes

    • Verification templates endpoints are ecosystem-scoped (ecosystemId primary); orgId is optional and templates can span member orgs. Response shape for templates updated.
  • Bug Fixes / Validation

    • Ecosystem ID inputs are trimmed, UUID-validated, and access requires membership/lead status.

@pranalidhanavade pranalidhanavade self-assigned this Mar 4, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 4, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Validate and propagate JWT ecosystem_access, extract/validate ecosystemId from request, authorize access via lead/member lists, set user.selectedEcosystem; remove EcosystemService usage from JWT strategy; extend JWT payload types; change invitation route to PUT; make verification-template flows ecosystem-centric and adjust related signatures.

Changes

Cohort / File(s) Summary
AuthZ interfaces
apps/api-gateway/src/authz/jwt-payload.interface.ts
Add ResourceAccess, EcosystemRole, EcosystemAccess; extend JwtPayload with resource_access? and ecosystem_access?.
JWT strategy
apps/api-gateway/src/authz/jwt.strategy.ts
Remove EcosystemService dependency and ecosystem-derivation logic; propagate payload.ecosystem_access into userDetails.
Ecosystem roles guard
apps/api-gateway/src/authz/guards/ecosystem-roles.guard.ts
Introduce EcosystemRoleGroup type; extract ecosystemId from params/query/body, trim/validate UUID when provided, require ecosystem_access and check lead/member lists for access, set user.selectedEcosystem, throw BadRequest/Forbidden per ResponseMessages.
Intent controller & params
apps/api-gateway/src/ecosystem/intent/intent.controller.ts
Add TrimStringParamPipe to ecosystemId params; rename and repurpose verification-templates endpoints to use ecosystemId, add optional orgId query param, update validation/messages and service call signatures.
Ecosystem controller routing
apps/api-gateway/src/ecosystem/ecosystem.controller.ts
Change updateEcosystemInvitationStatus route decorator from @Post('/invitation/status') to @Put('/invitation/status').
API Gateway service
apps/api-gateway/src/ecosystem/ecosystem.service.ts
Change getVerificationTemplates signature to (ecosystemId, pageDetail, orgId?); adjust NATS payload shape to include ecosystemId and optional orgId.
Ecosystem service & controller
apps/ecosystem/src/ecosystem.service.ts, apps/ecosystem/src/ecosystem.controller.ts
Swap updateEcosystemInvitationStatusByEmail arg order to (email, orgId, ecosystemId, status) in service/controller; relax invitation runtime check; update getTemplatesByOrgId to accept (ecosystemId, pageDetail, orgId?) and validate ecosystemId.
Repository & interfaces
apps/ecosystem/repositories/ecosystem.repository.ts, apps/ecosystem/interfaces/ecosystem.interfaces.ts
Reorder repository method params; implement getTemplatesByOrgId(ecosystemId, pageDetail, orgId?) returning IVerificationTemplateList shape; add IVerificationTemplateList interface and adjust imports/types.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant API as "API Gateway"
    participant Jwt as "JwtStrategy"
    participant Guard as "EcosystemRolesGuard"
    participant Token as "JWT (ecosystem_access)"

    Client->>API: HTTP request (may include ecosystemId)
    API->>Jwt: validate token, attach payload
    Jwt->>Token: extract payload.ecosystem_access -> request.user.ecosystem_access
    API->>Guard: guard invoked for route
    Guard->>API: extract/trim ecosystemId from params/query/body
    Guard->>Token: verify payload.ecosystem_access contains ecosystemId in lead/member lists
    alt access allowed
        Guard->>API: set request.user.selectedEcosystem = ecosystemId
        Guard-->>API: allow request
    else access denied
        Guard-->>API: throw BadRequest/Forbidden
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • sujitaw
  • shitrerohit
  • RinkalBhojani

Poem

🐰 I trimmed a param and checked its UUID,
I peeked inside tokens for the ecosystem view,
I hopped through guards to find where access lies,
I set the chosen home and gave the request the prize,
A little rabbit cheer — smooth hops and happy skies!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main objective: refactoring to add validations for ecosystem details from JWT tokens. It aligns with the significant changes across multiple authentication/authorization files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/check-ecosystem-exist-from-jwt-token

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.

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: 3

🧹 Nitpick comments (1)
apps/api-gateway/src/authz/guards/ecosystem-roles.guard.ts (1)

10-15: Consider reusing EcosystemAccess type from jwt-payload.interface.ts.

This EcosystemRoleGroup interface mirrors the structure of EcosystemAccess defined in jwt-payload.interface.ts. Consider importing and reusing that type to avoid duplication and ensure consistency.

♻️ Suggested refactor
+import { EcosystemAccess } from './jwt-payload.interface';
-interface EcosystemRoleGroup {
-  ecosystem_role?: {
-    lead?: string[];
-    member?: string[];
-  };
-}

Then update line 92:

-const hasAccess = Object.values(ecosystemAccess).some((entry: EcosystemRoleGroup) => {
+const hasAccess = Object.values(ecosystemAccess).some((entry: EcosystemAccess) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api-gateway/src/authz/guards/ecosystem-roles.guard.ts` around lines 10 -
15, The local EcosystemRoleGroup interface duplicates the existing
EcosystemAccess type in jwt-payload.interface.ts; remove the local interface and
import EcosystemAccess, then update all type annotations that used
EcosystemRoleGroup (e.g., the parameter/variable types referenced in
ecosystem-roles.guard.ts, including the usage at the location currently
annotated with EcosystemRoleGroup on the role-check logic) to use
EcosystemAccess instead to avoid duplication and keep types consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/api-gateway/src/authz/jwt.strategy.ts`:
- Around line 110-112: The code can null-dereference userDetails when
payload.ecosystem_access exists but userDetails is null (e.g., when
isServiceToken is true); update the logic around userDetails in the JWT
validation flow (the validate function / jwt.strategy.ts) to ensure userDetails
is initialized before assigning ecosystem_access (either create a minimal
userDetails object when isServiceToken is true and payload.ecosystem_access
exists, or guard the assignment with a check like if (userDetails)
userDetails.ecosystem_access = payload.ecosystem_access), referencing the
symbols userDetails, isServiceToken, and payload.ecosystem_access so the fix is
applied at the correct assignment site.

In `@apps/api-gateway/src/ecosystem/ecosystem.controller.ts`:
- Around line 210-214: Confirm whether excluding OrgRoles.PLATFORM_ADMIN from
the `@Roles` decorator on this endpoint was intentional; if it was not, add
OrgRoles.PLATFORM_ADMIN to the `@Roles`(...) list alongside OrgRoles.OWNER and
OrgRoles.ECOSYSTEM_LEAD so PLATFORM_ADMIN users can access it (matching other
ecosystem endpoints), otherwise leave it out and add a clear comment explaining
the deliberate exclusion and update/add a guard or unit test that enforces this
intended behavior; refer to the `@Roles` decorator and the OrgRoles enum to locate
and change the authorization config.

In `@apps/ecosystem/repositories/ecosystem.repository.ts`:
- Around line 401-406: The first call to updateEcosystemInvitationStatusByEmail
in ecosystem.service.ts passes arguments in the wrong order; change the
invocation that currently passes (orgId, userEmail, ecosystemId,
Invitation.PENDING) so it instead passes (userEmail, orgId, ecosystemId,
Invitation.PENDING) to match the method signature (email, orgId, ecosystemId,
status) used in updateEcosystemInvitationStatusByEmail.

---

Nitpick comments:
In `@apps/api-gateway/src/authz/guards/ecosystem-roles.guard.ts`:
- Around line 10-15: The local EcosystemRoleGroup interface duplicates the
existing EcosystemAccess type in jwt-payload.interface.ts; remove the local
interface and import EcosystemAccess, then update all type annotations that used
EcosystemRoleGroup (e.g., the parameter/variable types referenced in
ecosystem-roles.guard.ts, including the usage at the location currently
annotated with EcosystemRoleGroup on the role-check logic) to use
EcosystemAccess instead to avoid duplication and keep types consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f9215cef-88da-48a9-8f7a-f9e3a9c33c3e

📥 Commits

Reviewing files that changed from the base of the PR and between 77d6319 and 03feb31.

📒 Files selected for processing (7)
  • apps/api-gateway/src/authz/guards/ecosystem-roles.guard.ts
  • apps/api-gateway/src/authz/jwt-payload.interface.ts
  • apps/api-gateway/src/authz/jwt.strategy.ts
  • apps/api-gateway/src/ecosystem/ecosystem.controller.ts
  • apps/api-gateway/src/ecosystem/intent/intent.controller.ts
  • apps/ecosystem/repositories/ecosystem.repository.ts
  • apps/ecosystem/src/ecosystem.service.ts
💤 Files with no reviewable changes (1)
  • apps/ecosystem/src/ecosystem.service.ts

@pranalidhanavade pranalidhanavade force-pushed the refactor/check-ecosystem-exist-from-jwt-token branch from 3957692 to 3299222 Compare March 4, 2026 13:50
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/ecosystem/src/ecosystem.service.ts (1)

481-486: ⚠️ Potential issue | 🔴 Critical

Incorrect parameter order - will update wrong invitation record.

This call site still uses the old parameter order (orgId, userEmail, ecosystemId, status), but the repository method signature was changed to (email, orgId, ecosystemId, status). This will cause the method to search for an invitation with email = orgId and invitedOrg = userEmail, which will either fail to find any record or update the wrong one.

🐛 Proposed fix
       const result = await this.ecosystemRepository.updateEcosystemInvitationStatusByEmail(
-        orgId,
         userEmail,
+        orgId,
         ecosystemId,
         status
       );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/ecosystem/src/ecosystem.service.ts` around lines 481 - 486, The call to
updateEcosystemInvitationStatusByEmail in ecosystem.service.ts is passing
arguments in the old order (orgId, userEmail, ecosystemId, status) but the
repository signature is now (email, orgId, ecosystemId, status); change the call
to pass userEmail first, then orgId, then ecosystemId and status so the call
becomes updateEcosystemInvitationStatusByEmail(userEmail, orgId, ecosystemId,
status) to ensure the correct invitation record is updated.
🧹 Nitpick comments (1)
apps/api-gateway/src/authz/guards/ecosystem-roles.guard.ts (1)

10-15: Consider importing the type from jwt-payload.interface.ts.

The EcosystemRoleGroup interface duplicates the EcosystemAccess type structure defined in jwt-payload.interface.ts. While functional, importing the existing type would improve maintainability and ensure consistency if the structure changes.

♻️ Suggested refactor
+import { EcosystemAccess } from '../jwt-payload.interface';
 import { Injectable } from '@nestjs/common';
 import { OrgRoles } from 'libs/org-roles/enums';
 import { ROLES_KEY } from '../decorators/roles.decorator';
 import { Reflector } from '@nestjs/core';
 import { ResponseMessages } from '@credebl/common/response-messages';
 import { validate as isValidUUID } from 'uuid';

-interface EcosystemRoleGroup {
-  ecosystem_role?: {
-    lead?: string[];
-    member?: string[];
-  };
-}

Then update line 92:

-      const hasAccess = Object.values(ecosystemAccess).some((entry: EcosystemRoleGroup) => {
+      const hasAccess = Object.values(ecosystemAccess).some((entry: EcosystemAccess) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/api-gateway/src/authz/guards/ecosystem-roles.guard.ts` around lines 10 -
15, Replace the duplicated local interface EcosystemRoleGroup with the existing
type from jwt-payload.interface.ts by removing the local declaration and
importing EcosystemAccess; then update any usages (e.g., the type annotation
that currently references EcosystemRoleGroup—seen near the code around line 92)
to use EcosystemAccess instead so the guard consistently depends on the single
shared type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/ecosystem/repositories/ecosystem.repository.ts`:
- Around line 401-406: The call site in ecosystem.service.ts is passing
arguments to updateEcosystemInvitationStatusByEmail in the wrong order (orgId,
userEmail, ecosystemId, status); change the call to pass (email, orgId,
ecosystemId, status) by swapping the first two arguments so it becomes
(userEmail, orgId, ecosystemId, status) to match the repository method signature
updateEcosystemInvitationStatusByEmail(email: string, orgId: string,
ecosystemId: string, status: Invitation).

---

Outside diff comments:
In `@apps/ecosystem/src/ecosystem.service.ts`:
- Around line 481-486: The call to updateEcosystemInvitationStatusByEmail in
ecosystem.service.ts is passing arguments in the old order (orgId, userEmail,
ecosystemId, status) but the repository signature is now (email, orgId,
ecosystemId, status); change the call to pass userEmail first, then orgId, then
ecosystemId and status so the call becomes
updateEcosystemInvitationStatusByEmail(userEmail, orgId, ecosystemId, status) to
ensure the correct invitation record is updated.

---

Nitpick comments:
In `@apps/api-gateway/src/authz/guards/ecosystem-roles.guard.ts`:
- Around line 10-15: Replace the duplicated local interface EcosystemRoleGroup
with the existing type from jwt-payload.interface.ts by removing the local
declaration and importing EcosystemAccess; then update any usages (e.g., the
type annotation that currently references EcosystemRoleGroup—seen near the code
around line 92) to use EcosystemAccess instead so the guard consistently depends
on the single shared type.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a9ba89b2-9758-4072-99ea-7c99e3569394

📥 Commits

Reviewing files that changed from the base of the PR and between 3957692 and 3299222.

📒 Files selected for processing (7)
  • apps/api-gateway/src/authz/guards/ecosystem-roles.guard.ts
  • apps/api-gateway/src/authz/jwt-payload.interface.ts
  • apps/api-gateway/src/authz/jwt.strategy.ts
  • apps/api-gateway/src/ecosystem/ecosystem.controller.ts
  • apps/api-gateway/src/ecosystem/intent/intent.controller.ts
  • apps/ecosystem/repositories/ecosystem.repository.ts
  • apps/ecosystem/src/ecosystem.service.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/api-gateway/src/ecosystem/ecosystem.controller.ts
  • apps/api-gateway/src/authz/jwt-payload.interface.ts

…er's token

Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
@pranalidhanavade pranalidhanavade force-pushed the refactor/check-ecosystem-exist-from-jwt-token branch from 6d949f1 to f034e8e Compare March 5, 2026 11:34
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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/api-gateway/src/authz/guards/ecosystem-roles.guard.ts`:
- Around line 76-105: The current guard returns after checking membership
(ecosystemIdExists -> hasAccess) which allows plain members to pass even when
the endpoint requires a higher org role; modify the logic in
ecosystem-roles.guard.ts to (1) determine the required role for the route (e.g.,
OrgRoles.ECOSYSTEM_LEAD) instead of treating membership as sufficient, (2)
inspect user?.ecosystem_access (EcosystemRoleGroup) for the specific role list
(entry.ecosystem_role.lead vs .member) for the given ecosystemId, (3) only set
user.selectedEcosystem and return true if the required role is present,
otherwise throw a ForbiddenException with the existing ResponseMessages error,
and (4) ensure this check occurs before the early return that currently follows
hasAccess so role requirements are enforced.

In `@apps/ecosystem/repositories/ecosystem.repository.ts`:
- Around line 1193-1218: The code sets finalOrgIds directly when orgId is
provided, allowing cross-ecosystem access; change the branch so that when orgId
is present you first validate membership by querying this.prisma.ecosystem_orgs
(use findFirst/findUnique) with both orgId and ecosystemId and the same
deletedAt/null and status ACTIVE checks, and if that membership record is
missing return { totalPages: 0, data: [] }; only then set finalOrgIds = [orgId].
This ensures finalOrgIds, orgId and ecosystemId are always scoped to the
ecosystem before building the whereClause (also apply same validation where
similar logic appears around the subsequent orgId handling).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fa27a995-1a49-4d44-acec-a30341fd30e2

📥 Commits

Reviewing files that changed from the base of the PR and between 3299222 and f034e8e.

📒 Files selected for processing (10)
  • apps/api-gateway/src/authz/guards/ecosystem-roles.guard.ts
  • apps/api-gateway/src/authz/jwt-payload.interface.ts
  • apps/api-gateway/src/authz/jwt.strategy.ts
  • apps/api-gateway/src/ecosystem/ecosystem.controller.ts
  • apps/api-gateway/src/ecosystem/ecosystem.service.ts
  • apps/api-gateway/src/ecosystem/intent/intent.controller.ts
  • apps/ecosystem/interfaces/ecosystem.interfaces.ts
  • apps/ecosystem/repositories/ecosystem.repository.ts
  • apps/ecosystem/src/ecosystem.controller.ts
  • apps/ecosystem/src/ecosystem.service.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/api-gateway/src/authz/jwt-payload.interface.ts
  • apps/api-gateway/src/authz/jwt.strategy.ts

Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
@pranalidhanavade pranalidhanavade requested a review from sujitaw March 6, 2026 07:48
Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 6, 2026

@pranalidhanavade pranalidhanavade merged commit 1d4c59b into main Mar 6, 2026
8 checks passed
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