models.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. const ObjectID = require("mongodb").ObjectID;
  2. const {connect} = require('mm')
  3. module.exports = async (dbName='graphql-chat') => {
  4. const {Savable, slice} = await connect(dbName)
  5. async function getModels({id, acl}){
  6. const SlicedSavable = slice(id === 'anon' ? [id] : [...acl])
  7. class User extends SlicedSavable {
  8. constructor(...params){
  9. super(...params)
  10. this.originalACL = this.acl && [...this.acl]
  11. }
  12. async save(...params){
  13. console.log(this)
  14. let otherUserWithThisLogin = this.login && await Savable.m.User.findOne({login: this.login})
  15. if (this._id){
  16. if (otherUserWithThisLogin && otherUserWithThisLogin._id.toString() !== this._id.toString()){
  17. throw new ReferenceError(`User ${this.login} already exists`)
  18. }
  19. if (!acl.includes('admin') && this.originalACL.toString() !== this.acl.toString())
  20. throw new ReferenceError(`Not enough permissions for changing acl on ${this.login}`)
  21. else return await super.save(...params)
  22. }
  23. else {
  24. if (otherUserWithThisLogin){
  25. throw new ReferenceError(`User ${this.login} already exists`)
  26. }
  27. await super.save(...params)
  28. this.___owner = this._id.toString()
  29. this.acl = [this.___owner, "user"]
  30. return await Savable.prototype.save.call(this, ...params)
  31. }
  32. }
  33. static get relations(){ //don't needed due to ___owner in most cases
  34. return {
  35. avatar : "userAvatar",
  36. chats: ["members"]
  37. }
  38. }
  39. static get defaultPermissions(){
  40. return {
  41. create: ['anon'],
  42. read: ['owner', 'user', 'admin'],
  43. write: ['owner', 'admin'],
  44. delete: []
  45. }
  46. }
  47. }
  48. SlicedSavable.addClass(User)
  49. class OwnerSlicedSavable extends SlicedSavable {
  50. get owner(){
  51. if (!this.___owner) return this.___owner
  52. return SlicedSavable.m.User.findOne({_id: ObjectID(this.___owner)})
  53. }
  54. }
  55. class Media extends OwnerSlicedSavable {
  56. constructor(...params){
  57. super(...params)
  58. }
  59. static async fromFileData(fileData){
  60. let media = new Media({})
  61. media.fileData = fileData
  62. media.url = `images/${fileData.filename}`
  63. media.originalFileName = fileData.originalname
  64. media.type = fileData.mimetype
  65. await media.save()
  66. return media;
  67. }
  68. //async save(...params){
  69. //if (this.userAvatar){
  70. //if (this.userAvatar._id.toString() !== id){
  71. //throw new ReferenceError(`You can't set ava for other user`)
  72. //}
  73. //}
  74. //return await super.save(...params)
  75. //}
  76. static get relations(){
  77. return {
  78. userAvatar: "avatar", //if it is ava
  79. chatAvatars: "avatar",
  80. messages: ["media"]
  81. }
  82. }
  83. static get defaultPermissions(){
  84. return {
  85. create: ['user', 'admin'],
  86. read: ['anon', 'user', 'admin'],
  87. write: ["owner", 'admin'],
  88. delete: ['admin']
  89. }
  90. }
  91. }
  92. SlicedSavable.addClass(Media)
  93. class Message extends OwnerSlicedSavable {
  94. static get relations(){
  95. return {
  96. media: ['messages'],
  97. replyTo: ['replies'],
  98. replies: 'replyTo',
  99. forwardWith: 'forwarded',
  100. forwarded: ['forwardWith'],
  101. chat: ['messages']
  102. }
  103. }
  104. static get defaultPermissions(){
  105. return {
  106. create: ['user'],
  107. read: ['owner', 'user', 'admin'],
  108. write: ['owner','admin'],
  109. delete: ['admin']
  110. }
  111. }
  112. static get guestRelations(){
  113. return ['replies']
  114. return ['forwardWith']
  115. }
  116. }
  117. SlicedSavable.addClass(Message)
  118. class Chat extends OwnerSlicedSavable {
  119. constructor(...params){
  120. super(...params)
  121. }
  122. static get relations(){
  123. return {
  124. members: ['chats'],
  125. messages: 'chat',
  126. avatar: ["chatAvatars"]
  127. }
  128. }
  129. static get defaultPermissions(){
  130. return {
  131. create: ['user'],
  132. read: ['owner', 'admin'],
  133. write: ['owner'],
  134. delete: []
  135. }
  136. }
  137. }
  138. SlicedSavable.addClass(TimeTrack)
  139. const thisUser = id !== 'anon' && await Savable.m.User.findOne({_id: ObjectID(id)})
  140. return {models: {
  141. SlicedSavable, ...SlicedSavable.classes
  142. },
  143. thisUser}
  144. }
  145. return {
  146. Savable,
  147. slice,
  148. getModels
  149. }
  150. }