index.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. const ObjectID = require("mongodb").ObjectID;
  2. const jwt = require('jsonwebtoken')
  3. const jwtSecret = 'CbymrfGfnB'
  4. const expressJwt = require('express-jwt');
  5. const anonResolvers = ['login', 'createUser'];
  6. ;(async () => {
  7. const {Savable, slice} = await require('./models.js')('cb')
  8. class User extends Savable {
  9. static get relations(){
  10. return {
  11. events: "users"
  12. }
  13. }
  14. }
  15. Savable.addClass(User)
  16. const express = require('express');
  17. const express_graphql = require('express-graphql');
  18. const { buildSchema } = require('graphql');
  19. const schema = buildSchema(`
  20. type Query {
  21. login(login: String!, password: String!): String
  22. events: [Event]
  23. event(eventId: String!): Event
  24. eventMoneysByEvent(eventId: String!): [EventMoney]
  25. eventMoneys: [EventMoney]
  26. }
  27. type Mutation {
  28. createUser(login: String!, password: String!): User
  29. changePassword(password: String!): User
  30. createEvent(name: String!, total: Float!):Event
  31. changeEvent(eventId:String!, name: String!, total: Float!):Event
  32. createEventMoney(eventId: String!, amount: Float):EventMoney
  33. }
  34. type User {
  35. _id: String
  36. login: String
  37. nick : String
  38. moneyEvents: [EventMoney]
  39. }
  40. type Event {
  41. _id: String
  42. name: String
  43. moneyEvents: [EventMoney]
  44. owner: String,
  45. total: Float,
  46. usersSum: Float,
  47. moneyDiff: Float,
  48. avg: Float
  49. }
  50. type EventMoney {
  51. _id: String
  52. user: User
  53. event: Event
  54. amount: Float
  55. owner: String
  56. avgDiff: Float
  57. }
  58. `);
  59. var app = express();
  60. app.use(express.static('public'));
  61. const rootResolvers = {
  62. createUser:async function ({login, password}){
  63. let user = await Savable.m.User.findOne({login, password})
  64. if (user)
  65. return null;
  66. user = await (new User({login, password})).save()
  67. user.___owner = user._id.toString()
  68. user.___permissions = {
  69. read: ["owner", "user"]
  70. }
  71. return await user.save()
  72. },
  73. login: async function({login, password}){
  74. const user = await Savable.m.User.findOne({login, password})
  75. if (!user)
  76. return null;
  77. const token = jwt.sign({ sub: {id: user._id, login}}, jwtSecret); //подписывам токен нашим ключем
  78. return token
  79. },
  80. changePassword:async function ({password}, {jwt: {id}, models: {SlicedSavable, User}} ){
  81. id = new ObjectID(id)
  82. const user = await SlicedSavable.m.User.findOne({_id: id})
  83. if (!user)
  84. return null;
  85. user.password = password;
  86. return await user.save()
  87. },
  88. async createEvent({name, total}, {jwt: {id}, models: {Event}}){
  89. return await (new Event({name, total})).save()
  90. },
  91. async changeEvent({eventId, name, total}, {jwt: {id}, models: {SlicedSavable}}){
  92. const event = await SlicedSavable.m.Event.findOne({_id: ObjectID(eventId)})
  93. if (!event)
  94. return null;
  95. event.name = name
  96. event.total = total
  97. return await event.save()
  98. },
  99. async events({}, {jwt: {id}, models: {SlicedSavable}}){
  100. let events = []
  101. for (let event of SlicedSavable.m.Event.find({})){
  102. event = await event
  103. //const {_id, name, owner, moneyEvents, usersSum, moneyDiff, total} = event
  104. //event = {_id, name, owner, moneyEvents, usersSum: await event.usersSum, total}
  105. //console.log(event)
  106. events.push(event)
  107. }
  108. return events;
  109. },
  110. async event({eventId}, {jwt: {id}, models: {SlicedSavable}}){
  111. return await SlicedSavable.m.Event.findOne({_id: ObjectID(eventId)});
  112. },
  113. async createEventMoney({eventId, amount}, {jwt: {id}, models: {SlicedSavable, EventMoney}}){
  114. let eventMoney = await SlicedSavable.m.EventMoney.findOne({"user._id": ObjectID(id), "event._id": ObjectID(eventId)})
  115. if (eventMoney){
  116. eventMoney.amount = amount;
  117. return await eventMoney.save()
  118. }
  119. const event = await SlicedSavable.m.Event.findOne({_id: ObjectID(eventId)})
  120. if (!event)
  121. return null;
  122. const me = await SlicedSavable.m.User.findOne({_id: ObjectID(id)})
  123. if (!me)
  124. return null;
  125. return await (new EventMoney({user: me, event, amount})).save()
  126. },
  127. async eventMoneysByEvent({eventId}, {jwt: {id}, models: {SlicedSavable}}){
  128. const event = await SlicedSavable.m.Event.findOne({_id: ObjectID(eventId)});
  129. if (!event)
  130. return null
  131. const moneys = [];
  132. for (let money of event.moneyEvents){
  133. try {
  134. await money
  135. console.log(money)
  136. }
  137. catch (e){
  138. console.log('skip no access user' ,e)
  139. }
  140. moneys.push(money)
  141. console.log('in loop')
  142. }
  143. //for (let money of event.moneyEvents){
  144. //moneys.push(await money)
  145. //}
  146. console.log('after loop')
  147. return moneys;
  148. },
  149. async eventMoneys({}, {jwt: {id}, models: {SlicedSavable}}){
  150. const me = await SlicedSavable.m.User.findOne({_id: ObjectID(id)});
  151. if (!me)
  152. return null
  153. const moneys = [];
  154. for (let money of me.moneyEvents){
  155. moneys.push(await money)
  156. }
  157. return moneys;
  158. },
  159. }
  160. /*
  161. mutation createUser($login:String!, $password:String!){
  162. createUser(login:$login, password:$password){
  163. _id, login
  164. }
  165. }
  166. query login($login:String!, $password:String!){
  167. login(login:$login, password:$password){
  168. _id, login
  169. }
  170. }
  171. */
  172. function getModels(id){
  173. const SlicedSavable = slice([id, 'user'])
  174. class User extends SlicedSavable {
  175. constructor(...params){
  176. super(...params)
  177. if (this.moneyEvents instanceof Array)
  178. return
  179. if (this.moneyEvents instanceof SlicedSavable)
  180. this.moneyEvents = [this.moneyEvents];
  181. this.moneyEvents = [];
  182. }
  183. static get relations(){
  184. return {
  185. moneyEvents: "user"
  186. }
  187. }
  188. }
  189. SlicedSavable.addClass(User)
  190. class Event extends SlicedSavable {
  191. constructor(...params){
  192. super(...params)
  193. if (this.moneyEvents instanceof Array)
  194. return
  195. if (this.moneyEvents instanceof SlicedSavable)
  196. this.moneyEvents = [this.moneyEvents];
  197. this.moneyEvents = [];
  198. }
  199. get owner(){
  200. return this.___owner
  201. }
  202. get usersSum(){
  203. return (async () => {
  204. var result = 0;
  205. for (let money of this.moneyEvents){
  206. result += (await money).amount
  207. console.log('MONEY SUM', money.amount, money._id)
  208. }
  209. return result;
  210. })()
  211. }
  212. get moneyDiff(){
  213. return (async () => {
  214. return (await this.usersSum) - (this.total || 0);
  215. })()
  216. }
  217. get avg(){
  218. return this.total/((this.moneyEvents && this.moneyEvents.length) || 1)
  219. }
  220. static get relations(){
  221. return {
  222. moneyEvents: "event"
  223. }
  224. }
  225. }
  226. SlicedSavable.addClass(Event)
  227. class EventMoney extends SlicedSavable {
  228. get owner(){
  229. return this.___owner
  230. }
  231. get avgDiff(){
  232. return (async () => this.amount - (await this.event).avg)()
  233. }
  234. static get relations(){
  235. return {
  236. user: "moneyEvents",
  237. event: "moneyEvents"
  238. }
  239. }
  240. }
  241. SlicedSavable.addClass(EventMoney)
  242. return {
  243. SlicedSavable, User, Event, EventMoney
  244. }
  245. }
  246. app.use('/graphql', express_graphql(async (req, res, gql) => {
  247. if (gql.operationName === null || anonResolvers.includes(gql.operationName))
  248. return {
  249. schema: schema,
  250. rootValue: rootResolvers,
  251. graphiql: true,
  252. }
  253. const authorization = req.headers.authorization
  254. if (authorization && authorization.startsWith('Bearer ')){
  255. console.log('token provided')
  256. const token = authorization.substr("Bearer ".length)
  257. const decoded = jwt.verify(token, jwtSecret)
  258. if (decoded){
  259. console.log('token verified', decoded)
  260. let slicedModels = getModels(decoded.sub.id)
  261. return {
  262. schema: schema,
  263. rootValue: rootResolvers,
  264. graphiql: true,
  265. context: {jwt: decoded.sub,
  266. models: slicedModels}
  267. }
  268. }
  269. }
  270. }))
  271. app.listen(4000, () => console.log('Express GraphQL Server Now Running On localhost:4000/graphql'));
  272. })()