user-registration-order.ts 2.0 KB

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