mirror of
https://github.com/bitwarden/browser
synced 2026-02-02 17:53:41 +00:00
Added log message on every logout with a reason.
This commit is contained in:
@@ -141,7 +141,7 @@ export class AccountSwitcherComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
|
||||
if (confirmed) {
|
||||
await this.logoutService.logout(userId);
|
||||
await this.logoutService.logout(userId, "userInitiated");
|
||||
// navigate to root so redirect guard can properly route next active user or null user to correct page
|
||||
await this.router.navigate(["/"]);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { LogoutReason, LogoutService } from "@bitwarden/auth/common";
|
||||
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { LogService } from "@bitwarden/logging";
|
||||
|
||||
import { AccountSwitcherService } from "../account-switching/services/account-switcher.service";
|
||||
|
||||
@@ -13,6 +14,7 @@ describe("ExtensionLogoutService", () => {
|
||||
let logoutService: LogoutService;
|
||||
let messagingService: MockProxy<MessagingService>;
|
||||
let accountSwitcherService: MockProxy<AccountSwitcherService>;
|
||||
let logService: MockProxy<LogService>;
|
||||
|
||||
let primaryUserId: UserId;
|
||||
let secondaryUserId: UserId;
|
||||
@@ -25,7 +27,12 @@ describe("ExtensionLogoutService", () => {
|
||||
|
||||
messagingService = mock<MessagingService>();
|
||||
accountSwitcherService = mock<AccountSwitcherService>();
|
||||
logoutService = new ExtensionLogoutService(messagingService, accountSwitcherService);
|
||||
|
||||
logoutService = new ExtensionLogoutService(
|
||||
messagingService,
|
||||
accountSwitcherService,
|
||||
logService,
|
||||
);
|
||||
});
|
||||
|
||||
it("instantiates", () => {
|
||||
@@ -38,16 +45,7 @@ describe("ExtensionLogoutService", () => {
|
||||
accountSwitcherService.listenForSwitchAccountFinish.mockResolvedValue(null);
|
||||
});
|
||||
|
||||
it("sends logout message without a logout reason when not provided", async () => {
|
||||
const result = await logoutService.logout(primaryUserId);
|
||||
|
||||
expect(accountSwitcherService.listenForSwitchAccountFinish).toHaveBeenCalledTimes(1);
|
||||
expect(messagingService.send).toHaveBeenCalledWith("logout", { userId: primaryUserId });
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it("sends logout message with a logout reason when provided", async () => {
|
||||
it("sends logout message with a logout reason", async () => {
|
||||
const result = await logoutService.logout(primaryUserId, logoutReason);
|
||||
|
||||
expect(accountSwitcherService.listenForSwitchAccountFinish).toHaveBeenCalledTimes(1);
|
||||
@@ -69,20 +67,7 @@ describe("ExtensionLogoutService", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("sends logout message without a logout reason when not provided and returns the new active user", async () => {
|
||||
const result = await logoutService.logout(primaryUserId);
|
||||
|
||||
expect(accountSwitcherService.listenForSwitchAccountFinish).toHaveBeenCalledTimes(1);
|
||||
|
||||
expect(messagingService.send).toHaveBeenCalledWith("logout", { userId: primaryUserId });
|
||||
|
||||
expect(result).toEqual({
|
||||
userId: secondaryUserId,
|
||||
authenticationStatus: newActiveUserAuthenticationStatus,
|
||||
});
|
||||
});
|
||||
|
||||
it("sends logout message with a logout reason when provided and returns the new active user", async () => {
|
||||
it("sends logout message with a logout reason and returns the new active user", async () => {
|
||||
const result = await logoutService.logout(primaryUserId, logoutReason);
|
||||
|
||||
expect(accountSwitcherService.listenForSwitchAccountFinish).toHaveBeenCalledTimes(1);
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
} from "@bitwarden/auth/common";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { LogService } from "@bitwarden/logging";
|
||||
|
||||
import { AccountSwitcherService } from "../account-switching/services/account-switcher.service";
|
||||
|
||||
@@ -13,14 +14,17 @@ export class ExtensionLogoutService extends DefaultLogoutService implements Logo
|
||||
constructor(
|
||||
protected messagingService: MessagingService,
|
||||
private accountSwitcherService: AccountSwitcherService,
|
||||
protected logService: LogService,
|
||||
) {
|
||||
super(messagingService);
|
||||
super(messagingService, logService);
|
||||
}
|
||||
|
||||
override async logout(
|
||||
userId: UserId,
|
||||
logoutReason?: LogoutReason,
|
||||
logoutReason: LogoutReason,
|
||||
): Promise<NewActiveUser | undefined> {
|
||||
this.logService.info("Logging out user %s for reason: %s", userId, logoutReason);
|
||||
|
||||
// logout can result in an account switch to the next up user
|
||||
const accountSwitchFinishPromise =
|
||||
this.accountSwitcherService.listenForSwitchAccountFinish(null);
|
||||
|
||||
@@ -1256,7 +1256,7 @@ export default class MainBackground {
|
||||
this.authService,
|
||||
);
|
||||
|
||||
const logoutService = new DefaultLogoutService(this.messagingService);
|
||||
const logoutService = new DefaultLogoutService(this.messagingService, this.logService);
|
||||
this.lockService = new ExtensionLockService(
|
||||
this.accountService,
|
||||
this.biometricsService,
|
||||
|
||||
@@ -675,7 +675,7 @@ const safeProviders: SafeProvider[] = [
|
||||
safeProvider({
|
||||
provide: LogoutService,
|
||||
useClass: ExtensionLogoutService,
|
||||
deps: [MessagingServiceAbstraction, AccountSwitcherService],
|
||||
deps: [MessagingServiceAbstraction, AccountSwitcherService, LogService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: CompactModeService,
|
||||
|
||||
@@ -596,6 +596,7 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
let toastOptions: ToastOptions;
|
||||
|
||||
switch (logoutReason) {
|
||||
case "invalidAccessToken":
|
||||
case "invalidSecurityStamp":
|
||||
case "sessionExpired": {
|
||||
toastOptions = {
|
||||
|
||||
@@ -271,7 +271,7 @@ export class SetInitialPasswordComponent implements OnInit {
|
||||
|
||||
this.showSuccessToastByUserType();
|
||||
|
||||
await this.logoutService.logout(this.userId);
|
||||
await this.logoutService.logout(this.userId, "setInitialPassword");
|
||||
// navigate to root so redirect guard can properly route next active user or null user to correct page
|
||||
await this.router.navigate(["/"]);
|
||||
} catch (e) {
|
||||
|
||||
@@ -1697,7 +1697,7 @@ const safeProviders: SafeProvider[] = [
|
||||
safeProvider({
|
||||
provide: LogoutService,
|
||||
useClass: DefaultLogoutService,
|
||||
deps: [MessagingServiceAbstraction],
|
||||
deps: [MessagingServiceAbstraction, LogService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: DocumentLangSetter,
|
||||
|
||||
@@ -167,7 +167,7 @@ export class LoginDecryptionOptionsComponent implements OnInit {
|
||||
message: this.i18nService.t("activeUserEmailNotFoundLoggingYouOut"),
|
||||
});
|
||||
|
||||
await this.logoutService.logout(this.activeAccountId);
|
||||
await this.logoutService.logout(this.activeAccountId, "missingEmailError");
|
||||
// navigate to root so redirect guard can properly route next active user or null user to correct page
|
||||
await this.router.navigate(["/"]);
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ export abstract class LogoutService {
|
||||
/**
|
||||
* Logs out the user.
|
||||
* @param userId The user id.
|
||||
* @param logoutReason The optional reason for logging out.
|
||||
* @param logoutReason The reason for logging out.
|
||||
* @returns The new active user or undefined if there isn't a new active account.
|
||||
*/
|
||||
abstract logout(userId: UserId, logoutReason?: LogoutReason): Promise<NewActiveUser | undefined>;
|
||||
abstract logout(userId: UserId, logoutReason: LogoutReason): Promise<NewActiveUser | undefined>;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { MockProxy, mock } from "jest-mock-extended";
|
||||
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { LogService } from "@bitwarden/logging";
|
||||
|
||||
import { LogoutService } from "../../abstractions";
|
||||
import { LogoutReason } from "../../types";
|
||||
@@ -11,10 +12,12 @@ import { DefaultLogoutService } from "./default-logout.service";
|
||||
describe("DefaultLogoutService", () => {
|
||||
let logoutService: LogoutService;
|
||||
let messagingService: MockProxy<MessagingService>;
|
||||
let logService: MockProxy<LogService>;
|
||||
|
||||
beforeEach(() => {
|
||||
messagingService = mock<MessagingService>();
|
||||
logoutService = new DefaultLogoutService(messagingService);
|
||||
logService = mock<LogService>();
|
||||
logoutService = new DefaultLogoutService(messagingService, logService);
|
||||
});
|
||||
|
||||
it("instantiates", () => {
|
||||
@@ -22,15 +25,7 @@ describe("DefaultLogoutService", () => {
|
||||
});
|
||||
|
||||
describe("logout", () => {
|
||||
it("sends logout message without a logout reason when not provided", async () => {
|
||||
const userId = "1" as UserId;
|
||||
|
||||
await logoutService.logout(userId);
|
||||
|
||||
expect(messagingService.send).toHaveBeenCalledWith("logout", { userId });
|
||||
});
|
||||
|
||||
it("sends logout message with a logout reason when provided", async () => {
|
||||
it("sends logout message with a logout reason", async () => {
|
||||
const userId = "1" as UserId;
|
||||
const logoutReason: LogoutReason = "vaultTimeout";
|
||||
await logoutService.logout(userId, logoutReason);
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { LogService } from "@bitwarden/logging";
|
||||
|
||||
import { LogoutService, NewActiveUser } from "../../abstractions/logout.service";
|
||||
import { LogoutReason } from "../../types";
|
||||
|
||||
export class DefaultLogoutService implements LogoutService {
|
||||
constructor(protected messagingService: MessagingService) {}
|
||||
async logout(userId: UserId, logoutReason?: LogoutReason): Promise<NewActiveUser | undefined> {
|
||||
constructor(
|
||||
protected messagingService: MessagingService,
|
||||
protected logService: LogService,
|
||||
) {}
|
||||
async logout(userId: UserId, logoutReason: LogoutReason): Promise<NewActiveUser | undefined> {
|
||||
this.logService.info("Logging out user %s for reason: %s", userId, logoutReason);
|
||||
this.messagingService.send("logout", { userId, logoutReason });
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,7 +371,7 @@ export class LockComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
|
||||
if (confirmed && this.activeAccount != null) {
|
||||
await this.logoutService.logout(this.activeAccount.id);
|
||||
await this.logoutService.logout(this.activeAccount.id, "userInitiated");
|
||||
// navigate to root so redirect guard can properly route next active user or null user to correct page
|
||||
await this.router.navigate(["/"]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user