chore: IsOrg guard api v2 (#15563)
* chore: is org guard api v2 * fixup! chore: is org guard api v2 * fixup! fixup! chore: is org guard api v2
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
import { ExecutionContext } from "@nestjs/common";
|
||||
import { createParamDecorator } from "@nestjs/common";
|
||||
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
|
||||
export type GetOrgReturnType = Team;
|
||||
|
||||
export const GetOrg = createParamDecorator<
|
||||
keyof GetOrgReturnType | (keyof GetOrgReturnType)[],
|
||||
ExecutionContext
|
||||
>((data, ctx) => {
|
||||
const request = ctx.switchToHttp().getRequest();
|
||||
const organization = request.organization as GetOrgReturnType;
|
||||
|
||||
if (!organization) {
|
||||
throw new Error("GetOrg decorator : Org not found");
|
||||
}
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
return data.reduce((prev, curr) => {
|
||||
return {
|
||||
...prev,
|
||||
[curr]: organization[curr],
|
||||
};
|
||||
}, {});
|
||||
}
|
||||
|
||||
if (data) {
|
||||
return organization[data];
|
||||
}
|
||||
|
||||
return organization;
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
import { OrganizationsRepository } from "@/modules/organizations/organizations.repository";
|
||||
import { Injectable, CanActivate, ExecutionContext, ForbiddenException } from "@nestjs/common";
|
||||
import { Request } from "express";
|
||||
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
|
||||
@Injectable()
|
||||
export class isOrgGuard implements CanActivate {
|
||||
constructor(private organizationsRepository: OrganizationsRepository) {}
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const request = context.switchToHttp().getRequest<Request & { organization: Team }>();
|
||||
const organizationId: string = request.params.orgId;
|
||||
|
||||
if (!organizationId) {
|
||||
throw new ForbiddenException("No organization id found in request params.");
|
||||
}
|
||||
|
||||
const org = await this.organizationsRepository.findById(Number(organizationId));
|
||||
|
||||
if (org && org.isOrganization) {
|
||||
request.organization = org;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
import { bootstrap } from "@/app";
|
||||
import { AppModule } from "@/app.module";
|
||||
import { PrismaModule } from "@/modules/prisma/prisma.module";
|
||||
import { TokensModule } from "@/modules/tokens/tokens.module";
|
||||
import { UsersModule } from "@/modules/users/users.module";
|
||||
import { INestApplication } from "@nestjs/common";
|
||||
import { NestExpressApplication } from "@nestjs/platform-express";
|
||||
import { Test } from "@nestjs/testing";
|
||||
import { User } from "@prisma/client";
|
||||
import * as request from "supertest";
|
||||
import { TeamRepositoryFixture } from "test/fixtures/repository/team.repository.fixture";
|
||||
import { UserRepositoryFixture } from "test/fixtures/repository/users.repository.fixture";
|
||||
import { withApiAuth } from "test/utils/withApiAuth";
|
||||
|
||||
import { SUCCESS_STATUS } from "@calcom/platform-constants";
|
||||
import { ApiSuccessResponse } from "@calcom/platform-types";
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
|
||||
describe("Organizations Team Endpoints", () => {
|
||||
describe("User Authentication", () => {
|
||||
let app: INestApplication;
|
||||
|
||||
let userRepositoryFixture: UserRepositoryFixture;
|
||||
let organizationsRepositoryFixture: TeamRepositoryFixture;
|
||||
let org: Team;
|
||||
|
||||
const userEmail = "org-teams-controller-e2e@api.com";
|
||||
let user: User;
|
||||
|
||||
beforeAll(async () => {
|
||||
const moduleRef = await withApiAuth(
|
||||
userEmail,
|
||||
Test.createTestingModule({
|
||||
imports: [AppModule, PrismaModule, UsersModule, TokensModule],
|
||||
})
|
||||
).compile();
|
||||
|
||||
userRepositoryFixture = new UserRepositoryFixture(moduleRef);
|
||||
organizationsRepositoryFixture = new TeamRepositoryFixture(moduleRef);
|
||||
|
||||
user = await userRepositoryFixture.create({
|
||||
email: userEmail,
|
||||
username: userEmail,
|
||||
});
|
||||
|
||||
org = await organizationsRepositoryFixture.create({
|
||||
name: "Test Organization",
|
||||
isOrganization: true,
|
||||
});
|
||||
|
||||
app = moduleRef.createNestApplication();
|
||||
bootstrap(app as NestExpressApplication);
|
||||
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it("should be defined", () => {
|
||||
expect(userRepositoryFixture).toBeDefined();
|
||||
expect(organizationsRepositoryFixture).toBeDefined();
|
||||
expect(user).toBeDefined();
|
||||
expect(org).toBeDefined();
|
||||
});
|
||||
|
||||
it("should get all the teams of the org", async () => {
|
||||
return request(app.getHttpServer())
|
||||
.get(`/v2/organizations/${org.id}/teams`)
|
||||
.expect(200)
|
||||
.then((response) => {
|
||||
const responseBody: ApiSuccessResponse<Team[]> = response.body;
|
||||
expect(responseBody.status).toEqual(SUCCESS_STATUS);
|
||||
expect(responseBody.data).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await userRepositoryFixture.deleteByEmail(user.email);
|
||||
await organizationsRepositoryFixture.delete(org.id);
|
||||
await app.close();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
import { API_VERSIONS_VALUES } from "@/lib/api-versions";
|
||||
import { GetOrg } from "@/modules/auth/decorators/get-org/get-org.decorator";
|
||||
import { ApiAuthGuard } from "@/modules/auth/guards/api-auth/api-auth.guard";
|
||||
import { isOrgGuard } from "@/modules/auth/guards/organizations/is-org.guard";
|
||||
import { Controller, UseGuards, Get, Param, ParseIntPipe } from "@nestjs/common";
|
||||
import { ApiTags as DocsTags } from "@nestjs/swagger";
|
||||
|
||||
import { SUCCESS_STATUS } from "@calcom/platform-constants";
|
||||
import { ApiResponse } from "@calcom/platform-types";
|
||||
import { Team } from "@calcom/prisma/client";
|
||||
|
||||
@Controller({
|
||||
path: "/v2/organizations/:orgId/teams",
|
||||
version: API_VERSIONS_VALUES,
|
||||
})
|
||||
@UseGuards(ApiAuthGuard, isOrgGuard)
|
||||
@DocsTags("Organizations Teams")
|
||||
export class OrganizationsTeamsController {
|
||||
@Get()
|
||||
async getAllTeams(
|
||||
@Param("orgId", ParseIntPipe) orgId: number,
|
||||
@GetOrg() organization: Team,
|
||||
@GetOrg("name") orgName: string
|
||||
): Promise<ApiResponse<Team[]>> {
|
||||
console.log(orgId, organization, orgName);
|
||||
return {
|
||||
status: SUCCESS_STATUS,
|
||||
data: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { OrganizationsTeamsController } from "@/modules/organizations/controllers/organizations-teams.controller";
|
||||
import { OrganizationsRepository } from "@/modules/organizations/organizations.repository";
|
||||
import { OrganizationsService } from "@/modules/organizations/services/organizations.service";
|
||||
import { PrismaModule } from "@/modules/prisma/prisma.module";
|
||||
@@ -8,5 +9,6 @@ import { Module } from "@nestjs/common";
|
||||
imports: [PrismaModule, StripeModule],
|
||||
providers: [OrganizationsRepository, OrganizationsService],
|
||||
exports: [OrganizationsService, OrganizationsRepository],
|
||||
controllers: [OrganizationsTeamsController],
|
||||
})
|
||||
export class OrganizationsModule {}
|
||||
|
||||
@@ -16,6 +16,7 @@ export class OrganizationsRepository {
|
||||
return this.dbRead.prisma.team.findUnique({
|
||||
where: {
|
||||
id: organizationId,
|
||||
isOrganization: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user