summaryrefslogtreecommitdiffstats
path: root/finished-application/backend/src
diff options
context:
space:
mode:
Diffstat (limited to 'finished-application/backend/src')
-rw-r--r--finished-application/backend/src/createServer.js8
-rw-r--r--finished-application/backend/src/db.js9
-rw-r--r--finished-application/backend/src/generated/prisma.graphql549
-rw-r--r--finished-application/backend/src/index.js18
-rw-r--r--finished-application/backend/src/mail.js14
-rw-r--r--finished-application/backend/src/resolvers/Mutation.js380
-rw-r--r--finished-application/backend/src/resolvers/Query.js65
-rw-r--r--finished-application/backend/src/schema.graphql40
8 files changed, 398 insertions, 685 deletions
diff --git a/finished-application/backend/src/createServer.js b/finished-application/backend/src/createServer.js
index 036d15a..c552b02 100644
--- a/finished-application/backend/src/createServer.js
+++ b/finished-application/backend/src/createServer.js
@@ -3,16 +3,18 @@ const Mutation = require('./resolvers/Mutation');
const Query = require('./resolvers/Query');
const db = require('./db');
+// Create the GraphQL Yoga Server
+
function createServer() {
return new GraphQLServer({
typeDefs: 'src/schema.graphql',
- resolverValidationOptions: {
- requireResolversForResolveType: false,
- },
resolvers: {
Mutation,
Query,
},
+ resolverValidationOptions: {
+ requireResolversForResolveType: false,
+ },
context: req => ({ ...req, db }),
});
}
diff --git a/finished-application/backend/src/db.js b/finished-application/backend/src/db.js
index e8caa14..8f66240 100644
--- a/finished-application/backend/src/db.js
+++ b/finished-application/backend/src/db.js
@@ -1,10 +1,11 @@
+// This file connects to the remote prisma DB and gives us the ability to query it with JS
const { Prisma } = require('prisma-binding');
const db = new Prisma({
typeDefs: 'src/generated/prisma.graphql',
- endpoint: process.env.PRISMA_ENDPOINT, // the endpoint of the Prisma DB service (value is set in variables.env)
- secret: process.env.PRISMA_SECRET, // taken from prisma/prisma.yml (value is set in .env)
- debug: false, // log all GraphQL queries & mutations
+ endpoint: process.env.PRISMA_ENDPOINT,
+ secret: process.env.PRISMA_SECRET,
+ debug: false,
});
-module.exports = db; \ No newline at end of file
+module.exports = db;
diff --git a/finished-application/backend/src/generated/prisma.graphql b/finished-application/backend/src/generated/prisma.graphql
index 64f39a4..cc13ecf 100644
--- a/finished-application/backend/src/generated/prisma.graphql
+++ b/finished-application/backend/src/generated/prisma.graphql
@@ -1,5 +1,5 @@
-# source: https://us1.prisma.sh/wesbos/sick-fits/dev
-# timestamp: Thu Jun 21 2018 15:13:13 GMT-0400 (EDT)
+# source: https://us1.prisma.sh/wesbos/siccccccccck-fits/dev
+# timestamp: Tue Sep 11 2018 16:26:22 GMT-0400 (EDT)
type AggregateCartItem {
count: Int!
@@ -31,8 +31,6 @@ type CartItem implements Node {
quantity: Int!
item(where: ItemWhereInput): Item
user(where: UserWhereInput): User!
- createdAt: DateTime!
- updatedAt: DateTime!
}
"""A connection to a list of items."""
@@ -75,17 +73,15 @@ enum CartItemOrderByInput {
id_DESC
quantity_ASC
quantity_DESC
- createdAt_ASC
- createdAt_DESC
updatedAt_ASC
updatedAt_DESC
+ createdAt_ASC
+ createdAt_DESC
}
type CartItemPreviousValues {
id: ID!
quantity: Int!
- createdAt: DateTime!
- updatedAt: DateTime!
}
type CartItemSubscriptionPayload {
@@ -130,7 +126,7 @@ input CartItemSubscriptionWhereInput {
input CartItemUpdateInput {
quantity: Int
item: ItemUpdateOneInput
- user: UserUpdateOneWithoutCartInput
+ user: UserUpdateOneRequiredWithoutCartInput
}
input CartItemUpdateManyWithoutUserInput {
@@ -229,50 +225,6 @@ input CartItemWhereInput {
"""All values greater than or equal the given value."""
quantity_gte: Int
- createdAt: DateTime
-
- """All values that are not equal to given value."""
- createdAt_not: DateTime
-
- """All values that are contained in given list."""
- createdAt_in: [DateTime!]
-
- """All values that are not contained in given list."""
- createdAt_not_in: [DateTime!]
-
- """All values less than the given value."""
- createdAt_lt: DateTime
-
- """All values less than or equal the given value."""
- createdAt_lte: DateTime
-
- """All values greater than the given value."""
- createdAt_gt: DateTime
-
- """All values greater than or equal the given value."""
- createdAt_gte: DateTime
- updatedAt: DateTime
-
- """All values that are not equal to given value."""
- updatedAt_not: DateTime
-
- """All values that are contained in given list."""
- updatedAt_in: [DateTime!]
-
- """All values that are not contained in given list."""
- updatedAt_not_in: [DateTime!]
-
- """All values less than the given value."""
- updatedAt_lt: DateTime
-
- """All values less than or equal the given value."""
- updatedAt_lte: DateTime
-
- """All values greater than the given value."""
- updatedAt_gt: DateTime
-
- """All values greater than or equal the given value."""
- updatedAt_gte: DateTime
item: ItemWhereInput
user: UserWhereInput
}
@@ -290,8 +242,6 @@ type Item implements Node {
image: String
largeImage: String
price: Int!
- createdAt: DateTime!
- updatedAt: DateTime!
user(where: UserWhereInput): User!
}
@@ -341,10 +291,10 @@ enum ItemOrderByInput {
largeImage_DESC
price_ASC
price_DESC
- createdAt_ASC
- createdAt_DESC
updatedAt_ASC
updatedAt_DESC
+ createdAt_ASC
+ createdAt_DESC
}
type ItemPreviousValues {
@@ -354,8 +304,6 @@ type ItemPreviousValues {
image: String
largeImage: String
price: Int!
- createdAt: DateTime!
- updatedAt: DateTime!
}
type ItemSubscriptionPayload {
@@ -403,7 +351,7 @@ input ItemUpdateDataInput {
image: String
largeImage: String
price: Int
- user: UserUpdateOneInput
+ user: UserUpdateOneRequiredInput
}
input ItemUpdateInput {
@@ -412,7 +360,7 @@ input ItemUpdateInput {
image: String
largeImage: String
price: Int
- user: UserUpdateOneInput
+ user: UserUpdateOneRequiredInput
}
input ItemUpdateOneInput {
@@ -660,54 +608,7 @@ input ItemWhereInput {
"""All values greater than or equal the given value."""
price_gte: Int
- createdAt: DateTime
-
- """All values that are not equal to given value."""
- createdAt_not: DateTime
-
- """All values that are contained in given list."""
- createdAt_in: [DateTime!]
-
- """All values that are not contained in given list."""
- createdAt_not_in: [DateTime!]
-
- """All values less than the given value."""
- createdAt_lt: DateTime
-
- """All values less than or equal the given value."""
- createdAt_lte: DateTime
-
- """All values greater than the given value."""
- createdAt_gt: DateTime
-
- """All values greater than or equal the given value."""
- createdAt_gte: DateTime
- updatedAt: DateTime
-
- """All values that are not equal to given value."""
- updatedAt_not: DateTime
-
- """All values that are contained in given list."""
- updatedAt_in: [DateTime!]
-
- """All values that are not contained in given list."""
- updatedAt_not_in: [DateTime!]
-
- """All values less than the given value."""
- updatedAt_lt: DateTime
-
- """All values less than or equal the given value."""
- updatedAt_lte: DateTime
-
- """All values greater than the given value."""
- updatedAt_gt: DateTime
-
- """All values greater than or equal the given value."""
- updatedAt_gte: DateTime
user: UserWhereInput
- _MagicalBackRelation_CartItemToItem_every: CartItemWhereInput
- _MagicalBackRelation_CartItemToItem_some: CartItemWhereInput
- _MagicalBackRelation_CartItemToItem_none: CartItemWhereInput
}
input ItemWhereUniqueInput {
@@ -723,34 +624,34 @@ scalar Long
type Mutation {
createCartItem(data: CartItemCreateInput!): CartItem!
createOrder(data: OrderCreateInput!): Order!
- createUser(data: UserCreateInput!): User!
createItem(data: ItemCreateInput!): Item!
createOrderItem(data: OrderItemCreateInput!): OrderItem!
+ createUser(data: UserCreateInput!): User!
updateCartItem(data: CartItemUpdateInput!, where: CartItemWhereUniqueInput!): CartItem
updateOrder(data: OrderUpdateInput!, where: OrderWhereUniqueInput!): Order
- updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput!): User
updateItem(data: ItemUpdateInput!, where: ItemWhereUniqueInput!): Item
updateOrderItem(data: OrderItemUpdateInput!, where: OrderItemWhereUniqueInput!): OrderItem
+ updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput!): User
deleteCartItem(where: CartItemWhereUniqueInput!): CartItem
deleteOrder(where: OrderWhereUniqueInput!): Order
- deleteUser(where: UserWhereUniqueInput!): User
deleteItem(where: ItemWhereUniqueInput!): Item
deleteOrderItem(where: OrderItemWhereUniqueInput!): OrderItem
+ deleteUser(where: UserWhereUniqueInput!): User
upsertCartItem(where: CartItemWhereUniqueInput!, create: CartItemCreateInput!, update: CartItemUpdateInput!): CartItem!
upsertOrder(where: OrderWhereUniqueInput!, create: OrderCreateInput!, update: OrderUpdateInput!): Order!
- upsertUser(where: UserWhereUniqueInput!, create: UserCreateInput!, update: UserUpdateInput!): User!
upsertItem(where: ItemWhereUniqueInput!, create: ItemCreateInput!, update: ItemUpdateInput!): Item!
upsertOrderItem(where: OrderItemWhereUniqueInput!, create: OrderItemCreateInput!, update: OrderItemUpdateInput!): OrderItem!
+ upsertUser(where: UserWhereUniqueInput!, create: UserCreateInput!, update: UserUpdateInput!): User!
updateManyCartItems(data: CartItemUpdateInput!, where: CartItemWhereInput): BatchPayload!
updateManyOrders(data: OrderUpdateInput!, where: OrderWhereInput): BatchPayload!
- updateManyUsers(data: UserUpdateInput!, where: UserWhereInput): BatchPayload!
updateManyItems(data: ItemUpdateInput!, where: ItemWhereInput): BatchPayload!
updateManyOrderItems(data: OrderItemUpdateInput!, where: OrderItemWhereInput): BatchPayload!
+ updateManyUsers(data: UserUpdateInput!, where: UserWhereInput): BatchPayload!
deleteManyCartItems(where: CartItemWhereInput): BatchPayload!
deleteManyOrders(where: OrderWhereInput): BatchPayload!
- deleteManyUsers(where: UserWhereInput): BatchPayload!
deleteManyItems(where: ItemWhereInput): BatchPayload!
deleteManyOrderItems(where: OrderItemWhereInput): BatchPayload!
+ deleteManyUsers(where: UserWhereInput): BatchPayload!
}
enum MutationType {
@@ -770,9 +671,9 @@ type Order implements Node {
items(where: OrderItemWhereInput, orderBy: OrderItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [OrderItem!]
total: Int!
user(where: UserWhereInput): User!
+ charge: String!
createdAt: DateTime!
updatedAt: DateTime!
- charge: String!
}
"""A connection to a list of items."""
@@ -789,18 +690,7 @@ input OrderCreateInput {
total: Int!
charge: String!
items: OrderItemCreateManyInput
- user: UserCreateOneWithoutOrdersInput!
-}
-
-input OrderCreateManyWithoutUserInput {
- create: [OrderCreateWithoutUserInput!]
- connect: [OrderWhereUniqueInput!]
-}
-
-input OrderCreateWithoutUserInput {
- total: Int!
- charge: String!
- items: OrderItemCreateManyInput
+ user: UserCreateOneInput!
}
"""An edge in a connection."""
@@ -816,11 +706,9 @@ type OrderItem implements Node {
id: ID!
title: String!
description: String!
- image: String
- largeImage: String
+ image: String!
+ largeImage: String!
price: Int!
- createdAt: DateTime!
- updatedAt: DateTime!
quantity: Int!
user(where: UserWhereInput): User
}
@@ -838,8 +726,8 @@ type OrderItemConnection {
input OrderItemCreateInput {
title: String!
description: String!
- image: String
- largeImage: String
+ image: String!
+ largeImage: String!
price: Int!
quantity: Int
user: UserCreateOneInput
@@ -872,23 +760,21 @@ enum OrderItemOrderByInput {
largeImage_DESC
price_ASC
price_DESC
- createdAt_ASC
- createdAt_DESC
- updatedAt_ASC
- updatedAt_DESC
quantity_ASC
quantity_DESC
+ updatedAt_ASC
+ updatedAt_DESC
+ createdAt_ASC
+ createdAt_DESC
}
type OrderItemPreviousValues {
id: ID!
title: String!
description: String!
- image: String
- largeImage: String
+ image: String!
+ largeImage: String!
price: Int!
- createdAt: DateTime!
- updatedAt: DateTime!
quantity: Int!
}
@@ -1202,50 +1088,6 @@ input OrderItemWhereInput {
"""All values greater than or equal the given value."""
price_gte: Int
- createdAt: DateTime
-
- """All values that are not equal to given value."""
- createdAt_not: DateTime
-
- """All values that are contained in given list."""
- createdAt_in: [DateTime!]
-
- """All values that are not contained in given list."""
- createdAt_not_in: [DateTime!]
-
- """All values less than the given value."""
- createdAt_lt: DateTime
-
- """All values less than or equal the given value."""
- createdAt_lte: DateTime
-
- """All values greater than the given value."""
- createdAt_gt: DateTime
-
- """All values greater than or equal the given value."""
- createdAt_gte: DateTime
- updatedAt: DateTime
-
- """All values that are not equal to given value."""
- updatedAt_not: DateTime
-
- """All values that are contained in given list."""
- updatedAt_in: [DateTime!]
-
- """All values that are not contained in given list."""
- updatedAt_not_in: [DateTime!]
-
- """All values less than the given value."""
- updatedAt_lt: DateTime
-
- """All values less than or equal the given value."""
- updatedAt_lte: DateTime
-
- """All values greater than the given value."""
- updatedAt_gt: DateTime
-
- """All values greater than or equal the given value."""
- updatedAt_gte: DateTime
quantity: Int
"""All values that are not equal to given value."""
@@ -1269,9 +1111,6 @@ input OrderItemWhereInput {
"""All values greater than or equal the given value."""
quantity_gte: Int
user: UserWhereInput
- _MagicalBackRelation_OrderToOrderItem_every: OrderWhereInput
- _MagicalBackRelation_OrderToOrderItem_some: OrderWhereInput
- _MagicalBackRelation_OrderToOrderItem_none: OrderWhereInput
}
input OrderItemWhereUniqueInput {
@@ -1283,20 +1122,20 @@ enum OrderOrderByInput {
id_DESC
total_ASC
total_DESC
+ charge_ASC
+ charge_DESC
createdAt_ASC
createdAt_DESC
updatedAt_ASC
updatedAt_DESC
- charge_ASC
- charge_DESC
}
type OrderPreviousValues {
id: ID!
total: Int!
+ charge: String!
createdAt: DateTime!
updatedAt: DateTime!
- charge: String!
}
type OrderSubscriptionPayload {
@@ -1342,33 +1181,7 @@ input OrderUpdateInput {
total: Int
charge: String
items: OrderItemUpdateManyInput
- user: UserUpdateOneWithoutOrdersInput
-}
-
-input OrderUpdateManyWithoutUserInput {
- create: [OrderCreateWithoutUserInput!]
- connect: [OrderWhereUniqueInput!]
- disconnect: [OrderWhereUniqueInput!]
- delete: [OrderWhereUniqueInput!]
- update: [OrderUpdateWithWhereUniqueWithoutUserInput!]
- upsert: [OrderUpsertWithWhereUniqueWithoutUserInput!]
-}
-
-input OrderUpdateWithoutUserDataInput {
- total: Int
- charge: String
- items: OrderItemUpdateManyInput
-}
-
-input OrderUpdateWithWhereUniqueWithoutUserInput {
- where: OrderWhereUniqueInput!
- data: OrderUpdateWithoutUserDataInput!
-}
-
-input OrderUpsertWithWhereUniqueWithoutUserInput {
- where: OrderWhereUniqueInput!
- update: OrderUpdateWithoutUserDataInput!
- create: OrderCreateWithoutUserInput!
+ user: UserUpdateOneRequiredInput
}
input OrderWhereInput {
@@ -1442,6 +1255,46 @@ input OrderWhereInput {
"""All values greater than or equal the given value."""
total_gte: Int
+ charge: String
+
+ """All values that are not equal to given value."""
+ charge_not: String
+
+ """All values that are contained in given list."""
+ charge_in: [String!]
+
+ """All values that are not contained in given list."""
+ charge_not_in: [String!]
+
+ """All values less than the given value."""
+ charge_lt: String
+
+ """All values less than or equal the given value."""
+ charge_lte: String
+
+ """All values greater than the given value."""
+ charge_gt: String
+
+ """All values greater than or equal the given value."""
+ charge_gte: String
+
+ """All values containing the given string."""
+ charge_contains: String
+
+ """All values not containing the given string."""
+ charge_not_contains: String
+
+ """All values starting with the given string."""
+ charge_starts_with: String
+
+ """All values not starting with the given string."""
+ charge_not_starts_with: String
+
+ """All values ending with the given string."""
+ charge_ends_with: String
+
+ """All values not ending with the given string."""
+ charge_not_ends_with: String
createdAt: DateTime
"""All values that are not equal to given value."""
@@ -1486,46 +1339,6 @@ input OrderWhereInput {
"""All values greater than or equal the given value."""
updatedAt_gte: DateTime
- charge: String
-
- """All values that are not equal to given value."""
- charge_not: String
-
- """All values that are contained in given list."""
- charge_in: [String!]
-
- """All values that are not contained in given list."""
- charge_not_in: [String!]
-
- """All values less than the given value."""
- charge_lt: String
-
- """All values less than or equal the given value."""
- charge_lte: String
-
- """All values greater than the given value."""
- charge_gt: String
-
- """All values greater than or equal the given value."""
- charge_gte: String
-
- """All values containing the given string."""
- charge_contains: String
-
- """All values not containing the given string."""
- charge_not_contains: String
-
- """All values starting with the given string."""
- charge_starts_with: String
-
- """All values not starting with the given string."""
- charge_not_starts_with: String
-
- """All values ending with the given string."""
- charge_ends_with: String
-
- """All values not ending with the given string."""
- charge_not_ends_with: String
items_every: OrderItemWhereInput
items_some: OrderItemWhereInput
items_none: OrderItemWhereInput
@@ -1563,19 +1376,19 @@ enum Permission {
type Query {
cartItems(where: CartItemWhereInput, orderBy: CartItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [CartItem]!
orders(where: OrderWhereInput, orderBy: OrderOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Order]!
- users(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [User]!
items(where: ItemWhereInput, orderBy: ItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Item]!
orderItems(where: OrderItemWhereInput, orderBy: OrderItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [OrderItem]!
+ users(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [User]!
cartItem(where: CartItemWhereUniqueInput!): CartItem
order(where: OrderWhereUniqueInput!): Order
- user(where: UserWhereUniqueInput!): User
item(where: ItemWhereUniqueInput!): Item
orderItem(where: OrderItemWhereUniqueInput!): OrderItem
+ user(where: UserWhereUniqueInput!): User
cartItemsConnection(where: CartItemWhereInput, orderBy: CartItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): CartItemConnection!
ordersConnection(where: OrderWhereInput, orderBy: OrderOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): OrderConnection!
- usersConnection(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): UserConnection!
itemsConnection(where: ItemWhereInput, orderBy: ItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): ItemConnection!
orderItemsConnection(where: OrderItemWhereInput, orderBy: OrderItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): OrderItemConnection!
+ usersConnection(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): UserConnection!
"""Fetches an object given its ID"""
node(
@@ -1587,23 +1400,20 @@ type Query {
type Subscription {
cartItem(where: CartItemSubscriptionWhereInput): CartItemSubscriptionPayload
order(where: OrderSubscriptionWhereInput): OrderSubscriptionPayload
- user(where: UserSubscriptionWhereInput): UserSubscriptionPayload
item(where: ItemSubscriptionWhereInput): ItemSubscriptionPayload
orderItem(where: OrderItemSubscriptionWhereInput): OrderItemSubscriptionPayload
+ user(where: UserSubscriptionWhereInput): UserSubscriptionPayload
}
type User implements Node {
id: ID!
+ name: String!
email: String!
password: String!
- name: String!
- orders(where: OrderWhereInput, orderBy: OrderOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Order!]
resetToken: String
resetTokenExpiry: String
- cart(where: CartItemWhereInput, orderBy: CartItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [CartItem!]
- createdAt: DateTime!
- updatedAt: DateTime!
permissions: [Permission!]!
+ cart(where: CartItemWhereInput, orderBy: CartItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [CartItem!]
}
"""A connection to a list of items."""
@@ -1617,13 +1427,12 @@ type UserConnection {
}
input UserCreateInput {
+ name: String!
email: String!
password: String!
- name: String!
resetToken: String
resetTokenExpiry: String
permissions: UserCreatepermissionsInput
- orders: OrderCreateManyWithoutUserInput
cart: CartItemCreateManyWithoutUserInput
}
@@ -1637,33 +1446,17 @@ input UserCreateOneWithoutCartInput {
connect: UserWhereUniqueInput
}
-input UserCreateOneWithoutOrdersInput {
- create: UserCreateWithoutOrdersInput
- connect: UserWhereUniqueInput
-}
-
input UserCreatepermissionsInput {
set: [Permission!]
}
input UserCreateWithoutCartInput {
- email: String!
- password: String!
name: String!
- resetToken: String
- resetTokenExpiry: String
- permissions: UserCreatepermissionsInput
- orders: OrderCreateManyWithoutUserInput
-}
-
-input UserCreateWithoutOrdersInput {
email: String!
password: String!
- name: String!
resetToken: String
resetTokenExpiry: String
permissions: UserCreatepermissionsInput
- cart: CartItemCreateManyWithoutUserInput
}
"""An edge in a connection."""
@@ -1678,31 +1471,29 @@ type UserEdge {
enum UserOrderByInput {
id_ASC
id_DESC
+ name_ASC
+ name_DESC
email_ASC
email_DESC
password_ASC
password_DESC
- name_ASC
- name_DESC
resetToken_ASC
resetToken_DESC
resetTokenExpiry_ASC
resetTokenExpiry_DESC
- createdAt_ASC
- createdAt_DESC
updatedAt_ASC
updatedAt_DESC
+ createdAt_ASC
+ createdAt_DESC
}
type UserPreviousValues {
id: ID!
+ name: String!
email: String!
password: String!
- name: String!
resetToken: String
resetTokenExpiry: String
- createdAt: DateTime!
- updatedAt: DateTime!
permissions: [Permission!]!
}
@@ -1746,49 +1537,46 @@ input UserSubscriptionWhereInput {
}
input UserUpdateDataInput {
+ name: String
email: String
password: String
- name: String
resetToken: String
resetTokenExpiry: String
permissions: UserUpdatepermissionsInput
- orders: OrderUpdateManyWithoutUserInput
cart: CartItemUpdateManyWithoutUserInput
}
input UserUpdateInput {
+ name: String
email: String
password: String
- name: String
resetToken: String
resetTokenExpiry: String
permissions: UserUpdatepermissionsInput
- orders: OrderUpdateManyWithoutUserInput
cart: CartItemUpdateManyWithoutUserInput
}
input UserUpdateOneInput {
create: UserCreateInput
connect: UserWhereUniqueInput
+ disconnect: Boolean
delete: Boolean
update: UserUpdateDataInput
upsert: UserUpsertNestedInput
}
-input UserUpdateOneWithoutCartInput {
- create: UserCreateWithoutCartInput
+input UserUpdateOneRequiredInput {
+ create: UserCreateInput
connect: UserWhereUniqueInput
- delete: Boolean
- update: UserUpdateWithoutCartDataInput
- upsert: UserUpsertWithoutCartInput
+ update: UserUpdateDataInput
+ upsert: UserUpsertNestedInput
}
-input UserUpdateOneWithoutOrdersInput {
- create: UserCreateWithoutOrdersInput
+input UserUpdateOneRequiredWithoutCartInput {
+ create: UserCreateWithoutCartInput
connect: UserWhereUniqueInput
- delete: Boolean
- update: UserUpdateWithoutOrdersDataInput
- upsert: UserUpsertWithoutOrdersInput
+ update: UserUpdateWithoutCartDataInput
+ upsert: UserUpsertWithoutCartInput
}
input UserUpdatepermissionsInput {
@@ -1796,23 +1584,12 @@ input UserUpdatepermissionsInput {
}
input UserUpdateWithoutCartDataInput {
- email: String
- password: String
name: String
- resetToken: String
- resetTokenExpiry: String
- permissions: UserUpdatepermissionsInput
- orders: OrderUpdateManyWithoutUserInput
-}
-
-input UserUpdateWithoutOrdersDataInput {
email: String
password: String
- name: String
resetToken: String
resetTokenExpiry: String
permissions: UserUpdatepermissionsInput
- cart: CartItemUpdateManyWithoutUserInput
}
input UserUpsertNestedInput {
@@ -1825,11 +1602,6 @@ input UserUpsertWithoutCartInput {
create: UserCreateWithoutCartInput!
}
-input UserUpsertWithoutOrdersInput {
- update: UserUpdateWithoutOrdersDataInput!
- create: UserCreateWithoutOrdersInput!
-}
-
input UserWhereInput {
"""Logical AND on all given filters."""
AND: [UserWhereInput!]
@@ -1879,6 +1651,46 @@ input UserWhereInput {
"""All values not ending with the given string."""
id_not_ends_with: ID
+ name: String
+
+ """All values that are not equal to given value."""
+ name_not: String
+
+ """All values that are contained in given list."""
+ name_in: [String!]
+
+ """All values that are not contained in given list."""
+ name_not_in: [String!]
+
+ """All values less than the given value."""
+ name_lt: String
+
+ """All values less than or equal the given value."""
+ name_lte: String
+
+ """All values greater than the given value."""
+ name_gt: String
+
+ """All values greater than or equal the given value."""
+ name_gte: String
+
+ """All values containing the given string."""
+ name_contains: String
+
+ """All values not containing the given string."""
+ name_not_contains: String
+
+ """All values starting with the given string."""
+ name_starts_with: String
+
+ """All values not starting with the given string."""
+ name_not_starts_with: String
+
+ """All values ending with the given string."""
+ name_ends_with: String
+
+ """All values not ending with the given string."""
+ name_not_ends_with: String
email: String
"""All values that are not equal to given value."""
@@ -1959,46 +1771,6 @@ input UserWhereInput {
"""All values not ending with the given string."""
password_not_ends_with: String
- name: String
-
- """All values that are not equal to given value."""
- name_not: String
-
- """All values that are contained in given list."""
- name_in: [String!]
-
- """All values that are not contained in given list."""
- name_not_in: [String!]
-
- """All values less than the given value."""
- name_lt: String
-
- """All values less than or equal the given value."""
- name_lte: String
-
- """All values greater than the given value."""
- name_gt: String
-
- """All values greater than or equal the given value."""
- name_gte: String
-
- """All values containing the given string."""
- name_contains: String
-
- """All values not containing the given string."""
- name_not_contains: String
-
- """All values starting with the given string."""
- name_starts_with: String
-
- """All values not starting with the given string."""
- name_not_starts_with: String
-
- """All values ending with the given string."""
- name_ends_with: String
-
- """All values not ending with the given string."""
- name_not_ends_with: String
resetToken: String
"""All values that are not equal to given value."""
@@ -2079,62 +1851,9 @@ input UserWhereInput {
"""All values not ending with the given string."""
resetTokenExpiry_not_ends_with: String
- createdAt: DateTime
-
- """All values that are not equal to given value."""
- createdAt_not: DateTime
-
- """All values that are contained in given list."""
- createdAt_in: [DateTime!]
-
- """All values that are not contained in given list."""
- createdAt_not_in: [DateTime!]
-
- """All values less than the given value."""
- createdAt_lt: DateTime
-
- """All values less than or equal the given value."""
- createdAt_lte: DateTime
-
- """All values greater than the given value."""
- createdAt_gt: DateTime
-
- """All values greater than or equal the given value."""
- createdAt_gte: DateTime
- updatedAt: DateTime
-
- """All values that are not equal to given value."""
- updatedAt_not: DateTime
-
- """All values that are contained in given list."""
- updatedAt_in: [DateTime!]
-
- """All values that are not contained in given list."""
- updatedAt_not_in: [DateTime!]
-
- """All values less than the given value."""
- updatedAt_lt: DateTime
-
- """All values less than or equal the given value."""
- updatedAt_lte: DateTime
-
- """All values greater than the given value."""
- updatedAt_gt: DateTime
-
- """All values greater than or equal the given value."""
- updatedAt_gte: DateTime
- orders_every: OrderWhereInput
- orders_some: OrderWhereInput
- orders_none: OrderWhereInput
cart_every: CartItemWhereInput
cart_some: CartItemWhereInput
cart_none: CartItemWhereInput
- _MagicalBackRelation_OrderItemToUser_every: OrderItemWhereInput
- _MagicalBackRelation_OrderItemToUser_some: OrderItemWhereInput
- _MagicalBackRelation_OrderItemToUser_none: OrderItemWhereInput
- _MagicalBackRelation_ItemToUser_every: ItemWhereInput
- _MagicalBackRelation_ItemToUser_some: ItemWhereInput
- _MagicalBackRelation_ItemToUser_none: ItemWhereInput
}
input UserWhereUniqueInput {
diff --git a/finished-application/backend/src/index.js b/finished-application/backend/src/index.js
index 2a1b433..804d6d6 100644
--- a/finished-application/backend/src/index.js
+++ b/finished-application/backend/src/index.js
@@ -1,30 +1,33 @@
-/* eslint-disable */
-require('dotenv').config({ path: 'variables.env' });
-/* eslint-enable */
+const cookieParser = require('cookie-parser');
const jwt = require('jsonwebtoken');
+
+require('dotenv').config({ path: 'variables.env' });
const createServer = require('./createServer');
const db = require('./db');
-const cookieParser = require('cookie-parser');
const server = createServer();
server.express.use(cookieParser());
+// decode the JWT so we can get the user Id on each request
server.express.use((req, res, next) => {
const { token } = req.cookies;
if (token) {
const { userId } = jwt.verify(token, process.env.APP_SECRET);
+ // put the userId onto the req for future requests to access
req.userId = userId;
}
next();
});
-// 2. Get User from their ID
+// 2. Create a middleware that populates the user on each request
+
server.express.use(async (req, res, next) => {
+ // if they aren't logged in, skip this
if (!req.userId) return next();
const user = await db.query.user(
{ where: { id: req.userId } },
- `{ id, permissions, email, name }`
+ '{ id, permissions, email, name }'
);
req.user = user;
next();
@@ -36,9 +39,8 @@ server.start(
credentials: true,
origin: process.env.FRONTEND_URL,
},
- port: process.env.PORT,
},
deets => {
- console.log(`Server is running on http://localhost:${deets.port}`);
+ console.log(`Server is now running on port http://localhost:${deets.port}`);
}
);
diff --git a/finished-application/backend/src/mail.js b/finished-application/backend/src/mail.js
index fc4a47b..5274310 100644
--- a/finished-application/backend/src/mail.js
+++ b/finished-application/backend/src/mail.js
@@ -1,26 +1,26 @@
const nodemailer = require('nodemailer');
const transport = nodemailer.createTransport({
- host: 'smtp.mailtrap.io',
- port: 2525,
+ host: process.env.MAIL_HOST,
+ port: process.env.MAIL_PORT,
auth: {
- user: 'c41bab08214808',
- pass: '04992d4af4bdcf',
+ user: process.env.MAIL_USER,
+ pass: process.env.MAIL_PASS,
},
});
const makeANiceEmail = text => `
<div className="email" style="
- border:1px solid black;
+ border: 1px solid black;
padding: 20px;
font-family: sans-serif;
line-height: 2;
font-size: 20px;
">
- <h2>Hello There</h2>
+ <h2>Hello There!</h2>
<p>${text}</p>
- <p>😘 Wes Bos</p>
+ <p>😘, Wes Bos</p>
</div>
`;
diff --git a/finished-application/backend/src/resolvers/Mutation.js b/finished-application/backend/src/resolvers/Mutation.js
index 80ff3f2..f0ea6a8 100644
--- a/finished-application/backend/src/resolvers/Mutation.js
+++ b/finished-application/backend/src/resolvers/Mutation.js
@@ -1,16 +1,75 @@
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
-const { hasPermission } = require('../utils');
const { randomBytes } = require('crypto');
const { promisify } = require('util');
-const mail = require('../mail');
+const { transport, makeANiceEmail } = require('../mail');
+const { hasPermission } = require('../utils');
const stripe = require('../stripe');
-const mutations = {
- // Signup Mutations
+const Mutations = {
+ async createItem(parent, args, ctx, info) {
+ if (!ctx.request.userId) {
+ throw new Error('You must be logged in to do that!');
+ }
+
+ const item = await ctx.db.mutation.createItem(
+ {
+ data: {
+ // This is how to create a relationship between the Item and the User
+ user: {
+ connect: {
+ id: ctx.request.userId,
+ },
+ },
+ ...args,
+ },
+ },
+ info
+ );
+
+ console.log(item);
+
+ return item;
+ },
+ updateItem(parent, args, ctx, info) {
+ // first take a copy of the updates
+ const updates = { ...args };
+ // remove the ID from the updates
+ delete updates.id;
+ // run the update method
+ return ctx.db.mutation.updateItem(
+ {
+ data: updates,
+ where: {
+ id: args.id,
+ },
+ },
+ info
+ );
+ },
+ async deleteItem(parent, args, ctx, info) {
+ const where = { id: args.id };
+ // 1. find the item
+ const item = await ctx.db.query.item({ where }, `{ id title user { id }}`);
+ // 2. Check if they own that item, or have the permissions
+ const ownsItem = item.user.id === ctx.request.userId;
+ const hasPermissions = ctx.request.user.permissions.some(permission =>
+ ['ADMIN', 'ITEMDELETE'].includes(permission)
+ );
+
+ if (!ownsItem && hasPermissions) {
+ throw new Error("You don't have permission to do that!");
+ }
+
+ // 3. Delete it!
+ return ctx.db.mutation.deleteItem({ where }, info);
+ },
async signup(parent, args, ctx, info) {
+ // lowercase their email
args.email = args.email.toLowerCase();
+ // hash their password
const password = await bcrypt.hash(args.password, 10);
+ // create the user in the database
const user = await ctx.db.mutation.createUser(
{
data: {
@@ -21,153 +80,88 @@ const mutations = {
},
info
);
+ // create the JWT token for them
const token = jwt.sign({ userId: user.id }, process.env.APP_SECRET);
+ // We set the jwt as a cookie on the response
ctx.response.cookie('token', token, {
- maxAge: 1000 * 60 * 60 * 24 * 365,
httpOnly: true,
+ maxAge: 1000 * 60 * 60 * 24 * 365, // 1 year cookie
});
+ // Finalllllly we return the user to the browser
return user;
},
-
- async signout(parent, args, ctx, info) {
- ctx.response.clearCookie('token');
- return { message: 'goodbye!' };
- },
-
async signin(parent, { email, password }, ctx, info) {
+ // 1. check if there is a user with that email
const user = await ctx.db.query.user({ where: { email } });
if (!user) {
- throw new Error(`No such user found for email: ${email}`);
+ throw new Error(`No such user found for email ${email}`);
}
-
+ // 2. Check if their password is correct
const valid = await bcrypt.compare(password, user.password);
if (!valid) {
- throw new Error('Invalid password');
+ throw new Error('Invalid Password!');
}
- // set the cookie
+ // 3. generate the JWT Token
const token = jwt.sign({ userId: user.id }, process.env.APP_SECRET);
+ // 4. Set the cookie with the token
ctx.response.cookie('token', token, {
- maxAge: 1000 * 60 * 60 * 24 * 365,
httpOnly: true,
+ maxAge: 1000 * 60 * 60 * 24 * 365,
});
+ // 5. Return the user
return user;
},
-
- // 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');
- }
-
- const item = await ctx.db.mutation.createItem(
- {
- data: {
- user: {
- connect: {
- id: ctx.request.userId,
- },
- },
- ...args,
- },
- },
- info
- );
- return item;
- },
-
- async deleteItem(parent, args, ctx, info) {
- const where = {
- id: args.id,
- };
- // 1. find the item
- const item = await ctx.db.query.item({ where }, `{ user {id}, title, id, description }`);
- // 2. if they 1. Don't own it AND 2. aren't an admin
- if (item.user.id !== ctx.request.user.id && !ctx.request.user.permissions.includes('ADMIN')) {
- throw new Error("You aren't allowed to delete that item!");
- }
-
- // 3. remove any orderItems this item is in
-
- return ctx.db.mutation.deleteItem({ where }, info);
- },
-
- 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 || !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,
- },
- },
- info
- );
+ signout(parent, args, ctx, info) {
+ ctx.response.clearCookie('token');
+ return { message: 'Goodbye!' };
},
-
- // Send password request
async requestReset(parent, args, ctx, info) {
- // 1. find if there is a user with that email
+ // 1. Check if this is a real user
const user = await ctx.db.query.user({ where: { email: args.email } });
-
if (!user) {
- throw new Error(`No user with the email ${args.email}`);
+ throw new Error(`No such user found for email ${args.email}`);
}
- // 2. Set a reset token, and a reset date
- const resetToken = (await promisify(randomBytes)(20)).toString('hex');
+ // 2. Set a reset token and expiry on that user
+ const randomBytesPromiseified = promisify(randomBytes);
+ const resetToken = (await randomBytesPromiseified(20)).toString('hex');
const resetTokenExpiry = Date.now() + 3600000; // 1 hour from now
- console.log({ resetToken, resetTokenExpiry });
const res = await ctx.db.mutation.updateUser({
where: { email: args.email },
data: { resetToken, resetTokenExpiry },
});
-
- // 3. Send them their token via email
- const mailRes = await mail.transport.sendMail({
- from: 'wesbos@gmail.com',
+ // 3. Email them that reset token
+ const mailRes = await transport.sendMail({
+ from: 'wes@wesbos.com',
to: user.email,
- subject: 'Your password reset token',
- html: mail.makeANiceEmail(
- `Your password reset link is here! \n\n<a href="${process.env
- .FRONTEND_URL}/reset?resetToken=${resetToken}">Click Here to reset</a>`
- ),
+ subject: 'Your Password Reset Token',
+ html: makeANiceEmail(`Your Password Reset Token is here!
+ \n\n
+ <a href="${process.env
+ .FRONTEND_URL}/reset?resetToken=${resetToken}">Click Here to Reset</a>`),
});
- return res.updateUser;
- },
+ // 4. Return the message
+ return { message: 'Thanks!' };
+ },
async resetPassword(parent, args, ctx, info) {
- // 1. Check that the passwords match
+ // 1. check if the passwords match
if (args.password !== args.confirmPassword) {
- throw new Error('Passwords do not match');
+ throw new Error("Yo Passwords don't match!");
}
-
- // 2. Check that this is a legit resetToken
- // 3. Check that it's not expired
- // Note: If we didn't need the user here, we could also use db.exists()
+ // 2. check if its a legit reset token
+ // 3. Check if its expired
const [user] = await ctx.db.query.users({
where: {
resetToken: args.resetToken,
- resetTokenExpiry_gte: Date.now() - 3600000, // within the last hour
+ resetTokenExpiry_gte: Date.now() - 3600000,
},
});
-
if (!user) {
- throw new Error('This token is either invalid or expired.');
+ throw new Error('This token is either invalid or expired!');
}
-
- // 4. Hash the password
+ // 4. Hash their new password
const password = await bcrypt.hash(args.password, 10);
-
- // 5. Update the users password
- // clean up the resetToken fields at the same time
+ // 5. Save the new password to the user and remove old resetToken fields
const updatedUser = await ctx.db.mutation.updateUser({
where: { email: user.email },
data: {
@@ -176,34 +170,63 @@ const mutations = {
resetTokenExpiry: null,
},
});
+ // 6. Generate JWT
const token = jwt.sign({ userId: updatedUser.id }, process.env.APP_SECRET);
+ // 7. Set the JWT cookie
ctx.response.cookie('token', token, {
- maxAge: 1000 * 60 * 60 * 24 * 365,
httpOnly: true,
+ maxAge: 1000 * 60 * 60 * 24 * 365,
});
-
- // 6. send back the User for the GraphQL request on the client
+ // 8. return the new user
return updatedUser;
},
- /*
- Add to cart
- */
+ async updatePermissions(parent, args, ctx, info) {
+ // 1. Check if they are logged in
+ if (!ctx.request.userId) {
+ throw new Error('You must be logged in!');
+ }
+ // 2. Query the current user
+ const currentUser = await ctx.db.query.user(
+ {
+ where: {
+ id: ctx.request.userId,
+ },
+ },
+ info
+ );
+ // 3. Check if they have permissions to do this
+ hasPermission(currentUser, ['ADMIN', 'PERMISSIONUPDATE']);
+ // 4. Update the permissions
+ return ctx.db.mutation.updateUser(
+ {
+ data: {
+ permissions: {
+ set: args.permissions,
+ },
+ },
+ where: {
+ id: args.userId,
+ },
+ },
+ info
+ );
+ },
async addToCart(parent, args, ctx, info) {
- const userId = ctx.request.userId;
-
+ // 1. Make sure they are signed in
+ const { userId } = ctx.request;
if (!userId) {
- throw new Error('You must be signed in to add to cart!');
+ throw new Error('You must be signed in soooon');
}
-
- // 1. Check if there is a CartItem for this user and item already
+ // 2. Query the users current cart
const [existingCartItem] = await ctx.db.query.cartItems({
where: {
user: { id: userId },
item: { id: args.id },
},
});
-
+ // 3. Check if that item is already in their cart and increment by 1 if it is
if (existingCartItem) {
+ console.log('This item is already in their cart');
return ctx.db.mutation.updateCartItem(
{
where: { id: existingCartItem.id },
@@ -212,15 +235,12 @@ const mutations = {
info
);
}
-
- // Otherwise create a new cartItem
+ // 4. If its not, create a fresh CartItem for that user!
return ctx.db.mutation.createCartItem(
{
data: {
user: {
- connect: {
- id: userId,
- },
+ connect: { id: userId },
},
item: {
connect: { id: args.id },
@@ -230,126 +250,88 @@ const mutations = {
info
);
},
-
- // delete that cart item
async removeFromCart(parent, args, ctx, info) {
- console.log(args.id);
- // 1. Find the CartItem
+ // 1. Find the cart item
const cartItem = await ctx.db.query.cartItem(
{
- where: { id: args.id },
+ where: {
+ id: args.id,
+ },
},
- `{ id, user { id, permissions }}`
+ `{ id, user { id }}`
);
- // 2. Check they own it
+ // 1.5 Make sure we found an item
+ if (!cartItem) throw new Error('No CartItem Found!');
+ // 2. Make sure they own that cart item
if (cartItem.user.id !== ctx.request.userId) {
- throw new Error("Cheatin' huh");
+ throw new Error('Cheatin huhhhh');
}
- // 3. Delete it
+ // 3. Delete that cart item
return ctx.db.mutation.deleteCartItem(
{
- where: {
- id: args.id,
- },
+ where: { id: args.id },
},
info
);
},
-
async createOrder(parent, args, ctx, info) {
- const userId = ctx.request.userId;
+ // 1. Query the current user and make sure they are signed in
+ const { userId } = ctx.request;
+ if (!userId) throw new Error('You must be signed in to complete this order.');
const user = await ctx.db.query.user(
{ where: { id: userId } },
- '{ id, name, email, cart { id, quantity, item { title, price, id, description, image } }}'
+ `{
+ id
+ name
+ email
+ cart {
+ id
+ quantity
+ item { title price id description image largeImage }
+ }}`
);
- // 1. Recalculate the total for the price
+ // 2. recalculate the total for the price
const amount = user.cart.reduce(
(tally, cartItem) => tally + cartItem.item.price * cartItem.quantity,
0
);
- // 2. Create a stripe charge
+ console.log(`Going to charge for a total of ${amount}`);
+ // 3. Create the stripe charge (turn token into $$$)
const charge = await stripe.charges.create({
amount,
- currency: 'usd',
+ currency: 'USD',
source: args.token,
});
-
- // 3. convert the items they want to OrderItems
+ // 4. Convert the CartItems to OrderItems
const orderItems = user.cart.map(cartItem => {
- console.log(cartItem);
const orderItem = {
- quantity: cartItem.quantity,
- // copy all the item details so it's there forever
...cartItem.item,
- // item: {
- // // relationship to the Item incase we need it
- // connect: { id: cartItem.item.id },
- // },
- user: { connect: { id: user.id } },
+ quantity: cartItem.quantity,
+ user: { connect: { id: userId } },
};
- // scrub the ID from it because the orderItem will have it's own ID
delete orderItem.id;
return orderItem;
});
- // 4. Create the Order
+ // 5. create the Order
const order = await ctx.db.mutation.createOrder({
data: {
total: charge.amount,
charge: charge.id,
- items: {
- create: orderItems,
- },
- user: {
- connect: {
- id: user.id,
- },
- },
+ items: { create: orderItems },
+ user: { connect: { id: userId } },
},
});
-
- // 5. Clean up, clear the users cart and send back { user, order }
- // Delete the users current cart items
+ // 6. Clean up - clear the users cart, delete cartItems
const cartItemIds = user.cart.map(cartItem => cartItem.id);
await ctx.db.mutation.deleteManyCartItems({
where: {
id_in: cartItemIds,
},
});
-
- // 6. Send the order back to the client
+ // 7. Return the Order to the client
return order;
},
-
- async updateUser(parent, args, ctx, info) {
- 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 = 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']);
- return ctx.db.mutation.updateUser(
- {
- data: {
- permissions: {
- set: args.permissions,
- },
- },
- where: { id: args.userId },
- },
- info
- );
- },
};
-module.exports = mutations;
+module.exports = Mutations;
diff --git a/finished-application/backend/src/resolvers/Query.js b/finished-application/backend/src/resolvers/Query.js
index 51c2c42..22a6414 100644
--- a/finished-application/backend/src/resolvers/Query.js
+++ b/finished-application/backend/src/resolvers/Query.js
@@ -1,52 +1,59 @@
-const { hasPermission } = require('../utils');
-
const { forwardTo } = require('prisma-binding');
+const { hasPermission } = require('../utils');
const Query = {
items: forwardTo('db'),
+ item: forwardTo('db'),
itemsConnection: forwardTo('db'),
-
- async order(parent, args, ctx, info) {
- // 1. make sure they are signed in
+ me(parent, args, ctx, info) {
+ // check if there is a current user ID
if (!ctx.request.userId) {
- throw new Error('You Must be signed in to view an order');
+ return null;
}
-
- // 2. Create the query
- const where = {
- id: args.id,
- user: {
- id: ctx.request.userId,
+ return ctx.db.query.user(
+ {
+ where: { 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;
+ info
+ );
},
-
- me(parent, args, ctx, info) {
+ async users(parent, args, ctx, info) {
+ // 1. Check if they are logged in
if (!ctx.request.userId) {
- return null; // don't error out, just return nothing
+ throw new Error('You must be logged in!');
}
+ console.log(ctx.request.userId);
+ // 2. Check if the user has the permissions to query all the users
+ hasPermission(ctx.request.user, ['ADMIN', 'PERMISSIONUPDATE']);
- return ctx.db.query.user(
+ // 2. if they do, query all the users!
+ return ctx.db.query.users({}, info);
+ },
+ async order(parent, args, ctx, info) {
+ // 1. Make sure they are logged in
+ if (!ctx.request.userId) {
+ throw new Error('You arent logged in!');
+ }
+ // 2. Query the current order
+ const order = await ctx.db.query.order(
{
- where: { id: ctx.request.userId },
+ where: { id: args.id },
},
info
);
+ // 3. Check if the have the permissions to see this order
+ const ownsOrder = order.user.id === ctx.request.userId;
+ const hasPermissionToSeeOrder = ctx.request.user.permissions.includes('ADMIN');
+ if (!ownsOrder || !hasPermission) {
+ throw new Error('You cant see this buddd');
+ }
+ // 4. Return the order
+ return order;
},
-
async orders(parent, args, ctx, info) {
const { userId } = ctx.request;
if (!userId) {
- throw new Error('You must be signed in to see your orders');
+ throw new Error('you must be signed in!');
}
return ctx.db.query.orders(
{
diff --git a/finished-application/backend/src/schema.graphql b/finished-application/backend/src/schema.graphql
index 07533eb..8a8eeeb 100644
--- a/finished-application/backend/src/schema.graphql
+++ b/finished-application/backend/src/schema.graphql
@@ -1,39 +1,39 @@
-# The Below line looks like a comment, but it's not!
# import * from './generated/prisma.graphql'
-type Query {
- me: User
- order(id: ID!): Order!
- orders(where: OrderWhereInput, orderBy: OrderOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Order]!
- items(where: ItemWhereInput, orderBy: ItemOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [Item]!
- itemsConnection(where: ItemWhereInput, orderBy: ItemOrderByInput, first: Int, last: Int, skip: Int): ItemConnection!
+type SuccessMessage {
+ message: String
}
type Mutation {
+ createItem(title: String, description: String, price: Int, image: String, largeImage: String): Item!
+ updateItem(id: ID!, title: String, description: String, price: Int): Item!
+ deleteItem(id: ID!): Item
signup(email: String!, password: String!, name: String!): User!
signin(email: String!, password: String!): User!
- requestReset(email: String!): User
+ signout: SuccessMessage
+ requestReset(email: String!): SuccessMessage
resetPassword(resetToken: String!, password: String!, confirmPassword: String!): User!
- createItem(title: String, description: String, price: Int, image: String, largeImage: String): Item!
- deleteItem(id: ID!): Item!
- updateItem(id: ID!, title: String, description: String, price: Int): Item!
+ updatePermissions(permissions: [Permission], userId: ID!): User
addToCart(id: ID!): CartItem
removeFromCart(id: ID!): CartItem
createOrder(token: String!): Order!
- updateUser(name: String): User
- signout: SuccessMessage
- updatePermissions(permissions: [Permission], userId: ID!): User
}
-type SuccessMessage {
- message: String
+type Query {
+ items(where: ItemWhereInput, orderBy: ItemOrderByInput, skip: Int, first: Int): [Item]!
+ item(where: ItemWhereUniqueInput!): Item
+ itemsConnection(where: ItemWhereInput): ItemConnection!
+ me: User
+ users: [User]!
+ order(id: ID!): Order
+ orders(orderBy: OrderOrderByInput): [Order]!
}
-type User {
+type User{
id: ID!
- email: String!
name: String!
- orders: [Order!]!
+ email: String!
+ permissions: [Permission!]!
cart: [CartItem!]!
- permissions: [Permission]!
+ orders: [OrderItem]
}