diff options
Diffstat (limited to 'graphcool/src')
| -rw-r--r-- | graphcool/src/auth0/auth0Authentication.graphql | 8 | ||||
| -rw-r--r-- | graphcool/src/auth0/auth0Authentication.js | 104 | ||||
| -rw-r--r-- | graphcool/src/createCharge.js | 52 | ||||
| -rw-r--r-- | graphcool/src/createCharge.test.js | 23 | ||||
| -rw-r--r-- | graphcool/src/getPrice.js | 26 | ||||
| -rw-r--r-- | graphcool/src/hello.graphql | 7 | ||||
| -rw-r--r-- | graphcool/src/hello.js | 11 | ||||
| -rw-r--r-- | graphcool/src/index.js | 2 |
8 files changed, 233 insertions, 0 deletions
diff --git a/graphcool/src/auth0/auth0Authentication.graphql b/graphcool/src/auth0/auth0Authentication.graphql new file mode 100644 index 0000000..823a71b --- /dev/null +++ b/graphcool/src/auth0/auth0Authentication.graphql @@ -0,0 +1,8 @@ +type AuthenticateUserPayload { + id: String! + token: String! +} + +extend type Mutation { + authenticateUser(accessToken: String!): AuthenticateUserPayload +} diff --git a/graphcool/src/auth0/auth0Authentication.js b/graphcool/src/auth0/auth0Authentication.js new file mode 100644 index 0000000..4e1b4fa --- /dev/null +++ b/graphcool/src/auth0/auth0Authentication.js @@ -0,0 +1,104 @@ +const isomorphicFetch = require('isomorphic-fetch'); +const jwt = require('jsonwebtoken'); +const jwkRsa = require('jwks-rsa'); +const fromEvent = require('graphcool-lib').fromEvent; + +//Validates the request JWT token +const verifyToken = token => + new Promise(resolve => { + //Decode the JWT Token + const decoded = jwt.decode(token, { complete: true }); + if (!decoded || !decoded.header || !decoded.header.kid) { + throw new Error('Unable to retrieve key identifier from token'); + } + if (decoded.header.alg !== 'RS256') { + throw new Error( + `Wrong signature algorithm, expected RS256, got ${decoded.header.alg}` + ); + } + const jkwsClient = jwkRsa({ + cache: true, + jwksUri: `https://${process.env.AUTH0_DOMAIN}/.well-known/jwks.json` + }); + //Retrieve the JKWS's signing key using the decode token's key identifier (kid) + jkwsClient.getSigningKey(decoded.header.kid, (err, key) => { + if (err) throw new Error(err); + const signingKey = key.publicKey || key.rsaPublicKey; + //If the JWT Token was valid, verify its validity against the JKWS's signing key + jwt.verify( + token, + signingKey, + { + algorithms: ['RS256'], + audience: process.env.AUTH0_API_IDENTIFIER, + ignoreExpiration: false, + issuer: `https://${process.env.AUTH0_DOMAIN}/` + }, + (err, decoded) => { + if (err) throw new Error(err); + return resolve(decoded); + } + ); + }); + }); + +//Retrieves the Graphcool user record using the Auth0 user id +const getGraphcoolUser = (auth0UserId, api) => + api + .request( + ` + query getUser($auth0UserId: String!){ + User(auth0UserId: $auth0UserId){ + id + } + } + `, + { auth0UserId } + ) + .then(queryResult => queryResult.User); + +//Creates a new User record. +const createGraphCoolUser = ({ sub }, api) => + api + .request( + ` + mutation createUser($auth0UserId: String!) { + createUser( + auth0UserId: $auth0UserId + ){ + id + } + } + `, + { auth0UserId: sub } + ) + .then(queryResult => queryResult.createUser); + +export default async event => { + try { + if (!process.env.AUTH0_DOMAIN || !process.env.AUTH0_API_IDENTIFIER) { + throw new Error( + 'Missing AUTH0_DOMAIN or AUTH0_API_IDENTIFIER environment variable' + ); + } + const { accessToken } = event.data; + + const decodedToken = await verifyToken(accessToken); + const graphcool = fromEvent(event); + const api = graphcool.api('simple/v1'); + + let graphCoolUser = null; + + graphCoolUser = await getGraphcoolUser(decodedToken.sub, api); + //If the user doesn't exist. a new record is created. + if (graphCoolUser === null) { + graphCoolUser = await createGraphCoolUser(decodedToken, api); + } + const token = await graphcool.generateAuthToken(graphCoolUser.id, 'User'); + + return { data: { id: graphCoolUser.id, token } }; + } catch (err) { + console.log(err); + return { error: 'An unexpected error occured' }; + } +}; diff --git a/graphcool/src/createCharge.js b/graphcool/src/createCharge.js new file mode 100644 index 0000000..ccf9c11 --- /dev/null +++ b/graphcool/src/createCharge.js @@ -0,0 +1,52 @@ +const stripe = require('stripe')('sk_ycLkGc2cAaBDSCKkHiKVBeT71CMxd'); + +const endpoint = 'https://api.graph.cool/simple/v1/cj99zm6ye06sb01325ic751ww'; + +require('isomorphic-fetch'); + +const getPrice = itemId => { + const query = ` + query SingleItem { + Item(id: "${itemId}") { + price + } + } + `; + + return fetch(endpoint, { + method: 'post', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query }), + }); +}; + +const createStripeCharge = (token, amount) => + stripe.charges.create({ + amount, + currency: 'usd', + description: `a test charge`, + source: token, + }); + +module.exports = function(event) { + return new Promise((resolve, reject) => { + // first find out the price of the item + getPrice(event.data.itemId) + .then(res => res.json()) + .then(res => { + console.log(`Back with the price ${res.data.Item.price}!`); + return createStripeCharge(event.data.token, res.data.Item.price); + }) + .then(res => { + console.log(`Back! charge ${res.id} for the amount ${res.amount}`); + event.data.charge = res.id; + event.data.amount = res.amount; + resolve(event); + }) + .catch(err => { + reject(err); + }); + }); +}; diff --git a/graphcool/src/createCharge.test.js b/graphcool/src/createCharge.test.js new file mode 100644 index 0000000..65dde47 --- /dev/null +++ b/graphcool/src/createCharge.test.js @@ -0,0 +1,23 @@ +const takeMoney = require('./createCharge'); + +const event = { + "data": { + "user": "cj6ntm8qic3260140vkuzif9d", + "token": "tok_visa", + }, + "context": { + "headers": {} + } +} + + +describe('Take Money', () => { + + test('A charge has come back', async () => { + const res = await takeMoney(event); + console.log(res); + expect(res.data.amount).toBeGreaterThanOrEqual(0); + }); + +}); + diff --git a/graphcool/src/getPrice.js b/graphcool/src/getPrice.js new file mode 100644 index 0000000..7808a85 --- /dev/null +++ b/graphcool/src/getPrice.js @@ -0,0 +1,26 @@ +require('isomorphic-fetch') + +const query = ` +query SingleItem { + Item(id: "cj64bs7vuuqgu0116ul5cm223") { + price + } +} +`; + +function getItem(id) { + return fetch('https://api.graph.cool/simple/v1/cj5xz8szs28930145gct82bdj', { + method: 'post', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ query }), + }) +} + + +module.exports = function(event) { + getItem().then(x => x.json()).then(res => { + console.log(res.data.Item.price); + }).catch(console.log) +} diff --git a/graphcool/src/hello.graphql b/graphcool/src/hello.graphql new file mode 100644 index 0000000..d43c729 --- /dev/null +++ b/graphcool/src/hello.graphql @@ -0,0 +1,7 @@ +type HelloPayload { + message: String! +} + +extend type Query { + hello(name: String): HelloPayload +} diff --git a/graphcool/src/hello.js b/graphcool/src/hello.js new file mode 100644 index 0000000..0e3e7ba --- /dev/null +++ b/graphcool/src/hello.js @@ -0,0 +1,11 @@ +export default async event => { + // you can use ES7 with async/await and even TypeScript in your functions :) + + await new Promise(r => setTimeout(r, 50)) + + return { + data: { + message: `Hello ${event.data.name || 'World'}` + } + } +}
\ No newline at end of file diff --git a/graphcool/src/index.js b/graphcool/src/index.js new file mode 100644 index 0000000..ee451f6 --- /dev/null +++ b/graphcool/src/index.js @@ -0,0 +1,2 @@ +module.exports = () => 'Welcome to Micro' +exports.what = () => 'What' |
