1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-07 20:24:01 +00:00
Files
browser/apps/web/src/app/tools/send/access.component.ts
Daniel James Smith 8d04731633 [PM-6568][PM-8820][Tech-Debt] Migrate all tools owned toasts to use CL ToastService instead of PlatformUtilsService (#9405)
* Migrate all tools owned toasts to use CL ToastService instead of PlatformUtilsService

* Fix test that was missing a mock

* Fix double checking file and file-content selection

---------

Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
2024-06-19 18:28:47 +02:00

168 lines
5.9 KiB
TypeScript

import { Component, OnInit } from "@angular/core";
import { FormBuilder } from "@angular/forms";
import { ActivatedRoute } from "@angular/router";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
import { SendAccess } from "@bitwarden/common/tools/send/models/domain/send-access";
import { SendAccessRequest } from "@bitwarden/common/tools/send/models/request/send-access.request";
import { SendAccessResponse } from "@bitwarden/common/tools/send/models/response/send-access.response";
import { SendAccessView } from "@bitwarden/common/tools/send/models/view/send-access.view";
import { SEND_KDF_ITERATIONS } from "@bitwarden/common/tools/send/send-kdf";
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
import { NoItemsModule, ToastService } from "@bitwarden/components";
import { SharedModule } from "../../shared";
import { ExpiredSend } from "./icons/expired-send.icon";
import { SendAccessFileComponent } from "./send-access-file.component";
import { SendAccessPasswordComponent } from "./send-access-password.component";
import { SendAccessTextComponent } from "./send-access-text.component";
@Component({
selector: "app-send-access",
templateUrl: "access.component.html",
standalone: true,
imports: [
SendAccessFileComponent,
SendAccessTextComponent,
SendAccessPasswordComponent,
SharedModule,
NoItemsModule,
],
})
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
export class AccessComponent implements OnInit {
protected send: SendAccessView;
protected sendType = SendType;
protected loading = true;
protected passwordRequired = false;
protected formPromise: Promise<SendAccessResponse>;
protected password: string;
protected unavailable = false;
protected error = false;
protected hideEmail = false;
protected decKey: SymmetricCryptoKey;
protected accessRequest: SendAccessRequest;
protected expiredSendIcon = ExpiredSend;
protected formGroup = this.formBuilder.group({});
// TODO: remove when email verification flag is removed
registerRoute = "/register";
private id: string;
private key: string;
constructor(
private cryptoFunctionService: CryptoFunctionService,
private route: ActivatedRoute,
private cryptoService: CryptoService,
private sendApiService: SendApiService,
private toastService: ToastService,
private i18nService: I18nService,
private configService: ConfigService,
protected formBuilder: FormBuilder,
) {}
protected get expirationDate() {
if (this.send == null || this.send.expirationDate == null) {
return null;
}
return this.send.expirationDate;
}
protected get creatorIdentifier() {
if (this.send == null || this.send.creatorIdentifier == null) {
return null;
}
return this.send.creatorIdentifier;
}
async ngOnInit() {
// TODO: remove when email verification flag is removed
const emailVerification = await this.configService.getFeatureFlag(
FeatureFlag.EmailVerification,
);
if (emailVerification) {
this.registerRoute = "/signup";
}
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
this.route.params.subscribe(async (params) => {
this.id = params.sendId;
this.key = params.key;
if (this.key == null || this.id == null) {
return;
}
await this.load();
});
}
protected load = async () => {
this.unavailable = false;
this.error = false;
this.hideEmail = false;
try {
const keyArray = Utils.fromUrlB64ToArray(this.key);
this.accessRequest = new SendAccessRequest();
if (this.password != null) {
const passwordHash = await this.cryptoFunctionService.pbkdf2(
this.password,
keyArray,
"sha256",
SEND_KDF_ITERATIONS,
);
this.accessRequest.password = Utils.fromBufferToB64(passwordHash);
}
let sendResponse: SendAccessResponse = null;
if (this.loading) {
sendResponse = await this.sendApiService.postSendAccess(this.id, this.accessRequest);
} else {
this.formPromise = this.sendApiService.postSendAccess(this.id, this.accessRequest);
sendResponse = await this.formPromise;
}
this.passwordRequired = false;
const sendAccess = new SendAccess(sendResponse);
this.decKey = await this.cryptoService.makeSendKey(keyArray);
this.send = await sendAccess.decrypt(this.decKey);
} catch (e) {
if (e instanceof ErrorResponse) {
if (e.statusCode === 401) {
this.passwordRequired = true;
} else if (e.statusCode === 404) {
this.unavailable = true;
} else if (e.statusCode === 400) {
this.toastService.showToast({
variant: "error",
title: this.i18nService.t("errorOccurred"),
message: e.message,
});
} else {
this.error = true;
}
} else {
this.error = true;
}
}
this.loading = false;
this.hideEmail =
this.creatorIdentifier == null &&
!this.passwordRequired &&
!this.loading &&
!this.unavailable;
};
protected setPassword(password: string) {
this.password = password;
}
}