[PS-788] - Item links use `cipherId` in query string (#2880)
* Replace 'cipherId' query param with 'itemId' for linkable ciphers
This commit is contained in:
parent
4f9079dd4f
commit
2d72201650
|
@ -7,7 +7,7 @@ import {
|
||||||
ViewChild,
|
ViewChild,
|
||||||
ViewContainerRef,
|
ViewContainerRef,
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Params, Router } from "@angular/router";
|
||||||
import { first } from "rxjs/operators";
|
import { first } from "rxjs/operators";
|
||||||
|
|
||||||
import { VaultFilter } from "jslib-angular/modules/vault-filter/models/vault-filter.model";
|
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 { StateService } from "jslib-common/abstractions/state.service";
|
||||||
import { SyncService } from "jslib-common/abstractions/sync.service";
|
import { SyncService } from "jslib-common/abstractions/sync.service";
|
||||||
import { TokenService } from "jslib-common/abstractions/token.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 { CipherView } from "jslib-common/models/view/cipherView";
|
||||||
|
|
||||||
import { UpdateKeyComponent } from "../../../../settings/update-key.component";
|
import { UpdateKeyComponent } from "../../../../settings/update-key.component";
|
||||||
|
@ -111,9 +110,11 @@ export class IndividualVaultComponent implements OnInit, OnDestroy {
|
||||||
this.filterComponent.reloadOrganizations();
|
this.filterComponent.reloadOrganizations();
|
||||||
this.showUpdateKey = !(await this.cryptoService.hasEncKey());
|
this.showUpdateKey = !(await this.cryptoService.hasEncKey());
|
||||||
|
|
||||||
if (params.cipherId) {
|
const cipherId = getCipherIdFromParams(params);
|
||||||
|
|
||||||
|
if (cipherId) {
|
||||||
const cipherView = new CipherView();
|
const cipherView = new CipherView();
|
||||||
cipherView.id = params.cipherId;
|
cipherView.id = cipherId;
|
||||||
if (params.action === "clone") {
|
if (params.action === "clone") {
|
||||||
await this.cloneCipher(cipherView);
|
await this.cloneCipher(cipherView);
|
||||||
} else if (params.action === "edit") {
|
} else if (params.action === "edit") {
|
||||||
|
@ -123,9 +124,10 @@ export class IndividualVaultComponent implements OnInit, OnDestroy {
|
||||||
await this.ciphersComponent.reload();
|
await this.ciphersComponent.reload();
|
||||||
|
|
||||||
this.route.queryParams.subscribe(async (params) => {
|
this.route.queryParams.subscribe(async (params) => {
|
||||||
if (params.cipherId) {
|
const cipherId = getCipherIdFromParams(params);
|
||||||
if ((await this.cipherService.get(params.cipherId)) != null) {
|
if (cipherId) {
|
||||||
this.editCipherId(params.cipherId);
|
if ((await this.cipherService.get(cipherId)) != null) {
|
||||||
|
this.editCipherId(cipherId);
|
||||||
} else {
|
} else {
|
||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
|
@ -133,7 +135,7 @@ export class IndividualVaultComponent implements OnInit, OnDestroy {
|
||||||
this.i18nService.t("unknownCipher")
|
this.i18nService.t("unknownCipher")
|
||||||
);
|
);
|
||||||
this.router.navigate([], {
|
this.router.navigate([], {
|
||||||
queryParams: { cipherId: null },
|
queryParams: { itemId: null, cipherId: null },
|
||||||
queryParamsHandling: "merge",
|
queryParamsHandling: "merge",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -356,7 +358,7 @@ export class IndividualVaultComponent implements OnInit, OnDestroy {
|
||||||
const cipher = await this.cipherService.get(id);
|
const cipher = await this.cipherService.get(id);
|
||||||
if (cipher != null && cipher.reprompt != 0) {
|
if (cipher != null && cipher.reprompt != 0) {
|
||||||
if (!(await this.passwordRepromptService.showPasswordPrompt())) {
|
if (!(await this.passwordRepromptService.showPasswordPrompt())) {
|
||||||
this.go({ cipherId: null });
|
this.go({ cipherId: null, itemId: null });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -382,7 +384,7 @@ export class IndividualVaultComponent implements OnInit, OnDestroy {
|
||||||
);
|
);
|
||||||
|
|
||||||
modal.onClosedPromise().then(() => {
|
modal.onClosedPromise().then(() => {
|
||||||
this.go({ cipherId: null });
|
this.go({ cipherId: null, itemId: null });
|
||||||
});
|
});
|
||||||
|
|
||||||
return childComponent;
|
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"];
|
||||||
|
};
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
ViewChild,
|
ViewChild,
|
||||||
ViewContainerRef,
|
ViewContainerRef,
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Params, Router } from "@angular/router";
|
||||||
import { first } from "rxjs/operators";
|
import { first } from "rxjs/operators";
|
||||||
|
|
||||||
import { VaultFilter } from "jslib-angular/modules/vault-filter/models/vault-filter.model";
|
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) => {
|
this.route.queryParams.subscribe(async (params) => {
|
||||||
if (params.cipherId) {
|
const cipherId = getCipherIdFromParams(params);
|
||||||
|
if (cipherId) {
|
||||||
if (
|
if (
|
||||||
// Handle users with implicit collection access since they use the admin endpoint
|
// Handle users with implicit collection access since they use the admin endpoint
|
||||||
this.organization.canEditAnyCollection ||
|
this.organization.canEditAnyCollection ||
|
||||||
(await this.cipherService.get(params.cipherId)) != null
|
(await this.cipherService.get(cipherId)) != null
|
||||||
) {
|
) {
|
||||||
this.editCipherId(params.cipherId);
|
this.editCipherId(cipherId);
|
||||||
} else {
|
} else {
|
||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
|
@ -141,7 +142,7 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy {
|
||||||
this.i18nService.t("unknownCipher")
|
this.i18nService.t("unknownCipher")
|
||||||
);
|
);
|
||||||
this.router.navigate([], {
|
this.router.navigate([], {
|
||||||
queryParams: { cipherId: null },
|
queryParams: { cipherId: null, itemId: null },
|
||||||
queryParamsHandling: "merge",
|
queryParamsHandling: "merge",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -273,7 +274,7 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy {
|
||||||
const cipher = await this.cipherService.get(cipherId);
|
const cipher = await this.cipherService.get(cipherId);
|
||||||
if (cipher != null && cipher.reprompt != 0) {
|
if (cipher != null && cipher.reprompt != 0) {
|
||||||
if (!(await this.passwordRepromptService.showPasswordPrompt())) {
|
if (!(await this.passwordRepromptService.showPasswordPrompt())) {
|
||||||
this.go({ cipherId: null });
|
this.go({ cipherId: null, itemId: null });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -300,7 +301,7 @@ export class OrganizationVaultComponent implements OnInit, OnDestroy {
|
||||||
);
|
);
|
||||||
|
|
||||||
modal.onClosedPromise().then(() => {
|
modal.onClosedPromise().then(() => {
|
||||||
this.go({ cipherId: null });
|
this.go({ cipherId: null, itemId: null });
|
||||||
});
|
});
|
||||||
|
|
||||||
return childComponent;
|
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"];
|
||||||
|
};
|
||||||
|
|
|
@ -41,10 +41,12 @@ export class PermissionsGuard implements CanActivate {
|
||||||
if (permissions != null && !org.hasAnyPermission(permissions)) {
|
if (permissions != null && !org.hasAnyPermission(permissions)) {
|
||||||
// Handle linkable ciphers for organizations the user only has view access to
|
// Handle linkable ciphers for organizations the user only has view access to
|
||||||
// https://bitwarden.atlassian.net/browse/EC-203
|
// 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"], {
|
return this.router.createUrlTree(["/vault"], {
|
||||||
queryParams: {
|
queryParams: {
|
||||||
cipherId: state.root.queryParamMap.get("cipherId"),
|
itemId: cipherId,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<a
|
<a
|
||||||
appStopProp
|
appStopProp
|
||||||
[routerLink]="[]"
|
[routerLink]="[]"
|
||||||
[queryParams]="{ cipherId: c.id }"
|
[queryParams]="{ itemId: c.id }"
|
||||||
queryParamsHandling="merge"
|
queryParamsHandling="merge"
|
||||||
title="{{ 'editItem' | i18n }}"
|
title="{{ 'editItem' | i18n }}"
|
||||||
>{{ c.name }}</a
|
>{{ c.name }}</a
|
||||||
|
|
Loading…
Reference in New Issue