Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

Commit

Permalink
feat: validate command received in /commands
Browse files Browse the repository at this point in the history
  • Loading branch information
gustavopch committed Aug 19, 2020
1 parent 406fb4f commit ace8131
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"test": "./scripts/test.js"
},
"dependencies": {
"ajv": "^6.12.4",
"cors": "^2.8.5",
"express": "^4.17.1"
},
Expand Down
18 changes: 18 additions & 0 deletions src/apis/https/commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,24 @@ describe('/commands endpoint', () => {
},
)

it('returns an error if the command is invalid', async () => {
const res = await fetch(endpoint, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
contextName: 'shopping',
aggregateName: 'cart',
// 'aggregateId' left out to make the command invalid
name: 'initialize',
data: null,
}),
})

expect(res.status).toBe(422)
})

it('returns the ID of the new event', async () => {
const res = await fetch(endpoint, {
method: 'POST',
Expand Down
40 changes: 40 additions & 0 deletions src/apis/https/commands.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Ajv from 'ajv'
import cors from 'cors'
import express from 'express'
import firebaseAdmin from 'firebase-admin'
Expand All @@ -10,6 +11,37 @@ import { createEventStore } from '../../stores/event-store'
import { validateFirebaseIdToken } from './middlewares/validate-firebase-id-token'
import { parseLocationFromHeaders } from './utils/parse-location-from-headers'

const commandSchema = {
type: 'object',
properties: {
contextName: {
type: 'string',
minLength: 1,
},
aggregateName: {
type: 'string',
minLength: 1,
},
aggregateId: {
type: 'string',
minLength: 1,
},
name: {
type: 'string',
minLength: 1,
},
data: {
type: ['object', 'null'],
properties: {},
},
},
required: ['contextName', 'aggregateName', 'aggregateId', 'name', 'data'],
additionalProperties: false,
}

const ajv = new Ajv()
const validateCommand = ajv.compile(commandSchema)

export const createCommandsEndpoint = (
firebaseAdminApp: firebaseAdmin.app.App,
application: ApplicationDefinition,
Expand All @@ -23,6 +55,14 @@ export const createCommandsEndpoint = (

app.post('/', async (req, res) => {
try {
const isCommandValid = await validateCommand(req.body)

if (!isCommandValid) {
console.error('Invalid command:', validateCommand.errors)
res.status(422).send('Invalid command')
return
}

const command: CommandWithMetadata = {
contextName: req.body.contextName,
aggregateName: req.body.aggregateName,
Expand Down
10 changes: 10 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2164,6 +2164,16 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"

ajv@^6.12.4:
version "6.12.4"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234"
integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"

alphanum-sort@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3"
Expand Down

0 comments on commit ace8131

Please sign in to comment.