Skip to content

Commit

Permalink
Add isBackupDevice to DeviceSharedSecret (#416)
Browse files Browse the repository at this point in the history
* feat: add isBackupDevice to DeviceSharedSecret and DeviceOnboardingInfo

* feat: add showBackupDeviceOnboarding to UIBridge

* test: check profile name of backup device

* fix: parameters for matchers

* fix: typo

* refactor: remove showBackupDeviceOnboarding

* test: extend error message
  • Loading branch information
Milena-Czierlinski authored Feb 10, 2025
1 parent b0cf129 commit 004efe2
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 9 deletions.
9 changes: 5 additions & 4 deletions packages/app-runtime/test/lib/MockUIBridge.matchers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { DeviceOnboardingInfoDTO } from "@nmshd/runtime";
import { MockUIBridge } from "./MockUIBridge";

expect.extend({
showDeviceOnboardingCalled(mockUIBridge: unknown, deviceId: string) {
showDeviceOnboardingCalled(mockUIBridge: unknown, predicate: (deviceOnboardingInfo: DeviceOnboardingInfoDTO) => boolean) {
if (!(mockUIBridge instanceof MockUIBridge)) {
throw new Error("This method can only be used with expect(MockUIBridge).");
}
Expand All @@ -11,12 +12,12 @@ expect.extend({
return { pass: false, message: () => "The method showDeviceOnboarding was not called." };
}

const matchingCalls = calls.filter((x) => x.deviceOnboardingInfo.id === deviceId);
const matchingCalls = calls.filter((x) => predicate(x.deviceOnboardingInfo));
if (matchingCalls.length === 0) {
return {
pass: false,
message: () =>
`The method showDeviceOnboarding was called, but not with the specified device id '${deviceId}', instead with ids '${calls.map((e) => e.deviceOnboardingInfo.id).join(", ")}'.`
`The method showDeviceOnboarding was called, but not with the specified predicate, instead with payloads '${calls.map((e) => JSON.stringify(e.deviceOnboardingInfo)).join(", ")}'.`
};
}

Expand Down Expand Up @@ -112,7 +113,7 @@ expect.extend({
declare global {
namespace jest {
interface Matchers<R> {
showDeviceOnboardingCalled(deviceId: string): R;
showDeviceOnboardingCalled(predicate: (deviceOnboardingInfo: DeviceOnboardingInfoDTO) => boolean): R;
showDeviceOnboardingNotCalled(): R;
requestAccountSelectionCalled(possibleAccountsLength: number): R;
requestAccountSelectionNotCalled(): R;
Expand Down
19 changes: 17 additions & 2 deletions packages/app-runtime/test/runtime/AppStringProcessor.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ArbitraryRelationshipTemplateContentJSON } from "@nmshd/content";
import { CoreDate } from "@nmshd/core-types";
import { PeerRelationshipTemplateLoadedEvent } from "@nmshd/runtime";
import { DeviceOnboardingInfoDTO, PeerRelationshipTemplateLoadedEvent } from "@nmshd/runtime";
import assert from "assert";
import { AppRuntime, LocalAccountSession } from "../../src";
import { MockEventBus, MockUIBridge, TestUtil } from "../lib";
Expand Down Expand Up @@ -216,7 +216,22 @@ describe("AppStringProcessor", function () {
expect(result).toBeSuccessful();
expect(result.value).toBeUndefined();

expect(mockUiBridge).showDeviceOnboardingCalled(deviceResult.value.id);
expect(mockUiBridge).showDeviceOnboardingCalled((deviceOnboardingInfo: DeviceOnboardingInfoDTO) => deviceOnboardingInfo.id === deviceResult.value.id);
});

test("backup device onboarding with a password protected Token", async function () {
const tokenResult = await runtime1Session.transportServices.identityRecoveryKits.createIdentityRecoveryKit({
profileName: "profileNameForBackupDevice",
passwordProtection: { password: "password" }
});

mockUiBridge.setPasswordToReturnForAttempt(1, "password");

const result = await runtime2.stringProcessor.processTruncatedReference(tokenResult.value.truncatedReference);
expect(result).toBeSuccessful();
expect(result.value).toBeUndefined();

expect(mockUiBridge).showDeviceOnboardingCalled((deviceOnboardingInfo: DeviceOnboardingInfoDTO) => deviceOnboardingInfo.isBackupDevice === true);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ export interface DeviceOnboardingInfoDTO {
identity: IdentityDTO;
password: string;
username: string;
isBackupDevice?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ export class DeviceMapper {
},
password: deviceSharedSecret.password,
username: deviceSharedSecret.username,
profileName: deviceSharedSecret.profileName
profileName: deviceSharedSecret.profileName,
isBackupDevice: deviceSharedSecret.isBackupDevice
};
}

Expand All @@ -62,7 +63,8 @@ export class DeviceMapper {
},
password: deviceOnboardingDTO.password,
username: deviceOnboardingDTO.username,
profileName: deviceOnboardingDTO.profileName
profileName: deviceOnboardingDTO.profileName,
isBackupDevice: deviceOnboardingDTO.isBackupDevice
});
return sharedSecret;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ export class DeviceSecretController extends TransportController {
identityPrivateKey: identityPrivateKey?.secret as CryptoSignaturePrivateKey,
username: device.username,
password: device.initialPassword!,
identity: this.parent.identity.identity
identity: this.parent.identity.identity,
isBackupDevice: device.isBackupDevice
});

return deviceSharedSecret;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface IDeviceSharedSecret extends ISerializable {
identity: IIdentity;
password: string;
username: string;
isBackupDevice?: boolean;
}

@type("DeviceSharedSecret")
Expand Down Expand Up @@ -73,6 +74,10 @@ export class DeviceSharedSecret extends Serializable implements IDeviceSharedSec
@validate()
public password: string;

@serialize()
@validate({ nullable: true })
public isBackupDevice?: boolean;

public static from(value: IDeviceSharedSecret): DeviceSharedSecret {
return this.fromAny(value);
}
Expand Down

0 comments on commit 004efe2

Please sign in to comment.