external-account.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. const debug = require('debug')('crowi:models:external-account');
  2. const mongoose = require('mongoose');
  3. const uniqueValidator = require('mongoose-unique-validator');
  4. const ObjectId = mongoose.Schema.Types.ObjectId;
  5. /*
  6. * define schema
  7. */
  8. const schema = new mongoose.Schema({
  9. providerType: { type: String, required: true },
  10. accountId: { type: String, required: true },
  11. user: { type: ObjectId, ref: 'User', required: true },
  12. createdAt: { type: Date, default: Date.now, required: true },
  13. });
  14. // compound index
  15. schema.index({ providerType: 1, accountId: 1 });
  16. // apply plugins
  17. schema.plugin(uniqueValidator);
  18. /**
  19. * ExternalAccount Class
  20. *
  21. * @class ExternalAccount
  22. */
  23. class ExternalAccount {
  24. static set crowi(crowi) {
  25. this._crowi = crowi;
  26. }
  27. static get crowi() {
  28. return this._crowi;
  29. }
  30. /**
  31. * get the populated user entity
  32. *
  33. * @returns Promise<User>
  34. * @memberof ExternalAccount
  35. */
  36. getPopulatedUser() {
  37. return this.populate('user').execPopulate()
  38. .then((account) => {
  39. return account.user;
  40. })
  41. }
  42. /**
  43. * find an account or register if not found
  44. *
  45. * @static
  46. * @param {string} providerType
  47. * @param {string} accountId
  48. * @param {object} usernameToBeRegistered the username of User entity that will be created when accountId is not found
  49. * @returns {Promise<ExternalAccount>}
  50. * @memberof ExternalAccount
  51. */
  52. static findOrRegister(providerType, accountId, usernameToBeRegistered) {
  53. return this.findOne({ providerType, accountId })
  54. .then((account) => {
  55. // found
  56. if (account != null) {
  57. debug(`ExternalAccount '${accountId}' is found `, account);
  58. return account;
  59. }
  60. // not found
  61. else {
  62. debug(`ExternalAccount '${accountId}' is not found, it is going to be registered.`);
  63. const User = ExternalAccount.crowi.model('User');
  64. return User.count({username: usernameToBeRegistered})
  65. .then((count) => {
  66. // throw Exception when count is not zero
  67. if (count > 0) {
  68. throw new DuplicatedUsernameException(`username '${usernameToBeRegistered}' has already been existed`);
  69. }
  70. return User.createUser('', usernameToBeRegistered, undefined, undefined, undefined);
  71. })
  72. .then((user) => {
  73. return this.create({ providerType: 'ldap', accountId, user: user._id });
  74. });
  75. }
  76. });
  77. }
  78. }
  79. /**
  80. * The Exception class thrown when User.username is duplicated when creating user
  81. *
  82. * @class DuplicatedUsernameException
  83. */
  84. class DuplicatedUsernameException {
  85. constructor(message) {
  86. this.name = this.constructor.name;
  87. this.message = message;
  88. }
  89. }
  90. module.exports = function(crowi) {
  91. ExternalAccount.crowi = crowi;
  92. schema.loadClass(ExternalAccount);
  93. return mongoose.model('ExternalAccount', schema);
  94. }