const ObjectID = require("mongodb").ObjectID; const jwt = require('jsonwebtoken') const jwtSecret = 'CbymrfGfnB' const anonResolvers = ['login', 'createUser']; ;(async () => { const {Savable, slice, getModels} = await require('./models.js')() class User extends Savable { static get relations(){ return { } } } Savable.addClass(User) const express = require('express'); const express_graphql = require('express-graphql'); const { buildSchema } = require('graphql'); const schema = buildSchema(` type Query { login(login: String!, password: String!): String categories: [Category] category(_id: ID!): Category goods: [Good] good(_id: ID!): Good myOrders: [Order] orders: [Order] } type Mutation { createUser(login: String!, password: String!): User changePassword(password: String!): User setCategory(cat: CategoryInput!):Category setGood(good: GoodInput!):Good setOrder(order: OrderInput):Order setOrderGood(orderGood: OrderGoodInput):OrderGood } type User { _id: String login: String nick : String orders: [Order] } type Category { _id: ID, name: String!, goods: [Good] } type Good { _id: ID, name: String!, description: String price: Float orderGoods: [OrderGood] categories: [Category] } type OrderGood { _id: ID, price: Float, count: Float, good: Good, order: Order } type Order { _id: ID orderGoods: [OrderGood] } input UserInput { _id: String login: String nick : String } input CategoryInput { _id: ID, name: String!, goods: [ID] } input GoodInput { _id: ID, name: String!, description: String price: Float categories: [ID] } input OrderGoodInput { _id: ID, count: Int!, good: ID!, order: ID! } input OrderInput { _id: ID orderGoods: [ID] } `); var app = express(); app.use(express.static('public')); const rootResolvers = { createUser:async function ({login, password}){ let user = await Savable.m.User.findOne({login, password}) if (user) return null; user = await (new User({login, password})).save() user.___owner = user._id.toString() user.___permissions = { read: ["owner", "user"] } return await user.save() }, login: async function({login, password}){ console.log(Savable.classes) const user = await Savable.m.User.findOne({login, password}) if (!user) return null; const token = jwt.sign({ sub: {id: user._id, login}}, jwtSecret); //подписывам токен нашим ключем return token }, changePassword:async function ({password}, {jwt: {id}, models: {SlicedSavable, User}} ){ id = new ObjectID(id) const user = await SlicedSavable.m.User.findOne({_id: id}) if (!user) return null; user.password = password; return await user.save() }, async setCategory({cat}, {jwt: {id}, models: {SlicedSavable, Category}}){ if ('_id' in cat){ let entity = await SlicedSavable.m.Category.findOne({_id: ObjectID(cat._id)}) console.log(entity) if (entity){ entity.name = cat.name if (cat.goods){ entity.goods = [] for (goodId of cat.goods){ let good = await SlicedSavable.m.Good.findOne({_id: ObjectID(goodId)}); good && entity.goods.push(good) } } return await entity.save() } } return await (new Category(cat)).save() }, async categories({}, {jwt: {id}, models: {SlicedSavable, Category}}){ categories = [] for (let category of SlicedSavable.m.Category.find({})){ try {category = await category} catch (e) { break } categories.push(category) } return categories; }, async category({_id}, {jwt: {id}, models: {SlicedSavable, Category}}){ return await SlicedSavable.m.Category.findOne({_id: ObjectID(_id)}); }, async setGood({good}, {jwt: {id}, models: {SlicedSavable, Good}}){ if ('_id' in good){ let entity = await SlicedSavable.m.Good.findOne({_id: ObjectID(good._id)}) if (entity){ entity.name = good.name entity.description = good.description entity.price = good.price if (good.categories){ console.log(good.categories) entity.categories = [] for (catId of good.categories){ let cat = await SlicedSavable.m.Category.findOne({_id: ObjectID(catId)}); cat && entity.categories.push(cat) } } return await entity.save() } } return await (new Good(good)).save() }, async goods({}, {jwt: {id}, models: {SlicedSavable, Good}}){ goods = [] for (let good of SlicedSavable.m.Good.find({})){ try {good = await good} catch (e) { break } goods.push(good) } return goods; }, async good({_id}, {jwt: {id}, models: {SlicedSavable, Good}}){ return await SlicedSavable.m.Good.findOne({_id: ObjectID(_id)}); }, async setOrder({order}, {jwt: {id}, models: {SlicedSavable, Order, thisUser}}){ if ('_id' in order){ let entity = await SlicedSavable.m.Order.findOne({_id: ObjectID(good._id)}) if (entity){ //entity.name = good.name //entity.description = good.description if (order.orderGoods){ entity.orderGoods = [] for (orderGoodId of entity.orderGoods){ let orderGood = await SlicedSavable.m.OrderGood.findOne({_id: ObjectID(orderGoodId)}); orderGood && entity.orderGoods.push(orderGood) } } entity.user = thisUser return await entity.save() } } order.user = thisUser return await (new Order(order)).save() }, async orders({}, {jwt: {id}, models: {SlicedSavable}}){ orders = [] for (let order of SlicedSavable.m.Order.find({})){ try {order = await order} catch (e) { break } orders.push(order) } return order; }, async myOrders({}, {jwt: {id}, models: {SlicedSavable}}){ orders = [] for (let order of SlicedSavable.m.Order.find({___owner: id.toString(id)})){ try {order = await order} catch (e) { break } orders.push(order) } return orders; }, async order({_id}, {jwt: {id}, models: {SlicedSavable, Good}}){ return await SlicedSavable.m.Order.findOne({_id: ObjectID(_id)}); }, async setOrderGood({orderGood}, {jwt: {id}, models: {SlicedSavable, OrderGood, thisUser}}){ console.log(orderGood) let order = await SlicedSavable.m.Order.findOne({'_id': ObjectID(orderGood.order)}) let good = await SlicedSavable.m.Good.findOne ({'_id': ObjectID(orderGood.good)}) if (order && good){ let entity = await SlicedSavable.m.OrderGood.findOne({'order._id': order._id, 'good._id': good._id}) if (!entity){ entity = new OrderGood({}) } entity.price = good.price entity.count = orderGood.count entity.order = order entity.good = good await entity.save() console.log(entity) return entity } return null; }, async createEvent({name, total}, {jwt: {id}, models: {Event}}){ return await (new Event({name, total})).save() }, async changeEvent({eventId, name, total}, {jwt: {id}, models: {SlicedSavable}}){ const event = await SlicedSavable.m.Event.findOne({_id: ObjectID(eventId)}) if (!event) return null; event.name = name event.total = total return await event.save() }, async events({}, {jwt: {id}, models: {SlicedSavable}}){ let events = [] for (let event of SlicedSavable.m.Event.find({})){ event = await event //const {_id, name, owner, moneyEvents, usersSum, moneyDiff, total} = event //event = {_id, name, owner, moneyEvents, usersSum: await event.usersSum, total} //console.log(event) events.push(event) } return events; }, async event({eventId}, {jwt: {id}, models: {SlicedSavable}}){ return await SlicedSavable.m.Event.findOne({_id: ObjectID(eventId)}); }, async createEventMoney({eventId, amount}, {jwt: {id}, models: {SlicedSavable, EventMoney, thisUser}}){ let eventMoney = await SlicedSavable.m.EventMoney.findOne({"user._id": ObjectID(id), "event._id": ObjectID(eventId)}) if (eventMoney){ eventMoney.amount = amount; return await eventMoney.save() } const event = await SlicedSavable.m.Event.findOne({_id: ObjectID(eventId)}) if (!event) return null; if (!thisUser) return null; console.log(thisUser, event, amount) return await (new EventMoney({user: thisUser, event, amount})).save() }, async eventMoneysByEvent({eventId}, {jwt: {id}, models: {SlicedSavable}}){ const event = await SlicedSavable.m.Event.findOne({_id: ObjectID(eventId)}); if (!event) return null const moneys = []; for (let money of event.moneyEvents){ try { await money console.log(money) } catch (e){ console.log('skip no access user' ,e) } moneys.push(money) console.log('in loop') } console.log('after loop') return moneys; }, async eventMoneys({}, {jwt: {id}, models: {SlicedSavable}}){ const me = await SlicedSavable.m.User.findOne({_id: ObjectID(id)}); if (!me) return null const moneys = []; for (let money of me.moneyEvents){ moneys.push(await money) } return moneys; }, } app.use('/graphql', express_graphql(async (req, res, gql) => { const authorization = req.headers.authorization if (!authorization && (gql.operationName === null || anonResolvers.includes(gql.operationName))) return { schema: schema, rootValue: rootResolvers, graphiql: true, } if (authorization && authorization.startsWith('Bearer ')){ console.log('token provided') const token = authorization.substr("Bearer ".length) const decoded = jwt.verify(token, jwtSecret) if (decoded){ console.log('token verified', decoded) let slicedModels = await getModels(decoded.sub.id) return { schema: schema, rootValue: rootResolvers, graphiql: true, context: {jwt: decoded.sub, models: slicedModels} } } } })) app.listen(4000, () => console.log('Express GraphQL Server Now Running On localhost:4000/graphql')); })()