mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
[PM-18089] Update cipher permissions model and consumers (#13606)
* update cipher permissions model and consumers * add new property to tests * fix test, add property to toCipherData() * add missing ConfigService * fix story * refactor * fix error, cleanup * revert refactor * refactor * remove uneeded test * cleanup * fix build error * refactor * clean up * add tests * move validation check to after featrue flagged logic * iterate on feedback * feedback
This commit is contained in:
21
libs/common/src/vault/models/api/cipher-permissions.api.ts
Normal file
21
libs/common/src/vault/models/api/cipher-permissions.api.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
|
||||
export class CipherPermissionsApi extends BaseResponse {
|
||||
delete: boolean = false;
|
||||
restore: boolean = false;
|
||||
|
||||
constructor(data: any = null) {
|
||||
super(data);
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
this.delete = this.getResponseProperty("Delete");
|
||||
this.restore = this.getResponseProperty("Restore");
|
||||
}
|
||||
|
||||
static fromJSON(obj: Jsonify<CipherPermissionsApi>) {
|
||||
return Object.assign(new CipherPermissionsApi(), obj);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import { Jsonify } from "type-fest";
|
||||
|
||||
import { CipherRepromptType } from "../../enums/cipher-reprompt-type";
|
||||
import { CipherType } from "../../enums/cipher-type";
|
||||
import { CipherPermissionsApi } from "../api/cipher-permissions.api";
|
||||
import { CipherResponse } from "../response/cipher.response";
|
||||
|
||||
import { AttachmentData } from "./attachment.data";
|
||||
@@ -21,6 +22,7 @@ export class CipherData {
|
||||
folderId: string;
|
||||
edit: boolean;
|
||||
viewPassword: boolean;
|
||||
permissions: CipherPermissionsApi;
|
||||
organizationUseTotp: boolean;
|
||||
favorite: boolean;
|
||||
revisionDate: string;
|
||||
@@ -51,6 +53,7 @@ export class CipherData {
|
||||
this.folderId = response.folderId;
|
||||
this.edit = response.edit;
|
||||
this.viewPassword = response.viewPassword;
|
||||
this.permissions = response.permissions;
|
||||
this.organizationUseTotp = response.organizationUseTotp;
|
||||
this.favorite = response.favorite;
|
||||
this.revisionDate = response.revisionDate;
|
||||
@@ -95,6 +98,8 @@ export class CipherData {
|
||||
}
|
||||
|
||||
static fromJSON(obj: Jsonify<CipherData>) {
|
||||
return Object.assign(new CipherData(), obj);
|
||||
const result = Object.assign(new CipherData(), obj);
|
||||
result.permissions = CipherPermissionsApi.fromJSON(obj.permissions);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import { SecureNote } from "../../models/domain/secure-note";
|
||||
import { CardView } from "../../models/view/card.view";
|
||||
import { IdentityView } from "../../models/view/identity.view";
|
||||
import { LoginView } from "../../models/view/login.view";
|
||||
import { CipherPermissionsApi } from "../api/cipher-permissions.api";
|
||||
|
||||
describe("Cipher DTO", () => {
|
||||
it("Convert from empty CipherData", () => {
|
||||
@@ -54,6 +55,7 @@ describe("Cipher DTO", () => {
|
||||
fields: null,
|
||||
passwordHistory: null,
|
||||
key: null,
|
||||
permissions: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -75,6 +77,7 @@ describe("Cipher DTO", () => {
|
||||
notes: "EncryptedString",
|
||||
creationDate: "2022-01-01T12:00:00.000Z",
|
||||
deletedDate: null,
|
||||
permissions: new CipherPermissionsApi(),
|
||||
reprompt: CipherRepromptType.None,
|
||||
key: "EncryptedString",
|
||||
login: {
|
||||
@@ -149,6 +152,7 @@ describe("Cipher DTO", () => {
|
||||
localData: null,
|
||||
creationDate: new Date("2022-01-01T12:00:00.000Z"),
|
||||
deletedDate: null,
|
||||
permissions: new CipherPermissionsApi(),
|
||||
reprompt: 0,
|
||||
key: { encryptedString: "EncryptedString", encryptionType: 0 },
|
||||
login: {
|
||||
@@ -228,6 +232,7 @@ describe("Cipher DTO", () => {
|
||||
cipher.deletedDate = null;
|
||||
cipher.reprompt = CipherRepromptType.None;
|
||||
cipher.key = mockEnc("EncKey");
|
||||
cipher.permissions = new CipherPermissionsApi();
|
||||
|
||||
const loginView = new LoginView();
|
||||
loginView.username = "username";
|
||||
@@ -270,6 +275,7 @@ describe("Cipher DTO", () => {
|
||||
deletedDate: null,
|
||||
reprompt: 0,
|
||||
localData: undefined,
|
||||
permissions: new CipherPermissionsApi(),
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -297,6 +303,7 @@ describe("Cipher DTO", () => {
|
||||
secureNote: {
|
||||
type: SecureNoteType.Generic,
|
||||
},
|
||||
permissions: new CipherPermissionsApi(),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -326,6 +333,7 @@ describe("Cipher DTO", () => {
|
||||
fields: null,
|
||||
passwordHistory: null,
|
||||
key: { encryptedString: "EncKey", encryptionType: 0 },
|
||||
permissions: new CipherPermissionsApi(),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -353,6 +361,7 @@ describe("Cipher DTO", () => {
|
||||
cipher.secureNote = new SecureNote();
|
||||
cipher.secureNote.type = SecureNoteType.Generic;
|
||||
cipher.key = mockEnc("EncKey");
|
||||
cipher.permissions = new CipherPermissionsApi();
|
||||
|
||||
const keyService = mock<KeyService>();
|
||||
const encryptService = mock<EncryptService>();
|
||||
@@ -387,6 +396,7 @@ describe("Cipher DTO", () => {
|
||||
deletedDate: null,
|
||||
reprompt: 0,
|
||||
localData: undefined,
|
||||
permissions: new CipherPermissionsApi(),
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -409,6 +419,7 @@ describe("Cipher DTO", () => {
|
||||
notes: "EncryptedString",
|
||||
creationDate: "2022-01-01T12:00:00.000Z",
|
||||
deletedDate: null,
|
||||
permissions: new CipherPermissionsApi(),
|
||||
reprompt: CipherRepromptType.None,
|
||||
card: {
|
||||
cardholderName: "EncryptedString",
|
||||
@@ -455,6 +466,7 @@ describe("Cipher DTO", () => {
|
||||
fields: null,
|
||||
passwordHistory: null,
|
||||
key: { encryptedString: "EncKey", encryptionType: 0 },
|
||||
permissions: new CipherPermissionsApi(),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -480,6 +492,7 @@ describe("Cipher DTO", () => {
|
||||
cipher.deletedDate = null;
|
||||
cipher.reprompt = CipherRepromptType.None;
|
||||
cipher.key = mockEnc("EncKey");
|
||||
cipher.permissions = new CipherPermissionsApi();
|
||||
|
||||
const cardView = new CardView();
|
||||
cardView.cardholderName = "cardholderName";
|
||||
@@ -522,6 +535,7 @@ describe("Cipher DTO", () => {
|
||||
deletedDate: null,
|
||||
reprompt: 0,
|
||||
localData: undefined,
|
||||
permissions: new CipherPermissionsApi(),
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -544,6 +558,7 @@ describe("Cipher DTO", () => {
|
||||
notes: "EncryptedString",
|
||||
creationDate: "2022-01-01T12:00:00.000Z",
|
||||
deletedDate: null,
|
||||
permissions: new CipherPermissionsApi(),
|
||||
reprompt: CipherRepromptType.None,
|
||||
key: "EncKey",
|
||||
identity: {
|
||||
@@ -614,6 +629,7 @@ describe("Cipher DTO", () => {
|
||||
fields: null,
|
||||
passwordHistory: null,
|
||||
key: { encryptedString: "EncKey", encryptionType: 0 },
|
||||
permissions: new CipherPermissionsApi(),
|
||||
});
|
||||
});
|
||||
|
||||
@@ -639,6 +655,7 @@ describe("Cipher DTO", () => {
|
||||
cipher.deletedDate = null;
|
||||
cipher.reprompt = CipherRepromptType.None;
|
||||
cipher.key = mockEnc("EncKey");
|
||||
cipher.permissions = new CipherPermissionsApi();
|
||||
|
||||
const identityView = new IdentityView();
|
||||
identityView.firstName = "firstName";
|
||||
@@ -681,6 +698,7 @@ describe("Cipher DTO", () => {
|
||||
deletedDate: null,
|
||||
reprompt: 0,
|
||||
localData: undefined,
|
||||
permissions: new CipherPermissionsApi(),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ import { SymmetricCryptoKey } from "../../../platform/models/domain/symmetric-cr
|
||||
import { InitializerKey } from "../../../platform/services/cryptography/initializer-key";
|
||||
import { CipherRepromptType } from "../../enums/cipher-reprompt-type";
|
||||
import { CipherType } from "../../enums/cipher-type";
|
||||
import { CipherPermissionsApi } from "../api/cipher-permissions.api";
|
||||
import { CipherData } from "../data/cipher.data";
|
||||
import { LocalData } from "../data/local.data";
|
||||
import { AttachmentView } from "../view/attachment.view";
|
||||
@@ -39,6 +40,7 @@ export class Cipher extends Domain implements Decryptable<CipherView> {
|
||||
organizationUseTotp: boolean;
|
||||
edit: boolean;
|
||||
viewPassword: boolean;
|
||||
permissions: CipherPermissionsApi;
|
||||
revisionDate: Date;
|
||||
localData: LocalData;
|
||||
login: Login;
|
||||
@@ -84,6 +86,7 @@ export class Cipher extends Domain implements Decryptable<CipherView> {
|
||||
} else {
|
||||
this.viewPassword = true; // Default for already synced Ciphers without viewPassword
|
||||
}
|
||||
this.permissions = obj.permissions;
|
||||
this.revisionDate = obj.revisionDate != null ? new Date(obj.revisionDate) : null;
|
||||
this.collectionIds = obj.collectionIds;
|
||||
this.localData = localData;
|
||||
@@ -244,6 +247,7 @@ export class Cipher extends Domain implements Decryptable<CipherView> {
|
||||
c.deletedDate = this.deletedDate != null ? this.deletedDate.toISOString() : null;
|
||||
c.reprompt = this.reprompt;
|
||||
c.key = this.key?.encryptedString;
|
||||
c.permissions = this.permissions;
|
||||
|
||||
this.buildDataModel(this, c, {
|
||||
name: null,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import { BaseResponse } from "../../../models/response/base.response";
|
||||
import { CipherRepromptType } from "../../enums/cipher-reprompt-type";
|
||||
import { CardApi } from "../api/card.api";
|
||||
import { CipherPermissionsApi } from "../api/cipher-permissions.api";
|
||||
import { FieldApi } from "../api/field.api";
|
||||
import { IdentityApi } from "../api/identity.api";
|
||||
import { LoginApi } from "../api/login.api";
|
||||
@@ -28,6 +29,7 @@ export class CipherResponse extends BaseResponse {
|
||||
favorite: boolean;
|
||||
edit: boolean;
|
||||
viewPassword: boolean;
|
||||
permissions: CipherPermissionsApi;
|
||||
organizationUseTotp: boolean;
|
||||
revisionDate: string;
|
||||
attachments: AttachmentResponse[];
|
||||
@@ -53,6 +55,7 @@ export class CipherResponse extends BaseResponse {
|
||||
} else {
|
||||
this.viewPassword = this.getResponseProperty("ViewPassword");
|
||||
}
|
||||
this.permissions = new CipherPermissionsApi(this.getResponseProperty("Permissions"));
|
||||
this.organizationUseTotp = this.getResponseProperty("OrganizationUseTotp");
|
||||
this.revisionDate = this.getResponseProperty("RevisionDate");
|
||||
this.collectionIds = this.getResponseProperty("CollectionIds");
|
||||
|
||||
@@ -6,6 +6,7 @@ import { InitializerKey } from "../../../platform/services/cryptography/initiali
|
||||
import { DeepJsonify } from "../../../types/deep-jsonify";
|
||||
import { CipherType, LinkedIdType } from "../../enums";
|
||||
import { CipherRepromptType } from "../../enums/cipher-reprompt-type";
|
||||
import { CipherPermissionsApi } from "../api/cipher-permissions.api";
|
||||
import { LocalData } from "../data/local.data";
|
||||
import { Cipher } from "../domain/cipher";
|
||||
|
||||
@@ -29,6 +30,7 @@ export class CipherView implements View, InitializerMetadata {
|
||||
type: CipherType = null;
|
||||
favorite = false;
|
||||
organizationUseTotp = false;
|
||||
permissions: CipherPermissionsApi = new CipherPermissionsApi();
|
||||
edit = false;
|
||||
viewPassword = true;
|
||||
localData: LocalData;
|
||||
@@ -63,6 +65,7 @@ export class CipherView implements View, InitializerMetadata {
|
||||
this.organizationUseTotp = c.organizationUseTotp;
|
||||
this.edit = c.edit;
|
||||
this.viewPassword = c.viewPassword;
|
||||
this.permissions = c.permissions;
|
||||
this.type = c.type;
|
||||
this.localData = c.localData;
|
||||
this.collectionIds = c.collectionIds;
|
||||
|
||||
Reference in New Issue
Block a user