1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-12 22:33:35 +00:00

Added permission check for organizational unsecure website (#13611)

Only display the cipher's name if the user running the report does not have permissions to view/edit the cipher

Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
This commit is contained in:
Daniel James Smith
2025-02-27 20:55:38 +01:00
committed by GitHub
parent 407368b3ea
commit eaeea195e4
3 changed files with 37 additions and 32 deletions

View File

@@ -13,6 +13,7 @@ import { AccountService } from "@bitwarden/common/auth/abstractions/account.serv
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction"; import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view"; import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
import { DialogService } from "@bitwarden/components"; import { DialogService } from "@bitwarden/components";
import { CipherFormConfigService, PasswordRepromptService } from "@bitwarden/vault"; import { CipherFormConfigService, PasswordRepromptService } from "@bitwarden/vault";
@@ -41,6 +42,9 @@ export class UnsecuredWebsitesReportComponent
extends BaseUnsecuredWebsitesReportComponent extends BaseUnsecuredWebsitesReportComponent
implements OnInit implements OnInit
{ {
// Contains a list of ciphers, the user running the report, can manage
private manageableCiphers: Cipher[];
constructor( constructor(
cipherService: CipherService, cipherService: CipherService,
dialogService: DialogService, dialogService: DialogService,
@@ -80,6 +84,7 @@ export class UnsecuredWebsitesReportComponent
.organizations$(userId) .organizations$(userId)
.pipe(getOrganizationById(params.organizationId)), .pipe(getOrganizationById(params.organizationId)),
); );
this.manageableCiphers = await this.cipherService.getAll(userId);
await super.ngOnInit(); await super.ngOnInit();
}); });
} }
@@ -87,4 +92,8 @@ export class UnsecuredWebsitesReportComponent
getAllCiphers(): Promise<CipherView[]> { getAllCiphers(): Promise<CipherView[]> {
return this.cipherService.getAllFromApiForOrganization(this.organization.id); return this.cipherService.getAllFromApiForOrganization(this.organization.id);
} }
protected canManageCipher(c: CipherView): boolean {
return this.manageableCiphers.some((x) => x.id === c.id);
}
} }

View File

@@ -47,15 +47,19 @@
<app-vault-icon [cipher]="r"></app-vault-icon> <app-vault-icon [cipher]="r"></app-vault-icon>
</td> </td>
<td bitCell> <td bitCell>
<a <ng-container *ngIf="!organization || canManageCipher(r); else cantManage">
bitLink <a
href="#" bitLink
appStopClick href="#"
(click)="selectCipher(r)" appStopClick
title="{{ 'editItemWithName' | i18n: r.name }}" (click)="selectCipher(r)"
> title="{{ 'editItemWithName' | i18n: r.name }}"
{{ r.name }} >{{ r.name }}</a
</a> >
</ng-container>
<ng-template #cantManage>
<span>{{ r.name }}</span>
</ng-template>
<ng-container *ngIf="!organization && r.organizationId"> <ng-container *ngIf="!organization && r.organizationId">
<i <i
class="bwi bwi-collection" class="bwi bwi-collection"

View File

@@ -1,6 +1,6 @@
import { Component, OnInit } from "@angular/core"; import { Component, OnInit } from "@angular/core";
import { CollectionService, Collection } from "@bitwarden/admin-console/common"; import { CollectionService } from "@bitwarden/admin-console/common";
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction"; import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service"; import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -53,17 +53,10 @@ export class UnsecuredWebsitesReportComponent extends CipherReportComponent impl
async setCiphers() { async setCiphers() {
const allCiphers = await this.getAllCiphers(); const allCiphers = await this.getAllCiphers();
const allCollections = await this.collectionService.getAll();
this.filterStatus = [0]; this.filterStatus = [0];
const unsecuredCiphers = allCiphers.filter((c) => { const unsecuredCiphers = allCiphers.filter((c) => {
const containsUnsecured = this.cipherContainsUnsecured(c); return this.cipherContainsUnsecured(c);
if (containsUnsecured === false) {
return false;
}
const canView = this.canView(c, allCollections);
return canView;
}); });
this.filterCiphersByOrg(unsecuredCiphers); this.filterCiphersByOrg(unsecuredCiphers);
@@ -74,7 +67,12 @@ export class UnsecuredWebsitesReportComponent extends CipherReportComponent impl
* @param cipher Current cipher with unsecured uri * @param cipher Current cipher with unsecured uri
*/ */
private cipherContainsUnsecured(cipher: CipherView): boolean { private cipherContainsUnsecured(cipher: CipherView): boolean {
if (cipher.type !== CipherType.Login || !cipher.login.hasUris || cipher.isDeleted) { if (
cipher.type !== CipherType.Login ||
!cipher.login.hasUris ||
cipher.isDeleted ||
(!this.organization && !cipher.edit)
) {
return false; return false;
} }
@@ -85,19 +83,13 @@ export class UnsecuredWebsitesReportComponent extends CipherReportComponent impl
} }
/** /**
* If the user does not have readonly set or it's false they have the ability to edit * Provides a way to determine if someone with permissions to run an organizational report is also able to view/edit ciphers within the results
* @param cipher Current cipher with unsecured uri * Default to true for indivduals running reports on their own vault.
* @param allCollections The collections for the user * @param c CipherView
* @returns boolean
*/ */
private canView(cipher: CipherView, allCollections: Collection[]): boolean { protected canManageCipher(c: CipherView): boolean {
if (!cipher.organizationId) { // this will only ever be false from the org view;
return true; return true;
}
return (
allCollections.filter(
(item) => cipher.collectionIds.indexOf(item.id) > -1 && !(item.readOnly ?? false),
).length > 0
);
} }
} }