mirror of
https://github.com/shuaiplus/nodewarden.git
synced 2026-08-05 14:50:11 +00:00
feat: support Bitwarden extended cipher types
This commit is contained in:
@@ -327,6 +327,55 @@ export default function VaultDetailView(props: VaultDetailViewProps) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{props.selectedCipher.bankAccount && (
|
||||
<div className="card">
|
||||
<h4>{t('txt_bank_account_details')}</h4>
|
||||
<div className="kv-line"><span>{t('txt_bank_name')}</span><strong>{props.selectedCipher.bankAccount.decBankName || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_name_on_account')}</span><strong>{props.selectedCipher.bankAccount.decNameOnAccount || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_account_type')}</span><strong>{props.selectedCipher.bankAccount.decAccountType || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_account_number')}</span><strong>{props.selectedCipher.bankAccount.decAccountNumber || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_routing_number')}</span><strong>{props.selectedCipher.bankAccount.decRoutingNumber || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_branch_number')}</span><strong>{props.selectedCipher.bankAccount.decBranchNumber || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_pin')}</span><strong>{props.selectedCipher.bankAccount.decPin || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_swift_code')}</span><strong>{props.selectedCipher.bankAccount.decSwiftCode || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_iban')}</span><strong>{props.selectedCipher.bankAccount.decIban || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_bank_contact_phone')}</span><strong>{props.selectedCipher.bankAccount.decBankContactPhone || ''}</strong></div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{props.selectedCipher.driversLicense && (
|
||||
<div className="card">
|
||||
<h4>{t('txt_drivers_license_details')}</h4>
|
||||
<div className="kv-line"><span>{t('txt_name')}</span><strong>{[props.selectedCipher.driversLicense.decFirstName, props.selectedCipher.driversLicense.decMiddleName, props.selectedCipher.driversLicense.decLastName].filter(Boolean).join(' ')}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_date_of_birth')}</span><strong>{props.selectedCipher.driversLicense.decDateOfBirth || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_license_number')}</span><strong>{props.selectedCipher.driversLicense.decLicenseNumber || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_issuing_country')}</span><strong>{props.selectedCipher.driversLicense.decIssuingCountry || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_issuing_state')}</span><strong>{props.selectedCipher.driversLicense.decIssuingState || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_issue_date')}</span><strong>{props.selectedCipher.driversLicense.decIssueDate || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_expiration_date')}</span><strong>{props.selectedCipher.driversLicense.decExpirationDate || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_issuing_authority')}</span><strong>{props.selectedCipher.driversLicense.decIssuingAuthority || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_license_class')}</span><strong>{props.selectedCipher.driversLicense.decLicenseClass || ''}</strong></div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{props.selectedCipher.passport && (
|
||||
<div className="card">
|
||||
<h4>{t('txt_passport_details')}</h4>
|
||||
<div className="kv-line"><span>{t('txt_name')}</span><strong>{[props.selectedCipher.passport.decGivenName, props.selectedCipher.passport.decSurname].filter(Boolean).join(' ')}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_date_of_birth')}</span><strong>{props.selectedCipher.passport.decDateOfBirth || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_sex')}</span><strong>{props.selectedCipher.passport.decSex || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_birth_place')}</span><strong>{props.selectedCipher.passport.decBirthPlace || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_nationality')}</span><strong>{props.selectedCipher.passport.decNationality || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_issuing_country')}</span><strong>{props.selectedCipher.passport.decIssuingCountry || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_passport_number')}</span><strong>{props.selectedCipher.passport.decPassportNumber || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_passport_type')}</span><strong>{props.selectedCipher.passport.decPassportType || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_national_id_number')}</span><strong>{props.selectedCipher.passport.decNationalIdentificationNumber || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_issuing_authority')}</span><strong>{props.selectedCipher.passport.decIssuingAuthority || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_issue_date')}</span><strong>{props.selectedCipher.passport.decIssueDate || ''}</strong></div>
|
||||
<div className="kv-line"><span>{t('txt_expiration_date')}</span><strong>{props.selectedCipher.passport.decExpirationDate || ''}</strong></div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!!(props.selectedCipher.decNotes || '').trim() && (
|
||||
<div className="card">
|
||||
<h4>{t('txt_notes')}</h4>
|
||||
|
||||
@@ -589,6 +589,64 @@ export default function VaultEditor(props: VaultEditorProps) {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{props.draft.type === 6 && (
|
||||
<div className="card">
|
||||
<h4>{t('txt_bank_account_details')}</h4>
|
||||
<div className="field-grid">
|
||||
<label className="field"><span>{t('txt_bank_name')}</span><input className="input" value={props.draft.bankName} onInput={(e) => props.onUpdateDraft({ bankName: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_name_on_account')}</span><input className="input" value={props.draft.bankNameOnAccount} onInput={(e) => props.onUpdateDraft({ bankNameOnAccount: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_account_type')}</span><input className="input" value={props.draft.bankAccountType} onInput={(e) => props.onUpdateDraft({ bankAccountType: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_account_number')}</span><input className="input" value={props.draft.bankAccountNumber} onInput={(e) => props.onUpdateDraft({ bankAccountNumber: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_routing_number')}</span><input className="input" value={props.draft.bankRoutingNumber} onInput={(e) => props.onUpdateDraft({ bankRoutingNumber: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_branch_number')}</span><input className="input" value={props.draft.bankBranchNumber} onInput={(e) => props.onUpdateDraft({ bankBranchNumber: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_pin')}</span><input className="input" value={props.draft.bankPin} onInput={(e) => props.onUpdateDraft({ bankPin: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_swift_code')}</span><input className="input" value={props.draft.bankSwiftCode} onInput={(e) => props.onUpdateDraft({ bankSwiftCode: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_iban')}</span><input className="input" value={props.draft.bankIban} onInput={(e) => props.onUpdateDraft({ bankIban: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_bank_contact_phone')}</span><input className="input" value={props.draft.bankContactPhone} onInput={(e) => props.onUpdateDraft({ bankContactPhone: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{props.draft.type === 7 && (
|
||||
<div className="card">
|
||||
<h4>{t('txt_drivers_license_details')}</h4>
|
||||
<div className="field-grid">
|
||||
<label className="field"><span>{t('txt_first_name')}</span><input className="input" value={props.draft.licenseFirstName} onInput={(e) => props.onUpdateDraft({ licenseFirstName: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_middle_name')}</span><input className="input" value={props.draft.licenseMiddleName} onInput={(e) => props.onUpdateDraft({ licenseMiddleName: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_last_name')}</span><input className="input" value={props.draft.licenseLastName} onInput={(e) => props.onUpdateDraft({ licenseLastName: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_date_of_birth')}</span><input className="input" value={props.draft.licenseDateOfBirth} onInput={(e) => props.onUpdateDraft({ licenseDateOfBirth: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_license_number')}</span><input className="input" value={props.draft.licenseNumber} onInput={(e) => props.onUpdateDraft({ licenseNumber: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_issuing_country')}</span><input className="input" value={props.draft.licenseIssuingCountry} onInput={(e) => props.onUpdateDraft({ licenseIssuingCountry: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_issuing_state')}</span><input className="input" value={props.draft.licenseIssuingState} onInput={(e) => props.onUpdateDraft({ licenseIssuingState: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_issue_date')}</span><input className="input" value={props.draft.licenseIssueDate} onInput={(e) => props.onUpdateDraft({ licenseIssueDate: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_expiration_date')}</span><input className="input" value={props.draft.licenseExpirationDate} onInput={(e) => props.onUpdateDraft({ licenseExpirationDate: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_issuing_authority')}</span><input className="input" value={props.draft.licenseIssuingAuthority} onInput={(e) => props.onUpdateDraft({ licenseIssuingAuthority: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_license_class')}</span><input className="input" value={props.draft.licenseClass} onInput={(e) => props.onUpdateDraft({ licenseClass: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{props.draft.type === 8 && (
|
||||
<div className="card">
|
||||
<h4>{t('txt_passport_details')}</h4>
|
||||
<div className="field-grid">
|
||||
<label className="field"><span>{t('txt_surname')}</span><input className="input" value={props.draft.passportSurname} onInput={(e) => props.onUpdateDraft({ passportSurname: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_given_name')}</span><input className="input" value={props.draft.passportGivenName} onInput={(e) => props.onUpdateDraft({ passportGivenName: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_date_of_birth')}</span><input className="input" value={props.draft.passportDateOfBirth} onInput={(e) => props.onUpdateDraft({ passportDateOfBirth: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_sex')}</span><input className="input" value={props.draft.passportSex} onInput={(e) => props.onUpdateDraft({ passportSex: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_birth_place')}</span><input className="input" value={props.draft.passportBirthPlace} onInput={(e) => props.onUpdateDraft({ passportBirthPlace: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_nationality')}</span><input className="input" value={props.draft.passportNationality} onInput={(e) => props.onUpdateDraft({ passportNationality: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_issuing_country')}</span><input className="input" value={props.draft.passportIssuingCountry} onInput={(e) => props.onUpdateDraft({ passportIssuingCountry: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_passport_number')}</span><input className="input" value={props.draft.passportNumber} onInput={(e) => props.onUpdateDraft({ passportNumber: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_passport_type')}</span><input className="input" value={props.draft.passportType} onInput={(e) => props.onUpdateDraft({ passportType: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_national_id_number')}</span><input className="input" value={props.draft.passportNationalIdentificationNumber} onInput={(e) => props.onUpdateDraft({ passportNationalIdentificationNumber: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_issuing_authority')}</span><input className="input" value={props.draft.passportIssuingAuthority} onInput={(e) => props.onUpdateDraft({ passportIssuingAuthority: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_issue_date')}</span><input className="input" value={props.draft.passportIssueDate} onInput={(e) => props.onUpdateDraft({ passportIssueDate: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
<label className="field"><span>{t('txt_expiration_date')}</span><input className="input" value={props.draft.passportExpirationDate} onInput={(e) => props.onUpdateDraft({ passportExpirationDate: (e.currentTarget as HTMLInputElement).value })} /></label>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="card">
|
||||
<div className="section-head attachment-head">
|
||||
<h4>{t('txt_attachments')}</h4>
|
||||
|
||||
@@ -117,9 +117,18 @@ export default function VaultSidebar(props: VaultSidebarProps) {
|
||||
<button type="button" className={`tree-btn ${props.sidebarFilter.kind === 'type' && props.sidebarFilter.value === 'card' ? 'active' : ''}`} onClick={() => props.onChangeFilter({ kind: 'type', value: 'card' })}>
|
||||
<CreditCard size={14} className="tree-icon" /> <span className="tree-label">{t('txt_card')}</span>
|
||||
</button>
|
||||
<button type="button" className={`tree-btn ${props.sidebarFilter.kind === 'type' && props.sidebarFilter.value === 'bank' ? 'active' : ''}`} onClick={() => props.onChangeFilter({ kind: 'type', value: 'bank' })}>
|
||||
<CreditCard size={14} className="tree-icon" /> <span className="tree-label">{t('txt_bank_account')}</span>
|
||||
</button>
|
||||
<button type="button" className={`tree-btn ${props.sidebarFilter.kind === 'type' && props.sidebarFilter.value === 'identity' ? 'active' : ''}`} onClick={() => props.onChangeFilter({ kind: 'type', value: 'identity' })}>
|
||||
<ShieldUser size={14} className="tree-icon" /> <span className="tree-label">{t('txt_identity')}</span>
|
||||
</button>
|
||||
<button type="button" className={`tree-btn ${props.sidebarFilter.kind === 'type' && props.sidebarFilter.value === 'license' ? 'active' : ''}`} onClick={() => props.onChangeFilter({ kind: 'type', value: 'license' })}>
|
||||
<ShieldUser size={14} className="tree-icon" /> <span className="tree-label">{t('txt_drivers_license')}</span>
|
||||
</button>
|
||||
<button type="button" className={`tree-btn ${props.sidebarFilter.kind === 'type' && props.sidebarFilter.value === 'passport' ? 'active' : ''}`} onClick={() => props.onChangeFilter({ kind: 'type', value: 'passport' })}>
|
||||
<KeyRound size={14} className="tree-icon" /> <span className="tree-label">{t('txt_passport')}</span>
|
||||
</button>
|
||||
<button type="button" className={`tree-btn ${props.sidebarFilter.kind === 'type' && props.sidebarFilter.value === 'note' ? 'active' : ''}`} onClick={() => props.onChangeFilter({ kind: 'type', value: 'note' })}>
|
||||
<StickyNote size={14} className="tree-icon" /> <span className="tree-label">{t('txt_note')}</span>
|
||||
</button>
|
||||
|
||||
@@ -14,7 +14,7 @@ import { firstCipherUri, hostFromUri, websiteIconUrl } from '@/lib/website-utils
|
||||
import { normalizeEquivalentDomain } from '@shared/domain-normalize';
|
||||
import WebsiteIcon from './WebsiteIcon';
|
||||
|
||||
export type TypeFilter = 'login' | 'card' | 'identity' | 'note' | 'ssh';
|
||||
export type TypeFilter = 'login' | 'card' | 'identity' | 'note' | 'ssh' | 'bank' | 'license' | 'passport';
|
||||
export type VaultSortMode = 'edited' | 'created' | 'name';
|
||||
export type DuplicateDetectionMode = 'exact' | 'login-site' | 'login-credentials' | 'password';
|
||||
export type SidebarFilter =
|
||||
@@ -98,6 +98,32 @@ export function cardListSubtitle(cipher: Cipher): string {
|
||||
return cipherTypeLabel(3);
|
||||
}
|
||||
|
||||
export function bankAccountListSubtitle(cipher: Cipher): string {
|
||||
const bankName = valueOrFallback(cipher.bankAccount?.decBankName ?? cipher.bankAccount?.bankName).trim();
|
||||
const accountType = valueOrFallback(cipher.bankAccount?.decAccountType ?? cipher.bankAccount?.accountType).trim();
|
||||
const accountNumber = valueOrFallback(cipher.bankAccount?.decAccountNumber ?? cipher.bankAccount?.accountNumber).replace(/\D/g, '');
|
||||
const last4 = accountNumber.length >= 4 ? accountNumber.slice(-4) : '';
|
||||
return [bankName, accountType, last4 ? `*${last4}` : ''].filter(Boolean).join(', ') || cipherTypeLabel(6);
|
||||
}
|
||||
|
||||
export function driversLicenseListSubtitle(cipher: Cipher): string {
|
||||
const licenseNumber = valueOrFallback(cipher.driversLicense?.decLicenseNumber ?? cipher.driversLicense?.licenseNumber).trim();
|
||||
const name = [
|
||||
valueOrFallback(cipher.driversLicense?.decFirstName ?? cipher.driversLicense?.firstName).trim(),
|
||||
valueOrFallback(cipher.driversLicense?.decLastName ?? cipher.driversLicense?.lastName).trim(),
|
||||
].filter(Boolean).join(' ');
|
||||
return licenseNumber || name || cipherTypeLabel(7);
|
||||
}
|
||||
|
||||
export function passportListSubtitle(cipher: Cipher): string {
|
||||
const passportNumber = valueOrFallback(cipher.passport?.decPassportNumber ?? cipher.passport?.passportNumber).trim();
|
||||
const name = [
|
||||
valueOrFallback(cipher.passport?.decGivenName ?? cipher.passport?.givenName).trim(),
|
||||
valueOrFallback(cipher.passport?.decSurname ?? cipher.passport?.surname).trim(),
|
||||
].filter(Boolean).join(' ');
|
||||
return passportNumber || name || cipherTypeLabel(8);
|
||||
}
|
||||
|
||||
export function CardBrandIcon({ brand }: { brand?: string | null }) {
|
||||
const display = displayCardBrand(brand);
|
||||
const key = display.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'generic';
|
||||
@@ -118,7 +144,10 @@ export function getCreateTypeOptions(): TypeOption[] {
|
||||
return [
|
||||
{ type: 1, label: t('txt_login') },
|
||||
{ type: 3, label: t('txt_card') },
|
||||
{ type: 6, label: t('txt_bank_account') },
|
||||
{ type: 4, label: t('txt_identity') },
|
||||
{ type: 7, label: t('txt_drivers_license') },
|
||||
{ type: 8, label: t('txt_passport') },
|
||||
{ type: 2, label: t('txt_note') },
|
||||
{ type: 5, label: t('txt_ssh_key') },
|
||||
];
|
||||
@@ -185,6 +214,9 @@ export function CreateTypeIcon({ type }: { type: number }) {
|
||||
if (type === 4) return <ShieldUser size={15} />;
|
||||
if (type === 2) return <StickyNote size={15} />;
|
||||
if (type === 5) return <KeyRound size={15} />;
|
||||
if (type === 6) return <CreditCard size={15} />;
|
||||
if (type === 7) return <ShieldUser size={15} />;
|
||||
if (type === 8) return <FileKey2 size={15} />;
|
||||
return <FileKey2 size={15} />;
|
||||
}
|
||||
|
||||
@@ -193,7 +225,11 @@ export function cipherTypeKey(type: number): TypeFilter {
|
||||
if (type === 3) return 'card';
|
||||
if (type === 4) return 'identity';
|
||||
if (type === 2) return 'note';
|
||||
return 'ssh';
|
||||
if (type === 5) return 'ssh';
|
||||
if (type === 6) return 'bank';
|
||||
if (type === 7) return 'license';
|
||||
if (type === 8) return 'passport';
|
||||
return 'note';
|
||||
}
|
||||
|
||||
function cipherDeletedValue(cipher: Cipher): boolean {
|
||||
@@ -230,6 +266,9 @@ export function cipherTypeLabel(type: number): string {
|
||||
if (type === 4) return t('txt_identity');
|
||||
if (type === 2) return t('txt_secure_note');
|
||||
if (type === 5) return t('txt_ssh_key');
|
||||
if (type === 6) return t('txt_bank_account');
|
||||
if (type === 7) return t('txt_drivers_license');
|
||||
if (type === 8) return t('txt_passport');
|
||||
return t('txt_item');
|
||||
}
|
||||
|
||||
@@ -239,6 +278,9 @@ export function TypeIcon({ type }: { type: number }) {
|
||||
if (type === 4) return <ShieldUser size={18} />;
|
||||
if (type === 2) return <StickyNote size={18} />;
|
||||
if (type === 5) return <KeyRound size={18} />;
|
||||
if (type === 6) return <CreditCard size={18} />;
|
||||
if (type === 7) return <ShieldUser size={18} />;
|
||||
if (type === 8) return <FileKey2 size={18} />;
|
||||
return <FileKey2 size={18} />;
|
||||
}
|
||||
|
||||
@@ -355,6 +397,52 @@ export function buildCipherDuplicateSignature(cipher: Cipher): string {
|
||||
fingerprint: valueOrFallback(cipher.sshKey.decFingerprint ?? cipher.sshKey.keyFingerprint ?? cipher.sshKey.fingerprint),
|
||||
}
|
||||
: null,
|
||||
bankAccount: cipher.bankAccount
|
||||
? {
|
||||
bankName: valueOrFallback(cipher.bankAccount.decBankName ?? cipher.bankAccount.bankName),
|
||||
nameOnAccount: valueOrFallback(cipher.bankAccount.decNameOnAccount ?? cipher.bankAccount.nameOnAccount),
|
||||
accountType: valueOrFallback(cipher.bankAccount.decAccountType ?? cipher.bankAccount.accountType),
|
||||
accountNumber: valueOrFallback(cipher.bankAccount.decAccountNumber ?? cipher.bankAccount.accountNumber),
|
||||
routingNumber: valueOrFallback(cipher.bankAccount.decRoutingNumber ?? cipher.bankAccount.routingNumber),
|
||||
branchNumber: valueOrFallback(cipher.bankAccount.decBranchNumber ?? cipher.bankAccount.branchNumber),
|
||||
pin: valueOrFallback(cipher.bankAccount.decPin ?? cipher.bankAccount.pin),
|
||||
swiftCode: valueOrFallback(cipher.bankAccount.decSwiftCode ?? cipher.bankAccount.swiftCode),
|
||||
iban: valueOrFallback(cipher.bankAccount.decIban ?? cipher.bankAccount.iban),
|
||||
bankContactPhone: valueOrFallback(cipher.bankAccount.decBankContactPhone ?? cipher.bankAccount.bankContactPhone),
|
||||
}
|
||||
: null,
|
||||
driversLicense: cipher.driversLicense
|
||||
? {
|
||||
firstName: valueOrFallback(cipher.driversLicense.decFirstName ?? cipher.driversLicense.firstName),
|
||||
middleName: valueOrFallback(cipher.driversLicense.decMiddleName ?? cipher.driversLicense.middleName),
|
||||
lastName: valueOrFallback(cipher.driversLicense.decLastName ?? cipher.driversLicense.lastName),
|
||||
dateOfBirth: valueOrFallback(cipher.driversLicense.decDateOfBirth ?? cipher.driversLicense.dateOfBirth),
|
||||
licenseNumber: valueOrFallback(cipher.driversLicense.decLicenseNumber ?? cipher.driversLicense.licenseNumber),
|
||||
issuingCountry: valueOrFallback(cipher.driversLicense.decIssuingCountry ?? cipher.driversLicense.issuingCountry),
|
||||
issuingState: valueOrFallback(cipher.driversLicense.decIssuingState ?? cipher.driversLicense.issuingState),
|
||||
issueDate: valueOrFallback(cipher.driversLicense.decIssueDate ?? cipher.driversLicense.issueDate),
|
||||
expirationDate: valueOrFallback(cipher.driversLicense.decExpirationDate ?? cipher.driversLicense.expirationDate),
|
||||
issuingAuthority: valueOrFallback(cipher.driversLicense.decIssuingAuthority ?? cipher.driversLicense.issuingAuthority),
|
||||
licenseClass: valueOrFallback(cipher.driversLicense.decLicenseClass ?? cipher.driversLicense.licenseClass),
|
||||
}
|
||||
: null,
|
||||
passport: cipher.passport
|
||||
? {
|
||||
surname: valueOrFallback(cipher.passport.decSurname ?? cipher.passport.surname),
|
||||
givenName: valueOrFallback(cipher.passport.decGivenName ?? cipher.passport.givenName),
|
||||
dateOfBirth: valueOrFallback(cipher.passport.decDateOfBirth ?? cipher.passport.dateOfBirth),
|
||||
sex: valueOrFallback(cipher.passport.decSex ?? cipher.passport.sex),
|
||||
birthPlace: valueOrFallback(cipher.passport.decBirthPlace ?? cipher.passport.birthPlace),
|
||||
nationality: valueOrFallback(cipher.passport.decNationality ?? cipher.passport.nationality),
|
||||
issuingCountry: valueOrFallback(cipher.passport.decIssuingCountry ?? cipher.passport.issuingCountry),
|
||||
passportNumber: valueOrFallback(cipher.passport.decPassportNumber ?? cipher.passport.passportNumber),
|
||||
passportType: valueOrFallback(cipher.passport.decPassportType ?? cipher.passport.passportType),
|
||||
nationalIdentificationNumber: valueOrFallback(cipher.passport.decNationalIdentificationNumber ?? cipher.passport.nationalIdentificationNumber),
|
||||
issuingAuthority: valueOrFallback(cipher.passport.decIssuingAuthority ?? cipher.passport.issuingAuthority),
|
||||
issueDate: valueOrFallback(cipher.passport.decIssueDate ?? cipher.passport.issueDate),
|
||||
expirationDate: valueOrFallback(cipher.passport.decExpirationDate ?? cipher.passport.expirationDate),
|
||||
}
|
||||
: null,
|
||||
secureNoteType: cipher.secureNote?.type ?? null,
|
||||
fields: (cipher.fields || []).map((field) => ({
|
||||
type: field.type ?? null,
|
||||
@@ -427,6 +515,40 @@ export function createEmptyDraft(type: number): VaultDraft {
|
||||
sshPrivateKey: '',
|
||||
sshPublicKey: '',
|
||||
sshFingerprint: '',
|
||||
bankName: '',
|
||||
bankNameOnAccount: '',
|
||||
bankAccountType: '',
|
||||
bankAccountNumber: '',
|
||||
bankRoutingNumber: '',
|
||||
bankBranchNumber: '',
|
||||
bankPin: '',
|
||||
bankSwiftCode: '',
|
||||
bankIban: '',
|
||||
bankContactPhone: '',
|
||||
licenseFirstName: '',
|
||||
licenseMiddleName: '',
|
||||
licenseLastName: '',
|
||||
licenseDateOfBirth: '',
|
||||
licenseNumber: '',
|
||||
licenseIssuingCountry: '',
|
||||
licenseIssuingState: '',
|
||||
licenseIssueDate: '',
|
||||
licenseExpirationDate: '',
|
||||
licenseIssuingAuthority: '',
|
||||
licenseClass: '',
|
||||
passportSurname: '',
|
||||
passportGivenName: '',
|
||||
passportDateOfBirth: '',
|
||||
passportSex: '',
|
||||
passportBirthPlace: '',
|
||||
passportNationality: '',
|
||||
passportIssuingCountry: '',
|
||||
passportNumber: '',
|
||||
passportType: '',
|
||||
passportNationalIdentificationNumber: '',
|
||||
passportIssuingAuthority: '',
|
||||
passportIssueDate: '',
|
||||
passportExpirationDate: '',
|
||||
customFields: [],
|
||||
};
|
||||
}
|
||||
@@ -490,6 +612,46 @@ export function draftFromCipher(cipher: Cipher): VaultDraft {
|
||||
draft.sshPublicKey = cipher.sshKey.decPublicKey || '';
|
||||
draft.sshFingerprint = cipher.sshKey.decFingerprint || '';
|
||||
}
|
||||
if (cipher.bankAccount) {
|
||||
draft.bankName = cipher.bankAccount.decBankName || '';
|
||||
draft.bankNameOnAccount = cipher.bankAccount.decNameOnAccount || '';
|
||||
draft.bankAccountType = cipher.bankAccount.decAccountType || '';
|
||||
draft.bankAccountNumber = cipher.bankAccount.decAccountNumber || '';
|
||||
draft.bankRoutingNumber = cipher.bankAccount.decRoutingNumber || '';
|
||||
draft.bankBranchNumber = cipher.bankAccount.decBranchNumber || '';
|
||||
draft.bankPin = cipher.bankAccount.decPin || '';
|
||||
draft.bankSwiftCode = cipher.bankAccount.decSwiftCode || '';
|
||||
draft.bankIban = cipher.bankAccount.decIban || '';
|
||||
draft.bankContactPhone = cipher.bankAccount.decBankContactPhone || '';
|
||||
}
|
||||
if (cipher.driversLicense) {
|
||||
draft.licenseFirstName = cipher.driversLicense.decFirstName || '';
|
||||
draft.licenseMiddleName = cipher.driversLicense.decMiddleName || '';
|
||||
draft.licenseLastName = cipher.driversLicense.decLastName || '';
|
||||
draft.licenseDateOfBirth = cipher.driversLicense.decDateOfBirth || '';
|
||||
draft.licenseNumber = cipher.driversLicense.decLicenseNumber || '';
|
||||
draft.licenseIssuingCountry = cipher.driversLicense.decIssuingCountry || '';
|
||||
draft.licenseIssuingState = cipher.driversLicense.decIssuingState || '';
|
||||
draft.licenseIssueDate = cipher.driversLicense.decIssueDate || '';
|
||||
draft.licenseExpirationDate = cipher.driversLicense.decExpirationDate || '';
|
||||
draft.licenseIssuingAuthority = cipher.driversLicense.decIssuingAuthority || '';
|
||||
draft.licenseClass = cipher.driversLicense.decLicenseClass || '';
|
||||
}
|
||||
if (cipher.passport) {
|
||||
draft.passportSurname = cipher.passport.decSurname || '';
|
||||
draft.passportGivenName = cipher.passport.decGivenName || '';
|
||||
draft.passportDateOfBirth = cipher.passport.decDateOfBirth || '';
|
||||
draft.passportSex = cipher.passport.decSex || '';
|
||||
draft.passportBirthPlace = cipher.passport.decBirthPlace || '';
|
||||
draft.passportNationality = cipher.passport.decNationality || '';
|
||||
draft.passportIssuingCountry = cipher.passport.decIssuingCountry || '';
|
||||
draft.passportNumber = cipher.passport.decPassportNumber || '';
|
||||
draft.passportType = cipher.passport.decPassportType || '';
|
||||
draft.passportNationalIdentificationNumber = cipher.passport.decNationalIdentificationNumber || '';
|
||||
draft.passportIssuingAuthority = cipher.passport.decIssuingAuthority || '';
|
||||
draft.passportIssueDate = cipher.passport.decIssueDate || '';
|
||||
draft.passportExpirationDate = cipher.passport.decExpirationDate || '';
|
||||
}
|
||||
draft.customFields = (cipher.fields || []).map((field) => ({
|
||||
type: parseFieldType(field.type),
|
||||
label: field.decName || '',
|
||||
|
||||
Reference in New Issue
Block a user