account.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. if (!convertSchema.changes) convertSchema.changes = {};
  77. let oldSchema;
  78. try { oldSchema = await this.accountSchemaModule.getByVersion(convertSchema.versionFrom); } catch { return reject("Couldn't get from schema."); }
  79. let newSchema;
  80. try { newSchema = await this.accountSchemaModule.getByVersion(convertSchema.versionTo) } catch { return reject("Couldn't get new schema"); }
  81. let defaultNewObjects = {};
  82. let newAccount = {
  83. fields: {},
  84. version: convertSchema.versionTo
  85. };
  86. newSchema.fields.forEach(newField => {
  87. const oldField = oldSchema.fields.find(oldField => oldField.fieldId === newField.fieldId);
  88. let defaultNewObject = {};
  89. newField.fieldTypes.forEach(newFieldType => {
  90. if (newFieldType.type === "text" || newFieldType.type === "select") defaultNewObject[newFieldType.fieldTypeId] = "";
  91. else if (newFieldType.type === "checkbox") defaultNewObject[newFieldType.fieldTypeId] = false;
  92. });
  93. defaultNewObjects[newField.fieldId] = defaultNewObject;
  94. newAccount.fields[newField.fieldId] = [];
  95. if (oldField) {
  96. let entries = [];
  97. oldAccount.fields[oldField.fieldId].forEach(oldAccountFieldEntry => {
  98. entries.push({});
  99. });
  100. newField.fieldTypes.forEach(newFieldType => {
  101. const oldFieldType = oldField.fieldTypes.find(oldFieldType => oldFieldType.fieldTypeId === newFieldType.fieldTypeId);
  102. if (oldFieldType) {
  103. oldAccount.fields[oldField.fieldId].forEach((oldAccountFieldEntry, index) => {
  104. entries[index][newFieldType.fieldTypeId] = oldAccountFieldEntry[newFieldType.fieldTypeId];
  105. });
  106. } else {
  107. entries = entries.map(entry => {
  108. entry[newFieldType.fieldTypeId] = defaultNewObject[newFieldType.fieldTypeId];
  109. return entry;
  110. });
  111. }
  112. });
  113. newAccount.fields[newField.fieldId] = entries;
  114. }
  115. });
  116. Object.keys(convertSchema.changes).forEach(changeOld => {
  117. const oldFieldId = changeOld.split("+")[0];
  118. const oldFieldTypeId = changeOld.split("+")[1];
  119. const changeNew = convertSchema.changes[changeOld];
  120. const newFieldId = changeNew.split("+")[0];
  121. const newFieldTypeId = changeNew.split("+")[1];
  122. const oldField = oldAccount.fields[oldFieldId];
  123. const newField = newAccount.fields[newFieldId];
  124. const entriesToAdd = oldField.length - newField.length;
  125. for(let i = 0; i < entriesToAdd; i++) {
  126. newAccount.fields[newFieldId].push(JSON.parse(JSON.stringify(defaultNewObjects[newFieldId])));
  127. }
  128. for(let i = 0; i < newField.length; i++) {
  129. newAccount.fields[newFieldId][i][newFieldTypeId] = oldAccount.fields[oldFieldId][i][oldFieldTypeId];
  130. }
  131. });
  132. newSchema.fields.forEach(newField => {
  133. const entriesToAdd = newField.minEntries - newAccount.fields[newField.fieldId];
  134. for(let i = 0; i < entriesToAdd; i++) {
  135. newAccount.fields[newField.fieldId].push(JSON.parse(JSON.stringify(defaultNewObjects[newField.fieldId])));
  136. }
  137. });
  138. resolve(newAccount);
  139. });
  140. }
  141. async migrateAccounts(accountIds) {
  142. return new Promise(async (resolve, reject) => {
  143. try { await this._validateHook(); } catch { return; }
  144. let successful = 0;
  145. let failed = 0;
  146. async.eachLimit(
  147. accountIds,
  148. 10,
  149. (accountId, next) => {
  150. this.getMigratedAccount(accountId).then(account => {
  151. if (!account) {
  152. failed++;
  153. return next();
  154. }
  155. this.editById(accountId, account).then(() => {
  156. successful++;
  157. return next();
  158. }).catch(err => {
  159. failed++;
  160. return next();
  161. });
  162. }).catch(err => {
  163. failed++;
  164. return next();
  165. });
  166. },
  167. (err) => {
  168. resolve({
  169. successful,
  170. failed
  171. });
  172. }
  173. );
  174. });
  175. }
  176. }