[PM-9809] attachments v2 refactor (#10142)
* update attachments v2 view. using download attachment component. remove excess code. Refactor location of attachments v2
This commit is contained in:
parent
decc7a3031
commit
6041c460b7
|
@ -12,12 +12,12 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { ButtonComponent } from "@bitwarden/components";
|
import { ButtonComponent } from "@bitwarden/components";
|
||||||
|
import { CipherAttachmentsComponent } from "@bitwarden/vault";
|
||||||
|
|
||||||
import { PopupFooterComponent } from "../../../../../platform/popup/layout/popup-footer.component";
|
import { PopupFooterComponent } from "../../../../../platform/popup/layout/popup-footer.component";
|
||||||
import { PopupHeaderComponent } from "../../../../../platform/popup/layout/popup-header.component";
|
import { PopupHeaderComponent } from "../../../../../platform/popup/layout/popup-header.component";
|
||||||
|
|
||||||
import { AttachmentsV2Component } from "./attachments-v2.component";
|
import { AttachmentsV2Component } from "./attachments-v2.component";
|
||||||
import { CipherAttachmentsComponent } from "./cipher-attachments/cipher-attachments.component";
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
standalone: true,
|
standalone: true,
|
||||||
|
|
|
@ -8,14 +8,13 @@ import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { CipherId } from "@bitwarden/common/types/guid";
|
import { CipherId } from "@bitwarden/common/types/guid";
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { ButtonModule } from "@bitwarden/components";
|
import { ButtonModule } from "@bitwarden/components";
|
||||||
|
import { CipherAttachmentsComponent } from "@bitwarden/vault";
|
||||||
|
|
||||||
import { PopOutComponent } from "../../../../../platform/popup/components/pop-out.component";
|
import { PopOutComponent } from "../../../../../platform/popup/components/pop-out.component";
|
||||||
import { PopupFooterComponent } from "../../../../../platform/popup/layout/popup-footer.component";
|
import { PopupFooterComponent } from "../../../../../platform/popup/layout/popup-footer.component";
|
||||||
import { PopupHeaderComponent } from "../../../../../platform/popup/layout/popup-header.component";
|
import { PopupHeaderComponent } from "../../../../../platform/popup/layout/popup-header.component";
|
||||||
import { PopupPageComponent } from "../../../../../platform/popup/layout/popup-page.component";
|
import { PopupPageComponent } from "../../../../../platform/popup/layout/popup-page.component";
|
||||||
|
|
||||||
import { CipherAttachmentsComponent } from "./cipher-attachments/cipher-attachments.component";
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
standalone: true,
|
standalone: true,
|
||||||
selector: "app-attachments-v2",
|
selector: "app-attachments-v2",
|
||||||
|
|
|
@ -13,10 +13,10 @@ import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view";
|
import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
import { ButtonComponent, ToastService } from "@bitwarden/components";
|
import { ButtonComponent, ToastService } from "@bitwarden/components";
|
||||||
|
import { DownloadAttachmentComponent } from "@bitwarden/vault";
|
||||||
|
|
||||||
import { CipherAttachmentsComponent } from "./cipher-attachments.component";
|
import { CipherAttachmentsComponent } from "./cipher-attachments.component";
|
||||||
import { DeleteAttachmentComponent } from "./delete-attachment/delete-attachment.component";
|
import { DeleteAttachmentComponent } from "./delete-attachment/delete-attachment.component";
|
||||||
import { DownloadAttachmentComponent } from "./download-attachment/download-attachment.component";
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
standalone: true,
|
standalone: true,
|
|
@ -39,8 +39,9 @@ import {
|
||||||
TypographyModule,
|
TypographyModule,
|
||||||
} from "@bitwarden/components";
|
} from "@bitwarden/components";
|
||||||
|
|
||||||
|
import { DownloadAttachmentComponent } from "../../../components/download-attachment/download-attachment.component";
|
||||||
|
|
||||||
import { DeleteAttachmentComponent } from "./delete-attachment/delete-attachment.component";
|
import { DeleteAttachmentComponent } from "./delete-attachment/delete-attachment.component";
|
||||||
import { DownloadAttachmentComponent } from "./download-attachment/download-attachment.component";
|
|
||||||
|
|
||||||
type CipherAttachmentForm = FormGroup<{
|
type CipherAttachmentForm = FormGroup<{
|
||||||
file: FormControl<File | null>;
|
file: FormControl<File | null>;
|
|
@ -0,0 +1,22 @@
|
||||||
|
<bit-section>
|
||||||
|
<bit-section-header>
|
||||||
|
<h2 bitTypography="h6">{{ "attachments" | i18n }}</h2>
|
||||||
|
</bit-section-header>
|
||||||
|
<bit-item-group>
|
||||||
|
<bit-item *ngFor="let attachment of cipher.attachments">
|
||||||
|
<bit-item-content>
|
||||||
|
<span data-testid="file-name">{{ attachment.fileName }}</span>
|
||||||
|
<span slot="secondary" data-testid="file-size">{{ attachment.sizeName }}</span>
|
||||||
|
</bit-item-content>
|
||||||
|
<ng-container slot="end">
|
||||||
|
<bit-item-action>
|
||||||
|
<app-download-attachment
|
||||||
|
[cipher]="cipher"
|
||||||
|
[attachment]="attachment"
|
||||||
|
[checkPwReprompt]="true"
|
||||||
|
></app-download-attachment>
|
||||||
|
</bit-item-action>
|
||||||
|
</ng-container>
|
||||||
|
</bit-item>
|
||||||
|
</bit-item-group>
|
||||||
|
</bit-section>
|
|
@ -0,0 +1,73 @@
|
||||||
|
import { CommonModule } from "@angular/common";
|
||||||
|
import { Component, Input } from "@angular/core";
|
||||||
|
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||||
|
import { NEVER, switchMap } from "rxjs";
|
||||||
|
|
||||||
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
|
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions";
|
||||||
|
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||||
|
import { StateProvider } from "@bitwarden/common/platform/state";
|
||||||
|
import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||||
|
import { OrgKey } from "@bitwarden/common/types/key";
|
||||||
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
|
import {
|
||||||
|
ItemModule,
|
||||||
|
IconButtonModule,
|
||||||
|
SectionComponent,
|
||||||
|
SectionHeaderComponent,
|
||||||
|
TypographyModule,
|
||||||
|
} from "@bitwarden/components";
|
||||||
|
|
||||||
|
import { DownloadAttachmentComponent } from "../../components/download-attachment/download-attachment.component";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: "app-attachments-v2-view",
|
||||||
|
templateUrl: "attachments-v2-view.component.html",
|
||||||
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
JslibModule,
|
||||||
|
ItemModule,
|
||||||
|
IconButtonModule,
|
||||||
|
SectionComponent,
|
||||||
|
SectionHeaderComponent,
|
||||||
|
TypographyModule,
|
||||||
|
DownloadAttachmentComponent,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class AttachmentsV2ViewComponent {
|
||||||
|
@Input() cipher: CipherView;
|
||||||
|
|
||||||
|
canAccessPremium: boolean;
|
||||||
|
orgKey: OrgKey;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private cryptoService: CryptoService,
|
||||||
|
private billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||||
|
private stateProvider: StateProvider,
|
||||||
|
) {
|
||||||
|
this.subscribeToHasPremiumCheck();
|
||||||
|
this.subscribeToOrgKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeToHasPremiumCheck() {
|
||||||
|
this.billingAccountProfileStateService.hasPremiumFromAnySource$
|
||||||
|
.pipe(takeUntilDestroyed())
|
||||||
|
.subscribe((data) => {
|
||||||
|
this.canAccessPremium = data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeToOrgKey() {
|
||||||
|
this.stateProvider.activeUserId$
|
||||||
|
.pipe(
|
||||||
|
switchMap((userId) => (userId != null ? this.cryptoService.orgKeys$(userId) : NEVER)),
|
||||||
|
takeUntilDestroyed(),
|
||||||
|
)
|
||||||
|
.subscribe((data: Record<OrganizationId, OrgKey> | null) => {
|
||||||
|
if (data) {
|
||||||
|
this.orgKey = data[this.cipher.organizationId as OrganizationId];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,32 +0,0 @@
|
||||||
<bit-section>
|
|
||||||
<bit-section-header>
|
|
||||||
<h2 bitTypography="h6">{{ "attachments" | i18n }}</h2>
|
|
||||||
</bit-section-header>
|
|
||||||
<bit-item-group>
|
|
||||||
<bit-item *ngFor="let attachment of cipher.attachments">
|
|
||||||
<div slot="start" class="tw-py-4 tw-px-3">
|
|
||||||
<h3>
|
|
||||||
{{ attachment.fileName }}
|
|
||||||
</h3>
|
|
||||||
<div class="tw-mb-1 tw-text-xs tw-text-muted tw-select-none">
|
|
||||||
{{ attachment.sizeName }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="tw-flex tw-items-center" (click)="downloadAttachment(attachment)" slot="end">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
bitIconButton="bwi-download"
|
|
||||||
size="small"
|
|
||||||
[appA11yTitle]="'downloadAttachment' | i18n: attachment.fileName"
|
|
||||||
*ngIf="!$any(attachment).downloading"
|
|
||||||
></button>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
bitIconButton="bwi-spinner bwi-spin"
|
|
||||||
size="small"
|
|
||||||
*ngIf="$any(attachment).downloading"
|
|
||||||
></button>
|
|
||||||
</div>
|
|
||||||
</bit-item>
|
|
||||||
</bit-item-group>
|
|
||||||
</bit-section>
|
|
|
@ -1,155 +0,0 @@
|
||||||
import { CommonModule } from "@angular/common";
|
|
||||||
import { Component, Input } from "@angular/core";
|
|
||||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
|
||||||
import { NEVER, switchMap } from "rxjs";
|
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
||||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions";
|
|
||||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
|
||||||
import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service";
|
|
||||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
||||||
import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer";
|
|
||||||
import { StateProvider } from "@bitwarden/common/platform/state";
|
|
||||||
import { OrganizationId } from "@bitwarden/common/types/guid";
|
|
||||||
import { OrgKey } from "@bitwarden/common/types/key";
|
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
|
||||||
import {
|
|
||||||
ToastService,
|
|
||||||
ItemModule,
|
|
||||||
IconButtonModule,
|
|
||||||
SectionComponent,
|
|
||||||
SectionHeaderComponent,
|
|
||||||
TypographyModule,
|
|
||||||
} from "@bitwarden/components";
|
|
||||||
import { PasswordRepromptService } from "@bitwarden/vault";
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: "app-attachments-v2",
|
|
||||||
templateUrl: "attachments-v2.component.html",
|
|
||||||
standalone: true,
|
|
||||||
imports: [
|
|
||||||
CommonModule,
|
|
||||||
JslibModule,
|
|
||||||
ItemModule,
|
|
||||||
IconButtonModule,
|
|
||||||
SectionComponent,
|
|
||||||
SectionHeaderComponent,
|
|
||||||
TypographyModule,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
export class AttachmentsV2Component {
|
|
||||||
@Input() cipher: CipherView;
|
|
||||||
|
|
||||||
canAccessPremium: boolean;
|
|
||||||
orgKey: OrgKey;
|
|
||||||
private passwordReprompted = false;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private passwordRepromptService: PasswordRepromptService,
|
|
||||||
private i18nService: I18nService,
|
|
||||||
private apiService: ApiService,
|
|
||||||
private fileDownloadService: FileDownloadService,
|
|
||||||
private cryptoService: CryptoService,
|
|
||||||
private billingAccountProfileStateService: BillingAccountProfileStateService,
|
|
||||||
private toastService: ToastService,
|
|
||||||
private stateProvider: StateProvider,
|
|
||||||
private encryptService: EncryptService,
|
|
||||||
) {
|
|
||||||
this.subscribeToHasPremiumCheck();
|
|
||||||
this.subscribeToOrgKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
subscribeToHasPremiumCheck() {
|
|
||||||
this.billingAccountProfileStateService.hasPremiumFromAnySource$
|
|
||||||
.pipe(takeUntilDestroyed())
|
|
||||||
.subscribe((data) => {
|
|
||||||
this.canAccessPremium = data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
subscribeToOrgKey() {
|
|
||||||
this.stateProvider.activeUserId$
|
|
||||||
.pipe(
|
|
||||||
switchMap((userId) => (userId != null ? this.cryptoService.orgKeys$(userId) : NEVER)),
|
|
||||||
takeUntilDestroyed(),
|
|
||||||
)
|
|
||||||
.subscribe((data: Record<OrganizationId, OrgKey> | null) => {
|
|
||||||
if (data) {
|
|
||||||
this.orgKey = data[this.cipher.organizationId as OrganizationId];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async downloadAttachment(attachment: any) {
|
|
||||||
this.passwordReprompted =
|
|
||||||
this.passwordReprompted ||
|
|
||||||
(await this.passwordRepromptService.passwordRepromptCheck(this.cipher));
|
|
||||||
if (!this.passwordReprompted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const file = attachment as any;
|
|
||||||
|
|
||||||
if (file.downloading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.cipher.organizationId == null && !this.canAccessPremium) {
|
|
||||||
this.toastService.showToast({
|
|
||||||
variant: "error",
|
|
||||||
title: this.i18nService.t("premiumRequired"),
|
|
||||||
message: this.i18nService.t("premiumRequiredDesc"),
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let url: string;
|
|
||||||
try {
|
|
||||||
const attachmentDownloadResponse = await this.apiService.getAttachmentData(
|
|
||||||
this.cipher.id,
|
|
||||||
attachment.id,
|
|
||||||
);
|
|
||||||
url = attachmentDownloadResponse.url;
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof ErrorResponse && (e as ErrorResponse).statusCode === 404) {
|
|
||||||
url = attachment.url;
|
|
||||||
} else if (e instanceof ErrorResponse) {
|
|
||||||
throw new Error((e as ErrorResponse).getSingleMessage());
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file.downloading = true;
|
|
||||||
const response = await fetch(new Request(url, { cache: "no-store" }));
|
|
||||||
if (response.status !== 200) {
|
|
||||||
this.toastService.showToast({
|
|
||||||
variant: "error",
|
|
||||||
title: null,
|
|
||||||
message: this.i18nService.t("errorOccurred"),
|
|
||||||
});
|
|
||||||
file.downloading = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const encBuf = await EncArrayBuffer.fromResponse(response);
|
|
||||||
const key = attachment.key != null ? attachment.key : this.orgKey;
|
|
||||||
const decBuf = await this.encryptService.decryptToBytes(encBuf, key);
|
|
||||||
this.fileDownloadService.download({
|
|
||||||
fileName: attachment.fileName,
|
|
||||||
blobData: decBuf,
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
this.toastService.showToast({
|
|
||||||
variant: "error",
|
|
||||||
title: null,
|
|
||||||
message: this.i18nService.t("errorOccurred"),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
file.downloading = false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
<!-- ATTACHMENTS SECTION -->
|
<!-- ATTACHMENTS SECTION -->
|
||||||
<ng-container *ngIf="cipher.attachments">
|
<ng-container *ngIf="cipher.attachments">
|
||||||
<app-attachments-v2 [cipher]="cipher"> </app-attachments-v2>
|
<app-attachments-v2-view [cipher]="cipher"> </app-attachments-v2-view>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- ITEM HISTORY SECTION -->
|
<!-- ITEM HISTORY SECTION -->
|
||||||
|
|
|
@ -18,7 +18,7 @@ import { PopupHeaderComponent } from "../../../../apps/browser/src/platform/popu
|
||||||
import { PopupPageComponent } from "../../../../apps/browser/src/platform/popup/layout/popup-page.component";
|
import { PopupPageComponent } from "../../../../apps/browser/src/platform/popup/layout/popup-page.component";
|
||||||
|
|
||||||
import { AdditionalInformationComponent } from "./additional-information/additional-information.component";
|
import { AdditionalInformationComponent } from "./additional-information/additional-information.component";
|
||||||
import { AttachmentsV2Component } from "./attachments/attachments-v2.component";
|
import { AttachmentsV2ViewComponent } from "./attachments/attachments-v2-view.component";
|
||||||
import { CustomFieldV2Component } from "./custom-fields/custom-fields-v2.component";
|
import { CustomFieldV2Component } from "./custom-fields/custom-fields-v2.component";
|
||||||
import { ItemDetailsV2Component } from "./item-details/item-details-v2.component";
|
import { ItemDetailsV2Component } from "./item-details/item-details-v2.component";
|
||||||
import { ItemHistoryV2Component } from "./item-history/item-history-v2.component";
|
import { ItemHistoryV2Component } from "./item-history/item-history-v2.component";
|
||||||
|
@ -36,7 +36,7 @@ import { ItemHistoryV2Component } from "./item-history/item-history-v2.component
|
||||||
PopupFooterComponent,
|
PopupFooterComponent,
|
||||||
ItemDetailsV2Component,
|
ItemDetailsV2Component,
|
||||||
AdditionalInformationComponent,
|
AdditionalInformationComponent,
|
||||||
AttachmentsV2Component,
|
AttachmentsV2ViewComponent,
|
||||||
ItemHistoryV2Component,
|
ItemHistoryV2Component,
|
||||||
CustomFieldV2Component,
|
CustomFieldV2Component,
|
||||||
],
|
],
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
export * from "./cipher-view.component";
|
export * from "./cipher-view.component";
|
||||||
|
export { CipherAttachmentsComponent } from "../cipher-form/components/attachments/cipher-attachments.component";
|
||||||
|
|
|
@ -14,8 +14,9 @@ import { StateProvider } from "@bitwarden/common/platform/state";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||||
import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view";
|
import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.view";
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
|
import { ToastService } from "@bitwarden/components";
|
||||||
|
|
||||||
import { ToastService } from "../../../../../../../../../../libs/components/src/toast";
|
import { PasswordRepromptService } from "../../services/password-reprompt.service";
|
||||||
|
|
||||||
import { DownloadAttachmentComponent } from "./download-attachment.component";
|
import { DownloadAttachmentComponent } from "./download-attachment.component";
|
||||||
|
|
||||||
|
@ -65,6 +66,7 @@ describe("DownloadAttachmentComponent", () => {
|
||||||
{ provide: ToastService, useValue: { showToast } },
|
{ provide: ToastService, useValue: { showToast } },
|
||||||
{ provide: ApiService, useValue: { getAttachmentData } },
|
{ provide: ApiService, useValue: { getAttachmentData } },
|
||||||
{ provide: FileDownloadService, useValue: { download } },
|
{ provide: FileDownloadService, useValue: { download } },
|
||||||
|
{ provide: PasswordRepromptService, useValue: mock<PasswordRepromptService>() },
|
||||||
],
|
],
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
});
|
});
|
|
@ -18,6 +18,8 @@ import { AttachmentView } from "@bitwarden/common/vault/models/view/attachment.v
|
||||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||||
import { AsyncActionsModule, IconButtonModule, ToastService } from "@bitwarden/components";
|
import { AsyncActionsModule, IconButtonModule, ToastService } from "@bitwarden/components";
|
||||||
|
|
||||||
|
import { PasswordRepromptService } from "../../services/password-reprompt.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
standalone: true,
|
standalone: true,
|
||||||
selector: "app-download-attachment",
|
selector: "app-download-attachment",
|
||||||
|
@ -31,9 +33,14 @@ export class DownloadAttachmentComponent {
|
||||||
/** The cipher associated with the attachment */
|
/** The cipher associated with the attachment */
|
||||||
@Input({ required: true }) cipher: CipherView;
|
@Input({ required: true }) cipher: CipherView;
|
||||||
|
|
||||||
|
// When in view mode, we will want to check for the master password reprompt
|
||||||
|
@Input() checkPwReprompt?: boolean = false;
|
||||||
|
|
||||||
/** The organization key if the cipher is associated with one */
|
/** The organization key if the cipher is associated with one */
|
||||||
private orgKey: OrgKey | null = null;
|
private orgKey: OrgKey | null = null;
|
||||||
|
|
||||||
|
private passwordReprompted = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private apiService: ApiService,
|
private apiService: ApiService,
|
||||||
|
@ -42,6 +49,7 @@ export class DownloadAttachmentComponent {
|
||||||
private encryptService: EncryptService,
|
private encryptService: EncryptService,
|
||||||
private stateProvider: StateProvider,
|
private stateProvider: StateProvider,
|
||||||
private cryptoService: CryptoService,
|
private cryptoService: CryptoService,
|
||||||
|
private passwordRepromptService: PasswordRepromptService,
|
||||||
) {
|
) {
|
||||||
this.stateProvider.activeUserId$
|
this.stateProvider.activeUserId$
|
||||||
.pipe(
|
.pipe(
|
||||||
|
@ -57,6 +65,15 @@ export class DownloadAttachmentComponent {
|
||||||
|
|
||||||
/** Download the attachment */
|
/** Download the attachment */
|
||||||
download = async () => {
|
download = async () => {
|
||||||
|
if (this.checkPwReprompt) {
|
||||||
|
this.passwordReprompted =
|
||||||
|
this.passwordReprompted ||
|
||||||
|
(await this.passwordRepromptService.passwordRepromptCheck(this.cipher));
|
||||||
|
if (!this.passwordReprompted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let url: string;
|
let url: string;
|
||||||
|
|
||||||
try {
|
try {
|
|
@ -9,3 +9,5 @@ export {
|
||||||
CollectionAssignmentParams,
|
CollectionAssignmentParams,
|
||||||
CollectionAssignmentResult,
|
CollectionAssignmentResult,
|
||||||
} from "./components/assign-collections.component";
|
} from "./components/assign-collections.component";
|
||||||
|
|
||||||
|
export { DownloadAttachmentComponent } from "./components/download-attachment/download-attachment.component";
|
||||||
|
|
Loading…
Reference in New Issue