diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index 1443dfc81b4..d7cae01336d 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -3772,7 +3772,7 @@ "message": "Devices" }, "triggerTunnelDemo": { - "message": "Trigger tunnel demo" + "message": "Trigger tunnel demo ⚠️" }, "accessAttemptBy": { "message": "Access attempt by $EMAIL$", @@ -4757,6 +4757,9 @@ "demoSettings": { "message": "Demo settings" }, + "demoRetrieve": { + "message": "Fetch" + }, "notifications": { "message": "Notifications" }, diff --git a/apps/browser/src/tools/popup/settings/tunnel-demo.component.html b/apps/browser/src/tools/popup/settings/tunnel-demo.component.html index 0c22edec007..356ea88c950 100644 --- a/apps/browser/src/tools/popup/settings/tunnel-demo.component.html +++ b/apps/browser/src/tools/popup/settings/tunnel-demo.component.html @@ -5,7 +5,21 @@ -
-

Credential Tunnel Demo triggered

-
+ + +

{{ "retrieveCredentials" | i18n }}

+
+ +
+ + {{ "vaultItemName" | i18n }} + + Enter the name of the vault item to retrieve credentials from. + + +
+
+
diff --git a/apps/browser/src/tools/popup/settings/tunnel-demo.component.ts b/apps/browser/src/tools/popup/settings/tunnel-demo.component.ts index 4024960c3d3..507b8b631eb 100644 --- a/apps/browser/src/tools/popup/settings/tunnel-demo.component.ts +++ b/apps/browser/src/tools/popup/settings/tunnel-demo.component.ts @@ -1,6 +1,23 @@ -import { Component, OnInit } from "@angular/core"; +import { CommonModule } from "@angular/common"; +import { Component } from "@angular/core"; +import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms"; +import { firstValueFrom } from "rxjs"; -import { DialogService } from "@bitwarden/components"; +import { JslibModule } from "@bitwarden/angular/jslib.module"; +import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; +import { getUserId } from "@bitwarden/common/auth/services/account.service"; +import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; +import { CipherType } from "@bitwarden/common/vault/enums"; +import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; +import { + ButtonModule, + CardComponent, + DialogService, + FormFieldModule, + SectionComponent, + SectionHeaderComponent, + TypographyModule, +} from "@bitwarden/components"; import { PopOutComponent } from "../../../platform/popup/components/pop-out.component"; import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component"; @@ -12,19 +29,76 @@ import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.co standalone: true, selector: "tunnel-demo", templateUrl: "tunnel-demo.component.html", - imports: [PopOutComponent, PopupHeaderComponent, PopupPageComponent], + imports: [ + CommonModule, + PopOutComponent, + PopupHeaderComponent, + PopupPageComponent, + CardComponent, + SectionComponent, + SectionHeaderComponent, + FormFieldModule, + ButtonModule, + ReactiveFormsModule, + TypographyModule, + JslibModule, + ], }) -export class TunnelDemoComponent implements OnInit { - constructor(private dialogService: DialogService) {} +export class TunnelDemoComponent { + protected formGroup = this.formBuilder.group({ + vaultItemName: ["", Validators.required], + }); - async ngOnInit() { - await this.showDemoModal(); - } + constructor( + private dialogService: DialogService, + private cipherService: CipherService, + private accountService: AccountService, + private formBuilder: FormBuilder, + ) {} + + async submit() { + if (this.formGroup.invalid) { + return; + } + + const vaultItemName = this.formGroup.value.vaultItemName?.trim(); + + if (!vaultItemName) { + await this.dialogService.openSimpleDialog({ + title: "Tunnel Demo", + content: "No vault item name provided.", + type: "warning", + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + }); + return; + } + + const userId = await firstValueFrom(this.accountService.activeAccount$.pipe(getUserId)); + const allCiphers = await this.cipherService.getAllDecrypted(userId); + + // Find the cipher with the user-provided name + const tunnelDemoCipher = allCiphers.find( + (cipher: CipherView) => cipher.name === vaultItemName && cipher.type === CipherType.Login, + ); + + if (!tunnelDemoCipher || !tunnelDemoCipher.login) { + await this.dialogService.openSimpleDialog({ + title: "Tunnel Demo", + content: `No vault entry found with the name "${vaultItemName}". Please create one with a username and password.`, + type: "warning", + acceptButtonText: { key: "ok" }, + cancelButtonText: null, + }); + return; + } + + const username = tunnelDemoCipher.login.username || "(none)"; + const password = tunnelDemoCipher.login.password || "(none)"; - async showDemoModal() { await this.dialogService.openSimpleDialog({ - title: { key: "tunnelDemoTitle" }, - content: { key: "tunnelDemoContent" }, + title: "Tunnel Demo - Credentials Retrieved", + content: `Username: ${username}\nPassword: ${password}`, type: "info", acceptButtonText: { key: "ok" }, cancelButtonText: null,