forked from jsnbuchanan/crowd-funder-for-time-pwa
Apply full database migration (databaseUtil → PlatformServiceMixin), replace raw SQL with service methods, migrate 3 notifications to helper methods. Preserve 1 complex modal for advanced routing features while extracting all literal strings to NOTIFY_CAMERA_SHARE_METHOD constant. Add computed properties (offerTabClasses, projectTabClasses) to streamline template logic and comprehensive JSDoc documentation for all methods. Update migration templates to mandate literal extraction from complex modals. ProjectsView.vue now appropriately incomplete: helper methods for simple notifications, raw $notify preserved only where advanced features required.
224 lines
6.6 KiB
Vue
224 lines
6.6 KiB
Vue
<template>
|
|
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
|
|
<!-- Breadcrumb -->
|
|
<div id="ViewBreadcrumb" class="mb-8">
|
|
<h1 class="text-lg text-center font-light relative px-7">
|
|
<!-- Cancel -->
|
|
<button
|
|
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
|
@click="$router.go(-1)"
|
|
>
|
|
<font-awesome icon="chevron-left"></font-awesome>
|
|
</button>
|
|
Import Existing Identifier
|
|
</h1>
|
|
</div>
|
|
<!-- Import Account Form -->
|
|
<p class="text-center text-xl mb-4 font-light">
|
|
Enter your seed phrase below to import your identifier on this device.
|
|
</p>
|
|
<!-- id used by puppeteer test script -->
|
|
<textarea
|
|
id="seed-input"
|
|
v-model="mnemonic"
|
|
type="text"
|
|
placeholder="Seed Phrase"
|
|
class="block w-full rounded border border-slate-400 mb-4 px-3 py-2"
|
|
/>
|
|
|
|
<h3
|
|
class="text-blue-500 text-sm font-semibold mb-3"
|
|
@click="showAdvanced = !showAdvanced"
|
|
>
|
|
Advanced
|
|
</h3>
|
|
<div v-if="showAdvanced">
|
|
Enter a custom derivation path
|
|
<input
|
|
v-model="derivationPath"
|
|
type="text"
|
|
class="block w-full rounded border border-slate-400 mb-2 px-3 py-2"
|
|
/>
|
|
<span class="ml-4">
|
|
For previous uPort or Endorser users,
|
|
<a
|
|
class="text-blue-500"
|
|
@click="derivationPath = UPORT_DERIVATION_PATH"
|
|
>
|
|
click here to use that value.
|
|
</a>
|
|
</span>
|
|
|
|
<div v-if="numAccounts == 1" class="mt-4">
|
|
<input v-model="shouldErase" type="checkbox" class="mr-2" />
|
|
<label>Erase previous identifiers.</label>
|
|
</div>
|
|
|
|
<div v-if="isNotProdServer()" class="mt-4 text-blue-500">
|
|
<!-- if they click this, fill in the mnemonic seed-input with the test mnemonic -->
|
|
<button @click="mnemonic = TEST_USER_0_MNEMONIC">
|
|
Use mnemonic for Test User #0
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-8">
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-2">
|
|
<button
|
|
class="block w-full text-center text-lg font-bold uppercase bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md"
|
|
@click="fromMnemonic()"
|
|
>
|
|
Import
|
|
</button>
|
|
<button
|
|
type="button"
|
|
class="block w-full text-center text-md uppercase bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md"
|
|
@click="onCancelClick()"
|
|
>
|
|
Cancel
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { Component, Vue } from "vue-facing-decorator";
|
|
import { Router } from "vue-router";
|
|
|
|
import { AppString, NotificationIface } from "../constants/app";
|
|
import { DEFAULT_ROOT_DERIVATION_PATH } from "../libs/crypto";
|
|
import { retrieveAccountCount, importFromMnemonic } from "../libs/util";
|
|
import { logger } from "../utils/logger";
|
|
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
|
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
|
|
|
|
/**
|
|
* Import Account View Component
|
|
*
|
|
* Allows users to import existing identifiers using seed phrases:
|
|
* - Secure mnemonic phrase input with validation
|
|
* - Advanced options for custom derivation paths
|
|
* - Legacy uPort compatibility support
|
|
* - Test environment utilities for development
|
|
*
|
|
* Features:
|
|
* - Secure seed phrase import functionality
|
|
* - Custom derivation path configuration
|
|
* - Account erasure options for fresh imports
|
|
* - Development mode test utilities
|
|
* - Comprehensive error handling and validation
|
|
*
|
|
* Security Considerations:
|
|
* - Seed phrases are handled securely and not logged
|
|
* - Import process includes validation and error recovery
|
|
* - Advanced options are hidden by default
|
|
*
|
|
* @author Matthew Raymer
|
|
*/
|
|
@Component({
|
|
components: {},
|
|
mixins: [PlatformServiceMixin],
|
|
})
|
|
export default class ImportAccountView extends Vue {
|
|
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";
|
|
UPORT_DERIVATION_PATH = "m/7696500'/0'/0'/0'"; // for legacy imports, likely never used
|
|
|
|
AppString = AppString;
|
|
|
|
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
|
$router!: Router;
|
|
|
|
notify!: ReturnType<typeof createNotifyHelpers>;
|
|
|
|
apiServer = "";
|
|
derivationPath = DEFAULT_ROOT_DERIVATION_PATH;
|
|
mnemonic = "";
|
|
numAccounts = 0;
|
|
showAdvanced = false;
|
|
shouldErase = false;
|
|
|
|
/**
|
|
* Initializes notification helpers
|
|
*/
|
|
created() {
|
|
this.notify = createNotifyHelpers(this.$notify);
|
|
}
|
|
|
|
/**
|
|
* Component initialization
|
|
*
|
|
* Loads account count and server settings for import configuration
|
|
* Uses PlatformServiceMixin for secure database access
|
|
*/
|
|
async mounted() {
|
|
await this.initializeSettings();
|
|
}
|
|
|
|
/**
|
|
* Initializes component settings and account information
|
|
*/
|
|
private async initializeSettings() {
|
|
this.numAccounts = await retrieveAccountCount();
|
|
const settings = await this.$accountSettings();
|
|
this.apiServer = settings.apiServer || "";
|
|
}
|
|
|
|
/**
|
|
* Handles cancel button click
|
|
*
|
|
* Navigates back to previous view
|
|
*/
|
|
public onCancelClick() {
|
|
this.$router.back();
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* Imports identifier from mnemonic phrase
|
|
*
|
|
* Processes the mnemonic phrase with optional custom derivation path
|
|
* and account erasure options. Handles validation and error scenarios
|
|
* with appropriate user feedback.
|
|
*
|
|
* Error Handling:
|
|
* - Invalid mnemonic format validation
|
|
* - Import process failure recovery
|
|
* - User-friendly error messaging
|
|
*/
|
|
public async fromMnemonic() {
|
|
try {
|
|
await importFromMnemonic(
|
|
this.mnemonic,
|
|
this.derivationPath,
|
|
this.shouldErase,
|
|
);
|
|
this.$router.push({ name: "account" });
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
} catch (err: any) {
|
|
logger.error("Error importing from mnemonic:", err);
|
|
if (err == "Error: invalid mnemonic") {
|
|
this.notify.error(
|
|
"Please check your mnemonic and try again.",
|
|
TIMEOUTS.LONG,
|
|
);
|
|
} else {
|
|
this.notify.error(
|
|
"Got an error creating that identifier.",
|
|
TIMEOUTS.LONG,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|