Skip to content

Commit

Permalink
Implement ssh-key cipher type
Browse files Browse the repository at this point in the history
  • Loading branch information
quexten committed Aug 21, 2024
1 parent cfdc52e commit 99f10b1
Show file tree
Hide file tree
Showing 43 changed files with 700 additions and 6 deletions.
27 changes: 27 additions & 0 deletions apps/browser/src/_locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,9 @@
"typeIdentity": {
"message": "Identity"
},
"typeSSHKey": {
"message": "SSH key"
},
"newItemHeader": {
"message": "New $TYPE$",
"placeholders": {
Expand Down Expand Up @@ -4210,5 +4213,29 @@
},
"enterprisePolicyRequirementsApplied": {
"message": "Enterprise policy requirements have been applied to this setting"
},
"sshPrivateKey": {
"message": "Private key"
},
"sshPublicKey": {
"message": "Public key"
},
"sshFingerprint": {
"message": "Fingerprint"
},
"sshKeyAlgorithm": {
"message": "Key type"
},
"sshKeyAlgorithmED25519": {
"message": "ED25519"
},
"sshKeyAlgorithmRSA2048": {
"message": "RSA 2048-Bit"
},
"sshKeyAlgorithmRSA3072": {
"message": "RSA 3072-Bit"
},
"sshKeyAlgorithmRSA4096": {
"message": "RSA 4096-Bit"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ export class AddEditV2Component implements OnInit {
return this.i18nService.t(partOne, this.i18nService.t("typeIdentity"));
case CipherType.SecureNote:
return this.i18nService.t(partOne, this.i18nService.t("note"));
case CipherType.SSHKey:
return this.i18nService.t(partOne, this.i18nService.t("typeSSHKey"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,27 @@
[cipher]="cipher"
></button>
</bit-item-action>

<bit-item-action *ngIf="cipher.type === CipherType.SSHKey">
<button
type="button"
bitIconButton="bwi-clone"
size="small"
[appA11yTitle]="
hasIdentityValues ? ('copyInfoTitle' | i18n: cipher.name) : ('noValuesToCopy' | i18n)
"
[disabled]="!hasIdentityValues"
[bitMenuTriggerFor]="identityOptions"
></button>
<bit-menu #identityOptions>
<button type="button" bitMenuItem appCopyField="privateKey" [cipher]="cipher">
{{ "copyPrivateKey" | i18n }}
</button>
<button type="button" bitMenuItem appCopyField="publicKey" [cipher]="cipher">
{{ "copyPublicKey" | i18n }}
</button>
<button type="button" bitMenuItem appCopyField="keyFingerprint" [cipher]="cipher">
{{ "copyFingerprint" | i18n }}
</button>
</bit-menu>
</bit-item-action>
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,13 @@ export class ItemCopyActionsComponent {
return !!this.cipher.notes;
}

get hasSSHKeyValues() {
return (
!!this.cipher.sshKey.privateKey ||
!!this.cipher.sshKey.publicKey ||
!!this.cipher.sshKey.keyFingerprint
);
}

constructor() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ export class ViewV2Component {
);
case CipherType.SecureNote:
return this.i18nService.t("viewItemHeader", this.i18nService.t("note").toLowerCase());
case CipherType.SSHKey:
return this.i18nService.t("viewItemHeader", this.i18nService.t("typeSSHkey").toLowerCase());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,14 @@ <h2 class="box-header">
/>
</div>
</div>

<!-- SSHKey -->
<div *ngIf="cipher.sshKey">
<div class="box-content-row" *ngIf="cipher.sshKey.privateKey" style="overflow: hidden">
<span class="row-label"> {{ "sshPrivateKey" | i18n }}</span>
{{ cipher.sshKey.privateKey }}
</div>
</div>
</div>
</div>
<div class="box" *ngIf="cipher.type === cipherType.Login">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,19 @@ <h2 class="box-header">
<span class="row-sub-label">{{ typeCounts.get(cipherType.SecureNote) || 0 }}</span>
<span><i class="bwi bwi-angle-right bwi-lg row-sub-icon"></i></span>
</button>
<button
type="button"
class="box-content-row"
appStopClick
(click)="selectType(cipherType.SSHKey)"
>
<div class="row-main">
<div class="icon"><i class="bwi bwi-fw bwi-lg bwi-key"></i></div>
<span class="text">{{ "typeSSHKey" | i18n }}</span>
</div>
<span class="row-sub-label">{{ typeCounts.get(cipherType.SSHKey) || 0 }}</span>
<span><i class="bwi bwi-angle-right bwi-lg row-sub-icon"></i></span>
</button>
</div>
</div>
<div class="box list" *ngIf="nestedFolders?.length">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ export class VaultItemsComponent extends BaseVaultItemsComponent implements OnIn
case CipherType.SecureNote:
this.groupingTitle = this.i18nService.t("secureNotes");
break;
case CipherType.SSHKey:
this.groupingTitle = this.i18nService.t("sshKeys");
break;
default:
break;
}
Expand Down
23 changes: 23 additions & 0 deletions apps/browser/src/vault/popup/components/vault/view.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,29 @@ <h2 class="box-header">
<div *ngIf="cipher.identity.country">{{ cipher.identity.country }}</div>
</div>
</div>
<!-- SSHKey -->
<div *ngIf="cipher.sshKey">
<div class="box-content-row" *ngIf="cipher.sshKey.publicKey" style="overflow: hidden">
<span
class="row-label draggable"
draggable="true"
(dragstart)="setTextDataOnDrag($event, cipher.sshKey.publicKey)"
>
{{ "sshPublicKey" | i18n }}</span
>
{{ cipher.sshKey.publicKey }}
</div>
<div class="box-content-row" *ngIf="cipher.sshKey.keyFingerprint" style="overflow: hidden">
<span
class="row-label draggable"
draggable="true"
(dragstart)="setTextDataOnDrag($event, cipher.sshKey.keyFingerprint)"
>
{{ "sshFingerprint" | i18n }}</span
>
{{ cipher.sshKey.keyFingerprint }}
</div>
</div>
</div>
</div>
<div class="box" *ngIf="cipher.login && cipher.login.hasUris">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ describe("VaultPopupItemsService", () => {
[CipherType.Card]: 2,
[CipherType.Identity]: 3,
[CipherType.SecureNote]: 4,
[CipherType.SSHKey]: 5,
};

// Assume all ciphers are autofill ciphers to test sorting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ export class VaultPopupItemsService {
[CipherType.Card]: 2,
[CipherType.Identity]: 3,
[CipherType.SecureNote]: 4,
[CipherType.SSHKey]: 5,
};

// Compare types first
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,11 @@ export class VaultPopupListFiltersService {
label: this.i18nService.t("note"),
icon: "bwi-sticky-note",
},
{
value: CipherType.SSHKey,
label: this.i18nService.t("typeSSHKey"),
icon: "bwi-key",
},
];

/** Resets `filterForm` to the original state */
Expand Down
27 changes: 27 additions & 0 deletions apps/desktop/src/locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
"typeSecureNote": {
"message": "Secure note"
},
"typeSSHKey": {
"message": "SSH key"
},
"folders": {
"message": "Folders"
},
Expand Down Expand Up @@ -174,6 +177,30 @@
"address": {
"message": "Address"
},
"sshPrivateKey": {
"message": "Private key"
},
"sshPublicKey": {
"message": "Public key"
},
"sshFingerprint": {
"message": "Fingerprint"
},
"sshKeyAlgorithm": {
"message": "Key type"
},
"sshKeyAlgorithmED25519": {
"message": "ED25519"
},
"sshKeyAlgorithmRSA2048": {
"message": "RSA 2048-Bit"
},
"sshKeyAlgorithmRSA3072": {
"message": "RSA 3072-Bit"
},
"sshKeyAlgorithmRSA4096": {
"message": "RSA 4096-Bit"
},
"premiumRequired": {
"message": "Premium required"
},
Expand Down
38 changes: 38 additions & 0 deletions apps/desktop/src/vault/app/vault/add-edit.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,44 @@ <h2 class="box-header">
/>
</div>
</div>
<!-- SSH Key -->
<div *ngIf="cipher.type === cipherType.SSHKey">
<div class="box-content-row box-content-row-flex" appBoxRow>
<div class="row-main">
<label for="sshPrivateKey">{{ "sshPrivateKey" | i18n }}</label>
<input
id="sshPublicKey"
type="{{ showPrivateKey ? 'text' : 'password' }}"
name="SSHKey.SSHPrivateKey"
[ngModel]="cipher.sshKey.privateKey"
readonly
/>
</div>
<div class="action-buttons">
<button
type="button"
class="row-btn"
appStopClick
(click)="copy(this.cipher.sshKey.privateKey, 'sshPrivateKey', 'SSHPrivateKey')"
>
<i class="bwi bwi-lg bwi-clone" aria-hidden="true"></i>
</button>
<button
type="button"
class="row-btn"
appStopClick
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
(click)="togglePrivateKey()"
>
<i
class="bwi bwi-lg"
aria-hidden="true"
[ngClass]="{ 'bwi-eye': !showPrivateKey, 'bwi-eye-slash': showPrivateKey }"
></i>
</button>
</div>
</div>
</div>
</div>
</div>
<div class="box" *ngIf="cipher.type === cipherType.Login">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ <h2>
aria-hidden="true"
[ngClass]="{
'bwi-angle-right': isCollapsed,
'bwi-angle-down': !isCollapsed,
'bwi-angle-down': !isCollapsed
}"
></i>
&nbsp;{{ typesNode.name | i18n }}
Expand Down Expand Up @@ -79,4 +79,19 @@ <h2>
</button>
</span>
</li>
<li
class="filter-option"
[ngClass]="{ active: activeFilter.cipherType === cipherTypeEnum.SSHKey }"
>
<span class="filter-buttons">
<button
type="button"
class="filter-button"
(click)="applyFilter(cipherTypeEnum.SSHKey)"
[attr.aria-pressed]="activeFilter.cipherType === cipherTypeEnum.SSHKey"
>
<i class="bwi bwi-fw bwi-key" aria-hidden="true"></i>&nbsp;{{ "typeSSHKey" | i18n }}
</button>
</span>
</li>
</ul>
15 changes: 15 additions & 0 deletions apps/desktop/src/vault/app/vault/view.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,21 @@ <h2 class="box-header">
<div *ngIf="cipher.identity.country">{{ cipher.identity.country }}</div>
</div>
</div>
<!-- SSH Key -->
<div *ngIf="cipher.card">
<div class="box-content-row" *ngIf="cipher.sshKey.privateKey">
<span class="row-label">{{ "sshPrivatekey" | i18n }}</span>
{{ cipher.sshKey.privateKey }}
</div>
<div class="box-content-row" *ngIf="cipher.sshKey.publicKey">
<span class="row-label">{{ "sshPublicKey" | i18n }}</span>
{{ cipher.sshKey.publicKey }}
</div>
<div class="box-content-row" *ngIf="cipher.sshKey.keyFingerprint">
<span class="row-label">{{ "sshKeyFingerprint" | i18n }}</span>
{{ cipher.sshKey.keyFingerprint }}
</div>
</div>
</div>
</div>
<div class="box" *ngIf="cipher.login && cipher.login.hasUris">
Expand Down
Loading

0 comments on commit 99f10b1

Please sign in to comment.