password-reset-order.ts 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import mongoose, {
  2. Schema, Model, Document,
  3. } from 'mongoose';
  4. import uniqueValidator from 'mongoose-unique-validator';
  5. import crypto from 'crypto';
  6. import { getOrCreateModel } from '../util/mongoose-utils';
  7. const ObjectId = mongoose.Schema.Types.ObjectId;
  8. export interface IPasswordResetOrder {
  9. token: string,
  10. email: string,
  11. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  12. relatedUser: any,
  13. isRevoked: boolean,
  14. createdAt: Date,
  15. expiredAt: Date,
  16. }
  17. export interface PasswordResetOrderDocument extends IPasswordResetOrder, Document {
  18. isExpired(): Promise<boolean>
  19. revokeOneTimeToken(): Promise<void>
  20. }
  21. export interface PasswordResetOrderModel extends Model<PasswordResetOrderDocument> {
  22. generateOneTimeToken(): string
  23. createPasswordResetOrder(email: string): PasswordResetOrderDocument
  24. }
  25. const schema = new Schema<PasswordResetOrderDocument, PasswordResetOrderModel>({
  26. token: { type: String, required: true, unique: true },
  27. email: { type: String, required: true },
  28. relatedUser: { type: ObjectId, ref: 'User' },
  29. isRevoked: { type: Boolean, default: false, required: true },
  30. createdAt: { type: Date, default: Date.now, required: true },
  31. expiredAt: { type: Date, default: Date.now() + 600000, required: true },
  32. });
  33. schema.plugin(uniqueValidator);
  34. schema.statics.generateOneTimeToken = function() {
  35. const buf = crypto.randomBytes(256);
  36. const token = buf.toString('hex');
  37. return token;
  38. };
  39. schema.statics.createPasswordResetOrder = async function(email) {
  40. let token;
  41. let duplicateToken;
  42. do {
  43. token = this.generateOneTimeToken();
  44. // eslint-disable-next-line no-await-in-loop
  45. duplicateToken = await this.findOne({ token });
  46. } while (duplicateToken != null);
  47. const passwordResetOrderData = await this.create({ token, email });
  48. return passwordResetOrderData;
  49. };
  50. schema.methods.isExpired = function() {
  51. return this.expiredAt.getTime() < Date.now();
  52. };
  53. schema.methods.revokeOneTimeToken = async function() {
  54. this.isRevoked = true;
  55. return this.save();
  56. };
  57. export default getOrCreateModel<PasswordResetOrderDocument, PasswordResetOrderModel>('PasswordResetOrder', schema);