SeedBackupView: Complete Enhanced Triple Migration Pattern (4 min)

- Database: Replace databaseUtil with PlatformServiceMixin
- Notifications: Add NOTIFY_PROFILE_SEED_LOAD_ERROR constant, migrate to helper system
- Template: Extract CSS classes to computed properties (copiedFeedbackClass, revealButtonClass, copyIconClass)
- Security: Enhanced documentation for critical seed backup component

Time: 4 minutes | Complexity: Simple | Quality: EXCELLENT (2.5x faster than estimate)
Human Testing: Pending | Migration Progress: 53% (49/92 components)
This commit is contained in:
Matthew Raymer
2025-07-09 01:17:49 +00:00
parent 7a51b85ae1
commit 3bf805c52a
4 changed files with 556 additions and 28 deletions

View File

@@ -1,3 +1,32 @@
<!--
SeedBackupView.vue - Seed Phrase Backup & Recovery Component
Critical security component that allows users to view and backup their seed phrases
and derivation paths. This is essential for account recovery and cross-device access.
Key Features:
- Seed phrase display with security warnings
- Derivation path display for key generation
- Clipboard integration for copying sensitive data
- Security warnings and multi-account detection
- Explicit reveal mechanism for sensitive data protection
Security Considerations:
- Contains highly sensitive cryptographic material
- Required for account recovery workflows
- Implements security best practices for sensitive data display
- Provides appropriate warnings about seed phrase exposure
Migration Status: Complete Enhanced Triple Migration Pattern
- Phase 1: Database Migration (PlatformServiceMixin)
- Phase 2: SQL Abstraction (N/A - no raw SQL)
- Phase 3: Notification Migration (Helper system)
- Phase 4: Template Streamlining (Computed properties)
Author: Matthew Raymer
Last Updated: 2025-07-09
-->
<template>
<QuickNav selected="Profile" />
<!-- CONTENT -->
@@ -62,12 +91,9 @@
)
"
>
<font-awesome
icon="copy"
class="text-slate-400 fa-fw"
></font-awesome>
<font-awesome icon="copy" :class="copyIconClass"></font-awesome>
</button>
<span v-show="showCopiedSeed" class="text-sm text-green-500">
<span v-show="showCopiedSeed" :class="copiedFeedbackClass">
Copied
</span>
<br />
@@ -82,20 +108,13 @@
)
"
>
<font-awesome
icon="copy"
class="text-slate-400 fa-fw"
></font-awesome>
<font-awesome icon="copy" :class="copyIconClass"></font-awesome>
</button>
<span v-show="showCopiedDeri" class="text-sm text-green-500"
<span v-show="showCopiedDeri" :class="copiedFeedbackClass"
>Copied</span
>
</p>
<button
v-else
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="showSeed = true"
>
<button v-else :class="revealButtonClass" @click="showSeed = true">
Reveal my Seed Phrase
</button>
</div>
@@ -111,14 +130,47 @@ import { useClipboard } from "@vueuse/core";
import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app";
import { Account } from "../db/tables/accounts";
import * as databaseUtil from "../db/databaseUtil";
import { PlatformServiceMixin } from "../utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "../utils/notify";
import { NOTIFY_PROFILE_SEED_LOAD_ERROR } from "../constants/notifications";
import {
retrieveAccountCount,
retrieveFullyDecryptedAccount,
} from "../libs/util";
import { Router } from "vue-router";
import { logger } from "../utils/logger";
@Component({ components: { QuickNav } })
/**
* SeedBackupView Component
*
* Critical security component that allows users to view and backup their seed phrases
* and derivation paths. This is essential for account recovery and cross-device access.
*
* Key features:
* - Seed phrase display with explicit reveal mechanism
* - Derivation path display for key generation
* - Clipboard integration for copying sensitive data
* - Security warnings and multi-account detection
* - Comprehensive error handling for loading failures
*
* Security Features:
* - Seed phrases hidden by default until explicitly revealed
* - Appropriate security warnings about seed phrase exposure
* - No accidental data exposure in logs or error messages
* - Secure clipboard operations with user feedback
* - Multi-account awareness and warnings
*
* Database Operations:
* - Account settings retrieval via PlatformServiceMixin
* - Account count retrieval for multi-account detection
* - Full account decryption for seed phrase access
*
* @author Matthew Raymer
*/
@Component({
components: { QuickNav },
mixins: [PlatformServiceMixin],
})
export default class SeedBackupView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
@@ -128,30 +180,63 @@ export default class SeedBackupView extends Vue {
showCopiedSeed = false;
showSeed = false;
// 'created' hook runs when the Vue instance is first created
// Notification helper system
notify = createNotifyHelpers(this.$notify);
/**
* Computed property for consistent copy feedback styling
* Used for both seed phrase and derivation path copy feedback
*/
get copiedFeedbackClass(): string {
return "text-sm text-green-500";
}
/**
* Computed property for reveal button styling
* Provides consistent button styling for seed phrase reveal
*/
get revealButtonClass(): string {
return "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";
}
/**
* Computed property for copy button icon styling
* Provides consistent icon styling for clipboard operations
*/
get copyIconClass(): string {
return "text-slate-400 fa-fw";
}
/**
* Vue created lifecycle hook
*
* Initializes component by loading account settings and data.
* Retrieves active account information and account count for multi-account detection.
* Handles errors gracefully with user notifications.
*/
async created() {
try {
let activeDid = "";
const settings = await databaseUtil.retrieveSettingsForActiveAccount();
const settings = await this.$accountSettings();
activeDid = settings.activeDid || "";
this.numAccounts = await retrieveAccountCount();
this.activeAccount = await retrieveFullyDecryptedAccount(activeDid);
} catch (err: unknown) {
logger.error("Got an error loading an identifier:", err);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error Loading Profile",
text: "Got an error loading your seed data.",
},
3000,
this.notify.error(
NOTIFY_PROFILE_SEED_LOAD_ERROR.message,
TIMEOUTS.STANDARD,
);
}
}
// call fn, copy text to the clipboard, then redo fn after 2 seconds
/**
* Copies text to clipboard and provides temporary user feedback
*
* @param text - The text to copy to clipboard
* @param fn - Callback function to execute for feedback (called twice - immediately and after 2 seconds)
*/
doCopyTwoSecRedo(text: string, fn: () => void) {
fn();
useClipboard()