Skip to content

Commit

Permalink
Merge branch 'main' into feature/block-sending-messages-to-a-deleted-…
Browse files Browse the repository at this point in the history
…or-toBeDeleted-Identity
  • Loading branch information
britsta authored Dec 2, 2024
2 parents b61547c + 2241e42 commit a6b79df
Show file tree
Hide file tree
Showing 114 changed files with 3,215 additions and 724 deletions.
5 changes: 5 additions & 0 deletions .dev/appsettings.override.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@
"ConnectionString": "User ID=tokens;Password=Passw0rd;Server=postgres;Port=5432;Database=enmeshed;"
}
}
},
"Tags": {
"Application": {
"SupportedLanguages": ["en"]
}
}
},
"Serilog": {
Expand Down
3 changes: 2 additions & 1 deletion .dev/compose.backbone.env
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
BACKBONE_VERSION=6.15.0
BACKBONE_VERSION=6.20.0

42 changes: 42 additions & 0 deletions .github/settings.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
# https://github.com/repository-settings/app

repository:
allow_squash_merge: true
allow_merge_commit: false
allow_rebase_merge: false
allow_auto_merge: true
allow_update_branch: true
delete_branch_on_merge: true

labels:
- name: breaking-change
color: "#16060F"
description: A breaking change
- name: bug
color: "#d73a4a"
description: Something isn't working
- name: chore
color: "#c2e0c6"
description: Some routine work like updating dependencies
- name: ci
color: "#DFB5FD"
description: Continuous Integration related stuff
- name: dependencies
color: "#0366d6"
description: Pull requests that update dependencies
- name: documentation
color: "#0075ca"
description: Improvements or additions to documentation
- name: enhancement
color: "#a2eeef"
description: New feature or request
- name: refactoring
color: "#880361"
description: Refactoring of code
- name: test
color: "#20D89D"
description: This pull request contains only new or changed tests
- name: wip
color: "#32BF4C"
description: Work in Progress (blocks mergify from auto update the branch)
5 changes: 4 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions packages/app-runtime/src/AppConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,18 @@ export function createAppConfig(...configs: AppConfigOverwrite[]): AppConfig {
location: "onboardingChangeReceived",
enabled: true
},
datawalletSynchronized: {
name: "datawalletSynchronized",
displayName: "Datawallet Synchronized Module",
location: "datawalletSynchronized",
enabled: true
},
identityDeletionProcessStatusChanged: {
name: "identityDeletionProcessStatusChanged",
displayName: "Identity Deletion Process Status Changed Module",
location: "identityDeletionProcessStatusChanged",
enabled: true
},
messageReceived: {
name: "messageReceived",
displayName: "Message Received Module",
Expand Down
28 changes: 5 additions & 23 deletions packages/app-runtime/src/AppRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ import { AppConfig, AppConfigOverwrite, createAppConfig } from "./AppConfig";
import { AppRuntimeErrors } from "./AppRuntimeErrors";
import { AppRuntimeServices } from "./AppRuntimeServices";
import { AppStringProcessor } from "./AppStringProcessor";
import { AccountSelectedEvent, RelationshipSelectedEvent } from "./events";
import { AccountSelectedEvent } from "./events";
import { AppServices, IUIBridge } from "./extensibility";
import {
AppLaunchModule,
AppRuntimeModuleConfiguration,
AppSyncModule,
DatawalletSynchronizedModule,
IAppRuntimeModuleConstructor,
IdentityDeletionProcessStatusChangedModule,
MailReceivedModule,
MessageReceivedModule,
OnboardingChangeReceivedModule,
Expand Down Expand Up @@ -86,14 +88,6 @@ export class AppRuntime extends Runtime<AppConfig> {

private readonly sessionStorage = new SessionStorage();

public get currentAccount(): LocalAccountDTO {
return this.sessionStorage.currentSession.account;
}

public get currentSession(): LocalAccountSession {
return this.sessionStorage.currentSession;
}

public getSessions(): LocalAccountSession[] {
return this.sessionStorage.getSessions();
}
Expand Down Expand Up @@ -209,20 +203,6 @@ export class AppRuntime extends Runtime<AppConfig> {
return UserfriendlyResult.ok(accountSelectionResult.value);
}

public async selectRelationship(id?: string): Promise<void> {
if (!id) {
this.currentSession.selectedRelationship = undefined;
return;
}

const result = await this.currentSession.appServices.relationships.renderRelationship(id);
if (result.isError) throw result.error;

const relationship = result.value;
this.currentSession.selectedRelationship = relationship;
this.eventBus.publish(new RelationshipSelectedEvent(this.currentSession.address, relationship));
}

public getHealth(): Promise<RuntimeHealth> {
const health = {
isHealthy: true,
Expand Down Expand Up @@ -298,6 +278,8 @@ export class AppRuntime extends Runtime<AppConfig> {
pushNotification: PushNotificationModule,
mailReceived: MailReceivedModule,
onboardingChangeReceived: OnboardingChangeReceivedModule,
datawalletSynchronized: DatawalletSynchronizedModule,
identityDeletionProcessStatusChanged: IdentityDeletionProcessStatusChangedModule,
messageReceived: MessageReceivedModule,
relationshipChanged: RelationshipChangedModule,
relationshipTemplateProcessed: RelationshipTemplateProcessedModule
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { DataEvent } from "@nmshd/runtime";
import { LocalAccountDTO } from "../multiAccount";

export class LocalAccountDeletionDateChangedEvent extends DataEvent<LocalAccountDTO> {
public static readonly namespace: string = "app.localAccountDeletionDateChanged";

public constructor(address: string, localAccount: LocalAccountDTO) {
super(LocalAccountDeletionDateChangedEvent.namespace, address, localAccount);
}
}
2 changes: 1 addition & 1 deletion packages/app-runtime/src/events/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export * from "./AccountSelectedEvent";
export * from "./DatawalletSynchronizedEvent";
export * from "./ExternalEventReceivedEvent";
export * from "./LocalAccountDeletionDateChangedEvent";
export * from "./MailReceivedEvent";
export * from "./OnboardingChangeReceivedEvent";
export * from "./RelationshipSelectedEvent";
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Result } from "@js-soft/ts-utils";
import { AppRuntimeErrors } from "../../AppRuntimeErrors";
import { AccountSelectedEvent, DatawalletSynchronizedEvent, ExternalEventReceivedEvent } from "../../events";
import { AccountSelectedEvent, ExternalEventReceivedEvent } from "../../events";
import { RemoteNotificationEvent, RemoteNotificationRegistrationEvent } from "../../natives";
import { AppRuntimeModule, AppRuntimeModuleConfiguration } from "../AppRuntimeModule";
import { BackboneEventName, IBackboneEventContent } from "./IBackboneEventContent";
Expand Down Expand Up @@ -35,7 +35,6 @@ export class PushNotificationModule extends AppRuntimeModule<PushNotificationMod
this.logger.error(walletResult);
return;
}
this.runtime.eventBus.publish(new DatawalletSynchronizedEvent(accRef));
break;
case BackboneEventName.ExternalEventCreated:
const syncResult = await services.transportServices.account.syncEverything();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { CoreDate } from "@nmshd/core-types";
import { DatawalletSynchronizedEvent, IdentityDeletionProcessStatus } from "@nmshd/runtime";
import { AppRuntimeError } from "../../AppRuntimeError";
import { LocalAccountDeletionDateChangedEvent } from "../../events";
import { LocalAccountMapper } from "../../multiAccount";
import { AppRuntimeModule, AppRuntimeModuleConfiguration } from "../AppRuntimeModule";

export interface DatawalletSynchronizedModuleConfig extends AppRuntimeModuleConfiguration {}

export class DatawalletSynchronizedModuleError extends AppRuntimeError {}

export class DatawalletSynchronizedModule extends AppRuntimeModule<DatawalletSynchronizedModuleConfig> {
public async init(): Promise<void> {
// Nothing to do here
}

public start(): Promise<void> | void {
this.subscribeToEvent(DatawalletSynchronizedEvent, this.handleDatawalletSynchronized.bind(this));
}

private async handleDatawalletSynchronized(event: DatawalletSynchronizedEvent) {
const services = await this.runtime.getServices(event.eventTargetAddress);
const identityDeletionProcessResult = await services.transportServices.identityDeletionProcesses.getIdentityDeletionProcesses();

if (identityDeletionProcessResult.isError) {
this.logger.error(identityDeletionProcessResult);
return;
}

if (identityDeletionProcessResult.value.length === 0) return;

const mostRecentIdentityDeletionProcess = identityDeletionProcessResult.value.at(-1)!;
let newDeletionDate;
switch (mostRecentIdentityDeletionProcess.status) {
case IdentityDeletionProcessStatus.Approved:
newDeletionDate = CoreDate.from(mostRecentIdentityDeletionProcess.gracePeriodEndsAt!);
break;
case IdentityDeletionProcessStatus.Cancelled:
case IdentityDeletionProcessStatus.Rejected:
case IdentityDeletionProcessStatus.WaitingForApproval:
newDeletionDate = undefined;
break;
}

const account = await this.runtime.multiAccountController.getAccountByAddress(event.eventTargetAddress);
const previousDeletionDate = account.deletionDate;

if (previousDeletionDate === newDeletionDate) return;

await this.runtime.multiAccountController.updateLocalAccountDeletionDate(event.eventTargetAddress, newDeletionDate);

const updatedAccount = await this.runtime.multiAccountController.getAccountByAddress(event.eventTargetAddress);
this.runtime.eventBus.publish(new LocalAccountDeletionDateChangedEvent(event.eventTargetAddress, LocalAccountMapper.toLocalAccountDTO(updatedAccount)));
}

public override stop(): Promise<void> | void {
this.unsubscribeFromAllEvents();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { CoreDate } from "@nmshd/core-types";
import { IdentityDeletionProcessStatus, IdentityDeletionProcessStatusChangedEvent } from "@nmshd/runtime";
import { AppRuntimeError } from "../../AppRuntimeError";
import { AppRuntimeModule, AppRuntimeModuleConfiguration } from "../AppRuntimeModule";

export interface IdentityDeletionProcessStatusChangedModuleConfig extends AppRuntimeModuleConfiguration {}

export class IdentityDeletionProcessChangedModuleError extends AppRuntimeError {}

export class IdentityDeletionProcessStatusChangedModule extends AppRuntimeModule<IdentityDeletionProcessStatusChangedModuleConfig> {
public async init(): Promise<void> {
// Nothing to do here
}

public start(): Promise<void> | void {
this.subscribeToEvent(IdentityDeletionProcessStatusChangedEvent, this.handleIdentityDeletionProcessStatusChanged.bind(this));
}

private async handleIdentityDeletionProcessStatusChanged(event: IdentityDeletionProcessStatusChangedEvent) {
const identityDeletionProcess = event.data;

switch (identityDeletionProcess.status) {
case IdentityDeletionProcessStatus.Approved:
await this.runtime.multiAccountController.updateLocalAccountDeletionDate(event.eventTargetAddress, CoreDate.from(identityDeletionProcess.gracePeriodEndsAt!));
break;

case IdentityDeletionProcessStatus.Cancelled:
const account = await this.runtime.multiAccountController.getAccountByAddress(event.eventTargetAddress);
const previousDeletionDate = account.deletionDate;

if (!previousDeletionDate) break;

await this.runtime.multiAccountController.updateLocalAccountDeletionDate(event.eventTargetAddress, undefined);
break;

default:
break;
}
}

public override stop(): Promise<void> | void {
this.unsubscribeFromAllEvents();
}
}
2 changes: 2 additions & 0 deletions packages/app-runtime/src/modules/runtimeEvents/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from "./DatawalletSynchronizedModule";
export * from "./IdentityDeletionProcessStatusChangedModule";
export * from "./MessageReceivedModule";
export * from "./RelationshipChangedModule";
10 changes: 10 additions & 0 deletions packages/app-runtime/src/multiAccount/AccountServices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ export class AccountServices {
return localAccounts.map((account) => LocalAccountMapper.toLocalAccountDTO(account));
}

public async getAccountsInDeletion(): Promise<LocalAccountDTO[]> {
const localAccounts = await this.multiAccountController.getAccountsInDeletion();
return localAccounts.map((account) => LocalAccountMapper.toLocalAccountDTO(account));
}

public async getAccountsNotInDeletion(): Promise<LocalAccountDTO[]> {
const localAccounts = await this.multiAccountController.getAccountsNotInDeletion();
return localAccounts.map((account) => LocalAccountMapper.toLocalAccountDTO(account));
}

public async getAccount(id: string): Promise<LocalAccountDTO> {
const localAccount = await this.multiAccountController.getAccount(CoreId.from(id));
return LocalAccountMapper.toLocalAccountDTO(localAccount);
Expand Down
33 changes: 31 additions & 2 deletions packages/app-runtime/src/multiAccount/MultiAccountController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export class MultiAccountController {

this._dbClosed = false;
this._localAccounts = await this._db.getCollection("LocalAccounts");

return this;
}

Expand Down Expand Up @@ -77,8 +78,20 @@ export class MultiAccountController {
}

public async getAccounts(): Promise<LocalAccount[]> {
const dbAccounts = await this._localAccounts.list();
return dbAccounts.map((account) => LocalAccount.from(account));
return await this._findAccounts();
}

public async getAccountsInDeletion(): Promise<LocalAccount[]> {
return await this._findAccounts({ deletionDate: { $exists: true } });
}

public async getAccountsNotInDeletion(): Promise<LocalAccount[]> {
return await this._findAccounts({ deletionDate: { $exists: false } });
}

private async _findAccounts(query?: any) {
const accounts = await this._localAccounts.find(query);
return accounts.map((account) => LocalAccount.from(account));
}

public async selectAccount(id: CoreId): Promise<[LocalAccount, AccountController]> {
Expand Down Expand Up @@ -238,6 +251,22 @@ export class MultiAccountController {
await this._localAccounts.update(oldAccount, renamedAccount);
}

public async updateLocalAccountDeletionDate(address: string, deletionDate?: CoreDate): Promise<void> {
const oldAccount = await this._localAccounts.findOne({ address });

if (!oldAccount) {
throw TransportCoreErrors.general.recordNotFound(LocalAccount, address).logWith(this._log);
}

const account = LocalAccount.from(oldAccount);

account.deletionDate = deletionDate ?? undefined;
await this._localAccounts.update(oldAccount, account);

const cachedAccount = this.sessionStorage.findSession(address)?.account;
if (cachedAccount) cachedAccount.deletionDate = deletionDate?.toString();
}

public async updateLastAccessedAt(accountId: string): Promise<void> {
const document = await this._localAccounts.read(accountId);
if (!document) {
Expand Down
Loading

0 comments on commit a6b79df

Please sign in to comment.