Merge pull request #8958 from ever-co/fix/convert-native-parameters-dto

[Fix] DTO Request
This commit is contained in:
Rahul R.
2025-05-15 16:17:43 +05:30
committed by GitHub
3 changed files with 58 additions and 44 deletions
@@ -100,29 +100,37 @@ export function escapeQueryWithParameters(nativeParameters: PlainObject): Tenant
}
/**
* Recursively converts raw parameters, parsing booleans and handling arrays and objects.
* Parses the given value and converts it to a boolean using JSON.parse.
*
* @param parameters - Raw input parameters
* @returns Converted parameters with booleans properly parsed
* @param value - The value to be parsed.
* @returns {boolean} - The boolean representation of the parsed value.
*/
export function convertNativeParameters(parameters: PlainObject): any {
if (parameters === null || parameters === undefined) {
export const parseBool = (value: any): boolean => Boolean(JSON.parse(value));
/**
* Converts native parameters based on the database connection type.
*
* @param parameters - The parameters to be converted.
* @returns {any} - The converted parameters based on the database connection type.
*/
export const convertNativeParameters = (parameters: PlainObject): any => {
try {
if (Array.isArray(parameters)) {
// Process each array item recursively
return parameters.map((item) => convertNativeParameters(item));
}
if (typeof parameters === 'object' && parameters !== null) {
// Recursively convert nested objects
return Object.keys(parameters).reduce((acc, key) => {
acc[key] = convertNativeParameters(parameters[key]);
return acc;
}, {});
}
// Convert boolean values to their numeric representation
return parseBool(parameters);
} catch (error) {
return parameters;
}
if (Array.isArray(parameters)) {
// Process each array item recursively
return parameters.map((item) => convertNativeParameters(item));
}
if (typeof parameters === 'object') {
// Recursively convert nested objects
return Object.keys(parameters).reduce((acc, key) => {
acc[key] = convertNativeParameters(parameters[key]);
return acc;
}, {} as Record<string, any>);
}
// Primitive value: try to parse boolean
return parseToBoolean(parameters);
}
};
@@ -1,6 +1,6 @@
import { Injectable } from '@nestjs/common';
import { ValidationArguments, ValidatorConstraint, ValidatorConstraintInterface } from 'class-validator';
import { IOrganization } from '@gauzy/contracts';
import { ID, IOrganization } from '@gauzy/contracts';
import { isEmpty } from '@gauzy/utils';
import { RequestContext } from '../../../core/context';
import { MultiORM, MultiORMEnum, getORMType } from '../../../core/utils';
@@ -27,59 +27,64 @@ export class OrganizationBelongsToUserConstraint implements ValidatorConstraintI
* @param value - The organization ID or organization object.
* @returns {Promise<boolean>} - True if the user belongs to the organization, otherwise false.
*/
async validate(value: IOrganization['id'] | IOrganization): Promise<boolean> {
async validate(value: ID | IOrganization): Promise<boolean> {
if (isEmpty(value)) {
return true;
}
// 'value' can be either a string (organization ID) or an organization object.
const organizationId: string = typeof value === 'string' ? value : value.id;
const organizationId = typeof value === 'string' ? value : value.id;
// Use the consolidated ORM logic function
return await this.checkOrganizationExistence(organizationId);
return this.checkOrganizationExistence(organizationId);
}
/**
* Checks if the given organization exists for the current user in the database.
*
* @param organizationId The ID of the organization.
* @param organizationId - The ID of the organization.
* @returns {Promise<boolean>} - True if found, false otherwise.
*/
async checkOrganizationExistence(organizationId: string): Promise<boolean> {
const tenantId = RequestContext.currentTenantId();
const userId = RequestContext.currentUserId();
if (!tenantId || !userId) {
return false;
}
try {
switch (ormType) {
case MultiORMEnum.MikroORM:
return !!(await this.mikroOrmUserOrganizationRepository.findOneOrFail({
case MultiORMEnum.MikroORM: {
await this.mikroOrmUserOrganizationRepository.findOneOrFail({
tenantId,
userId,
organizationId
}));
case MultiORMEnum.TypeORM:
return !!(await this.typeOrmUserOrganizationRepository.findOneByOrFail({
});
return true;
}
case MultiORMEnum.TypeORM: {
await this.typeOrmUserOrganizationRepository.findOneByOrFail({
tenantId,
userId,
organizationId
}));
});
return true;
}
default:
throw new Error(`Not implemented for ${ormType}`);
throw new Error(`ORM type "${ormType}" not implemented.`);
}
} catch (error) {
} catch {
return false;
}
}
/**
* Gets the default error message when the validation fails.
* @param validationArguments - Validation arguments containing the value.
* Gets the default error message when validation fails.
*
* @returns {string} - Default error message.
*/
defaultMessage(validationArguments?: ValidationArguments): string {
const { value } = validationArguments;
return `The user with ID ${RequestContext.currentUserId()} is not associated with the specified organization (${JSON.stringify(
value
)}).`;
defaultMessage(): string {
const userId = RequestContext.currentUserId();
return `The user with ID ${userId} is not associated with the specified organization.`;
}
}
@@ -2,6 +2,7 @@ import { CallHandler, ExecutionContext, Inject, Injectable, NestInterceptor, Opt
import { ContextType, HttpArgumentsHost, RpcArgumentsHost, WsArgumentsHost } from '@nestjs/common/interfaces';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import * as crypto from 'crypto';
import { PosthogEventInterceptorOptions } from './posthog.interfaces';
import { PosthogService } from './posthog.service';
import { SanitizerUtil } from './utils';
@@ -289,7 +290,7 @@ export class PosthogEventInterceptor implements NestInterceptor {
*/
private extractUserId(request: any): string {
// Generate a random ID if no user identifier is found
const anonymousId = `anon-${Math.random().toString(36).substring(2, 15)}`;
const anonymousId = `anon-${crypto.randomUUID()}`;
// Check common user ID locations
return (