@nmshd/app-runtime 3.0.4 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -297,6 +297,16 @@ class LokiJsConnection {
297
297
  onCollectionClosed(name) {
298
298
  this.providers.delete(name);
299
299
  }
300
+ async deleteDatabase(name) {
301
+ const database = await this.getDatabase(name);
302
+ const loki = database["db"];
303
+ await new Promise((resolve, reject) => loki.deleteDatabase((err) => {
304
+ if (err)
305
+ reject(err);
306
+ resolve();
307
+ }));
308
+ this.providers.delete(name);
309
+ }
300
310
  async getDatabase(name) {
301
311
  const givenProvider = this.providers.get(name);
302
312
  if (givenProvider) {
@@ -21655,7 +21665,8 @@ function createAppConfig(...configs) {
21655
21665
  displayName: "Notification Module",
21656
21666
  location: "@nmshd/runtime:NotificationModule"
21657
21667
  }
21658
- }
21668
+ },
21669
+ allowMultipleAccountsWithSameAddress: false
21659
21670
  };
21660
21671
  const mergedConfig = (0, lodash_1.defaultsDeep)({}, ...configs, appConfig);
21661
21672
  return mergedConfig;
@@ -21683,12 +21694,12 @@ const transport_1 = __webpack_require__(/*! @nmshd/transport */ "@nmshd/transpor
21683
21694
  const AppConfig_1 = __webpack_require__(/*! ./AppConfig */ "./dist/AppConfig.js");
21684
21695
  const AppRuntimeErrors_1 = __webpack_require__(/*! ./AppRuntimeErrors */ "./dist/AppRuntimeErrors.js");
21685
21696
  const AppStringProcessor_1 = __webpack_require__(/*! ./AppStringProcessor */ "./dist/AppStringProcessor.js");
21686
- const SessionStorage_1 = __webpack_require__(/*! ./SessionStorage */ "./dist/SessionStorage.js");
21687
- const UserfriendlyResult_1 = __webpack_require__(/*! ./UserfriendlyResult */ "./dist/UserfriendlyResult.js");
21688
21697
  const events_1 = __webpack_require__(/*! ./events */ "./dist/events/index.js");
21689
21698
  const extensibility_1 = __webpack_require__(/*! ./extensibility */ "./dist/extensibility/index.js");
21690
21699
  const modules_1 = __webpack_require__(/*! ./modules */ "./dist/modules/index.js");
21691
21700
  const multiAccount_1 = __webpack_require__(/*! ./multiAccount */ "./dist/multiAccount/index.js");
21701
+ const SessionStorage_1 = __webpack_require__(/*! ./SessionStorage */ "./dist/SessionStorage.js");
21702
+ const UserfriendlyResult_1 = __webpack_require__(/*! ./UserfriendlyResult */ "./dist/UserfriendlyResult.js");
21692
21703
  class AppRuntime extends runtime_1.Runtime {
21693
21704
  constructor(_nativeEnvironment, appConfig) {
21694
21705
  super(appConfig, _nativeEnvironment.loggerFactory);
@@ -21759,7 +21770,7 @@ class AppRuntime extends runtime_1.Runtime {
21759
21770
  dataViewExpander: session.expander
21760
21771
  };
21761
21772
  }
21762
- async selectAccount(accountReference, _password) {
21773
+ async selectAccount(accountReference) {
21763
21774
  const session = await this.getOrCreateSession(accountReference);
21764
21775
  this.sessionStorage.currentSession = session;
21765
21776
  this.eventBus.publish(new events_1.AccountSelectedEvent(session.address, session.account.id));
@@ -21773,7 +21784,7 @@ class AppRuntime extends runtime_1.Runtime {
21773
21784
  }
21774
21785
  return await this.createSession(accountReference);
21775
21786
  }
21776
- async createSession(accountReference, masterPassword = "") {
21787
+ async createSession(accountReference) {
21777
21788
  const accountId = accountReference.length === 20 ? accountReference : (await this.multiAccountController.getAccountByAddress(accountReference)).id.toString();
21778
21789
  if (this.currentSessionPromise?.accountId === accountId) {
21779
21790
  return await this.currentSessionPromise.promise;
@@ -21782,9 +21793,9 @@ class AppRuntime extends runtime_1.Runtime {
21782
21793
  await this.currentSessionPromise.promise.catch(() => {
21783
21794
  // ignore
21784
21795
  });
21785
- return await this.createSession(accountId, masterPassword);
21796
+ return await this.createSession(accountId);
21786
21797
  }
21787
- this.currentSessionPromise = { promise: this._createSession(accountId, masterPassword), accountId };
21798
+ this.currentSessionPromise = { promise: this._createSession(accountId), accountId };
21788
21799
  try {
21789
21800
  return await this.currentSessionPromise.promise;
21790
21801
  }
@@ -21792,8 +21803,8 @@ class AppRuntime extends runtime_1.Runtime {
21792
21803
  this.currentSessionPromise = undefined;
21793
21804
  }
21794
21805
  }
21795
- async _createSession(accountId, masterPassword) {
21796
- const [localAccount, accountController] = await this._multiAccountController.selectAccount(transport_1.CoreId.from(accountId), masterPassword);
21806
+ async _createSession(accountId) {
21807
+ const [localAccount, accountController] = await this._multiAccountController.selectAccount(transport_1.CoreId.from(accountId));
21797
21808
  if (!localAccount.address) {
21798
21809
  throw AppRuntimeErrors_1.AppRuntimeErrors.general.addressUnavailable().logWith(this.logger);
21799
21810
  }
@@ -21821,7 +21832,7 @@ class AppRuntime extends runtime_1.Runtime {
21821
21832
  return UserfriendlyResult_1.UserfriendlyResult.fail(AppRuntimeErrors_1.AppRuntimeErrors.general.noAccountAvailable(accountSelectionResult.error));
21822
21833
  }
21823
21834
  if (accountSelectionResult.value)
21824
- await this.selectAccount(accountSelectionResult.value.id, "");
21835
+ await this.selectAccount(accountSelectionResult.value.id);
21825
21836
  return UserfriendlyResult_1.UserfriendlyResult.ok(accountSelectionResult.value);
21826
21837
  }
21827
21838
  async selectRelationship(id) {
@@ -21844,7 +21855,7 @@ class AppRuntime extends runtime_1.Runtime {
21844
21855
  return Promise.resolve(health);
21845
21856
  }
21846
21857
  async initAccount() {
21847
- this._multiAccountController = new multiAccount_1.MultiAccountController(this.transport, this.runtimeConfig);
21858
+ this._multiAccountController = new multiAccount_1.MultiAccountController(this.transport, this.runtimeConfig, this.lokiConnection, this.sessionStorage);
21848
21859
  await this._multiAccountController.init();
21849
21860
  this._accountServices = new multiAccount_1.AccountServices(this._multiAccountController);
21850
21861
  }
@@ -22194,6 +22205,12 @@ class SessionStorage {
22194
22205
  throw new Error("Session already exists");
22195
22206
  this._availableSessions.push(session);
22196
22207
  }
22208
+ removeSession(accountReference) {
22209
+ const session = this.findSession(accountReference);
22210
+ if (!session)
22211
+ return;
22212
+ this._availableSessions.splice(this._availableSessions.indexOf(session), 1);
22213
+ }
22197
22214
  }
22198
22215
  exports.SessionStorage = SessionStorage;
22199
22216
  //# sourceMappingURL=SessionStorage.js.map
@@ -22263,11 +22280,11 @@ const crypto_1 = __webpack_require__(/*! @nmshd/crypto */ "@nmshd/crypto");
22263
22280
  const runtime_1 = __webpack_require__(/*! @nmshd/runtime */ "@nmshd/runtime");
22264
22281
  const transport_1 = __webpack_require__(/*! @nmshd/transport */ "@nmshd/transport");
22265
22282
  exports.buildInformation = {
22266
- version: "3.0.4",
22267
- build: "21",
22268
- date: "2024-02-13T07:12:58+00:00",
22269
- commit: "a0b7c20718e10aba493f26ea129344f104822503",
22270
- dependencies: {"@js-soft/docdb-access-loki":"^1.0.6","@js-soft/native-abstractions":"^1.2.2","lodash":"^4.17.21"},
22283
+ version: "3.1.0",
22284
+ build: "64",
22285
+ date: "2024-04-08T14:18:55+00:00",
22286
+ commit: "2c9d6dbb7fd529de72e9693b07ad44c49073c795",
22287
+ dependencies: {"@js-soft/docdb-access-loki":"^1.1.0","@js-soft/native-abstractions":"^1.2.2","lodash":"^4.17.21"},
22271
22288
  libraries: {
22272
22289
  serval: ts_serval_1.buildInformation,
22273
22290
  crypto: crypto_1.buildInformation,
@@ -23439,6 +23456,9 @@ class AccountServices {
23439
23456
  const localAccount = await this.multiAccountController.getAccount(transport_1.CoreId.from(id));
23440
23457
  return LocalAccountMapper_1.LocalAccountMapper.toLocalAccountDTO(localAccount);
23441
23458
  }
23459
+ async deleteAccount(id) {
23460
+ await this.multiAccountController.deleteAccount(transport_1.CoreId.from(id));
23461
+ }
23442
23462
  async getAccountByAddress(address) {
23443
23463
  const localAccount = await this.multiAccountController.getAccountByAddress(address);
23444
23464
  return LocalAccountMapper_1.LocalAccountMapper.toLocalAccountDTO(localAccount);
@@ -23474,10 +23494,12 @@ class MultiAccountController {
23474
23494
  get path() {
23475
23495
  return this._path;
23476
23496
  }
23477
- constructor(transport, config) {
23497
+ constructor(transport, config, databaseConnection, sessionStorage) {
23478
23498
  this.config = config;
23499
+ this.databaseConnection = databaseConnection;
23500
+ this.sessionStorage = sessionStorage;
23479
23501
  this._dbClosed = false;
23480
- this._openAccounts = [];
23502
+ this._openAccounts = {};
23481
23503
  this._transport = transport;
23482
23504
  this._log = transport_1.TransportLoggerFactory.getLogger(MultiAccountController);
23483
23505
  }
@@ -23497,9 +23519,6 @@ class MultiAccountController {
23497
23519
  this._dbClosed = true;
23498
23520
  }
23499
23521
  }
23500
- get openAccounts() {
23501
- return this._openAccounts;
23502
- }
23503
23522
  async getAccount(id) {
23504
23523
  const dbAccount = await this._localAccounts.read(id.toString());
23505
23524
  if (!dbAccount) {
@@ -23518,13 +23537,16 @@ class MultiAccountController {
23518
23537
  const dbAccounts = await this._localAccounts.list();
23519
23538
  return dbAccounts.map((account) => LocalAccount_1.LocalAccount.from(account));
23520
23539
  }
23521
- async selectAccount(id, _masterPassword) {
23540
+ async selectAccount(id) {
23522
23541
  this._log.trace(`Selecting LocalAccount with id ${id}...`);
23523
23542
  const account = await this._localAccounts.read(id.toString());
23524
23543
  if (!account) {
23525
23544
  throw transport_1.CoreErrors.general.recordNotFound(LocalAccount_1.LocalAccount, id.toString()).logWith(this._log);
23526
23545
  }
23527
23546
  let localAccount = LocalAccount_1.LocalAccount.from(account);
23547
+ if (this._openAccounts[localAccount.id.toString()]) {
23548
+ return [localAccount, this._openAccounts[localAccount.id.toString()]];
23549
+ }
23528
23550
  this._log.trace(`Opening DB for account ${localAccount.id}...`);
23529
23551
  const db = await this.transport.createDatabase(`acc-${localAccount.id.toString()}`);
23530
23552
  this._log.trace(`DB for account ${id} opened.`);
@@ -23532,26 +23554,39 @@ class MultiAccountController {
23532
23554
  const accountController = new transport_1.AccountController(this.transport, db, this.transport.config);
23533
23555
  await accountController.init();
23534
23556
  this._log.trace(`AccountController for local account ${id} initialized.`);
23535
- this._openAccounts.push(accountController);
23557
+ this._openAccounts[localAccount.id.toString()] = accountController;
23536
23558
  if (!localAccount.address) {
23537
23559
  // Update address after first login if not set already
23538
23560
  localAccount = await this.updateLocalAccountAddress(localAccount.id, accountController.identity.address);
23539
23561
  }
23540
23562
  return [localAccount, accountController];
23541
23563
  }
23564
+ async deleteAccount(id) {
23565
+ const [localAccount, accountController] = await this.selectAccount(id);
23566
+ await accountController.unregisterPushNotificationToken();
23567
+ await accountController.activeDevice.markAsOffboarded();
23568
+ await accountController.close();
23569
+ delete this._openAccounts[localAccount.id.toString()];
23570
+ await this.databaseConnection.deleteDatabase(`acc-${id.toString()}`);
23571
+ await this._localAccounts.delete({ id: id.toString() });
23572
+ this.sessionStorage.removeSession(id.toString());
23573
+ }
23542
23574
  async clearAccounts() {
23543
23575
  await this._localAccounts.delete({});
23544
23576
  }
23545
23577
  async closeAccounts() {
23546
- for (let i = 0, l = this._openAccounts.length; i < l; i++) {
23547
- const account = this._openAccounts[i];
23548
- await account.close();
23578
+ for (const account of Object.values(this._openAccounts)) {
23579
+ await account?.close();
23549
23580
  }
23550
23581
  }
23551
23582
  async onboardDevice(deviceSharedSecret) {
23583
+ const existingAccounts = await this._localAccounts.find({ address: deviceSharedSecret.identity.address.toString() });
23584
+ if (existingAccounts.length > 0 && !this.config.allowMultipleAccountsWithSameAddress) {
23585
+ throw new transport_1.CoreError("error.app-runtime.onboardedAccountAlreadyExists", `An account with the address '${deviceSharedSecret.identity.address.toString()}' already exists in this app-runtime instance.`).logWith(this._log);
23586
+ }
23552
23587
  this._log.trace(`Onboarding device ${deviceSharedSecret.id} for identity ${deviceSharedSecret.identity.address}...`);
23553
23588
  const id = await transport_1.CoreId.generate();
23554
- let localAccount = LocalAccount_1.LocalAccount.from({
23589
+ const localAccount = LocalAccount_1.LocalAccount.from({
23555
23590
  id,
23556
23591
  address: deviceSharedSecret.identity.address,
23557
23592
  directory: ".",
@@ -23568,9 +23603,9 @@ class MultiAccountController {
23568
23603
  const accountController = new transport_1.AccountController(this.transport, db, this.transport.config);
23569
23604
  await accountController.init(deviceSharedSecret);
23570
23605
  this._log.trace(`AccountController for local account ${id} initialized.`);
23571
- this._openAccounts.push(accountController);
23572
- localAccount = await this.updateLocalAccountAddress(localAccount.id, accountController.identity.address);
23573
- return [localAccount, accountController];
23606
+ this._openAccounts[id.toString()] = accountController;
23607
+ const updatedLocalAccount = await this.updateLocalAccountAddress(localAccount.id, accountController.identity.address);
23608
+ return [updatedLocalAccount, accountController];
23574
23609
  }
23575
23610
  async createAccount(realm, name) {
23576
23611
  this._log.trace(`Creating account for realm ${realm}.`);
@@ -23591,7 +23626,7 @@ class MultiAccountController {
23591
23626
  const accountController = new transport_1.AccountController(this.transport, db, this.transport.config);
23592
23627
  await accountController.init();
23593
23628
  this._log.trace(`AccountController for local account ${id} initialized.`);
23594
- this._openAccounts.push(accountController);
23629
+ this._openAccounts[id.toString()] = accountController;
23595
23630
  localAccount = await this.updateLocalAccountAddress(localAccount.id, accountController.identity.address);
23596
23631
  return [localAccount, accountController];
23597
23632
  }