mirror of
https://github.com/bitwarden/browser
synced 2026-01-26 14:23:46 +00:00
Expand generic pattern for notification queue messages.
This commit is contained in:
@@ -4,62 +4,62 @@ import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
||||
|
||||
import { CollectionView } from "../../content/components/common-types";
|
||||
import { NotificationType, NotificationTypes } from "../../enums/notification-type.enum";
|
||||
import { NotificationType } from "../../enums/notification-type.enum";
|
||||
import AutofillPageDetails from "../../models/autofill-page-details";
|
||||
|
||||
/**
|
||||
* @todo Remove Standard_ label when implemented as standard NotificationQueueMessage.
|
||||
* Generic notification queue message structure.
|
||||
* All notification types use this structure with type-specific data.
|
||||
*/
|
||||
export interface Standard_NotificationQueueMessage<T, D> {
|
||||
// universal notification properties
|
||||
export interface NotificationQueueMessage<T, D> {
|
||||
domain: string;
|
||||
tab: chrome.tabs.Tab;
|
||||
launchTimestamp: number;
|
||||
expires: Date;
|
||||
wasVaultLocked: boolean;
|
||||
|
||||
type: T; // NotificationType
|
||||
data: D; // notification-specific data
|
||||
type: T;
|
||||
data: D;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Deprecate in favor of Standard_NotificationQueueMessage.
|
||||
*/
|
||||
interface NotificationQueueMessage {
|
||||
type: NotificationTypes;
|
||||
domain: string;
|
||||
tab: chrome.tabs.Tab;
|
||||
launchTimestamp: number;
|
||||
expires: Date;
|
||||
wasVaultLocked: boolean;
|
||||
}
|
||||
// Notification data type definitions
|
||||
export type AddLoginNotificationData = {
|
||||
username: string;
|
||||
password: string;
|
||||
uri: string;
|
||||
};
|
||||
|
||||
type ChangePasswordNotificationData = {
|
||||
export type ChangePasswordNotificationData = {
|
||||
cipherIds: CipherView["id"][];
|
||||
newPassword: string;
|
||||
};
|
||||
|
||||
type AddChangePasswordNotificationQueueMessage = Standard_NotificationQueueMessage<
|
||||
export type UnlockVaultNotificationData = never;
|
||||
|
||||
export type AtRiskPasswordNotificationData = {
|
||||
organizationName: string;
|
||||
passwordChangeUri?: string;
|
||||
};
|
||||
|
||||
// Notification queue message types using generic pattern
|
||||
export type AddLoginQueueMessage = NotificationQueueMessage<
|
||||
typeof NotificationType.AddLogin,
|
||||
AddLoginNotificationData
|
||||
>;
|
||||
|
||||
export type AddChangePasswordNotificationQueueMessage = NotificationQueueMessage<
|
||||
typeof NotificationType.ChangePassword,
|
||||
ChangePasswordNotificationData
|
||||
>;
|
||||
|
||||
interface AddLoginQueueMessage extends NotificationQueueMessage {
|
||||
type: "add";
|
||||
username: string;
|
||||
password: string;
|
||||
uri: string;
|
||||
}
|
||||
export type AddUnlockVaultQueueMessage = NotificationQueueMessage<
|
||||
typeof NotificationType.UnlockVault,
|
||||
UnlockVaultNotificationData
|
||||
>;
|
||||
|
||||
interface AddUnlockVaultQueueMessage extends NotificationQueueMessage {
|
||||
type: "unlock";
|
||||
}
|
||||
|
||||
interface AtRiskPasswordQueueMessage extends NotificationQueueMessage {
|
||||
type: "at-risk-password";
|
||||
organizationName: string;
|
||||
passwordChangeUri?: string;
|
||||
}
|
||||
export type AtRiskPasswordQueueMessage = NotificationQueueMessage<
|
||||
typeof NotificationType.AtRiskPassword,
|
||||
AtRiskPasswordNotificationData
|
||||
>;
|
||||
|
||||
type NotificationQueueMessageItem =
|
||||
| AddLoginQueueMessage
|
||||
@@ -152,9 +152,6 @@ type NotificationBackgroundExtensionMessageHandlers = {
|
||||
};
|
||||
|
||||
export {
|
||||
AddChangePasswordNotificationQueueMessage,
|
||||
AddLoginQueueMessage,
|
||||
AddUnlockVaultQueueMessage,
|
||||
NotificationQueueMessageItem,
|
||||
LockedVaultPendingNotificationsData,
|
||||
AdjustNotificationBarMessageData,
|
||||
|
||||
@@ -122,9 +122,11 @@ describe("NotificationBackground", () => {
|
||||
it("returns a cipher view when passed an `AddLoginQueueMessage`", () => {
|
||||
const message: AddLoginQueueMessage = {
|
||||
type: "add",
|
||||
username: "test",
|
||||
password: "password",
|
||||
uri: "https://example.com",
|
||||
data: {
|
||||
username: "test",
|
||||
password: "password",
|
||||
uri: "https://example.com",
|
||||
},
|
||||
domain: "",
|
||||
tab: createChromeTabMock(),
|
||||
expires: new Date(),
|
||||
@@ -136,13 +138,13 @@ describe("NotificationBackground", () => {
|
||||
expect(cipherView.name).toEqual("example.com");
|
||||
expect(cipherView.login).toEqual({
|
||||
fido2Credentials: [],
|
||||
password: message.password,
|
||||
password: message.data.password,
|
||||
uris: [
|
||||
{
|
||||
_uri: message.uri,
|
||||
_uri: message.data.uri,
|
||||
},
|
||||
],
|
||||
username: message.username,
|
||||
username: message.data.username,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -150,9 +152,11 @@ describe("NotificationBackground", () => {
|
||||
const folderId = "folder-id";
|
||||
const message: AddLoginQueueMessage = {
|
||||
type: "add",
|
||||
username: "test",
|
||||
password: "password",
|
||||
uri: "https://example.com",
|
||||
data: {
|
||||
username: "test",
|
||||
password: "password",
|
||||
uri: "https://example.com",
|
||||
},
|
||||
domain: "example.com",
|
||||
tab: createChromeTabMock(),
|
||||
expires: new Date(),
|
||||
@@ -1051,8 +1055,11 @@ describe("NotificationBackground", () => {
|
||||
type: NotificationType.AddLogin,
|
||||
tab,
|
||||
domain: "example.com",
|
||||
username: "test",
|
||||
password: "updated-password",
|
||||
data: {
|
||||
username: "test",
|
||||
password: "updated-password",
|
||||
uri: "https://example.com",
|
||||
},
|
||||
wasVaultLocked: true,
|
||||
});
|
||||
notificationBackground["notificationQueue"] = [queueMessage];
|
||||
@@ -1066,7 +1073,7 @@ describe("NotificationBackground", () => {
|
||||
|
||||
expect(updatePasswordSpy).toHaveBeenCalledWith(
|
||||
cipherView,
|
||||
queueMessage.password,
|
||||
queueMessage.data.password,
|
||||
message.edit,
|
||||
sender.tab,
|
||||
"testId",
|
||||
|
||||
@@ -499,12 +499,14 @@ export default class NotificationBackground {
|
||||
|
||||
this.removeTabFromNotificationQueue(tab);
|
||||
const launchTimestamp = new Date().getTime();
|
||||
const queueMessage: NotificationQueueMessageItem = {
|
||||
const queueMessage: AtRiskPasswordQueueMessage = {
|
||||
domain,
|
||||
wasVaultLocked,
|
||||
type: NotificationType.AtRiskPassword,
|
||||
passwordChangeUri,
|
||||
organizationName: organization.name,
|
||||
data: {
|
||||
passwordChangeUri,
|
||||
organizationName: organization.name,
|
||||
},
|
||||
tab: tab,
|
||||
launchTimestamp,
|
||||
expires: new Date(launchTimestamp + NOTIFICATION_BAR_LIFESPAN_MS),
|
||||
@@ -583,10 +585,12 @@ export default class NotificationBackground {
|
||||
const launchTimestamp = new Date().getTime();
|
||||
const message: AddLoginQueueMessage = {
|
||||
type: NotificationType.AddLogin,
|
||||
username: loginInfo.username,
|
||||
password: loginInfo.password,
|
||||
data: {
|
||||
username: loginInfo.username,
|
||||
password: loginInfo.password,
|
||||
uri: loginInfo.url,
|
||||
},
|
||||
domain: loginDomain,
|
||||
uri: loginInfo.url,
|
||||
tab: tab,
|
||||
launchTimestamp,
|
||||
expires: new Date(launchTimestamp + NOTIFICATION_BAR_LIFESPAN_MS),
|
||||
@@ -843,16 +847,23 @@ export default class NotificationBackground {
|
||||
// If the vault was locked, check if a cipher needs updating instead of creating a new one
|
||||
if (queueMessage.wasVaultLocked) {
|
||||
const allCiphers = await this.cipherService.getAllDecryptedForUrl(
|
||||
queueMessage.uri,
|
||||
queueMessage.data.uri,
|
||||
activeUserId,
|
||||
);
|
||||
const existingCipher = allCiphers.find(
|
||||
(c) =>
|
||||
c.login.username != null && c.login.username.toLowerCase() === queueMessage.username,
|
||||
c.login.username != null &&
|
||||
c.login.username.toLowerCase() === queueMessage.data.username,
|
||||
);
|
||||
|
||||
if (existingCipher != null) {
|
||||
await this.updatePassword(existingCipher, queueMessage.password, edit, tab, activeUserId);
|
||||
await this.updatePassword(
|
||||
existingCipher,
|
||||
queueMessage.data.password,
|
||||
edit,
|
||||
tab,
|
||||
activeUserId,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1276,15 +1287,15 @@ export default class NotificationBackground {
|
||||
folderId?: string,
|
||||
): CipherView {
|
||||
const uriView = new LoginUriView();
|
||||
uriView.uri = message.uri;
|
||||
uriView.uri = message.data.uri;
|
||||
|
||||
const loginView = new LoginView();
|
||||
loginView.uris = [uriView];
|
||||
loginView.username = message.username;
|
||||
loginView.password = message.password;
|
||||
loginView.username = message.data.username;
|
||||
loginView.password = message.data.password;
|
||||
|
||||
const cipherView = new CipherView();
|
||||
cipherView.name = (Utils.getHostname(message.uri) || message.domain).replace(/^www\./, "");
|
||||
cipherView.name = (Utils.getHostname(message.data.uri) || message.domain).replace(/^www\./, "");
|
||||
cipherView.folderId = folderId;
|
||||
cipherView.type = CipherType.Login;
|
||||
cipherView.login = loginView;
|
||||
|
||||
Reference in New Issue
Block a user