-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #380 from internxt/feat/support-actions-on-sharing…
…s-root [PB-2430] fix: allow sharing password deactivation, workspace sharing permissions fixed
- Loading branch information
Showing
16 changed files
with
548 additions
and
211 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,133 @@ | ||
import { BadRequestException, ExecutionContext, Logger } from '@nestjs/common'; | ||
import { Reflector } from '@nestjs/core'; | ||
import { | ||
extractDataFromRequest, | ||
DataSource, | ||
} from './extract-data-from-request'; // Update with actual path | ||
|
||
describe('extractDataFromRequest', () => { | ||
let request; | ||
let reflector: Reflector; | ||
let context: ExecutionContext; | ||
|
||
beforeEach(() => { | ||
request = { | ||
body: { field1: 'value1' }, | ||
query: { field2: 'value2' }, | ||
params: { field3: 'value3' }, | ||
headers: { field4: 'value4' }, | ||
}; | ||
|
||
reflector = new Reflector(); | ||
context = { | ||
getHandler: jest.fn(), | ||
} as unknown as ExecutionContext; | ||
|
||
jest.spyOn(Logger.prototype, 'error').mockImplementation(() => {}); | ||
jest.spyOn(reflector, 'get').mockImplementation(); | ||
}); | ||
|
||
it('When all fields are present, then it should extract data correctly', () => { | ||
const dataSources: DataSource[] = [ | ||
{ sourceKey: 'body', fieldName: 'field1' }, | ||
{ sourceKey: 'query', fieldName: 'field2' }, | ||
{ | ||
sourceKey: 'params', | ||
fieldName: 'field3', | ||
newFieldName: 'renamedField3', | ||
}, | ||
{ sourceKey: 'headers', fieldName: 'field4' }, | ||
]; | ||
|
||
(reflector.get as jest.Mock).mockReturnValue({ dataSources }); | ||
(context.getHandler as jest.Mock).mockReturnValue('handler'); | ||
|
||
const result = extractDataFromRequest(request, reflector, context); | ||
|
||
expect(result).toEqual({ | ||
field1: 'value1', | ||
field2: 'value2', | ||
renamedField3: 'value3', | ||
field4: 'value4', | ||
}); | ||
}); | ||
|
||
it('When a required field is missing, then it should throw BadRequestException', () => { | ||
const dataSources: DataSource[] = [ | ||
{ sourceKey: 'body', fieldName: 'missingField' }, | ||
]; | ||
|
||
(reflector.get as jest.Mock).mockReturnValue({ dataSources }); | ||
(context.getHandler as jest.Mock).mockReturnValue('handler'); | ||
|
||
expect(() => extractDataFromRequest(request, reflector, context)).toThrow( | ||
BadRequestException, | ||
); | ||
expect(Logger.prototype.error).toHaveBeenCalledWith( | ||
'Missing required field for guard! field: missingField', | ||
); | ||
}); | ||
|
||
it('When a provided value is given, then it should use the provided value', () => { | ||
const dataSources: DataSource[] = [ | ||
{ sourceKey: 'body', fieldName: 'field1', value: 'providedValue' }, | ||
]; | ||
|
||
(reflector.get as jest.Mock).mockReturnValue({ dataSources }); | ||
(context.getHandler as jest.Mock).mockReturnValue('handler'); | ||
|
||
const result = extractDataFromRequest(request, reflector, context); | ||
|
||
expect(result).toEqual({ | ||
field1: 'providedValue', | ||
}); | ||
}); | ||
|
||
it('When the provided value is null or undefined, then it should throw BadRequestException', () => { | ||
const dataSources: DataSource[] = [ | ||
{ sourceKey: 'body', fieldName: 'field1', value: null }, | ||
]; | ||
|
||
(reflector.get as jest.Mock).mockReturnValue({ dataSources }); | ||
(context.getHandler as jest.Mock).mockReturnValue('handler'); | ||
|
||
expect(() => extractDataFromRequest(request, reflector, context)).toThrow( | ||
BadRequestException, | ||
); | ||
expect(Logger.prototype.error).toHaveBeenCalledWith( | ||
'Missing required field for guard! field: field1', | ||
); | ||
}); | ||
|
||
it('When fields need to be renamed, then it should rename fields correctly', () => { | ||
const dataSources: DataSource[] = [ | ||
{ sourceKey: 'query', fieldName: 'field2', newFieldName: 'newField2' }, | ||
]; | ||
|
||
(reflector.get as jest.Mock).mockReturnValue({ dataSources }); | ||
(context.getHandler as jest.Mock).mockReturnValue('handler'); | ||
|
||
const result = extractDataFromRequest(request, reflector, context); | ||
|
||
expect(result).toEqual({ | ||
newField2: 'value2', | ||
}); | ||
}); | ||
|
||
it('When multiple data sources are provided, then it should handle all sources correctly', () => { | ||
const dataSources: DataSource[] = [ | ||
{ sourceKey: 'body', fieldName: 'field1' }, | ||
{ sourceKey: 'query', fieldName: 'field2' }, | ||
]; | ||
|
||
(reflector.get as jest.Mock).mockReturnValue({ dataSources }); | ||
(context.getHandler as jest.Mock).mockReturnValue('handler'); | ||
|
||
const result = extractDataFromRequest(request, reflector, context); | ||
|
||
expect(result).toEqual({ | ||
field1: 'value1', | ||
field2: 'value2', | ||
}); | ||
}); | ||
}); |
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,55 @@ | ||
import { | ||
BadRequestException, | ||
ExecutionContext, | ||
Logger, | ||
SetMetadata, | ||
} from '@nestjs/common'; | ||
import { Reflector } from '@nestjs/core'; | ||
|
||
const extractDataFromRequestMetaName = 'dataFromRequest'; | ||
|
||
export const GetDataFromRequest = (dataSources: DataSource[]) => | ||
SetMetadata(extractDataFromRequestMetaName, { dataSources }); | ||
|
||
export interface DataSource { | ||
sourceKey?: 'body' | 'query' | 'params' | 'headers'; | ||
newFieldName?: string; // renames field name to be passed to guard | ||
fieldName: string; | ||
value?: any; | ||
} | ||
|
||
export const extractDataFromRequest = ( | ||
request: Request, | ||
reflector: Reflector, | ||
context: ExecutionContext, | ||
) => { | ||
const metadataOptions = reflector.get<{ dataSources: DataSource[] }>( | ||
extractDataFromRequestMetaName, | ||
context.getHandler(), | ||
); | ||
|
||
const { dataSources } = metadataOptions; | ||
|
||
const extractedData = {}; | ||
|
||
for (const { sourceKey, fieldName, value, newFieldName } of dataSources) { | ||
const extractedValue = | ||
value !== undefined ? value : request[sourceKey][fieldName]; | ||
|
||
const isValueUndefined = | ||
extractedValue === undefined || extractedValue === null; | ||
|
||
if (isValueUndefined) { | ||
new Logger().error( | ||
`Missing required field for guard! field: ${fieldName}`, | ||
); | ||
throw new BadRequestException(`Missing required field: ${fieldName}`); | ||
} | ||
|
||
const targetFieldName = newFieldName ?? fieldName; | ||
|
||
extractedData[targetFieldName] = extractedValue; | ||
} | ||
|
||
return extractedData; | ||
}; |
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
Oops, something went wrong.