From f20e17dcc1a97a861531e3413d36318fa2748126 Mon Sep 17 00:00:00 2001 From: Moriz Wahl Date: Tue, 12 Jan 2021 21:25:25 +0100 Subject: [PATCH] query for validation of invite code --- backend/src/db/factories.js | 4 +- backend/src/db/seed.js | 2 +- .../src/middleware/permissionsMiddleware.js | 1 + backend/src/schema/resolvers/inviteCodes.js | 25 ++++++++++++ .../src/schema/resolvers/inviteCodes.spec.js | 39 ++++++++++++++++++- backend/src/schema/types/type/InviteCode.gql | 3 +- 6 files changed, 67 insertions(+), 7 deletions(-) diff --git a/backend/src/db/factories.js b/backend/src/db/factories.js index ac77cdb31..8f1d3c718 100644 --- a/backend/src/db/factories.js +++ b/backend/src/db/factories.js @@ -235,9 +235,7 @@ Factory.define('inviteCode') neode.create('InviteCode', buildObject), options.generatedBy, ]) - await Promise.all([ - inviteCode.relateTo(generatedBy, 'generated'), - ]) + await Promise.all([inviteCode.relateTo(generatedBy, 'generated')]) return inviteCode }) diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js index f58a69e97..d7bd5c73b 100644 --- a/backend/src/db/seed.js +++ b/backend/src/db/seed.js @@ -550,7 +550,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl'] generatedBy: jennyRostock, }, ) - + authenticatedUser = await louie.toJson() const mention1 = 'Hey @jenny-rostock, what\'s up?' diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js index 27eb3aa08..ddf12598b 100644 --- a/backend/src/middleware/permissionsMiddleware.js +++ b/backend/src/middleware/permissionsMiddleware.js @@ -107,6 +107,7 @@ export default shield( Donations: isAuthenticated, userData: isAuthenticated, MyInviteCodes: isAuthenticated, + isValidInviteCode: allow, }, Mutation: { '*': deny, diff --git a/backend/src/schema/resolvers/inviteCodes.js b/backend/src/schema/resolvers/inviteCodes.js index 0f7666dc2..ec5517909 100644 --- a/backend/src/schema/resolvers/inviteCodes.js +++ b/backend/src/schema/resolvers/inviteCodes.js @@ -34,6 +34,31 @@ export default { session.close() } }, + isValidInviteCode: async (_parent, args, context, _resolveInfo) => { + const { code } = args + if (!code) return false + const session = context.driver.session() + const readTxResultPromise = session.readTransaction(async (txc) => { + const result = await txc.run( + `MATCH (ic:InviteCode { code: $code }) + RETURN + CASE + WHEN ic.expiresAt IS NULL THEN true + WHEN datetime(ic.expiresAt) >= datetime() THEN true + ELSE false END AS result`, + { + code, + }, + ) + return result.records.map((record) => record.get('result')) + }) + try { + const txResult = await readTxResultPromise + return !!txResult[0] + } finally { + session.close() + } + }, }, Mutation: { GenerateInviteCode: async (_parent, args, context, _resolveInfo) => { diff --git a/backend/src/schema/resolvers/inviteCodes.spec.js b/backend/src/schema/resolvers/inviteCodes.spec.js index f0fee4b8d..9fa3e188b 100644 --- a/backend/src/schema/resolvers/inviteCodes.spec.js +++ b/backend/src/schema/resolvers/inviteCodes.spec.js @@ -30,6 +30,12 @@ const myInviteCodesQuery = gql` } ` +const isValidInviteCodeQuery = gql` + query($code: ID) { + isValidInviteCode(code: $code) + } +` + beforeAll(async () => { await cleanDatabase() const { server } = createServer({ @@ -141,7 +147,36 @@ describe('inviteCodes', () => { expect(inviteCodes).toHaveLength(2) }) - // const expiringInviteCode = inviteCodes.filter((ic) => ic.expiresAt !== null) - // const unExpiringInviteCode = inviteCodes.filter((ic) => ic.expiresAt === null) + it('does not returns the created invite codes of other users when queried', async () => { + await Factory.build('inviteCode') + const response = await query({ query: myInviteCodesQuery }) + inviteCodes = response.data.MyInviteCodes + expect(inviteCodes).toHaveLength(2) + }) + + it('validates an invite code without expiresAt', async () => { + const unExpiringInviteCode = inviteCodes.filter((ic) => ic.expiresAt === null)[0].code + expect( + query({ query: isValidInviteCodeQuery, variables: { code: unExpiringInviteCode } }), + ).resolves.toBeTruthy() + }) + + it('validates an invite code with expiresAt in the future', async () => { + const expiringInviteCode = inviteCodes.filter((ic) => ic.expiresAt !== null)[0].code + expect( + query({ query: isValidInviteCodeQuery, variables: { code: expiringInviteCode } }), + ).resolves.toBeTruthy() + }) + + it.skip('does not validate an invite code which expired in the past', async () => { + const lastWeek = new Date() + lastWeek.setDate(lastWeek.getDate() - 7) + const code = await Factory.build('inviteCode', { + expiresAt: lastWeek.toISOString(), + }) + expect( + query({ query: isValidInviteCodeQuery, variables: { code: code.code } }), + ).resolves.toBeFalsy() + }) }) }) diff --git a/backend/src/schema/types/type/InviteCode.gql b/backend/src/schema/types/type/InviteCode.gql index 00ca99b75..e75764c1c 100644 --- a/backend/src/schema/types/type/InviteCode.gql +++ b/backend/src/schema/types/type/InviteCode.gql @@ -12,5 +12,6 @@ type Mutation { } type Query { - MyInviteCodes: [InviteCode] + MyInviteCodes: [InviteCode] + isValidInviteCode(code: ID): Boolean }