fix: Use Memberships with OWNER role for platform owner lookup (#22475)

* fix platform owner identification to use Memberships with OWNER role

* replaced the hardcoded OWNER string with the enum value

* replaced enum with hard coded OWNER value for safty

* added enum usage

* added admin lookout if owner validation fails

* chore

* chore

* fixed tests

* chore

* chore

* chore

* chore

---------

Co-authored-by: Devanshu Sharma <devanshusharma658@gmail.com>
Co-authored-by: Kartik Saini <41051387+kart1ka@users.noreply.github.com>
Co-authored-by: Rajiv Sahal <sahalrajiv-extc@atharvacoe.ac.in>
Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com>
This commit is contained in:
Sahitya Chandra
2025-08-22 14:14:28 +05:30
committed by GitHub
co-authored by Devanshu Sharma Kartik Saini Rajiv Sahal Anik Dhabal Babu
parent 2266301469
commit 99cd0c5c41
6 changed files with 75 additions and 6 deletions
@@ -6,7 +6,6 @@ import { NextAuthStrategy } from "@/modules/auth/strategies/next-auth/next-auth.
import { DeploymentsModule } from "@/modules/deployments/deployments.module";
import { MembershipsModule } from "@/modules/memberships/memberships.module";
import { OAuthFlowService } from "@/modules/oauth-clients/services/oauth-flow.service";
import { ProfilesModule } from "@/modules/profiles/profiles.module";
import { RedisModule } from "@/modules/redis/redis.module";
import { TokensModule } from "@/modules/tokens/tokens.module";
import { UsersModule } from "@/modules/users/users.module";
@@ -22,7 +21,6 @@ import { PassportModule } from "@nestjs/passport";
MembershipsModule,
TokensModule,
DeploymentsModule,
ProfilesModule,
],
providers: [NextAuthGuard, NextAuthStrategy, ApiAuthGuard, ApiAuthStrategy, OAuthFlowService],
exports: [NextAuthGuard, ApiAuthGuard],
@@ -4,6 +4,7 @@ import { ApiKeysRepository } from "@/modules/api-keys/api-keys-repository";
import { DeploymentsRepository } from "@/modules/deployments/deployments.repository";
import { DeploymentsService } from "@/modules/deployments/deployments.service";
import { JwtService } from "@/modules/jwt/jwt.service";
import { MembershipsModule } from "@/modules/memberships/memberships.module";
import { OAuthClientRepository } from "@/modules/oauth-clients/oauth-client.repository";
import { OAuthFlowService } from "@/modules/oauth-clients/services/oauth-flow.service";
import { PrismaReadService } from "@/modules/prisma/prisma-read.service";
@@ -20,6 +21,7 @@ import { Test, TestingModule } from "@nestjs/testing";
import { PlatformOAuthClient, Team, User } from "@prisma/client";
import { createRequest } from "node-mocks-http";
import { ApiKeysRepositoryFixture } from "test/fixtures/repository/api-keys.repository.fixture";
import { MembershipRepositoryFixture } from "test/fixtures/repository/membership.repository.fixture";
import { OAuthClientRepositoryFixture } from "test/fixtures/repository/oauth-client.repository.fixture";
import { ProfileRepositoryFixture } from "test/fixtures/repository/profiles.repository.fixture";
import { TeamRepositoryFixture } from "test/fixtures/repository/team.repository.fixture";
@@ -45,6 +47,7 @@ describe("ApiAuthStrategy", () => {
let apiKeysRepositoryFixture: ApiKeysRepositoryFixture;
let oAuthClientRepositoryFixture: OAuthClientRepositoryFixture;
let profilesRepositoryFixture: ProfileRepositoryFixture;
let membershipRepositoryFixture: MembershipRepositoryFixture;
const validApiKeyEmail = `api-auth-api-key-user-${randomString()}@api.com`;
const validAccessTokenEmail = `api-auth-access-token-user-${randomString()}@api.com`;
@@ -65,6 +68,7 @@ describe("ApiAuthStrategy", () => {
}),
ProfilesModule,
TokensModule,
MembershipsModule,
],
providers: [
MockedRedisService,
@@ -91,6 +95,7 @@ describe("ApiAuthStrategy", () => {
teamRepositoryFixture = new TeamRepositoryFixture(module);
oAuthClientRepositoryFixture = new OAuthClientRepositoryFixture(module);
profilesRepositoryFixture = new ProfileRepositoryFixture(module);
membershipRepositoryFixture = new MembershipRepositoryFixture(module);
organization = await teamRepositoryFixture.create({ name: `api-auth-organization-1-${randomString()}` });
organizationTwo = await teamRepositoryFixture.create({
name: `api-auth-organization-2-${randomString()}`,
@@ -121,6 +126,20 @@ describe("ApiAuthStrategy", () => {
organization: { connect: { id: organizationTwo.id } },
});
await membershipRepositoryFixture.create({
user: { connect: { id: validOAuthUser.id } },
team: { connect: { id: organization.id } },
role: "OWNER",
accepted: true,
});
await membershipRepositoryFixture.create({
user: { connect: { id: validOAuthUser.id } },
team: { connect: { id: organizationTwo.id } },
role: "OWNER",
accepted: true,
});
const data = {
logo: "logo-url",
name: "name",
@@ -4,9 +4,9 @@ import { isOriginAllowed } from "@/lib/is-origin-allowed/is-origin-allowed";
import { BaseStrategy } from "@/lib/passport/strategies/types";
import { ApiKeysRepository } from "@/modules/api-keys/api-keys-repository";
import { DeploymentsService } from "@/modules/deployments/deployments.service";
import { MembershipsRepository } from "@/modules/memberships/memberships.repository";
import { OAuthClientRepository } from "@/modules/oauth-clients/oauth-client.repository";
import { OAuthFlowService } from "@/modules/oauth-clients/services/oauth-flow.service";
import { ProfilesRepository } from "@/modules/profiles/profiles.repository";
import { TokensRepository } from "@/modules/tokens/tokens.repository";
import { TokensService } from "@/modules/tokens/tokens.service";
import { UsersService } from "@/modules/users/services/users.service";
@@ -45,8 +45,8 @@ export class ApiAuthStrategy extends PassportStrategy(BaseStrategy, "api-auth")
private readonly userRepository: UsersRepository,
private readonly apiKeyRepository: ApiKeysRepository,
private readonly oauthRepository: OAuthClientRepository,
private readonly profilesRepository: ProfilesRepository,
private readonly usersService: UsersService
private readonly usersService: UsersService,
private readonly membershipsRepository: MembershipsRepository
) {
super();
}
@@ -172,7 +172,9 @@ export class ApiAuthStrategy extends PassportStrategy(BaseStrategy, "api-auth")
throw new UnauthorizedException("ApiAuthStrategy - oAuth client - Invalid client secret");
}
const platformCreatorId = await this.profilesRepository.getPlatformOwnerUserId(client.organizationId);
const platformCreatorId =
(await this.membershipsRepository.findPlatformOwnerUserId(client.organizationId)) ||
(await this.membershipsRepository.findPlatformAdminUserId(client.organizationId));
if (!platformCreatorId) {
throw new UnauthorizedException(