account.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. 'use strict';
  2. const async = require("async");
  3. const coreClass = require("../core");
  4. const config = require('config');
  5. module.exports = class extends coreClass {
  6. constructor(name, moduleManager) {
  7. super(name, moduleManager);
  8. this.dependsOn = ["mongo"];
  9. }
  10. initialize() {
  11. return new Promise(async (resolve, reject) => {
  12. this.setStage(1);
  13. this.mongoModule = this.moduleManager.modules["mongo"];
  14. this.utilModule = this.moduleManager.modules["util"];
  15. this.accountSchemaModule = this.moduleManager.modules["accountSchema"];
  16. this.convertSchemaModule = this.moduleManager.modules["convertSchema"];
  17. this.accountSchema = await this.mongoModule.schema("account");
  18. this.accountModel = await this.mongoModule.model("account");
  19. resolve();
  20. })
  21. }
  22. async getAll() {
  23. return new Promise(async (resolve, reject) => {
  24. try { await this._validateHook(); } catch { return; }
  25. this.accountModel.find({}, (err, accounts) => {
  26. if (err) reject(new Error(err));
  27. else resolve(accounts);
  28. });
  29. });
  30. }
  31. async getById(accountId) {
  32. return new Promise(async (resolve, reject) => {
  33. try { await this._validateHook(); } catch { return; }
  34. this.accountModel.findById(accountId, (err, account) => {
  35. if (err) reject(new Error(err));
  36. else resolve(account);
  37. });
  38. });
  39. }
  40. async add(account) {
  41. return new Promise(async (resolve, reject) => {
  42. try { await this._validateHook(); } catch { return; }
  43. this.accountModel.create(account, (err) => {
  44. if (err) reject(new Error(err));
  45. else {
  46. this.utilModule.addAutosuggestAccount(account);
  47. resolve();
  48. }
  49. });
  50. });
  51. }
  52. async editById(accountId, account) {
  53. return new Promise(async (resolve, reject) => {
  54. try { await this._validateHook(); } catch { return; }
  55. if (!accountId || !account) return reject(new Error("Account ID or Account invalid."));
  56. this.accountModel.updateOne({ _id: accountId }, account, (err, res) => {
  57. if (err) reject(new Error(err));
  58. else {
  59. this.utilModule.addAutosuggestAccount(account);
  60. resolve();
  61. }
  62. });
  63. });
  64. }
  65. async getMigratedAccount(accountId) {
  66. return new Promise(async (resolve, reject) => {
  67. try { await this._validateHook(); } catch { return; }
  68. if (!accountId) return reject(new Error("Account ID invalid."));
  69. let oldAccount;
  70. try { oldAccount = await this.getById(accountId); } catch { return reject("Couldn't get account."); }
  71. let latestVersion;
  72. try { latestVersion = (await this.accountSchemaModule.getLatest()).version; } catch { return reject("Couldn't get latest schema."); }
  73. if (oldAccount.version === latestVersion) return reject(new Error("Account is already up-to-date"));
  74. let convertSchema;
  75. try { convertSchema = await this.convertSchemaModule.getForVersion(oldAccount.version); } catch(err) { reject(err); }
  76. let oldSchema;
  77. try { oldSchema = await this.accountSchemaModule.getByVersion(convertSchema.versionFrom); } catch { return reject("Couldn't get from schema."); }
  78. let newSchema;
  79. try { newSchema = await this.accountSchemaModule.getByVersion(convertSchema.versionTo) } catch { return reject("Couldn't get new schema"); }
  80. let defaultNewObjects = {};
  81. let newAccount = {
  82. fields: {},
  83. version: convertSchema.versionTo
  84. };
  85. newSchema.fields.forEach(newField => {
  86. const oldField = oldSchema.fields.find(oldField => oldField.fieldId === newField.fieldId);
  87. let defaultNewObject = {};
  88. newField.fieldTypes.forEach(newFieldType => {
  89. if (newFieldType.type === "text" || newFieldType.type === "select") defaultNewObject[newFieldType.fieldTypeId] = "";
  90. else if (newFieldType.type === "checkbox") defaultNewObject[newFieldType.fieldTypeId] = false;
  91. });
  92. defaultNewObjects[newField.fieldId] = defaultNewObject;
  93. newAccount.fields[newField.fieldId] = [];
  94. if (oldField) {
  95. let entries = [];
  96. oldAccount.fields[oldField.fieldId].forEach(oldAccountFieldEntry => {
  97. entries.push({});
  98. });
  99. newField.fieldTypes.forEach(newFieldType => {
  100. const oldFieldType = oldField.fieldTypes.find(oldFieldType => oldFieldType.fieldTypeId === newFieldType.fieldTypeId);
  101. if (oldFieldType) {
  102. oldAccount.fields[oldField.fieldId].forEach((oldAccountFieldEntry, index) => {
  103. entries[index][newFieldType.fieldTypeId] = oldAccountFieldEntry[newFieldType.fieldTypeId];
  104. });
  105. } else {
  106. entries = entries.map(entry => {
  107. entry[newFieldType.fieldTypeId] = defaultNewObject[newFieldType.fieldTypeId];
  108. return entry;
  109. });
  110. }
  111. });
  112. newAccount.fields[newField.fieldId] = entries;
  113. }
  114. });
  115. Object.keys(convertSchema.changes).forEach(changeOld => {
  116. const oldFieldId = changeOld.split("+")[0];
  117. const oldFieldTypeId = changeOld.split("+")[1];
  118. const changeNew = convertSchema.changes[changeOld];
  119. const newFieldId = changeNew.split("+")[0];
  120. const newFieldTypeId = changeNew.split("+")[1];
  121. const oldField = oldAccount.fields[oldFieldId];
  122. const newField = newAccount.fields[newFieldId];
  123. const entriesToAdd = oldField.length - newField.length;
  124. for(let i = 0; i < entriesToAdd; i++) {
  125. newAccount.fields[newFieldId].push(JSON.parse(JSON.stringify(defaultNewObjects[newFieldId])));
  126. }
  127. for(let i = 0; i < newField.length; i++) {
  128. newAccount.fields[newFieldId][i][newFieldTypeId] = oldAccount.fields[oldFieldId][i][oldFieldTypeId];
  129. }
  130. });
  131. newSchema.fields.forEach(newField => {
  132. const entriesToAdd = newField.minEntries - newAccount.fields[newField.fieldId];
  133. for(let i = 0; i < entriesToAdd; i++) {
  134. newAccount.fields[newField.fieldId].push(JSON.parse(JSON.stringify(defaultNewObjects[newField.fieldId])));
  135. }
  136. });
  137. resolve(newAccount);
  138. });
  139. }
  140. async migrateAccounts(accountIds) {
  141. return new Promise(async (resolve, reject) => {
  142. try { await this._validateHook(); } catch { return; }
  143. let successful = 0;
  144. let failed = 0;
  145. async.eachLimit(
  146. accountIds,
  147. 10,
  148. (accountId, next) => {
  149. this.getMigratedAccount(accountId).then(account => {
  150. if (!account) {
  151. failed++;
  152. return next();
  153. }
  154. this.editById(accountId, account).then(() => {
  155. successful++;
  156. return next();
  157. }).catch(err => {
  158. failed++;
  159. return next();
  160. });
  161. }).catch(err => {
  162. failed++;
  163. return next();
  164. });
  165. },
  166. (err) => {
  167. resolve({
  168. successful,
  169. failed
  170. });
  171. }
  172. );
  173. });
  174. }
  175. }