diff --git a/apps/web/src/app/modules/vault/modules/individual-vault/individual-vault.component.ts b/apps/web/src/app/modules/vault/modules/individual-vault/individual-vault.component.ts index 31a55264fd..718382a5c8 100644 --- a/apps/web/src/app/modules/vault/modules/individual-vault/individual-vault.component.ts +++ b/apps/web/src/app/modules/vault/modules/individual-vault/individual-vault.component.ts @@ -7,7 +7,7 @@ import { ViewChild, ViewContainerRef, } from "@angular/core"; -import { ActivatedRoute, Router } from "@angular/router"; +import { ActivatedRoute, Params, Router } from "@angular/router"; import { first } from "rxjs/operators"; import { VaultFilter } from "jslib-angular/modules/vault-filter/models/vault-filter.model"; @@ -23,7 +23,6 @@ import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.se import { StateService } from "jslib-common/abstractions/state.service"; import { SyncService } from "jslib-common/abstractions/sync.service"; import { TokenService } from "jslib-common/abstractions/token.service"; -import { CipherType } from "jslib-common/enums/cipherType"; import { CipherView } from "jslib-common/models/view/cipherView"; import { UpdateKeyComponent } from "../../../../settings/update-key.component"; @@ -111,9 +110,11 @@ export class IndividualVaultComponent implements OnInit, OnDestroy { this.filterComponent.reloadOrganizations(); this.showUpdateKey = !(await this.cryptoService.hasEncKey()); - if (params.cipherId) { + const cipherId = getCipherIdFromParams(params); + + if (cipherId) { const cipherView = new CipherView(); - cipherView.id = params.cipherId; + cipherView.id = cipherId; if (params.action === "clone") { await this.cloneCipher(cipherView); } else if (params.action === "edit") { @@ -123,9 +124,10 @@ export class IndividualVaultComponent implements OnInit, OnDestroy { await this.ciphersComponent.reload(); this.route.queryParams.subscribe(async (params) => { - if (params.cipherId) { - if ((await this.cipherService.get(params.cipherId)) != null) { - this.editCipherId(params.cipherId); + const cipherId = getCipherIdFromParams(params); + if (cipherId) { + if ((await this.cipherService.get(cipherId)) != null) { + this.editCipherId(cipherId); } else { this.platformUtilsService.showToast( "error", @@ -133,7 +135,7 @@ export class IndividualVaultComponent implements OnInit, OnDestroy { this.i18nService.t("unknownCipher") ); this.router.navigate([], { - queryParams: { cipherId: null }, + queryParams: { itemId: null, cipherId: null }, queryParamsHandling: "merge", }); } @@ -356,7 +358,7 @@ export class IndividualVaultComponent implements OnInit, OnDestroy { const cipher = await this.cipherService.get(id); if (cipher != null && cipher.reprompt != 0) { if (!(await this.passwordRepromptService.showPasswordPrompt())) { - this.go({ cipherId: null }); + this.go({ cipherId: null, itemId: null }); return; } } @@ -382,7 +384,7 @@ export class IndividualVaultComponent implements OnInit, OnDestroy { ); modal.onClosedPromise().then(() => { - this.go({ cipherId: null }); + this.go({ cipherId: null, itemId: null }); }); return childComponent; @@ -416,3 +418,11 @@ export class IndividualVaultComponent implements OnInit, OnDestroy { }); } } + +/** + * Allows backwards compatibility with + * old links that used the original `cipherId` param + */ +const getCipherIdFromParams = (params: Params): string => { + return params["itemId"] || params["cipherId"]; +}; diff --git a/apps/web/src/app/modules/vault/modules/organization-vault/organization-vault.component.ts b/apps/web/src/app/modules/vault/modules/organization-vault/organization-vault.component.ts index 83c182ea08..451e9ca504 100644 --- a/apps/web/src/app/modules/vault/modules/organization-vault/organization-vault.component.ts +++ b/apps/web/src/app/modules/vault/modules/organization-vault/organization-vault.component.ts @@ -7,7 +7,7 @@ import { ViewChild, ViewContainerRef, } from "@angular/core"; -import { ActivatedRoute, Router } from "@angular/router"; +import { ActivatedRoute, Params, Router } from "@angular/router"; import { first } from "rxjs/operators"; import { VaultFilter } from "jslib-angular/modules/vault-filter/models/vault-filter.model"; @@ -127,13 +127,14 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy { } this.route.queryParams.subscribe(async (params) => { - if (params.cipherId) { + const cipherId = getCipherIdFromParams(params); + if (cipherId) { if ( // Handle users with implicit collection access since they use the admin endpoint this.organization.canEditAnyCollection || - (await this.cipherService.get(params.cipherId)) != null + (await this.cipherService.get(cipherId)) != null ) { - this.editCipherId(params.cipherId); + this.editCipherId(cipherId); } else { this.platformUtilsService.showToast( "error", @@ -141,7 +142,7 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy { this.i18nService.t("unknownCipher") ); this.router.navigate([], { - queryParams: { cipherId: null }, + queryParams: { cipherId: null, itemId: null }, queryParamsHandling: "merge", }); } @@ -273,7 +274,7 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy { const cipher = await this.cipherService.get(cipherId); if (cipher != null && cipher.reprompt != 0) { if (!(await this.passwordRepromptService.showPasswordPrompt())) { - this.go({ cipherId: null }); + this.go({ cipherId: null, itemId: null }); return; } } @@ -300,7 +301,7 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy { ); modal.onClosedPromise().then(() => { - this.go({ cipherId: null }); + this.go({ cipherId: null, itemId: null }); }); return childComponent; @@ -353,3 +354,11 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy { }); } } + +/** + * Allows backwards compatibility with + * old links that used the original `cipherId` param + */ +const getCipherIdFromParams = (params: Params): string => { + return params["itemId"] || params["cipherId"]; +}; diff --git a/apps/web/src/app/organizations/guards/permissions.guard.ts b/apps/web/src/app/organizations/guards/permissions.guard.ts index 2f20355920..0d9ab6be17 100644 --- a/apps/web/src/app/organizations/guards/permissions.guard.ts +++ b/apps/web/src/app/organizations/guards/permissions.guard.ts @@ -41,10 +41,12 @@ export class PermissionsGuard implements CanActivate { if (permissions != null && !org.hasAnyPermission(permissions)) { // Handle linkable ciphers for organizations the user only has view access to // https://bitwarden.atlassian.net/browse/EC-203 - if (state.root.queryParamMap.has("cipherId")) { + const cipherId = + state.root.queryParamMap.get("itemId") || state.root.queryParamMap.get("cipherId"); + if (cipherId) { return this.router.createUrlTree(["/vault"], { queryParams: { - cipherId: state.root.queryParamMap.get("cipherId"), + itemId: cipherId, }, }); } diff --git a/apps/web/src/app/vault/ciphers.component.html b/apps/web/src/app/vault/ciphers.component.html index 096a0833ff..c9c58327b9 100644 --- a/apps/web/src/app/vault/ciphers.component.html +++ b/apps/web/src/app/vault/ciphers.component.html @@ -19,7 +19,7 @@ {{ c.name }}