Skip to content

Commit

Permalink
Adding joi validation for other content than the request body like qu…
Browse files Browse the repository at this point in the history
…ery parameter or something else in the request or context (#4)
  • Loading branch information
frudisch authored Jan 15, 2022
1 parent 4f87f86 commit a0e2c8d
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 22 deletions.
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,23 @@ The body of the response could be customized by adding a transformer like in the

```typescript
export default middleware(handler, [
validation(accountWithConnectionRequestSchema(), (message) => ({
validation(schema, (message) => ({
type: 'Invalid request object',
detail: message,
})),
])
```

By default the request body is getting validated. To validate other parts of the request or context the `extractValidationContentFromRequest` function could be used, when initializing the middleware.

```typescript
export default middleware(handler, [
validation(schema, undefined, (req, context) => req.query.name)),
])
```

In this example the `name` contained in the query is getting validated against the passed request.

### Authorization

To authorize a request the middleware function `authorization` could be used. The function is verifying a request parameter against a JWT Bearer Token. The information get extracted using two functions for the correct parameter and token counterpart.
Expand Down
7 changes: 4 additions & 3 deletions src/validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ describe('The joi validator should', () => {
expect(result).toBeUndefined();
});

test('not call the validation when the method is GET', async () => {
test('successfully validate the object extracted through the passed function', async () => {
requestMock.method = 'GET';
const schemaMock = mock<JoiValidator.ObjectSchema>();
schemaMock.validate.mockReturnValue({ error: undefined, value: 'Test Validation' });

const result = await sut(schemaMock)(contextMock, requestMock);
const result = await sut(schemaMock, undefined, () => 'test-extracted-content')(contextMock, requestMock);

expect(schemaMock.validate).not.toBeCalled();
expect(schemaMock.validate).toBeCalledWith('test-extracted-content');
expect(result).toBeUndefined();
});

Expand Down
40 changes: 22 additions & 18 deletions src/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,29 @@ import { ObjectSchema } from 'joi';
import { ApplicationError } from './applicationError';
import { MiddlewareFunction } from './middleware';

export default (schema: ObjectSchema, transformErrorMessage?: (message: string) => unknown): MiddlewareFunction => {
export default (
schema: ObjectSchema,
transformErrorMessage?: (message: string) => unknown,
extractValidationContentFromRequest?: (context: Context, req: HttpRequest) => unknown,
): MiddlewareFunction => {
return (context: Context, req: HttpRequest): Promise<void> => {
const body = req.body;
if (req.method !== 'GET') {
const validationResult = schema.validate(body);
if (validationResult && validationResult.error) {
context.log.verbose(validationResult);
return Promise.reject(
new ApplicationError(
'Validation Error',
400,
transformErrorMessage
? transformErrorMessage(validationResult.error.message)
: {
message: validationResult.error.message,
},
),
);
}
const toBeValidatedContent = extractValidationContentFromRequest
? extractValidationContentFromRequest(context, req)
: req.body;
const validationResult = schema.validate(toBeValidatedContent);
if (validationResult && validationResult.error) {
context.log.verbose(validationResult);
return Promise.reject(
new ApplicationError(
'Validation Error',
400,
transformErrorMessage
? transformErrorMessage(validationResult.error.message)
: {
message: validationResult.error.message,
},
),
);
}
return Promise.resolve();
};
Expand Down

0 comments on commit a0e2c8d

Please sign in to comment.