@positivegrid/pg-mongoose-schema 27.8.4 → 28.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/dist/index.d.ts +5 -0
  2. package/dist/index.js +34 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/models/banks.d.ts +3 -0
  5. package/dist/models/banks.js +33 -0
  6. package/dist/models/banks.js.map +1 -0
  7. package/dist/models/device.d.ts +3 -0
  8. package/dist/models/device.js +48 -0
  9. package/dist/models/device.js.map +1 -0
  10. package/dist/models/featuredList.d.ts +3 -0
  11. package/dist/models/featuredList.js +70 -0
  12. package/dist/models/featuredList.js.map +1 -0
  13. package/dist/models/hardware.d.ts +3 -0
  14. package/dist/models/hardware.js +213 -0
  15. package/dist/models/hardware.js.map +1 -0
  16. package/dist/models/homeConfig.d.ts +3 -0
  17. package/dist/models/homeConfig.js +38 -0
  18. package/dist/models/homeConfig.js.map +1 -0
  19. package/dist/models/oauth.d.ts +3 -0
  20. package/dist/models/oauth.js +48 -0
  21. package/dist/models/oauth.js.map +1 -0
  22. package/dist/models/partner.d.ts +3 -0
  23. package/dist/models/partner.js +165 -0
  24. package/dist/models/partner.js.map +1 -0
  25. package/dist/models/payment.d.ts +3 -0
  26. package/dist/models/payment.js +859 -0
  27. package/dist/models/payment.js.map +1 -0
  28. package/dist/models/pgConfig.d.ts +3 -0
  29. package/dist/models/pgConfig.js +64 -0
  30. package/dist/models/pgConfig.js.map +1 -0
  31. package/dist/models/preset.d.ts +3 -0
  32. package/dist/models/preset.js +802 -0
  33. package/dist/models/preset.js.map +1 -0
  34. package/dist/models/promotion.d.ts +3 -0
  35. package/dist/models/promotion.js +585 -0
  36. package/dist/models/promotion.js.map +1 -0
  37. package/dist/models/redeem.d.ts +3 -0
  38. package/dist/models/redeem.js +26 -0
  39. package/dist/models/redeem.js.map +1 -0
  40. package/dist/models/toneTheme.d.ts +3 -0
  41. package/dist/models/toneTheme.js +29 -0
  42. package/dist/models/toneTheme.js.map +1 -0
  43. package/dist/models/toneThemeFeaturedList.d.ts +3 -0
  44. package/dist/models/toneThemeFeaturedList.js +18 -0
  45. package/dist/models/toneThemeFeaturedList.js.map +1 -0
  46. package/dist/models/user.d.ts +3 -0
  47. package/dist/models/user.js +565 -0
  48. package/dist/models/user.js.map +1 -0
  49. package/dist/models/userTrack.d.ts +3 -0
  50. package/dist/models/userTrack.js +82 -0
  51. package/dist/models/userTrack.js.map +1 -0
  52. package/dist/types/banks.types.d.ts +25 -0
  53. package/dist/types/banks.types.js +3 -0
  54. package/dist/types/banks.types.js.map +1 -0
  55. package/dist/types/device.types.d.ts +41 -0
  56. package/dist/types/device.types.js +3 -0
  57. package/dist/types/device.types.js.map +1 -0
  58. package/dist/types/featuredList.types.d.ts +32 -0
  59. package/dist/types/featuredList.types.js +3 -0
  60. package/dist/types/featuredList.types.js.map +1 -0
  61. package/dist/types/hardware.types.d.ts +123 -0
  62. package/dist/types/hardware.types.js +3 -0
  63. package/dist/types/hardware.types.js.map +1 -0
  64. package/dist/types/homeConfig.types.d.ts +24 -0
  65. package/dist/types/homeConfig.types.js +3 -0
  66. package/dist/types/homeConfig.types.js.map +1 -0
  67. package/dist/types/index.d.ts +17 -0
  68. package/dist/types/index.js +34 -0
  69. package/dist/types/index.js.map +1 -0
  70. package/dist/types/oauth.types.d.ts +38 -0
  71. package/dist/types/oauth.types.js +3 -0
  72. package/dist/types/oauth.types.js.map +1 -0
  73. package/dist/types/partner.types.d.ts +91 -0
  74. package/dist/types/partner.types.js +3 -0
  75. package/dist/types/partner.types.js.map +1 -0
  76. package/dist/types/payment.types.d.ts +304 -0
  77. package/dist/types/payment.types.js +3 -0
  78. package/dist/types/payment.types.js.map +1 -0
  79. package/dist/types/pgConfig.types.d.ts +35 -0
  80. package/dist/types/pgConfig.types.js +3 -0
  81. package/dist/types/pgConfig.types.js.map +1 -0
  82. package/dist/types/preset.types.d.ts +110 -0
  83. package/dist/types/preset.types.js +3 -0
  84. package/dist/types/preset.types.js.map +1 -0
  85. package/dist/types/promotion.types.d.ts +282 -0
  86. package/dist/types/promotion.types.js +3 -0
  87. package/dist/types/promotion.types.js.map +1 -0
  88. package/dist/types/redeem.types.d.ts +16 -0
  89. package/dist/types/redeem.types.js +3 -0
  90. package/dist/types/redeem.types.js.map +1 -0
  91. package/dist/types/toneTheme.types.d.ts +16 -0
  92. package/dist/types/toneTheme.types.js +3 -0
  93. package/dist/types/toneTheme.types.js.map +1 -0
  94. package/dist/types/toneThemeFeaturedList.types.d.ts +9 -0
  95. package/dist/types/toneThemeFeaturedList.types.js +3 -0
  96. package/dist/types/toneThemeFeaturedList.types.js.map +1 -0
  97. package/dist/types/user.types.d.ts +166 -0
  98. package/dist/types/user.types.js +6 -0
  99. package/dist/types/user.types.js.map +1 -0
  100. package/dist/types/userTrack.types.d.ts +39 -0
  101. package/dist/types/userTrack.types.js +12 -0
  102. package/dist/types/userTrack.types.js.map +1 -0
  103. package/package.json +38 -12
  104. package/index.js +0 -28
  105. package/models/banks.js +0 -42
  106. package/models/device.js +0 -51
  107. package/models/featuredList.js +0 -91
  108. package/models/hardware.js +0 -256
  109. package/models/homeConfig.js +0 -86
  110. package/models/oauth.js +0 -52
  111. package/models/partner.js +0 -265
  112. package/models/payment.js +0 -899
  113. package/models/pgConfig.js +0 -88
  114. package/models/preset.js +0 -845
  115. package/models/promotion.js +0 -590
  116. package/models/redeem.js +0 -26
  117. package/models/toneTheme.js +0 -78
  118. package/models/toneThemeFeaturedList.js +0 -49
  119. package/models/user.js +0 -639
  120. package/models/userTrack.js +0 -107
@@ -1,49 +0,0 @@
1
- 'use strict'
2
-
3
- module.exports = function (mongoose) {
4
- const Schema = mongoose.Schema
5
- const ObjectId = Schema.Types.ObjectId
6
-
7
- const ToneThemeFeaturedListSchema = new Schema({
8
- tone_theme_id: {
9
- type: ObjectId,
10
- ref: 'ToneTheme',
11
- required: true
12
- },
13
- featured_list_id: {
14
- type: ObjectId,
15
- ref: 'FeaturedList',
16
- required: true
17
- },
18
- order: {
19
- type: Number,
20
- default: 0
21
- },
22
- created_on: {
23
- type: Date,
24
- default: Date.now
25
- }
26
- }, {
27
- collection: 'tone_theme_featured_list'
28
- })
29
-
30
- // 索引
31
- ToneThemeFeaturedListSchema.index({
32
- tone_theme_id: 1,
33
- order: 1
34
- })
35
-
36
- ToneThemeFeaturedListSchema.index({
37
- featured_list_id: 1
38
- })
39
-
40
- // 確保同一個 featured_list 不會被加入同一個 theme 兩次
41
- ToneThemeFeaturedListSchema.index({
42
- tone_theme_id: 1,
43
- featured_list_id: 1
44
- }, {
45
- unique: true
46
- })
47
-
48
- mongoose.model('ToneThemeFeaturedList', ToneThemeFeaturedListSchema)
49
- }
package/models/user.js DELETED
@@ -1,639 +0,0 @@
1
- 'use strict'
2
-
3
- const crypto = require('crypto')
4
- const randomString = require('random-string')
5
- const _ = require('lodash')
6
- const ApiErrorCode = require('@positivegrid/pg-error').ApiErrorCode
7
- const isEmail = require('is-email')
8
- const debug = require('debug')('model:user')
9
-
10
- module.exports = function (mongoose) {
11
- const Schema = mongoose.Schema
12
- const ObjectId = Schema.Types.ObjectId
13
-
14
- function encryptPassword (pwd) {
15
- if (!pwd) return ''
16
-
17
- const encryptType = 'sha1'
18
- const salt = randomString({ length: 5, numeric: true, letters: true }).toLowerCase()
19
- const password = crypto.createHash(encryptType).update(String(salt) + String(pwd)).digest('hex')
20
-
21
- return `${encryptType}$${salt}$${password}`
22
- }
23
-
24
- function verifyPassword (pwd, pwdArr) {
25
- if (!pwd) return false
26
-
27
- return (crypto.createHash(pwdArr[0]).update(String(pwdArr[1]) + String(pwd)).digest('hex') === pwdArr[2])
28
- }
29
-
30
- const FLAG_EMAIL_EVENTS = [
31
- 'bounce',
32
- 'complaint',
33
- 'reject'
34
- ]
35
- const UserEmailStatusSchema = new Schema({
36
- user_id: { type: ObjectId, ref: 'User', required: true },
37
- email_status: { type: String, enum: FLAG_EMAIL_EVENTS, required: true },
38
- creted_on: { type: Date, default: Date.now, required: true }
39
- }, { collection: 'user_email_status' })
40
-
41
- let UserProfileSchema = new Schema({
42
- user_id: { type: ObjectId, ref: 'User', required: true },
43
- full_name: { type: String, default: null },
44
- first_name: { type: String, default: null },
45
- last_name: { type: String, default: null },
46
- title: { type: String, default: null },
47
- gender: { type: String, default: null },
48
- country: { type: String, default: null },
49
- postal: { type: String, default: null },
50
- city: { type: String, default: null },
51
- state: { type: String, default: null },
52
- address: { type: String, default: null },
53
- phone: { type: String, default: null },
54
- description: { type: String },
55
- bc_token: { type: String, default: null },
56
- facebook_access_token: { type: String, default: null },
57
- reset_password_token: { type: String, default: null },
58
- profile_image_url: { type: String, default: null },
59
- profile_thumb_url: { type: String, default: null },
60
- facebook_image_url: { type: String, default: null },
61
- facebook_thumb_url: { type: String, default: null },
62
- reset_password_expire: { type: Date, default: null },
63
- is_email_verified: { type: Boolean, default: false },
64
- is_registered: { type: Boolean, default: true },
65
- stripe_customer_id: { type: String, default: null },
66
- selected_country: { type: String, default: null },
67
- date_joined: { type: Date, default: Date.now },
68
- search_mark: { type: Number, default: 0 } // control the order of search
69
- }, { collection: 'jamup_userprofile', toJSON: { virtuals: true }, toObject: { virtuals: true } })
70
- UserProfileSchema
71
- .index({ user_id: 1 }, { unique: true })
72
- .index({ reset_password_token: 1 })
73
- UserProfileSchema.index({full_name: 'text', first_name: 'text', last_name: 'text'})
74
-
75
- const UserAddressSchema = new Schema({
76
- user_id: { type: ObjectId, ref: 'User', required: true },
77
- country: { type: String, default: null },
78
- zip: { type: String, default: null },
79
- city: { type: String, default: null },
80
- state: { type: String, default: null },
81
- address: { type: String, default: null },
82
- phone: { type: String, default: null },
83
- default: { type: Boolean, default: false }
84
- })
85
-
86
- const emailFormat = [/^\S+@\S+\.\S+$/, 'Invalid Email Address']
87
- let UserSchema = new Schema({
88
- username: { type: String, trim: true, required: true },
89
- email: { type: String, trim: true, unique: true, match: emailFormat, required: true },
90
- password: { type: String, default: null, set: encryptPassword, required: true },
91
- user_status: { type: Number, default: 1 }, // 1: active 2: delete 3: migration
92
- user_role: { type: Number, default: 1 }, // 1: users, 2: member, 3: admin, 4: partner/dealer
93
- is_active: { type: Boolean, default: false },
94
- activate_token: { type: String, default: null },
95
- activate_expire: { type: Date, default: null },
96
- fb_access_token: { type: String, default: null },
97
- facebook_id: { type: String, default: null },
98
- shopify_id: { type: Schema.Types.Mixed, default: null },
99
- bk_username: [{ type: String }],
100
- auth: {
101
- firebase_id: { type: String },
102
- google_id: { type: String },
103
- apple_id: { type: String },
104
- wechat_id: { type: String }
105
- },
106
- metadata: {
107
- gdpr: { type: Boolean, default: false },
108
- country: { type: String, default: null },
109
- },
110
- date_joined: { type: Date, default: Date.now },
111
- last_login: { type: Date, default: Date.now }
112
- }, { collection: 'auth_user', toJSON: { virtuals: true }, toObject: { virtuals: true } })
113
- UserSchema
114
- .index({ shopify_id: 1 })
115
- .index({ username: 1 })
116
- .index({ email: 1 }, { unique: true })
117
- .index({ 'auth.firebase_id': 1 })
118
- .index({ 'auth.apple_id': 1 })
119
- .index({ 'auth.facebook_id': 1 })
120
-
121
- // Remove in the future?
122
- const UserProductSchema = new Schema({
123
- user_id: { type: ObjectId, ref: 'User', required: true },
124
- product: { type: String, required: true },
125
- platform: { type: 'String', required: true },
126
- metadata: { type: Schema.Types.Mixed, default: null },
127
- last_login: { type: Date, default: Date.now }
128
- }, { collection: 'user_product_meta' })
129
-
130
- /**
131
- * Save user product status which will co-work with Listrak segmentation
132
- * Hope to replace UserProductSchema after it works stable.
133
- */
134
- const UserProductTrackerSchema = new Schema({
135
- user_id: { type: ObjectId, ref: 'User', required: true },
136
- product: { type: String, required: true },
137
- status: { type: Number, default: 1 },
138
- created_on: { type: Date, default: Date.now }
139
- }, { collection: 'user_product_tracker' })
140
- UserProductTrackerSchema.index({ user_id: 1, product: 1 }, { unique: true })
141
-
142
- let ApikeySchema = new Schema({
143
- apikey: { type: String, required: true, unique: true },
144
- permission: { type: Array, required: true }, // follow model - user, payment
145
- description: { type: String, required: true },
146
- status: { type: Boolean, required: true },
147
- created_on: { type: Date, default: Date.now },
148
- call_number: { type: Number },
149
- partner_name: { type: String }, // Would be used when permission has 'partner'
150
- updated_on: { type: Date, default: Date.now }
151
- }, { collection: 'auth_apikey' })
152
-
153
- let UserReferralSchema = new Schema({
154
- user_id: { type: ObjectId, ref: 'User', required: true },
155
- referred_user_email: { type: 'String' },
156
- created_on: { type: Date, default: Date.now },
157
- updated_on: { type: Date, default: Date.now }
158
- }, { collection: 'user_referral' })
159
-
160
- const UserTokenSchema = new Schema({
161
- tid: { type: String, trim: true, required: true },
162
- expired_at: { type: Date, required: true },
163
- created_on: { type: Date, default: Date.now }
164
- }, {
165
- collection: 'auth_token',
166
- toJSON: { virtuals: true },
167
- toObject: { virtuals: true }
168
- })
169
- UserTokenSchema.index({
170
- tid: 1
171
- }, {
172
- unique: true
173
- })
174
- UserTokenSchema.index({
175
- expired_at: 1
176
- }, {
177
- expireAfterSeconds: 0
178
- })
179
-
180
- const UserFollowSchema = new Schema(
181
- {
182
- user_id: { type: Schema.Types.ObjectId, ref: 'User', required: true, index: true },
183
- follow_user_id: { type: Schema.Types.ObjectId, ref: 'User', required: true, index: true },
184
- follow_platform: { type: String } // spark or bias ...
185
- },
186
- {
187
- timestamps: { createdAt: true, updatedAt: false },
188
- versionKey: false,
189
- collection: 'jamup_userFollow',
190
- toJSON: { virtuals: true },
191
- toObject: { virtuals: true }
192
- }
193
- )
194
- UserFollowSchema.index(
195
- {
196
- user_id: 1,
197
- follow_platform: 1,
198
- follow_user_id: 1
199
- },
200
- { unique: true }
201
- )
202
- UserFollowSchema.index({
203
- follow_platform: 1
204
- }, {
205
- user_id: 1
206
- }, {
207
- createdAt: 1
208
- })
209
- UserFollowSchema.index({
210
- follow_platform: 1
211
- }, {
212
- follow_user_id: 1
213
- }, {
214
- createdAt: 1
215
- })
216
-
217
- /**
218
- * Methods
219
- */
220
- UserSchema.method({
221
- authenticate: function (plainText) {
222
- var passwordArr = this.password.split('$')
223
- if (passwordArr.length !== 3) {
224
- return false
225
- } else {
226
- return verifyPassword(plainText, passwordArr)
227
- }
228
- },
229
- makeSalt: function () {
230
- return Math.round((new Date().valueOf() * Math.random())) + ''
231
- }
232
- })
233
-
234
- // Statics
235
- UserTokenSchema.static({
236
- createTokenMeta: async function () {
237
- try {
238
- const tid = crypto.randomUUID()
239
- const nowDate = new Date()
240
- const expiredAt = new Date().setDate(nowDate.getDate() + 14)
241
- return await this.create({
242
- tid,
243
- expired_at: expiredAt,
244
- created_on: nowDate
245
- })
246
- } catch (err) {
247
- debug('ERR:createTokenMeta:%j', err)
248
- throw err
249
- }
250
- },
251
- isValid: async function (tid) {
252
- const userTokenMeta = await this.findOne({ tid }).exec()
253
- return (userTokenMeta) ? true : false
254
- },
255
- revokeToken: async function (tid) {
256
- return await this.findOneAndRemove({
257
- tid
258
- })
259
- }
260
- })
261
- UserSchema.static({
262
- _async_auth: async function (username, password) {
263
- username = String(username).toLowerCase().replace('@', '_')
264
- let user
265
- let bgUser
266
- try {
267
- user = await this.findOne({username}).exec()
268
- } catch (err) {
269
- throw new ApiErrorCode('internal_sysmtem_error', err.message)
270
- }
271
- if (!user) {
272
- // Fallback
273
- try {
274
- bgUser = await this.findOne({ bk_username: { $in: [username] } }).exec()
275
- } catch (err) {
276
- throw new ApiErrorCode('INTERNAL_SYSMTEM_ERROR', err.message)
277
- }
278
- if (!bgUser) {
279
- throw new ApiErrorCode('USER_NOT_EXIST', `Cannot find user ${username}`)
280
- } else if (!bgUser.authenticate(password)) {
281
- throw new ApiErrorCode('USER_UNAUTHORIZED', 'unauthorized')
282
- }
283
- return bgUser
284
- }
285
- if (user.user_status === 2) {
286
- // Account deleted
287
- throw new ApiErrorCode('ACCOUNT_WERE_DELETED', `Account ${user.email} already deleted`)
288
- }
289
- if (!user.authenticate(password)) {
290
- if (user.facebook_id !== null) {
291
- throw new ApiErrorCode('USER_OAUTH_LOGIN', 'Please use FB to login your account')
292
- } else {
293
- throw new ApiErrorCode('USER_UNAUTHORIZED', 'unauthorized')
294
- }
295
- }
296
- return user
297
- },
298
- auth: function (uname, password, cb) {
299
- if (!cb) {
300
- return this._async_auth(uname, password)
301
- }
302
- let username = String(uname).toLowerCase().replace('@', '_')
303
- let that = this
304
-
305
- that.findOne({ username: username }, function (err, user) {
306
- if (err) {
307
- return cb(new ApiErrorCode('internal_sysmtem_error', err.message))
308
- } else if (!user) {
309
- that.findOne({ bk_username: { $in: [uname] } }, function (err, bgUser) {
310
- if (err) {
311
- return cb(new ApiErrorCode('INTERNAL_SYSMTEM_ERROR', err.message))
312
- } else if (!bgUser) {
313
- return cb(new ApiErrorCode('USER_NOT_EXIST', `Cannot find user ${uname}`))
314
- }
315
-
316
- return (!user.authenticate(password))
317
- ? cb(new ApiErrorCode('USER_UNAUTHORIZED', 'unauthorized'))
318
- : cb(null, bgUser)
319
- })
320
- } else {
321
- if (user.user_status === 2) {
322
- return cb(new ApiErrorCode('ACCOUNT_WERE_DELETED', `Account ${user.email} already deleted`))
323
- } else if (!user.authenticate(password)) {
324
- if (user.facebook_id !== null) {
325
- return cb(new ApiErrorCode('USER_OAUTH_LOGIN', 'Please use FB to login your account'))
326
- } else {
327
- return cb(new ApiErrorCode('USER_UNAUTHORIZED', 'unauthorized'))
328
- }
329
- }
330
- return cb(null, user)
331
- }
332
- })
333
- },
334
- login: function (query, cb) {
335
- if (!_.isObject(query)) {
336
- return cb(Error('Invalid login parameter'))
337
- } else {
338
- this.findOne(query, cb)
339
- }
340
- },
341
- loginForPassport: function (query, cb) {
342
- let self = this
343
-
344
- if (!_.isObject(query)) {
345
- return cb(Error('Invalid login parameter'))
346
- }
347
-
348
- if (_.has(query, 'username')) {
349
- query['username'] = String(_.trim(query['username'])).toLowerCase()
350
- }
351
- if (_.has(query, 'email')) {
352
- query['email'] = String(_.trim(query['email'])).toLowerCase()
353
- }
354
-
355
- debug('loginForPassport:%o', query)
356
- self.findOne(query, function (err, user) {
357
- if (err) {
358
- return cb({ status: 500, errorMessage: err })
359
- } else if (!user) {
360
- return cb({ status: 404, errorMessage: `Cannot found target user` })
361
- } else if (user['user_status'] === 2) {
362
- return cb({ status: 410, errorMessage: `This account already deleted` })
363
- } else {
364
- return cb(null, user)
365
- }
366
- })
367
- },
368
- list: function (options, cb) {
369
- var criteria = options.criteria || {}
370
- var sort = options.sort || { createdAt: -1 }
371
- var limit = options.limit === 0 ? 0 : (options.limit || 10)
372
- var page = options.page || 0
373
-
374
- this.find(criteria)
375
- .select('name username email')
376
- .sort(sort)
377
- .skip(limit * page)
378
- .limit(limit)
379
- .exec(cb)
380
- },
381
- getUser: function (username, cb) {
382
- this.findOne({ username: String(username).toLowerCase() })
383
- .sort({ date_joined: -1 })
384
- .select('email user_role user_status auth')
385
- .exec(cb)
386
- },
387
- getUserPromise: async function (username) {
388
- const userData = await this.findOne({ username: String(username).toLowerCase() })
389
- .select('email user_role user_status auth')
390
- .exec()
391
- return userData
392
- },
393
- getUserById: function (id, cb) {
394
- this.findById(id).exec(cb)
395
- },
396
- getUserFullData: function (username) {
397
- const cursor = this.aggregate([
398
- { '$match': { username: String(username).toLowerCase(), user_status: 1 } },
399
- { '$lookup': { 'from': 'jamup_userprofile', 'localField': '_id', 'foreignField': 'user_id', 'as': 'userprofile' } },
400
- { '$unwind': '$userprofile' }
401
- ]).cursor({ batchSize: 100, useMongooseAggCursor: true }).exec()
402
- return cursor.eachAsync()
403
- },
404
- // Promise rewrite getUserFullData
405
- getUserDetail: async function (query, projectFields = {}) {
406
- try {
407
- if (!_.isObject(query)) {
408
- throw new Error('Query need to be object!')
409
- }
410
-
411
- const queryCondition = _.assign({}, {
412
- 'user_status': 1
413
- }, query)
414
-
415
- const defaultProjectFields = _.assign({}, {
416
- '_id': 1,
417
- 'email': 1,
418
- 'username': 1,
419
- 'date_joined': 1,
420
- 'last_login': 1,
421
- 'userprofile.first_name': 1,
422
- 'userprofile.last_name': 1,
423
- 'userprofile.full_name': 1
424
- }, projectFields)
425
- const ret = await this.aggregate([
426
- { '$match': queryCondition },
427
- {
428
- '$lookup': {
429
- 'from': 'jamup_userprofile',
430
- 'localField': '_id',
431
- 'foreignField': 'user_id',
432
- 'as': 'userprofile'
433
- }
434
- },
435
- { '$unwind': '$userprofile' },
436
- { '$project': defaultProjectFields }
437
- ]).exec()
438
-
439
- debug('INFO:getUserDetail %o:%o', queryCondition, ret)
440
- return ret
441
- } catch (err) {
442
- debug('ERR:getUserDetail %o', err)
443
- throw err
444
- }
445
- },
446
- getDealerDetail: async function (query) {
447
- try {
448
- if (!_.isObject(query)) {
449
- throw new Error('Query need to be object!')
450
- }
451
-
452
- const queryCondition = _.assign({}, {
453
- 'user_status': 1
454
- }, query)
455
-
456
- const ret = await this.aggregate([
457
- { '$match': queryCondition },
458
- {
459
- '$lookup': {
460
- 'from': 'jamup_userprofile',
461
- 'localField': '_id',
462
- 'foreignField': 'user_id',
463
- 'as': 'userprofile'
464
- }
465
- },
466
- { '$unwind': '$userprofile' },
467
- {
468
- '$lookup': {
469
- 'from': 'b2b_dealer_profile',
470
- 'localField': '_id',
471
- 'foreignField': 'dealer_id',
472
- 'as': 'dealer'
473
- }
474
- },
475
- { '$unwind': '$dealer' }
476
- ]).exec()
477
-
478
- debug('INFO:getDealerDetail %o:%o', queryCondition, ret)
479
- return ret
480
- } catch (err) {
481
- debug('ERR:getDealerDetail %o', err)
482
- throw err
483
- }
484
- },
485
- createUser: function (userObj, cb) {
486
- debug(userObj)
487
- this.create(userObj, function (err, userObj) {
488
- if (err) return cb(err)
489
-
490
- return cb(null, userObj)
491
- })
492
- },
493
- deleteUser: function (userId, cb) {
494
- this.remove({ _id: userId }).exec(cb)
495
- },
496
- findUserByEmail: function (email, cb) {
497
- this.find({ email: String(email).toLowerCase() }).exec(cb)
498
- },
499
- findByEmail: async function (email) {
500
- try {
501
- if (!isEmail(email)) {
502
- throw new Error(`Invalid email format: ${email}`)
503
- }
504
-
505
- return await this.findOne({
506
- email: String(email).toLowerCase(),
507
- user_status: 1
508
- }).exec()
509
- } catch (err) {
510
- debug('ERR:findByEmail:%o', email)
511
- throw err
512
- }
513
- }
514
- })
515
-
516
- UserProfileSchema.static({
517
- createProfile: function (profileObj, cb) {
518
- debug('createProfile:%o', profileObj)
519
- if (!profileObj['user_id']) {
520
- return cb(new Error('Missing User Id'))
521
- } else if (mongoose.Types.ObjectId.isValid(profileObj['user_id']) === false) {
522
- return cb(new Error('Invalid User Id'))
523
- }
524
-
525
- this.create(profileObj, function (err, profileObj) {
526
- if (err) return cb(err)
527
-
528
- return cb(null, profileObj)
529
- })
530
- },
531
- updateProfileByUserId: function (userId, updateData, cb) {
532
- debug(updateData)
533
- this.findOneAndUpdate(
534
- { user_id: userId },
535
- { $set: updateData },
536
- { new: true }).exec(cb)
537
- },
538
- updateProfile: async function (userId, updateProfileData) {
539
- try {
540
- return await this.findOneAndUpdate({
541
- user_id: mongoose.Types.ObjectId(userId)
542
- }, {
543
- '$set': updateProfileData
544
- }, { new: true }).exec()
545
- } catch (err) {
546
- debug('ERR:updateProfile:%o', err)
547
- throw err
548
- }
549
- },
550
- getUserProfile: function (userId, cb) {
551
- this.getUserProfilePromise(userId)
552
- .then(userData => cb(null, userData))
553
- .catch(err => cb(err))
554
- },
555
- getUserProfilePromise: async function (userId) {
556
- let selectField = [
557
- 'full_name',
558
- 'profile_image_url',
559
- 'profile_thumb_url',
560
- 'first_name',
561
- 'last_name',
562
- 'title',
563
- 'gender',
564
- 'date_joined'
565
- ].join(' ')
566
-
567
- const profileData= await this.findOne({ user_id: userId })
568
- .select(selectField)
569
- .exec()
570
- return profileData
571
- },
572
- getUserProfileDetail: function (userId, cb) {
573
- if (!cb) {
574
- return this.findOne({ user_id: userId }).exec()
575
- }
576
- this.findOne({ user_id: userId }).exec(cb)
577
- },
578
- getUserProfileByCondition: function (condition, cb) {
579
- this.findOne(condition).exec(cb)
580
- }
581
- })
582
-
583
- const jamupLitePattern = new RegExp('JamUp.+Lite\/([0-9.]+)')
584
- const biasAmpPattern = new RegExp('Bias\/([0-9.]+)')
585
- const biasAmpiPhonePattern = new RegExp('Bias.+iPhone\/([0-9.]+)')
586
- const biasFxPattern = new RegExp('BIAS.+FX\/([0-9.]+).+iPad')
587
- const biasPedalPattern = new RegExp('BIAS.+Pedal\/([0-9.]+).+iPad')
588
- UserProductSchema.static({
589
- detectUserProduct: function (userAgent) {
590
- let userMeta = {}
591
- const preUserAgent = String(userAgent)
592
-
593
- if (preUserAgent.match(jamupLitePattern)) {
594
- userMeta = {
595
- product: 'jamup-lite',
596
- platform: 'iOS'
597
- }
598
- } else if (preUserAgent.match(biasAmpPattern)) {
599
- userMeta = {
600
- product: 'biasamp',
601
- platform: 'iOS'
602
- }
603
- } else if (preUserAgent.match(biasAmpiPhonePattern)) {
604
- userMeta = {
605
- product: 'biasamp',
606
- platform: 'iOS'
607
- }
608
- } else if (preUserAgent.match(biasFxPattern)) {
609
- userMeta = {
610
- product: 'biasfx',
611
- platform: 'iOS'
612
- }
613
- } else if (preUserAgent.match(biasPedalPattern)) {
614
- userMeta = {
615
- product: 'pedal',
616
- platform: 'iOS'
617
- }
618
- }
619
-
620
- return (_.isEmpty(userMeta)) ? false : userMeta
621
- }
622
- })
623
-
624
- // Virtual
625
- UserSchema.virtual('id')
626
- .get(function () {
627
- return this._id.toHexString()
628
- })
629
-
630
- mongoose.model('User', UserSchema)
631
- mongoose.model('UserProfile', UserProfileSchema)
632
- mongoose.model('ApiKey', ApikeySchema)
633
- mongoose.model('UserProduct', UserProductSchema)
634
- mongoose.model('UserProductTracker', UserProductTrackerSchema)
635
- mongoose.model('UserReferral', UserReferralSchema)
636
- mongoose.model('UserEmailStatus', UserEmailStatusSchema)
637
- mongoose.model('UserToken', UserTokenSchema)
638
- mongoose.model('UserFollow', UserFollowSchema)
639
- }