Browse Source

feat: Add easier way for test users to register themselves.

pull/164/head^2
Trent Larson 3 days ago
parent
commit
a221a5c5ed
  1. 10
      src/libs/endorserServer.ts
  2. 18
      src/router/index.ts
  3. 32
      src/test/index.ts
  4. 67
      src/views/TestView.vue

10
src/libs/endorserServer.ts

@ -1348,12 +1348,12 @@ export async function createEndorserJwtVcFromClaim(
}
/**
* Create a JWT for a RegisterAction claim.
* Create a JWT for a RegisterAction claim, used for registrations & invites.
*
* @param activeDid - The DID of the user creating the invite
* @param contact - The contact to register, with a 'did' field (all optional for invites)
* @param identifier - The identifier for the invite, usually random
* @param expiresIn - The number of seconds until the invite expires
* @param contact - Optional - The contact to register, with a 'did' field (all optional for invites)
* @param identifier - Optional - The identifier for the invite, usually random
* @param expiresIn - Optional - The number of seconds until the invite expires
* @returns The JWT for the RegisterAction claim
*/
export async function createInviteJwt(
@ -1367,7 +1367,7 @@ export async function createInviteJwt(
"@type": "RegisterAction",
agent: { identifier: activeDid },
object: SERVICE_ID,
identifier: identifier,
identifier: identifier, // not sent if undefined
};
if (contact?.did) {
vcClaim.participant = { identifier: contact.did };

18
src/router/index.ts

@ -82,6 +82,15 @@ const routes: Array<RouteRecordRaw> = [
name: "database-migration",
component: () => import("../views/DatabaseMigration.vue"),
},
{
path: "/deep-link-error",
name: "deep-link-error",
component: () => import("../views/DeepLinkErrorView.vue"),
meta: {
title: "Invalid Deep Link",
requiresAuth: false,
},
},
{
path: "/did/:did?",
name: "did",
@ -276,15 +285,6 @@ const routes: Array<RouteRecordRaw> = [
name: "user-profile",
component: () => import("../views/UserProfileView.vue"),
},
{
path: "/deep-link-error",
name: "deep-link-error",
component: () => import("../views/DeepLinkErrorView.vue"),
meta: {
title: "Invalid Deep Link",
requiresAuth: false,
},
},
];
const isElectron = window.location.protocol === "file:";

32
src/test/index.ts

@ -1,9 +1,29 @@
import axios from "axios";
import * as didJwt from "did-jwt";
import { SERVICE_ID } from "../libs/endorserServer";
import { deriveAddress, newIdentifier } from "../libs/crypto";
import {
DEFAULT_ROOT_DERIVATION_PATH,
deriveAddress,
newIdentifier,
} from "../libs/crypto";
import { logger } from "../utils/logger";
import { AppString } from "../constants/app";
import { saveNewIdentity } from "@/libs/util";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
const TEST_USER_0_MNEMONIC =
"rigid shrug mobile smart veteran half all pond toilet brave review universe ship congress found yard skate elite apology jar uniform subway slender luggage";
export async function testBecomeUser0() {
const [addr, privateHex, publicHex, deriPath] = deriveAddress(TEST_USER_0_MNEMONIC);
const identity0 = newIdentifier(addr, publicHex, privateHex, deriPath);
await saveNewIdentity(identity0, TEST_USER_0_MNEMONIC, DEFAULT_ROOT_DERIVATION_PATH);
const platformService = await PlatformServiceFactory.getInstance();
await platformService.updateDidSpecificSettings(identity0.did, {
isRegistered: true,
});
}
/**
* Get User #0 to sign & submit a RegisterAction for the user's activeDid.
@ -15,10 +35,7 @@ import { AppString } from "../constants/app";
* @throws Error if registration fails or database access fails
*/
export async function testServerRegisterUser() {
const testUser0Mnem =
"seminar accuse mystery assist delay law thing deal image undo guard initial shallow wrestle list fragile borrow velvet tomorrow awake explain test offer control";
const [addr, privateHex, publicHex, deriPath] = deriveAddress(testUser0Mnem);
const [addr, privateHex, publicHex, deriPath] = deriveAddress(TEST_USER_0_MNEMONIC);
const identity0 = newIdentifier(addr, publicHex, privateHex, deriPath);
@ -32,9 +49,9 @@ export async function testServerRegisterUser() {
const vcClaim = {
"@context": "https://schema.org",
"@type": "RegisterAction",
agent: { did: identity0.did },
agent: { identifier: identity0.did },
object: SERVICE_ID,
participant: { did: settings.activeDid },
participant: { identifier: settings.activeDid },
};
// Make a payload for the claim
@ -71,4 +88,5 @@ export async function testServerRegisterUser() {
const resp = await axios.post(url, payload, { headers });
logger.log("User registration result:", resp);
return resp;
}

67
src/views/TestView.vue

@ -21,7 +21,17 @@
</h1>
</div>
<div>
<div v-if="isNotProdServer">
<h2 class="text-xl font-bold mb-4">User Registration</h2>
<button :class="primaryButtonClasses" @click="registerMe()">
Register Yourself
</button>
<button :class="primaryButtonClasses" @click="becomeUser0()">
Become User 0 (who can register others)
</button>
</div>
<div class="mt-8">
<h2 class="text-xl font-bold mb-4">Notiwind Alerts</h2>
<!-- Notification test buttons using computed configuration -->
@ -99,7 +109,7 @@
<div>
Register Passkey
<button :class="primaryButtonClasses" @click="register()">
<button :class="primaryButtonClasses" @click="registerPasskey()">
Simplewebauthn
</button>
</div>
@ -235,6 +245,7 @@ import {
registerAndSavePasskey,
SHARED_PHOTO_BASE64_KEY,
} from "../libs/util";
import { testBecomeUser0, testServerRegisterUser } from "@/test";
import { logger } from "../utils/logger";
import { Account } from "../db/tables/accounts";
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
@ -300,6 +311,7 @@ export default class Help extends Vue {
// for passkeys
credIdHex?: string;
activeDid?: string;
apiServer?: string;
jwt?: string;
peerSetup?: PeerSetup;
userName?: string;
@ -521,17 +533,6 @@ export default class Help extends Vue {
];
}
/**
* Method to trigger notification test
* Centralizes notification testing logic
*/
triggerTestNotification(config: {
notification: NotificationIface;
timeout?: number;
}) {
this.$notify(config.notification, config.timeout);
}
/**
* Component initialization
*
@ -541,6 +542,7 @@ export default class Help extends Vue {
async mounted() {
const settings = await this.$accountSettings();
this.activeDid = settings.activeDid || "";
this.apiServer = settings.apiServer || "";
this.userName = settings.firstName;
const account = await retrieveAccountMetadata(this.activeDid);
@ -553,6 +555,43 @@ export default class Help extends Vue {
}
}
/**
* Checks if running on production server
*
* @returns True if not on production server (enables test utilities)
*/
public isNotProdServer() {
return this.apiServer !== AppString.PROD_ENDORSER_API_SERVER;
}
async registerMe() {
const response = await testServerRegisterUser();
if (response.status === 201) {
alert("Registration successful.");
this.$router.push({ name: "home" }); // because this page checks for registered status and sets things if it detects a change
} else {
logger.error("Registration failure response:", response);
alert("Registration failed: " + (response.data.error || response.data));
}
}
async becomeUser0() {
await testBecomeUser0();
alert("You are now User 0.");
this.$router.push({ name: "home" }); // because this page checks for registered status and sets things if it detects a change
}
/**
* Method to trigger notification test
* Centralizes notification testing logic
*/
triggerTestNotification(config: {
notification: NotificationIface;
timeout?: number;
}) {
this.$notify(config.notification, config.timeout);
}
/**
* Handles file upload for image sharing tests
*
@ -609,7 +648,7 @@ export default class Help extends Vue {
* Includes validation and user confirmation workflow
* Uses notification helpers for consistent messaging
*/
public async register() {
public async registerPasskey() {
const DEFAULT_USERNAME = AppString.APP_NAME + " Tester";
if (!this.userName) {
const modalConfig = createPasskeyNameModal(

Loading…
Cancel
Save