diff --git a/api/src/email/sendgrid.js b/api/src/email/sendgrid.js index 20e1e9ffe..a30969ea8 100644 --- a/api/src/email/sendgrid.js +++ b/api/src/email/sendgrid.js @@ -7,7 +7,7 @@ const sendTeamMemberInvite = function(email, team) { const API_KEY = process.env.SG_APIKEY const token = jwt.sign({ email: email, team: team.slug }, API_KEY, { expiresIn: '7d' }) let origin = 'https://teams.advancedalgos.net' - const params = '/activate-team-membership?token=' + const params = '/activate-team-membership/' if (dev){ origin = 'http://localhost:3001' } @@ -67,4 +67,21 @@ const sendTeamMemberInvite = function(email, team) { return sendVerify } -module.exports = { sendTeamMemberInvite } +const verifyInviteToken = async function(token) { + const API_KEY = process.env.SG_APIKEY + let verifiedToken + try { + verifiedToken = await jwt.verify(token, API_KEY, {maxAge: '7d'}) + } catch(err) { + if (err.name === "TokenExpiredError"){ + throw new Error ("Error: Token Expired. Please request new invitation or apply to the team again") + } else { + throw new Error (`Error: Token error - ${err.message}`) + } + } + + console.log('verifyInviteToken', verifiedToken) + return verifiedToken +} + +module.exports = { sendTeamMemberInvite, verifyInviteToken } diff --git a/api/src/index.js b/api/src/index.js index 92b24b1e1..13f354638 100644 --- a/api/src/index.js +++ b/api/src/index.js @@ -14,7 +14,7 @@ const { getMember } = require('./auth/middleware/getMember') const { validateIdToken } = require('./auth/validateIdToken') const { directiveResolvers } = require('./auth/authDirectives') -const { sendTeamMemberInvite } = require('./email/sendgrid') +const { sendTeamMemberInvite, verifyInviteToken } = require('./email/sendgrid') const { createStoragePipline, @@ -136,6 +136,24 @@ const resolvers = { } return member }, + async verifyTeamInvite(parent, { token }, ctx, info) { + let verifiedToken = null + let team = null + try { + verifiedToken = await verifyInviteToken(token) + team = { + email: verifiedToken.email, + team: { + slug: verifiedToken.team + } + } + console.log('verifyTeamInvite.token: ', await verifiedToken) + } catch (err) { + console.log('verifyTeamInvite. err: ', err) + throw new Error(err.message) + } + return team + }, async createTeam(parent, { name, slug }, ctx, info) { const authId = ctx.request.user.sub return ctx.db.mutation.createTeam({ data: { name: name, slug: slug, owner: authId, members: { create: { member:{ connect:{ authId: authId} }, role: 'OWNER' } }, profile:{create:{avatar:"a"} } } }, TEAMS_FRAGMENT) diff --git a/api/src/schema.graphql b/api/src/schema.graphql index b6d7c40e7..0b969a608 100644 --- a/api/src/schema.graphql +++ b/api/src/schema.graphql @@ -20,6 +20,7 @@ type Query { type Mutation { authenticate(idToken: String!): Member + verifyTeamInvite(token: String!): TeamMembers createTeam(name: String!, slug: String!): Team @isAuthenticated updateTeamProfile(slug: String!, description: String, motto: String, avatar: String, banner: String): Team @isAuthenticated deleteTeam(slug: String!): Team @isAuthenticated @isOwner(type: "Team") diff --git a/client/package-lock.json b/client/package-lock.json index c0fbda736..dbfc71ab6 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -6266,8 +6266,7 @@ "decode-uri-component": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" }, "decompress-response": { "version": "3.3.0", @@ -12102,6 +12101,18 @@ "prepend-http": "^1.0.0", "query-string": "^4.1.0", "sort-keys": "^1.0.0" + }, + "dependencies": { + "query-string": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", + "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", + "dev": true, + "requires": { + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + } + } } }, "npm-run-all": { @@ -13791,13 +13802,19 @@ "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, "query-string": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz", - "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", - "dev": true, + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.1.0.tgz", + "integrity": "sha512-pNB/Gr8SA8ff8KpUFM36o/WFAlthgaThka5bV19AD9PNTH20Pwq5Zxodif2YyHwrctp6SkL4GqlOot0qR/wGaw==", "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" + "decode-uri-component": "^0.2.0", + "strict-uri-encode": "^2.0.0" + }, + "dependencies": { + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" + } } }, "querystring": { diff --git a/client/package.json b/client/package.json index 34a09ec19..950e4394c 100644 --- a/client/package.json +++ b/client/package.json @@ -89,6 +89,7 @@ "graphql": "^0.13.2", "graphql-tag": "^2.9.2", "prop-types": "^15.6.2", + "query-string": "^6.1.0", "react": "^16.5.0", "react-apollo": "^2.1.11", "react-dom": "^16.5.0", diff --git a/client/src/App.js b/client/src/App.js index 8ed26d1a8..b0fe69f45 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -19,6 +19,7 @@ import { NavBar, Footer, Callback, + AcceptTeamInvite, Home, About, Dashboard, @@ -171,6 +172,11 @@ class App extends Component { return }} /> + } + />