diff --git a/server/api/hooks.js b/server/api/hooks.js index 481d0a16..86fb4f23 100644 --- a/server/api/hooks.js +++ b/server/api/hooks.js @@ -1,5 +1,6 @@ // @flow import Router from 'koa-router'; +import { escapeRegExp } from 'lodash'; import { AuthenticationError, InvalidRequestError } from '../errors'; import { Authentication, Document, User, Team } from '../models'; import { presentSlackAttachment } from '../presenters'; @@ -13,7 +14,6 @@ router.post('hooks.unfurl', async ctx => { if (token !== process.env.SLACK_VERIFICATION_TOKEN) throw new AuthenticationError('Invalid token'); - // TODO: Everything from here onwards will get moved to an async job const user = await User.find({ where: { service: 'slack', serviceId: event.user }, }); @@ -75,7 +75,7 @@ router.post('hooks.slack', async ctx => { for (const result of results) { const queryIsInTitle = !!result.document.title .toLowerCase() - .match(text.toLowerCase()); + .match(escapeRegExp(text.toLowerCase())); attachments.push( presentSlackAttachment( diff --git a/server/api/hooks.test.js b/server/api/hooks.test.js index 117bc9bb..68031e92 100644 --- a/server/api/hooks.test.js +++ b/server/api/hooks.test.js @@ -86,6 +86,25 @@ describe('#hooks.slack', async () => { expect(body.attachments[0].text).toEqual(document.getSummary()); }); + it('should return search results if query is regex-like', async () => { + const user = await buildUser(); + await buildDocument({ + title: 'This title contains a search term', + userId: user.id, + teamId: user.teamId, + }); + const res = await server.post('/api/hooks.slack', { + body: { + token: process.env.SLACK_VERIFICATION_TOKEN, + user_id: user.serviceId, + text: '*contains', + }, + }); + const body = await res.json(); + expect(res.status).toEqual(200); + expect(body.attachments.length).toEqual(1); + }); + it('should return search results with snippet if query is in text', async () => { const user = await buildUser(); const document = await buildDocument({