Skip to content

Commit

Permalink
fix(qna): added input validation & schema
Browse files Browse the repository at this point in the history
  • Loading branch information
allardy committed Mar 25, 2019
1 parent 17eb281 commit f90c1fb
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 9 deletions.
11 changes: 8 additions & 3 deletions modules/qna/src/backend/api.ts
@@ -1,14 +1,16 @@
import * as sdk from 'botpress/sdk'
import iconv from 'iconv-lite'
import { validate } from 'joi'
import { Parser as Json2csvParser } from 'json2csv'
import _ from 'lodash'
import moment from 'moment'
import multer from 'multer'
import nanoid from 'nanoid'
import yn from 'yn'

import { QnaStorage } from './qna'
import { QnaEntry, QnaStorage } from './qna'
import { importQuestions, prepareExport } from './transfer'
import { QnaDefSchema } from './validation'

export default async (bp: typeof sdk, botScopedStorage: Map<string, QnaStorage>) => {
const csvUploadStatuses = {}
Expand All @@ -31,8 +33,9 @@ export default async (bp: typeof sdk, botScopedStorage: Map<string, QnaStorage>)

router.post('/questions', async (req, res, next) => {
try {
const qnaEntry = (await validate(req.body, QnaDefSchema)) as QnaEntry
const storage = botScopedStorage.get(req.params.botId)
const id = await storage.insert(req.body)
const id = await storage.insert(qnaEntry)
res.send(id)
} catch (e) {
next(new Error(e.message))
Expand All @@ -55,8 +58,10 @@ export default async (bp: typeof sdk, botScopedStorage: Map<string, QnaStorage>)
} = req

try {
const qnaEntry = (await validate(req.body, QnaDefSchema)) as QnaEntry
const storage = botScopedStorage.get(req.params.botId)
await storage.update(req.body, req.params.id)
await storage.update(qnaEntry, req.params.id)

const questions = await storage.getQuestions({ question, categories }, { limit, offset })
res.send(questions)
} catch (e) {
Expand Down
6 changes: 3 additions & 3 deletions modules/qna/src/backend/providers/nlu.ts
Expand Up @@ -4,7 +4,7 @@ import { Paging } from 'botpress/sdk'
import _ from 'lodash'
import nanoid from 'nanoid/generate'

import { QnaStorage } from '../qna'
import { QnaEntry, QnaStorage } from '../qna'

const safeId = (length = 10) => nanoid('1234567890abcdefghijklmnopqrsuvwxyz', length)

Expand Down Expand Up @@ -81,7 +81,7 @@ export default class Storage implements QnaStorage {
}
}

async update(data, id) {
async update(data: QnaEntry, id: string): Promise<string> {
const axiosConfig = await this.getAxiosConfig()
id = id || getQuestionId(data)
if (data.enabled) {
Expand All @@ -105,7 +105,7 @@ export default class Storage implements QnaStorage {
return id
}

async insert(qna, statusCb) {
async insert(qna: QnaEntry | QnaEntry[], statusCb): Promise<string[]> {
const ids = await Promise.mapSeries(_.isArray(qna) ? qna : [qna], async (data, i) => {
const id = getQuestionId(data)

Expand Down
18 changes: 15 additions & 3 deletions modules/qna/src/backend/qna.d.ts
Expand Up @@ -4,12 +4,24 @@ export interface QnaStorage {
initialize()
fetchAllQuestions(paging?: sdk.Paging)
getQuestions({ question, categories }, { limit, offset })
insert(qna: any, statusCallback?: any)
update(data: any, id: any): Promise<void>
delete(id: any, statusCallback?: any): void
insert(qna: QnaEntry, statusCallback?: any)
update(data: QnaEntry, id: string): Promise<string>
delete(id: string, statusCallback?: any): void
count(): Promise<number>
answersOn(question)
getQuestion(opts: any)
getCategories(): string[]
hasCategories(): boolean
}

export type Action = 'text' | 'redirect' | 'text_redirect'

export interface QnaEntry {
action: Action
category: string
enabled: boolean
questions: string[]
answers: string[]
redirectFlow: string
redirectNode: string
}
20 changes: 20 additions & 0 deletions modules/qna/src/backend/validation.ts
@@ -0,0 +1,20 @@
import Joi from 'joi'

export const QnaDefSchema = Joi.object().keys({
action: Joi.string().required(),
category: Joi.string().required(),
enabled: Joi.bool().required(),
redirectFlow: Joi.string()
.optional()
.allow(''),
redirectNode: Joi.string()
.optional()
.allow(''),
questions: Joi.array()
.items(Joi.string())
.default([]),
answers: Joi.array()
.items(Joi.string())
.default([]),
answer: Joi.string().optional()
})

0 comments on commit f90c1fb

Please sign in to comment.