forked from jsnbuchanan/crowd-funder-for-time-pwa
refactor: consolidate duplicate account checking logic into unified utility
- Extract checkForDuplicateAccount methods from ImportAccountView and ImportDerivedAccountView - Create unified utility function in src/libs/util.ts with TypeScript overloads - Support both direct DID checking and mnemonic+derivation path checking - Improve error handling with centralized logging via PlatformServiceFactory - Add comprehensive JSDoc documentation for both function overloads - Remove unused imports (deriveAddress, newIdentifier) from ImportAccountView The utility function now provides a clean API: - checkForDuplicateAccount(did) - for direct DID checking - checkForDuplicateAccount(mnemonic, derivationPath) - for derivation + checking Both components maintain identical functionality while using centralized logic.
This commit is contained in:
@@ -1042,3 +1042,69 @@ export async function importFromMnemonic(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an account with the given DID already exists in the database
|
||||||
|
*
|
||||||
|
* @param did - The DID to check for duplicates
|
||||||
|
* @returns Promise<boolean> - True if account already exists, false otherwise
|
||||||
|
* @throws Error if database query fails
|
||||||
|
*/
|
||||||
|
export async function checkForDuplicateAccount(did: string): Promise<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an account with the given DID already exists in the database
|
||||||
|
*
|
||||||
|
* @param mnemonic - The mnemonic phrase to derive DID from
|
||||||
|
* @param derivationPath - The derivation path to use
|
||||||
|
* @returns Promise<boolean> - True if account already exists, false otherwise
|
||||||
|
* @throws Error if database query fails
|
||||||
|
*/
|
||||||
|
export async function checkForDuplicateAccount(
|
||||||
|
mnemonic: string,
|
||||||
|
derivationPath: string,
|
||||||
|
): Promise<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of checkForDuplicateAccount with overloaded signatures
|
||||||
|
*/
|
||||||
|
export async function checkForDuplicateAccount(
|
||||||
|
didOrMnemonic: string,
|
||||||
|
derivationPath?: string,
|
||||||
|
): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
let didToCheck: string;
|
||||||
|
|
||||||
|
if (derivationPath) {
|
||||||
|
// Derive the DID from mnemonic and derivation path
|
||||||
|
const [address, privateHex, publicHex] = deriveAddress(
|
||||||
|
didOrMnemonic.trim().toLowerCase(),
|
||||||
|
derivationPath,
|
||||||
|
);
|
||||||
|
|
||||||
|
const newId = newIdentifier(
|
||||||
|
address,
|
||||||
|
privateHex,
|
||||||
|
publicHex,
|
||||||
|
derivationPath,
|
||||||
|
);
|
||||||
|
didToCheck = newId.did;
|
||||||
|
} else {
|
||||||
|
// Use the provided DID directly
|
||||||
|
didToCheck = didOrMnemonic;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if an account with this DID already exists
|
||||||
|
const platformService = await getPlatformService();
|
||||||
|
const existingAccount = await platformService.dbQuery(
|
||||||
|
"SELECT did FROM accounts WHERE did = ?",
|
||||||
|
[didToCheck],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (existingAccount?.values?.length ?? 0) > 0;
|
||||||
|
} catch (error) {
|
||||||
|
// If we can't check for duplicates, let the calling process handle the error
|
||||||
|
logger.error("Error checking for duplicate account:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -87,12 +87,12 @@ import { Component, Vue } from "vue-facing-decorator";
|
|||||||
import { Router } from "vue-router";
|
import { Router } from "vue-router";
|
||||||
|
|
||||||
import { AppString, NotificationIface } from "../constants/app";
|
import { AppString, NotificationIface } from "../constants/app";
|
||||||
|
import { DEFAULT_ROOT_DERIVATION_PATH } from "../libs/crypto";
|
||||||
import {
|
import {
|
||||||
DEFAULT_ROOT_DERIVATION_PATH,
|
retrieveAccountCount,
|
||||||
deriveAddress,
|
importFromMnemonic,
|
||||||
newIdentifier,
|
checkForDuplicateAccount,
|
||||||
} from "../libs/crypto";
|
} from "../libs/util";
|
||||||
import { retrieveAccountCount, importFromMnemonic } from "../libs/util";
|
|
||||||
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
|
||||||
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
|
import { createNotifyHelpers, TIMEOUTS } from "@/utils/notify";
|
||||||
import { NOTIFY_DUPLICATE_ACCOUNT_IMPORT } from "@/constants/notifications";
|
import { NOTIFY_DUPLICATE_ACCOUNT_IMPORT } from "@/constants/notifications";
|
||||||
@@ -204,7 +204,10 @@ export default class ImportAccountView extends Vue {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Check for duplicate account before importing
|
// Check for duplicate account before importing
|
||||||
const isDuplicate = await this.checkForDuplicateAccount();
|
const isDuplicate = await checkForDuplicateAccount(
|
||||||
|
this.mnemonic,
|
||||||
|
this.derivationPath,
|
||||||
|
);
|
||||||
if (isDuplicate) {
|
if (isDuplicate) {
|
||||||
this.notify.warning(
|
this.notify.warning(
|
||||||
NOTIFY_DUPLICATE_ACCOUNT_IMPORT.message,
|
NOTIFY_DUPLICATE_ACCOUNT_IMPORT.message,
|
||||||
@@ -259,43 +262,5 @@ export default class ImportAccountView extends Vue {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the account to be imported already exists
|
|
||||||
*
|
|
||||||
* Derives the DID from the mnemonic and checks if it exists in the database
|
|
||||||
* @returns Promise<boolean> - True if account already exists, false otherwise
|
|
||||||
*/
|
|
||||||
private async checkForDuplicateAccount(): Promise<boolean> {
|
|
||||||
try {
|
|
||||||
// Derive the address and create the identifier to get the DID
|
|
||||||
const [address, privateHex, publicHex] = deriveAddress(
|
|
||||||
this.mnemonic.trim().toLowerCase(),
|
|
||||||
this.derivationPath,
|
|
||||||
);
|
|
||||||
|
|
||||||
const newId = newIdentifier(
|
|
||||||
address,
|
|
||||||
publicHex,
|
|
||||||
privateHex,
|
|
||||||
this.derivationPath,
|
|
||||||
);
|
|
||||||
const didToCheck = newId.did;
|
|
||||||
|
|
||||||
// Check if an account with this DID already exists
|
|
||||||
const existingAccount = await this.$query(
|
|
||||||
"SELECT did FROM accounts WHERE did = ?",
|
|
||||||
[didToCheck],
|
|
||||||
);
|
|
||||||
|
|
||||||
return existingAccount?.values?.length > 0;
|
|
||||||
} catch (error) {
|
|
||||||
// If we can't check for duplicates (e.g., invalid mnemonic),
|
|
||||||
// let the import process handle the error
|
|
||||||
this.$logError("Error checking for duplicate account: " + error);
|
|
||||||
// Return false to let the import process continue and handle the error
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ import {
|
|||||||
retrieveAllAccountsMetadata,
|
retrieveAllAccountsMetadata,
|
||||||
retrieveFullyDecryptedAccount,
|
retrieveFullyDecryptedAccount,
|
||||||
saveNewIdentity,
|
saveNewIdentity,
|
||||||
|
checkForDuplicateAccount,
|
||||||
} from "../libs/util";
|
} from "../libs/util";
|
||||||
import { logger } from "../utils/logger";
|
import { logger } from "../utils/logger";
|
||||||
import { Account, AccountEncrypted } from "../db/tables/accounts";
|
import { Account, AccountEncrypted } from "../db/tables/accounts";
|
||||||
@@ -172,7 +173,7 @@ export default class ImportAccountView extends Vue {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Check for duplicate account before creating
|
// Check for duplicate account before creating
|
||||||
const isDuplicate = await this.checkForDuplicateAccount(newId.did);
|
const isDuplicate = await checkForDuplicateAccount(newId.did);
|
||||||
if (isDuplicate) {
|
if (isDuplicate) {
|
||||||
this.notify.warning(
|
this.notify.warning(
|
||||||
"This derived account already exists. Please try a different derivation path.",
|
"This derived account already exists. Please try a different derivation path.",
|
||||||
@@ -202,27 +203,5 @@ export default class ImportAccountView extends Vue {
|
|||||||
this.notify.error(NOTIFY_ACCOUNT_DERIVATION_ERROR.message, TIMEOUTS.LONG);
|
this.notify.error(NOTIFY_ACCOUNT_DERIVATION_ERROR.message, TIMEOUTS.LONG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the account to be created already exists
|
|
||||||
*
|
|
||||||
* @param did - The DID to check for duplicates
|
|
||||||
* @returns Promise<boolean> - True if account already exists, false otherwise
|
|
||||||
*/
|
|
||||||
private async checkForDuplicateAccount(did: string): Promise<boolean> {
|
|
||||||
try {
|
|
||||||
// Check if an account with this DID already exists
|
|
||||||
const existingAccount = await this.$query(
|
|
||||||
"SELECT did FROM accounts WHERE did = ?",
|
|
||||||
[did],
|
|
||||||
);
|
|
||||||
|
|
||||||
return existingAccount?.values?.length > 0;
|
|
||||||
} catch (error) {
|
|
||||||
// If we can't check for duplicates, let the save process handle the error
|
|
||||||
this.$logError("Error checking for duplicate account: " + error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user