forked from trent_larson/crowd-funder-for-time-pwa
feat: Add easier way for test users to register themselves.
This commit is contained in:
@@ -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 activeDid - The DID of the user creating the invite
|
||||||
* @param contact - The contact to register, with a 'did' field (all optional for invites)
|
* @param contact - Optional - The contact to register, with a 'did' field (all optional for invites)
|
||||||
* @param identifier - The identifier for the invite, usually random
|
* @param identifier - Optional - The identifier for the invite, usually random
|
||||||
* @param expiresIn - The number of seconds until the invite expires
|
* @param expiresIn - Optional - The number of seconds until the invite expires
|
||||||
* @returns The JWT for the RegisterAction claim
|
* @returns The JWT for the RegisterAction claim
|
||||||
*/
|
*/
|
||||||
export async function createInviteJwt(
|
export async function createInviteJwt(
|
||||||
@@ -1367,7 +1367,7 @@ export async function createInviteJwt(
|
|||||||
"@type": "RegisterAction",
|
"@type": "RegisterAction",
|
||||||
agent: { identifier: activeDid },
|
agent: { identifier: activeDid },
|
||||||
object: SERVICE_ID,
|
object: SERVICE_ID,
|
||||||
identifier: identifier,
|
identifier: identifier, // not sent if undefined
|
||||||
};
|
};
|
||||||
if (contact?.did) {
|
if (contact?.did) {
|
||||||
vcClaim.participant = { identifier: contact.did };
|
vcClaim.participant = { identifier: contact.did };
|
||||||
|
|||||||
@@ -82,6 +82,15 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
name: "database-migration",
|
name: "database-migration",
|
||||||
component: () => import("../views/DatabaseMigration.vue"),
|
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?",
|
path: "/did/:did?",
|
||||||
name: "did",
|
name: "did",
|
||||||
@@ -276,15 +285,6 @@ const routes: Array<RouteRecordRaw> = [
|
|||||||
name: "user-profile",
|
name: "user-profile",
|
||||||
component: () => import("../views/UserProfileView.vue"),
|
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:";
|
const isElectron = window.location.protocol === "file:";
|
||||||
|
|||||||
@@ -1,9 +1,29 @@
|
|||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import * as didJwt from "did-jwt";
|
import * as didJwt from "did-jwt";
|
||||||
import { SERVICE_ID } from "../libs/endorserServer";
|
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 { logger } from "../utils/logger";
|
||||||
import { AppString } from "../constants/app";
|
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.
|
* 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
|
* @throws Error if registration fails or database access fails
|
||||||
*/
|
*/
|
||||||
export async function testServerRegisterUser() {
|
export async function testServerRegisterUser() {
|
||||||
const testUser0Mnem =
|
const [addr, privateHex, publicHex, deriPath] = deriveAddress(TEST_USER_0_MNEMONIC);
|
||||||
"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 identity0 = newIdentifier(addr, publicHex, privateHex, deriPath);
|
const identity0 = newIdentifier(addr, publicHex, privateHex, deriPath);
|
||||||
|
|
||||||
@@ -32,9 +49,9 @@ export async function testServerRegisterUser() {
|
|||||||
const vcClaim = {
|
const vcClaim = {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "RegisterAction",
|
"@type": "RegisterAction",
|
||||||
agent: { did: identity0.did },
|
agent: { identifier: identity0.did },
|
||||||
object: SERVICE_ID,
|
object: SERVICE_ID,
|
||||||
participant: { did: settings.activeDid },
|
participant: { identifier: settings.activeDid },
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make a payload for the claim
|
// Make a payload for the claim
|
||||||
@@ -71,4 +88,5 @@ export async function testServerRegisterUser() {
|
|||||||
|
|
||||||
const resp = await axios.post(url, payload, { headers });
|
const resp = await axios.post(url, payload, { headers });
|
||||||
logger.log("User registration result:", resp);
|
logger.log("User registration result:", resp);
|
||||||
|
return resp;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,17 @@
|
|||||||
</h1>
|
</h1>
|
||||||
</div>
|
</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>
|
<h2 class="text-xl font-bold mb-4">Notiwind Alerts</h2>
|
||||||
|
|
||||||
<!-- Notification test buttons using computed configuration -->
|
<!-- Notification test buttons using computed configuration -->
|
||||||
@@ -99,7 +109,7 @@
|
|||||||
|
|
||||||
<div>
|
<div>
|
||||||
Register Passkey
|
Register Passkey
|
||||||
<button :class="primaryButtonClasses" @click="register()">
|
<button :class="primaryButtonClasses" @click="registerPasskey()">
|
||||||
Simplewebauthn
|
Simplewebauthn
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -235,6 +245,7 @@ import {
|
|||||||
registerAndSavePasskey,
|
registerAndSavePasskey,
|
||||||
SHARED_PHOTO_BASE64_KEY,
|
SHARED_PHOTO_BASE64_KEY,
|
||||||
} from "../libs/util";
|
} from "../libs/util";
|
||||||
|
import { testBecomeUser0, testServerRegisterUser } from "@/test";
|
||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
import { Account } from "../db/tables/accounts";
|
import { Account } from "../db/tables/accounts";
|
||||||
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||||
@@ -300,6 +311,7 @@ export default class Help extends Vue {
|
|||||||
// for passkeys
|
// for passkeys
|
||||||
credIdHex?: string;
|
credIdHex?: string;
|
||||||
activeDid?: string;
|
activeDid?: string;
|
||||||
|
apiServer?: string;
|
||||||
jwt?: string;
|
jwt?: string;
|
||||||
peerSetup?: PeerSetup;
|
peerSetup?: PeerSetup;
|
||||||
userName?: string;
|
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
|
* Component initialization
|
||||||
*
|
*
|
||||||
@@ -541,6 +542,7 @@ export default class Help extends Vue {
|
|||||||
async mounted() {
|
async mounted() {
|
||||||
const settings = await this.$accountSettings();
|
const settings = await this.$accountSettings();
|
||||||
this.activeDid = settings.activeDid || "";
|
this.activeDid = settings.activeDid || "";
|
||||||
|
this.apiServer = settings.apiServer || "";
|
||||||
this.userName = settings.firstName;
|
this.userName = settings.firstName;
|
||||||
|
|
||||||
const account = await retrieveAccountMetadata(this.activeDid);
|
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
|
* Handles file upload for image sharing tests
|
||||||
*
|
*
|
||||||
@@ -609,7 +648,7 @@ export default class Help extends Vue {
|
|||||||
* Includes validation and user confirmation workflow
|
* Includes validation and user confirmation workflow
|
||||||
* Uses notification helpers for consistent messaging
|
* Uses notification helpers for consistent messaging
|
||||||
*/
|
*/
|
||||||
public async register() {
|
public async registerPasskey() {
|
||||||
const DEFAULT_USERNAME = AppString.APP_NAME + " Tester";
|
const DEFAULT_USERNAME = AppString.APP_NAME + " Tester";
|
||||||
if (!this.userName) {
|
if (!this.userName) {
|
||||||
const modalConfig = createPasskeyNameModal(
|
const modalConfig = createPasskeyNameModal(
|
||||||
|
|||||||
Reference in New Issue
Block a user