mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 21:33:27 +00:00
[PM-21041] Fix cipher view security tasks fetching (#14569)
* [PM-21041] Add taskEnabled$ dependency to tasks$ observable * [PM-21041] Rework cipher view component to only check tasks for organization Login type ciphers - Remove dependency on feature flag check (handled by tasks$ observable now) - Add try/catch in case of request failures to avoid breaking component initialization * [PM-21041] Remove now redundant taskEnabled$ chain * [PM-21041] Fix tests
This commit is contained in:
@@ -3,19 +3,18 @@
|
||||
{{ "cardExpiredMessage" | i18n }}
|
||||
</bit-callout>
|
||||
|
||||
<ng-container *ngIf="isSecurityTasksEnabled$ | async">
|
||||
<bit-callout
|
||||
*ngIf="cipher?.login.uris.length > 0 && hadPendingChangePasswordTask"
|
||||
type="warning"
|
||||
[title]="''"
|
||||
>
|
||||
<i class="bwi bwi-exclamation-triangle tw-text-warning" aria-hidden="true"></i>
|
||||
<a bitLink href="#" appStopClick (click)="launchChangePassword()">
|
||||
{{ "changeAtRiskPassword" | i18n }}
|
||||
<i class="bwi bwi-external-link tw-ml-1" aria-hidden="true"></i>
|
||||
</a>
|
||||
</bit-callout>
|
||||
</ng-container>
|
||||
<bit-callout
|
||||
*ngIf="cipher?.login.uris.length > 0 && hadPendingChangePasswordTask"
|
||||
type="warning"
|
||||
[title]="''"
|
||||
>
|
||||
<i class="bwi bwi-exclamation-triangle tw-text-warning" aria-hidden="true"></i>
|
||||
<a bitLink href="#" appStopClick (click)="launchChangePassword()">
|
||||
{{ "changeAtRiskPassword" | i18n }}
|
||||
<i class="bwi bwi-external-link tw-ml-1" aria-hidden="true"></i>
|
||||
</a>
|
||||
</bit-callout>
|
||||
|
||||
<!-- HELPER TEXT -->
|
||||
<p
|
||||
class="tw-text-sm tw-text-muted"
|
||||
@@ -40,9 +39,7 @@
|
||||
*ngIf="hasLogin"
|
||||
[cipher]="cipher"
|
||||
[activeUserId]="activeUserId$ | async"
|
||||
[hadPendingChangePasswordTask]="
|
||||
hadPendingChangePasswordTask && (isSecurityTasksEnabled$ | async)
|
||||
"
|
||||
[hadPendingChangePasswordTask]="hadPendingChangePasswordTask"
|
||||
(handleChangePassword)="launchChangePassword()"
|
||||
></app-login-credentials-view>
|
||||
|
||||
|
||||
@@ -12,12 +12,12 @@ import { Organization } from "@bitwarden/common/admin-console/models/domain/orga
|
||||
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
|
||||
import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { isCardExpired } from "@bitwarden/common/autofill/utils";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { CipherId, CollectionId, EmergencyAccessId, UserId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
||||
import { SecurityTaskType, TaskService } from "@bitwarden/common/vault/tasks";
|
||||
@@ -80,7 +80,6 @@ export class CipherViewComponent implements OnChanges, OnDestroy {
|
||||
private destroyed$: Subject<void> = new Subject();
|
||||
cardIsExpired: boolean = false;
|
||||
hadPendingChangePasswordTask: boolean = false;
|
||||
isSecurityTasksEnabled$ = this.configService.getFeatureFlag$(FeatureFlag.SecurityTasks);
|
||||
|
||||
constructor(
|
||||
private organizationService: OrganizationService,
|
||||
@@ -90,8 +89,8 @@ export class CipherViewComponent implements OnChanges, OnDestroy {
|
||||
private defaultTaskService: TaskService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private changeLoginPasswordService: ChangeLoginPasswordService,
|
||||
private configService: ConfigService,
|
||||
private cipherService: CipherService,
|
||||
private logService: LogService,
|
||||
) {}
|
||||
|
||||
async ngOnChanges() {
|
||||
@@ -158,20 +157,15 @@ export class CipherViewComponent implements OnChanges, OnDestroy {
|
||||
|
||||
const userId = await firstValueFrom(this.activeUserId$);
|
||||
|
||||
// Show Tasks for Manage and Edit permissions
|
||||
// Using cipherService to see if user has access to cipher in a non-AC context to address with Edit Except Password permissions
|
||||
const allCiphers = await firstValueFrom(this.cipherService.ciphers$(userId));
|
||||
const cipherServiceCipher = allCiphers[this.cipher?.id as CipherId];
|
||||
|
||||
if (cipherServiceCipher?.edit && cipherServiceCipher?.viewPassword) {
|
||||
await this.checkPendingChangePasswordTasks(userId);
|
||||
}
|
||||
|
||||
if (this.cipher.organizationId && userId) {
|
||||
if (this.cipher.organizationId) {
|
||||
this.organization$ = this.organizationService
|
||||
.organizations$(userId)
|
||||
.pipe(getOrganizationById(this.cipher.organizationId))
|
||||
.pipe(takeUntil(this.destroyed$));
|
||||
|
||||
if (this.cipher.type === CipherType.Login) {
|
||||
await this.checkPendingChangePasswordTasks(userId);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.cipher.folderId) {
|
||||
@@ -182,17 +176,28 @@ export class CipherViewComponent implements OnChanges, OnDestroy {
|
||||
}
|
||||
|
||||
async checkPendingChangePasswordTasks(userId: UserId): Promise<void> {
|
||||
if (!(await firstValueFrom(this.isSecurityTasksEnabled$))) {
|
||||
return;
|
||||
try {
|
||||
// Show Tasks for Manage and Edit permissions
|
||||
// Using cipherService to see if user has access to cipher in a non-AC context to address with Edit Except Password permissions
|
||||
const allCiphers = await firstValueFrom(this.cipherService.ciphers$(userId));
|
||||
const cipherServiceCipher = allCiphers[this.cipher?.id as CipherId];
|
||||
|
||||
if (!cipherServiceCipher?.edit || !cipherServiceCipher?.viewPassword) {
|
||||
this.hadPendingChangePasswordTask = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const tasks = await firstValueFrom(this.defaultTaskService.pendingTasks$(userId));
|
||||
|
||||
this.hadPendingChangePasswordTask = tasks?.some((task) => {
|
||||
return (
|
||||
task.cipherId === this.cipher?.id && task.type === SecurityTaskType.UpdateAtRiskCredential
|
||||
);
|
||||
});
|
||||
} catch (error) {
|
||||
this.hadPendingChangePasswordTask = false;
|
||||
this.logService.error("Failed to retrieve change password tasks for cipher", error);
|
||||
}
|
||||
|
||||
const tasks = await firstValueFrom(this.defaultTaskService.pendingTasks$(userId));
|
||||
|
||||
this.hadPendingChangePasswordTask = tasks?.some((task) => {
|
||||
return (
|
||||
task.cipherId === this.cipher?.id && task.type === SecurityTaskType.UpdateAtRiskCredential
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
launchChangePassword = async () => {
|
||||
|
||||
Reference in New Issue
Block a user