-
Notifications
You must be signed in to change notification settings - Fork 8.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: oAuth client guard * refactor test * refactor: move oauth-client guard to oauth module * refactor: separate jest config from package.json * fix: resolving paths in jest tests * fix: tests * jest setup file * fix: jest test warnings about .js platform constants imports * refactor: test repository fixtures * remove allowjs * ignore js files in ts-jest * make oauth client module global * make oauth client module global
- Loading branch information
Showing
11 changed files
with
185 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"moduleFileExtensions": ["js", "json", "ts"], | ||
"rootDir": ".", | ||
"moduleNameMapper": { | ||
"@/(.*)": "<rootDir>/src/$1", | ||
"test/(.*)": "<rootDir>/test/$1" | ||
}, | ||
"testEnvironment": "node", | ||
"testRegex": ".*\\.spec\\.ts$", | ||
"transform": { | ||
"^.+\\.ts$": "ts-jest" | ||
}, | ||
"setupFiles": ["<rootDir>/test/setEnvVars.ts"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
apps/api/v2/src/modules/oauth/guard/oauth-client/oauth-client.guard.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { AppModule } from "@/app.module"; | ||
import { OAuthClientModule } from "@/modules/oauth/oauth-client.module"; | ||
import { createMock } from "@golevelup/ts-jest"; | ||
import { ExecutionContext } from "@nestjs/common"; | ||
import { Test, TestingModule } from "@nestjs/testing"; | ||
import { PlatformOAuthClient } from "@prisma/client"; | ||
import { OAuthClientRepositoryFixture } from "test/fixtures/repository/oauth-client.repository.fixture"; | ||
|
||
import { X_CAL_CLIENT_ID, X_CAL_SECRET_KEY } from "@calcom/platform-constants"; | ||
|
||
import { OAuthClientGuard } from "./oauth-client.guard"; | ||
|
||
describe("OAuthClientGuard", () => { | ||
let guard: OAuthClientGuard; | ||
let oauthClientRepositoryFixture: OAuthClientRepositoryFixture; | ||
let oauthClient: PlatformOAuthClient; | ||
|
||
beforeAll(async () => { | ||
const module: TestingModule = await Test.createTestingModule({ | ||
imports: [AppModule, OAuthClientModule], | ||
}).compile(); | ||
|
||
guard = module.get<OAuthClientGuard>(OAuthClientGuard); | ||
oauthClientRepositoryFixture = new OAuthClientRepositoryFixture(module); | ||
|
||
const organizationId = 1; | ||
const data = { | ||
logo: "logo-url", | ||
name: "name", | ||
redirect_uris: ["redirect-uri"], | ||
permissions: 32, | ||
}; | ||
const secret = "secret"; | ||
|
||
oauthClient = await oauthClientRepositoryFixture.create(organizationId, data, secret); | ||
}); | ||
|
||
it("should be defined", () => { | ||
expect(guard).toBeDefined(); | ||
expect(oauthClient).toBeDefined(); | ||
}); | ||
|
||
it("should return true if client ID and secret are valid", async () => { | ||
const mockContext = createMockExecutionContext({ | ||
[X_CAL_CLIENT_ID]: oauthClient.id, | ||
[X_CAL_SECRET_KEY]: oauthClient.secret, | ||
}); | ||
|
||
await expect(guard.canActivate(mockContext)).resolves.toBe(true); | ||
}); | ||
|
||
it("should return false if client ID is invalid", async () => { | ||
const mockContext = createMockExecutionContext({ | ||
[X_CAL_CLIENT_ID]: "invalid id", | ||
[X_CAL_SECRET_KEY]: oauthClient.secret, | ||
}); | ||
|
||
await expect(guard.canActivate(mockContext)).resolves.toBe(false); | ||
}); | ||
|
||
it("should return false if secret key is invalid", async () => { | ||
const mockContext = createMockExecutionContext({ | ||
[X_CAL_CLIENT_ID]: oauthClient.id, | ||
[X_CAL_SECRET_KEY]: "invalid secret", | ||
}); | ||
|
||
await expect(guard.canActivate(mockContext)).resolves.toBe(false); | ||
}); | ||
|
||
afterAll(async () => { | ||
await oauthClientRepositoryFixture.delete(oauthClient.id); | ||
}); | ||
|
||
function createMockExecutionContext(headers: Record<string, string>): ExecutionContext { | ||
return createMock<ExecutionContext>({ | ||
switchToHttp: () => ({ | ||
getRequest: () => ({ | ||
headers, | ||
}), | ||
}), | ||
}); | ||
} | ||
}); |
29 changes: 29 additions & 0 deletions
29
apps/api/v2/src/modules/oauth/guard/oauth-client/oauth-client.guard.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { OAuthClientRepository } from "@/modules/oauth/oauth-client.repository"; | ||
import { CanActivate, ExecutionContext, Injectable } from "@nestjs/common"; | ||
|
||
import { X_CAL_CLIENT_ID, X_CAL_SECRET_KEY } from "@calcom/platform-constants"; | ||
|
||
@Injectable() | ||
export class OAuthClientGuard implements CanActivate { | ||
constructor(private readonly oauthRepository: OAuthClientRepository) {} | ||
|
||
canActivate(context: ExecutionContext): Promise<boolean> { | ||
const request = context.switchToHttp().getRequest(); | ||
const { headers } = request; | ||
|
||
const oauthClientId = headers[X_CAL_CLIENT_ID]; | ||
const oauthClientSecret = headers[X_CAL_SECRET_KEY]; | ||
|
||
return this.validateOauthClient(oauthClientId, oauthClientSecret); | ||
} | ||
|
||
private async validateOauthClient(oauthClientId: string, oauthClientSecret: string): Promise<boolean> { | ||
const oauthClient = await this.oauthRepository.getOAuthClient(oauthClientId); | ||
|
||
if (!oauthClient || oauthClient.secret !== oauthClientSecret) { | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
apps/api/v2/test/fixtures/repository/oauth-client.repository.fixture.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { CreateOAuthClientInput } from "@/modules/oauth/input/create-oauth-client"; | ||
import { PrismaReadService } from "@/modules/prisma/prisma-read.service"; | ||
import { PrismaWriteService } from "@/modules/prisma/prisma-write.service"; | ||
import { TestingModule } from "@nestjs/testing"; | ||
import { PlatformOAuthClient } from "@prisma/client"; | ||
|
||
export class OAuthClientRepositoryFixture { | ||
private prismaReadClient: PrismaReadService["prisma"]; | ||
private prismaWriteClient: PrismaWriteService["prisma"]; | ||
|
||
constructor(private readonly module: TestingModule) { | ||
this.prismaReadClient = module.get(PrismaReadService).prisma; | ||
this.prismaWriteClient = module.get(PrismaWriteService).prisma; | ||
} | ||
|
||
async get(clientId: PlatformOAuthClient["id"]) { | ||
return this.prismaReadClient.platformOAuthClient.findFirst({ where: { id: clientId } }); | ||
} | ||
|
||
async create(organizationId: number, data: CreateOAuthClientInput, secret: string) { | ||
return this.prismaWriteClient.platformOAuthClient.create({ | ||
data: { | ||
...data, | ||
secret, | ||
organizationId, | ||
}, | ||
}); | ||
} | ||
|
||
async delete(clientId: PlatformOAuthClient["id"]) { | ||
return this.prismaWriteClient.platformOAuthClient.delete({ where: { id: clientId } }); | ||
} | ||
|
||
async deleteByClientId(clientId: PlatformOAuthClient["id"]) { | ||
return this.prismaWriteClient.platformOAuthClient.delete({ where: { id: clientId } }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters