feat: add duplicate account import prevention

- Add duplicate check in ImportAccountView before account import
- Add duplicate check in ImportDerivedAccountView for derived accounts
- Add safety check in saveNewIdentity function to prevent duplicate saves
- Implement user-friendly warning messages for duplicate attempts
- Add comprehensive error handling to catch duplicate errors from saveNewIdentity
- Create Playwright tests to verify duplicate prevention functionality
- Add documentation for duplicate prevention implementation

The system now prevents users from importing the same account multiple times
by checking for existing DIDs both before import (pre-check) and during
save (post-check). Users receive clear warning messages instead of
technical errors when attempting to import duplicate accounts.

Files modified:
- src/views/ImportAccountView.vue: Add duplicate check and error handling
- src/views/ImportDerivedAccountView.vue: Add duplicate check for derived accounts
- src/libs/util.ts: Add duplicate prevention in saveNewIdentity
- test-playwright/duplicate-import-test.spec.ts: Add comprehensive tests
- doc/duplicate-account-import-implementation.md: Add implementation docs

Resolves: Prevent duplicate account imports in IdentitySwitcherView
This commit is contained in:
Jose Olarte III
2025-08-28 16:35:04 +08:00
parent 6f9847b524
commit f51408e32a
5 changed files with 204 additions and 7 deletions

View File

@@ -171,6 +171,16 @@ export default class ImportAccountView extends Vue {
const newId = newIdentifier(address, publicHex, privateHex, newDerivPath);
try {
// Check for duplicate account before creating
const isDuplicate = await this.checkForDuplicateAccount(newId.did);
if (isDuplicate) {
this.notify.warning(
"This derived account already exists. Please try a different derivation path.",
TIMEOUTS.LONG,
);
return;
}
await saveNewIdentity(newId, mne, newDerivPath);
// record that as the active DID
@@ -192,5 +202,27 @@ export default class ImportAccountView extends Vue {
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>