Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion autoadmin-ws-server/src/services/token-validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export async function validateConnectionToken(connectionToken: string): Promise<

try {
const checkUrl = `${config.checkConnectionTokenUrl}?token=${connectionToken}`;
logger.info({ url: checkUrl }, 'Validating connection token');

const response = await fetch(checkUrl);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,8 @@ export function validateQuerySafety(query: string, connectionType: ConnectionTyp

function normalizeQuery(query: string): string {
return query
.replace(/\/\*!(\d+)?\s*([\s\S]*?)\*\//g, ' $2 ')
.replace(/#.*$/gm, '')
.replace(/--.*$/gm, '')
.replace(/\/\*[\s\S]*?\*\//g, '')
.replace(/\s+/g, ' ')
Expand Down
156 changes: 77 additions & 79 deletions backend/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,91 +15,89 @@ import { Constants } from './helpers/constants/constants.js';
import { requiredEnvironmentVariablesValidator } from './helpers/validators/required-environment-variables.validator.js';

async function bootstrap() {
try {
requiredEnvironmentVariablesValidator();
const appOptions: NestApplicationOptions = {
rawBody: true,
logger: new WinstonLogger(),
};

const app = await NestFactory.create<NestExpressApplication>(ApplicationModule, appOptions);
app.useLogger(app.get(WinstonLogger));
app.set('query parser', 'extended');

Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
});

const globalPrefix = process.env.GLOBAL_PREFIX || '/';
app.setGlobalPrefix(globalPrefix);

app.useGlobalFilters(new AllExceptionsFilter(app.get(WinstonLogger)));

app.use(helmet());

app.use(cookieParser());

app.enableCors({
origin: [
'https://app.autoadmin.org',
'http://localhost:4200',
'https://app.rocketadmin.org',
'https://saas.rocketadmin.com',
'https://app-beta.rocketadmin.com',
Constants.APP_DOMAIN_ADDRESS,
],
methods: 'GET,PUT,PATCH,POST,DELETE',
credentials: true,
preflightContinue: false,
optionsSuccessStatus: 204,
});

app.use(cookieParser());

app.use(bodyParser.json({ limit: '10mb' }));
app.use(bodyParser.urlencoded({ limit: '10mb', extended: true }));

const config = new DocumentBuilder()
.setTitle('Rocketadmin')
.setDescription('The Rocketadmin API description')
.setVersion('1.0')
.addTag('rocketadmin')
.setBasePath(globalPrefix)
.addApiKey({
type: 'apiKey',
name: 'x-api-key',
in: 'header',
})
.addCookieAuth(Constants.JWT_COOKIE_KEY_NAME)
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('docs', app, document);

app.useGlobalPipes(
new ValidationPipe({
exceptionFactory(validationErrors: ValidationError[] = []) {
return new ValidationException(validationErrors);
},
}),
);

await app.listen(3000);
} catch (e) {
console.error(`Failed to initialize, due to ${e}`);
process.exit(1);
}
try {
requiredEnvironmentVariablesValidator();
const appOptions: NestApplicationOptions = {
rawBody: true,
logger: new WinstonLogger(),
};

const app = await NestFactory.create<NestExpressApplication>(ApplicationModule, appOptions);
app.useLogger(app.get(WinstonLogger));
app.set('query parser', 'extended');

Sentry.init({
dsn: process.env.SENTRY_DSN,
tracesSampleRate: 1.0,
});

const globalPrefix = process.env.GLOBAL_PREFIX || '/';
app.setGlobalPrefix(globalPrefix);

app.useGlobalFilters(new AllExceptionsFilter(app.get(WinstonLogger)));

app.use(helmet());

app.enableCors({
origin: [
'https://app.autoadmin.org',
'http://localhost:4200',
'https://app.rocketadmin.org',
'https://saas.rocketadmin.com',
'https://app-beta.rocketadmin.com',
Constants.APP_DOMAIN_ADDRESS,
],
methods: 'GET,PUT,PATCH,POST,DELETE',
credentials: true,
preflightContinue: false,
optionsSuccessStatus: 204,
});

app.use(cookieParser());

app.use(bodyParser.json({ limit: '10mb' }));
app.use(bodyParser.urlencoded({ limit: '10mb', extended: true }));

const config = new DocumentBuilder()
.setTitle('Rocketadmin')
.setDescription('The Rocketadmin API description')
.setVersion('1.0')
.addTag('rocketadmin')
.setBasePath(globalPrefix)
.addApiKey({
type: 'apiKey',
name: 'x-api-key',
in: 'header',
})
.addCookieAuth(Constants.JWT_COOKIE_KEY_NAME)
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('docs', app, document);

app.useGlobalPipes(
new ValidationPipe({
exceptionFactory(validationErrors: ValidationError[] = []) {
return new ValidationException(validationErrors);
},
}),
);

await app.listen(3000);
} catch (e) {
console.error(`Failed to initialize, due to ${e}`);
process.exit(1);
}
}

const temp = process.exit;

process.exit = () => {
console.trace();
process.exit = temp;
process.exit();
console.trace();
process.exit = temp;
process.exit();
};

bootstrap().catch((e) => {
console.error(`Bootstrap promise failed with error: ${e}`);
process.exit(1);
console.error(`Bootstrap promise failed with error: ${e}`);
process.exit(1);
});
57 changes: 29 additions & 28 deletions backend/src/shared/services/turnstile.service.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,45 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import axios from 'axios';
import { isTest } from '../../helpers/app/is-test.js';
import { isSaaS } from '../../helpers/app/is-saas.js';

interface TurnstileVerifyResponse {
success: boolean;
'error-codes'?: string[];
challenge_ts?: string;
hostname?: string;
success: boolean;
'error-codes'?: string[];
challenge_ts?: string;
hostname?: string;
}

@Injectable()
export class TurnstileService {
private readonly verifyUrl = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';
private readonly verifyUrl = 'https://challenges.cloudflare.com/turnstile/v0/siteverify';

async verifyToken(token: string): Promise<boolean> {
const secretKey = process.env.TURNSTILE_SECRET_KEY;
async verifyToken(token: string): Promise<boolean> {
const secretKey = process.env.TURNSTILE_SECRET_KEY;

if (!secretKey) {
console.warn('Turnstile secret key is not configured. Skipping verification.');
return true;
}
if (isTest() || !isSaaS()) {
return true;
}

if (!token || typeof token !== 'string') {
throw new BadRequestException('Turnstile token is required.');
}
if (!token || typeof token !== 'string') {
throw new BadRequestException('Turnstile token is required.');
}

const formData = new URLSearchParams();
formData.append('secret', secretKey);
formData.append('response', token);
const formData = new URLSearchParams();
formData.append('secret', secretKey);
formData.append('response', token);

const response = await axios.post<TurnstileVerifyResponse>(this.verifyUrl, formData.toString(), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});
const response = await axios.post<TurnstileVerifyResponse>(this.verifyUrl, formData.toString(), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
});

if (!response.data.success) {
const errorCodes = response.data['error-codes']?.join(', ') || 'Unknown error';
throw new BadRequestException(`Turnstile verification failed: ${errorCodes}`);
}
if (!response.data.success) {
const errorCodes = response.data['error-codes']?.join(', ') || 'Unknown error';
throw new BadRequestException(`Turnstile verification failed: ${errorCodes}`);
}

return true;
}
return true;
}
}
Loading
Loading