user-registration-order.ts 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import {
  2. Schema, Model, Document,
  3. } from 'mongoose';
  4. import { addHours } from 'date-fns';
  5. import uniqueValidator from 'mongoose-unique-validator';
  6. import crypto from 'crypto';
  7. import { getOrCreateModel } from '@growi/core';
  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(): Promise<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: {
  33. createdAt: true,
  34. updatedAt: false,
  35. },
  36. });
  37. schema.plugin(uniqueValidator);
  38. schema.statics.generateOneTimeToken = function() {
  39. const buf = crypto.randomBytes(256);
  40. const token = buf.toString('hex');
  41. return token;
  42. };
  43. schema.statics.createUserRegistrationOrder = async function(email) {
  44. let token;
  45. let duplicateToken;
  46. do {
  47. token = this.generateOneTimeToken();
  48. // eslint-disable-next-line no-await-in-loop
  49. duplicateToken = await this.findOne({ token });
  50. } while (duplicateToken != null);
  51. const userRegistrationOrderData = await this.create({ token, email });
  52. return userRegistrationOrderData;
  53. };
  54. schema.methods.isExpired = function() {
  55. return this.expiredAt.getTime() < Date.now();
  56. };
  57. schema.methods.revokeOneTimeToken = async function() {
  58. this.isRevoked = true;
  59. return this.save();
  60. };
  61. export default getOrCreateModel<UserRegistrationOrderDocument, UserRegistrationOrderModel>('UserRegistrationOrder', schema);