models.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. const ObjectID = require("mongodb").ObjectID;
  2. const {connect} = require('mm')
  3. module.exports = async (dbName='shop-roles') => {
  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. }
  37. }
  38. static get defaultPermissions(){
  39. return {
  40. create: ['anon'],
  41. read: ['owner', 'user', 'admin'],
  42. write: ['owner', 'admin'],
  43. delete: []
  44. }
  45. }
  46. async getACL(){
  47. return [this._id.toString(), "user"]
  48. }
  49. }
  50. SlicedSavable.addClass(User)
  51. class OwnerSlicedSavable extends SlicedSavable {
  52. get owner(){
  53. if (!this.___owner) return this.___owner
  54. return SlicedSavable.m.User.findOne({_id: ObjectID(this.___owner)})
  55. }
  56. }
  57. class Image extends OwnerSlicedSavable {
  58. constructor(...params){
  59. super(...params)
  60. }
  61. static async fromFileData(fileData){
  62. if (!fileData) return
  63. let image = new Image({})
  64. image.fileData = fileData
  65. image.url = `images/${fileData.filename}`
  66. image.originalFileName = fileData.originalname
  67. await image.save()
  68. return image;
  69. }
  70. async save(...params){
  71. if (this.userAvatar){
  72. if (this.userAvatar._id.toString() !== id){
  73. throw new ReferenceError(`You can't set ava for other user`)
  74. }
  75. }
  76. return await super.save(...params)
  77. }
  78. static get relations(){
  79. return {
  80. userAvatar: "avatar", //if it is ava
  81. good: ["images"], //if it is ava
  82. category: "image", //if it is ava
  83. }
  84. }
  85. static get defaultPermissions(){
  86. return {
  87. create: ['user', 'admin'],
  88. read: ['anon', 'user', 'admin'],
  89. write: ['admin'],
  90. delete: ['admin']
  91. }
  92. }
  93. }
  94. SlicedSavable.addClass(Image)
  95. class Good extends OwnerSlicedSavable {
  96. constructor(...params){
  97. super(...params)
  98. }
  99. static get relations(){
  100. return {
  101. categories: ["goods"],
  102. orderGoods: "good",
  103. images: "good"
  104. }
  105. }
  106. static get defaultPermissions(){
  107. return {
  108. create: ['admin'],
  109. read: ['anon', 'user', 'admin'],
  110. write: ['admin'],
  111. delete: ['admin']
  112. }
  113. }
  114. static get guestRelations(){
  115. return ['orderGoods']
  116. }
  117. }
  118. SlicedSavable.addClass(Good)
  119. class Category extends SlicedSavable {
  120. constructor(...params){
  121. super(...params)
  122. }
  123. static get relations(){
  124. return {
  125. goods: ["categories"],
  126. image: "category",
  127. parent: ["subCategories"],
  128. subCategories: "parent"
  129. }
  130. }
  131. static get defaultPermissions(){
  132. return {
  133. create: ['admin'],
  134. read: ['anon', 'user', 'admin'],
  135. write: ['admin'],
  136. delete: ['admin']
  137. }
  138. }
  139. }
  140. SlicedSavable.addClass(Category)
  141. class Order extends OwnerSlicedSavable {
  142. constructor(...params){
  143. super(...params)
  144. }
  145. get total(){
  146. return (async () =>{
  147. let total = 0
  148. try {
  149. total = (await Promise.all(this.orderGoods)).reduce((a,b) => (a?.total || a) + (b?.total || 0), 0)
  150. }
  151. catch(e){
  152. }
  153. return total
  154. })()
  155. }
  156. static get relations(){
  157. return {
  158. orderGoods: "order"
  159. }
  160. }
  161. static get defaultPermissions(){
  162. return {
  163. //savable refs, objectid's, words like 'tags' or 'roles'
  164. read: ['owner', 'admin'],
  165. write: ['owner', 'admin'],
  166. create: ['user'],
  167. delete: [],
  168. /*permission
  169. * TODO: permissions for read and write permissions
  170. *
  171. */
  172. }
  173. }
  174. }
  175. SlicedSavable.addClass(Order)
  176. class OrderGood extends OwnerSlicedSavable {
  177. constructor(...params){
  178. super(...params)
  179. }
  180. get total(){
  181. return this.price*this.count
  182. }
  183. async save(...params){
  184. if (!this.good){
  185. throw new Error('Good Required for OrderGood')
  186. }
  187. if (!this.price && this.good && this.good.price){
  188. this.price = this.good.price
  189. this.goodName = this.good.name
  190. }
  191. return await super.save(...params)
  192. }
  193. static get relations(){
  194. return {
  195. good: ["orderGoods"],
  196. order: ["orderGoods"]
  197. }
  198. }
  199. static get defaultPermissions(){
  200. return {
  201. //savable refs, objectid's, words like 'tags' or 'roles'
  202. read: ['owner', 'admin'],
  203. write: ['owner', 'admin'],
  204. create: ['user'],
  205. delete: [],
  206. /*permission
  207. * TODO: permissions for read and write permissions
  208. *
  209. */
  210. }
  211. }
  212. }
  213. SlicedSavable.addClass(OrderGood)
  214. const thisUser = id !== 'anon' && await Savable.m.User.findOne({_id: ObjectID(id)})
  215. return {models: {
  216. SlicedSavable, ...SlicedSavable.classes
  217. },
  218. thisUser}
  219. }
  220. return {
  221. Savable,
  222. slice,
  223. getModels
  224. }
  225. }