diff options
| author | Wes Bos <wesbos@gmail.com> | 2018-04-12 16:31:01 -0400 |
|---|---|---|
| committer | Wes Bos <wesbos@gmail.com> | 2018-04-12 16:31:01 -0400 |
| commit | 97b6de6aa437f7a913a33b9e6aa18a919faf2caf (patch) | |
| tree | 431e12a535baf1d2ad59601ee7c5e8084ae7a263 /backend/src | |
| parent | d22616d5a675f5a381c741784333151255713b45 (diff) | |
a whole bunch of things that should be in their own commits
Diffstat (limited to 'backend/src')
| -rw-r--r-- | backend/src/index.js | 6 | ||||
| -rw-r--r-- | backend/src/mail.js | 18 | ||||
| -rw-r--r-- | backend/src/resolvers/Mutation.js | 95 | ||||
| -rw-r--r-- | backend/src/resolvers/Query.js | 48 | ||||
| -rw-r--r-- | backend/src/schema.graphql | 3 | ||||
| -rw-r--r-- | backend/src/utils.js | 35 |
6 files changed, 107 insertions, 98 deletions
diff --git a/backend/src/index.js b/backend/src/index.js index 8cf48fc..9f759ef 100644 --- a/backend/src/index.js +++ b/backend/src/index.js @@ -30,9 +30,3 @@ server.express.use(async (req, res, next) => { server.start({ port: 4444 }, deets => { console.log(`Server is running on http://localhost:${deets.port}`); }); - -// overwrite console.log -const chalk = require('chalk'); - -// global.console.l = (...butta) => console.log(chalk.bold.yellow(...butta)); -global.console.l = console.log; diff --git a/backend/src/mail.js b/backend/src/mail.js index 3159fe2..fc4a47b 100644 --- a/backend/src/mail.js +++ b/backend/src/mail.js @@ -9,4 +9,20 @@ const transport = nodemailer.createTransport({ }, }); -module.exports = transport; +const makeANiceEmail = text => ` + <div className="email" style=" + border:1px solid black; + padding: 20px; + font-family: sans-serif; + line-height: 2; + font-size: 20px; + "> + <h2>Hello There</h2> + <p>${text}</p> + + <p>😘 Wes Bos</p> + </div> +`; + +exports.transport = transport; +exports.makeANiceEmail = makeANiceEmail; diff --git a/backend/src/resolvers/Mutation.js b/backend/src/resolvers/Mutation.js index daaa7de..5886595 100644 --- a/backend/src/resolvers/Mutation.js +++ b/backend/src/resolvers/Mutation.js @@ -1,13 +1,11 @@ const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); -const { getUserId, Context, hasPermission } = require('../utils'); +const { hasPermission } = require('../utils'); const { randomBytes } = require('crypto'); const { promisify } = require('util'); const mail = require('../mail'); const stripe = require('../stripe'); -const wait = amount => new Promise(resolve => setTimeout(resolve, amount)); - const mutations = { // Signup Mutations async signup(parent, args, ctx, info) { @@ -29,7 +27,6 @@ const mutations = { async signin(parent, { email, password }, ctx, info) { const user = await ctx.db.query.user({ where: { email } }); - console.log(user); if (!user) { throw new Error(`No such user found for email: ${email}`); } @@ -44,7 +41,7 @@ const mutations = { }; }, - // Creation of Post Mutations + // Create An Item async createItem(parent, args, ctx, info) { if (!ctx.request.userId) { throw new Error('You must be logged in to create an item'); @@ -63,7 +60,6 @@ const mutations = { }, info ); - console.log(item); return item; }, @@ -85,19 +81,23 @@ const mutations = { async updateItem(parent, args, ctx, info) { const user = ctx.request.user; const item = await ctx.db.query.item({ where: { id: args.id } }, `{ user { id } }`); - if (item.user.id !== user.id || !user.permissions.includes('ADMIN')) { + + if (item.user.id !== user.id || !hasPermission(user, ['ADMIN'])) { throw new Error('You are not allowed to update that item!'); } const updates = { ...args }; // remove the ID because you can't update that delete updates.id; - return ctx.db.mutation.updateItem({ - where: { id: args.id }, - data: { - ...updates, + return ctx.db.mutation.updateItem( + { + where: { id: args.id }, + data: { + ...updates, + }, }, - }); + info + ); }, // Send password request @@ -117,14 +117,17 @@ const mutations = { data: { resetToken, resetTokenExpiry }, }); - console.log(res); // 3. Send them their token via email - const mailRes = await mail.sendMail({ + const mailRes = await mail.transport.sendMail({ from: 'wesbos@gmail.com', to: user.email, subject: 'Your password reset token', // TODO: don't hardcore localhost here - html: `Here is your reset link: http://localhost:3000/reset?resetToken=${resetToken}`, + html: mail.makeANiceEmail( + `Your password reset link is here! \n\n<a href="${ctx.request.protocol}://${ctx.request.get( + 'host' + )}/reset?resetToken=${resetToken}">Click Here to reset</a>s` + ), }); console.log(mailRes); return res.updateUser; @@ -175,8 +178,8 @@ const mutations = { Add to cart */ async addToCart(parent, args, ctx, info) { - console.l('Add to cart called'); - const userId = getUserId(ctx); + const userId = ctx.request.userId; + if (!userId) { throw new Error('You must be signed in to add to cart!'); } @@ -190,7 +193,6 @@ const mutations = { }); if (existingCartItem) { - console.log('Existing'); return ctx.db.mutation.updateCartItem( { where: { id: existingCartItem.id }, @@ -220,40 +222,46 @@ const mutations = { // delete that cart item async removeFromCart(parent, args, ctx, info) { - // TODO: add userId to where - return ctx.db.mutation.deleteCartItem({ - where: { id: args.id }, - }); + return ctx.db.mutation.deleteManyCartItems( + { + where: { + id: args.id, + user: { + id: ctx.request.userId, + }, + }, + }, + info + ); }, async createOrder(parent, args, ctx, info) { - const userId = getUserId(ctx); + const userId = ctx.request.userId; const user = await ctx.db.query.user( { where: { id: userId } }, // TODO - can we just pass info here? '{ id, name, email, cart { id, quantity, item { title, price, id, description, image } }}' ); // 1. Recalculate the total for the price - const amount = user.cart.reduce((tally, cartItem) => tally + cartItem.item.price * cartItem.quantity, 0); - // TODO Error Handling - // 2.1 Create a Stripe Customer - const customer = await stripe.customers.create({ - email: user.email, - }); - // 2.3 Charge the stripe token + const amount = user.cart.reduce( + (tally, cartItem) => tally + cartItem.item.price * cartItem.quantity, + 0 + ); + // 2. Create a stripe charge const charge = await stripe.charges.create({ amount, currency: 'usd', source: args.token, }); + // 3. convert the items they want to OrderItems const orderItems = user.cart.map(cartItem => { const orderItem = { quantity: cartItem.quantity, // copy all the item details so it's there forever ...cartItem.item, item: { - // realtionship to the Item incase we need it + // relationship to the Item incase we need it connect: { id: cartItem.item.id }, }, user: { connect: { id: user.id } }, @@ -263,7 +271,7 @@ const mutations = { return orderItem; }); - // Create the Order + // 4. Create the Order const order = await ctx.db.mutation.createOrder({ data: { total: charge.amount, @@ -279,8 +287,8 @@ const mutations = { }, }, }); - console.log('Gonna delete some items'); - // 6. Clean up, clear the users cart adn send back { user, order } + + // 5. Clean up, clear the users cart and send back { user, order } // Delete the users current cart items const cartItemIds = user.cart.map(cartItem => cartItem.id); await ctx.db.mutation.deleteManyCartItems({ @@ -289,21 +297,24 @@ const mutations = { }, }); - // 5. Send the order back to the client + // 6. Send the order back to the client return order; - // 4. TODO: Send an email with their order }, + async updateUser(parent, args, ctx, info) { - const userId = getUserId(ctx); - const updatedUser = await ctx.db.mutation.updateUser({ - data: args, - where: { id: userId }, - }); + const userId = ctx.request.userId; + const updatedUser = await ctx.db.mutation.updateUser( + { + data: args, + where: { id: userId }, + }, + info + ); return updatedUser; }, async updatePermissions(parent, args, ctx, info) { - const userId = getUserId(ctx); + const userId = ctx.request.userId; const currentUser = await ctx.db.query.user({ where: { id: userId } }, info); if (!currentUser) throw new Error('You Must be logged in to updat permissions!'); hasPermission(currentUser, ['ADMIN', 'PERMISSIONUPDATE']); diff --git a/backend/src/resolvers/Query.js b/backend/src/resolvers/Query.js index 22dcd2a..276f7fa 100644 --- a/backend/src/resolvers/Query.js +++ b/backend/src/resolvers/Query.js @@ -1,26 +1,52 @@ -const { getUserId, Context, checkForUserId } = require('../utils'); +const { hasPermission } = require('../utils'); + const { forwardTo } = require('prisma-binding'); const Query = { items(parent, args, ctx, info) { - console.log('ITEMS!'); - // check auth return ctx.db.query.items({ ...args }, info); }, itemsConnection: forwardTo('db'), // TODO: Make sure they own this order before looking it up - order: forwardTo('db'), + // order: forwardTo('db'), + async order(parent, args, ctx, info) { + // 1. make sure they are signed in + if (!ctx.request.userId) { + throw new Error('You Must be signed in to view an order'); + } + + // 2. Create the query + const where = { + id: args.id, + user: { + id: ctx.request.userId, + }, + }; + // 3. Fire off the query + const [order] = await ctx.db.query.orders({ where }, info); + + // 4. Check that they are allowed to view the order + if (order.user.id !== ctx.request.userId || hasPermission(ctx.request.user, ['ADMIN'])) { + throw new Error("You don't have permission"); + } + // 5. If everything checks out, return the order + return order; + }, me(parent, args, ctx, info) { const Authorization = ctx.request.get('Authorization'); if (!Authorization || Authorization === 'null') { - console.log('Authorization is null'); - return null; + return null; // don't error out, just return nothing } - const id = getUserId(ctx); - return ctx.db.query.user({ where: { id } }, info); + + return ctx.db.query.user( + { + where: { id: ctx.request.userId }, + }, + info + ); }, async orders(parent, args, ctx, info) { @@ -37,12 +63,6 @@ const Query = { info ); }, - - async users(parent, args, ctx, info) { - // TODO Permissions - const userId = getUserId(ctx); - return ctx.db.query.users({}, info); - }, }; module.exports = Query; diff --git a/backend/src/schema.graphql b/backend/src/schema.graphql index 6613004..4318d2a 100644 --- a/backend/src/schema.graphql +++ b/backend/src/schema.graphql @@ -1,4 +1,4 @@ -# import Permission, Order, OrderItem, CartItem, ItemWhereInput, ItemOrderByInput, allItems, Item, ItemCreateInput, ItemOrderByInput, ItemWhereInput, Query.order, Query.orders, Query.users from './generated/prisma.graphql' +# import Permission, Order, OrderItem, CartItem, ItemWhereInput, ItemOrderByInput, allItems, Item, ItemCreateInput, ItemOrderByInput, ItemWhereInput, Query.orders, Query.users from './generated/prisma.graphql' type Query { me: User @@ -17,6 +17,7 @@ type Query { skip: Int first: Int ): [Item]! + order(id: ID!): Order! } # import Mutation from './generated/prisma.graphql' diff --git a/backend/src/utils.js b/backend/src/utils.js index 2988b3d..faf028b 100644 --- a/backend/src/utils.js +++ b/backend/src/utils.js @@ -1,16 +1,3 @@ -const jwt = require('jsonwebtoken'); - -function getUserId(ctx) { - const Authorization = ctx.request.get('Authorization'); - if (Authorization) { - const token = Authorization.replace('Bearer ', ''); - const { userId } = jwt.verify(token, process.env.APP_SECRET); - return userId; - } - // TODO: Don't throw when they aren't logged in - // throw new Error('Sorry, you must be logged in to do that!'); -} - function hasPermission(user, permissionsNeeded) { const matchedPermissions = user.permissions.filter(permissionTheyHave => permissionsNeeded.includes(permissionTheyHave) @@ -27,24 +14,4 @@ function hasPermission(user, permissionsNeeded) { } } -function checkForUserId(ctx) { - const Authorization = ctx.request.get('Authorization'); - if (Authorization) { - const token = Authorization.replace('Bearer ', ''); - const { userId } = jwt.verify(token, process.env.APP_SECRET); - return userId; - } -} - -class AuthError extends Error { - constructor() { - super('Not authorized'); - } -} - -module.exports = { - getUserId, - AuthError, - checkForUserId, - hasPermission, -}; +exports.hasPermission = hasPermission; |
