Skip to content

Commit 0b2b17e

Browse files
committed
Add TurnstileService and SharedModule for token verification
1 parent 4d809c6 commit 0b2b17e

3 files changed

Lines changed: 55 additions & 0 deletions

File tree

backend/src/app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import { SaaSGatewayModule } from './microservices/gateways/saas-gateway.ts/saas
4040
import { SaasModule } from './microservices/saas-microservice/saas.module.js';
4141
import { AppLoggerMiddleware } from './middlewares/logging-middleware/app-logger-middlewate.js';
4242
import { DatabaseModule } from './shared/database/database.module.js';
43+
import { SharedModule } from './shared/shared.module.js';
4344
import { GetHelloUseCase } from './use-cases-app/get-hello.use.case.js';
4445
import { PersonalTableSettingsModule } from './entities/table-settings/personal-table-settings/personal-table-settings.module.js';
4546
import { SavedDbQueryModule } from './entities/visualizations/saved-db-query/saved-db-query.module.js';
@@ -71,6 +72,7 @@ import { DashboardWidgetModule } from './entities/visualizations/dashboard-widge
7172
UserActionModule,
7273
CronJobsModule,
7374
DatabaseModule,
75+
SharedModule,
7476
TableActionModule,
7577
SaasModule,
7678
CompanyInfoModule,
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { BadRequestException, Injectable } from '@nestjs/common';
2+
import axios from 'axios';
3+
4+
interface TurnstileVerifyResponse {
5+
success: boolean;
6+
'error-codes'?: string[];
7+
challenge_ts?: string;
8+
hostname?: string;
9+
}
10+
11+
@Injectable()
12+
export class TurnstileService {
13+
private readonly verifyUrl = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
14+
15+
async verifyToken(token: string): Promise<boolean> {
16+
const secretKey = process.env.TURNSTILE_SECRET_KEY;
17+
18+
if (!secretKey) {
19+
console.warn('Turnstile secret key is not configured. Skipping verification.');
20+
return true;
21+
}
22+
23+
if (!token || typeof token !== 'string') {
24+
throw new BadRequestException('Turnstile token is required.');
25+
}
26+
27+
const formData = new URLSearchParams();
28+
formData.append('secret', secretKey);
29+
formData.append('response', token);
30+
31+
const response = await axios.post<TurnstileVerifyResponse>(this.verifyUrl, formData.toString(), {
32+
headers: {
33+
'Content-Type': 'application/x-www-form-urlencoded',
34+
},
35+
});
36+
37+
if (!response.data.success) {
38+
const errorCodes = response.data['error-codes']?.join(', ') || 'Unknown error';
39+
throw new BadRequestException(`Turnstile verification failed: ${errorCodes}`);
40+
}
41+
42+
return true;
43+
}
44+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Global, Module } from '@nestjs/common';
2+
import { TurnstileService } from './services/turnstile.service.js';
3+
4+
@Global()
5+
@Module({
6+
providers: [TurnstileService],
7+
exports: [TurnstileService],
8+
})
9+
export class SharedModule {}

0 commit comments

Comments
 (0)