diff --git a/browser-extensions/chrome/src/app/components/GlobalStateChangeHandler.tsx b/browser-extensions/chrome/src/app/components/GlobalStateChangeHandler.tsx
index 3cb090cc3..614f51559 100644
--- a/browser-extensions/chrome/src/app/components/GlobalStateChangeHandler.tsx
+++ b/browser-extensions/chrome/src/app/components/GlobalStateChangeHandler.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect } from 'react';
+import React, { useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
@@ -9,13 +9,15 @@ import { useAuth } from '../context/AuthContext';
const GlobalStateChangeHandler: React.FC = () => {
const authContext = useAuth();
const navigate = useNavigate();
+ const lastLoginState = useRef(authContext.isLoggedIn);
/**
* Listen for auth logged in changes and redirect to home page if logged in state changes to handle logins and logouts.
*/
useEffect(() => {
- // Only navigate when auth state changes and we're not already on home page
- if (window.location.pathname !== '/index.html' && window.location.pathname !== '/') {
+ // Only navigate when auth state is different from the last state we acted on.
+ if (lastLoginState.current !== authContext.isLoggedIn) {
+ lastLoginState.current = authContext.isLoggedIn;
navigate('/');
}
}, [authContext.isLoggedIn]); // eslint-disable-line react-hooks/exhaustive-deps
diff --git a/browser-extensions/chrome/src/app/pages/CredentialsList.tsx b/browser-extensions/chrome/src/app/pages/CredentialsList.tsx
index 18c82a3e8..e53ee24cc 100644
--- a/browser-extensions/chrome/src/app/pages/CredentialsList.tsx
+++ b/browser-extensions/chrome/src/app/pages/CredentialsList.tsx
@@ -10,7 +10,6 @@ import ReloadButton from '../components/ReloadButton';
import { useAuth } from '../context/AuthContext';
import LoadingSpinner from '../components/LoadingSpinner';
import { useMinDurationLoading } from '../hooks/useMinDurationLoading';
-import { AppInfo } from '../../shared/AppInfo';
/**
* Credentials list page.
@@ -38,15 +37,9 @@ const CredentialsList: React.FC = () => {
// Do status check first to ensure the extension is (still) supported.
const statusResponse = await webApi.getStatus();
- console.log('CredentialsList: statusResponse', statusResponse);
- if (!statusResponse.clientVersionSupported) {
- authContext.logout('This version of the AliasVault browser extension is outdated. Please update your browser extension to the latest version.');
- return;
- }
-
- // Check if server version is supported by this client.
- if (!AppInfo.isServerVersionSupported(statusResponse.serverVersion)) {
- authContext.logout('The AliasVault server needs to be updated to a newer version in order to use this browser extension. Please contact support if you need help.');
+ const statusError = webApi.validateStatusResponse(statusResponse);
+ if (statusError !== null) {
+ authContext.logout(statusError);
return;
}
diff --git a/browser-extensions/chrome/src/app/pages/Home.tsx b/browser-extensions/chrome/src/app/pages/Home.tsx
index 81ff82c7d..e2995e7a9 100644
--- a/browser-extensions/chrome/src/app/pages/Home.tsx
+++ b/browser-extensions/chrome/src/app/pages/Home.tsx
@@ -38,29 +38,20 @@ const Home: React.FC = () => {
// Show loading state if not fully initialized or when about to redirect to credentials.
if (!isFullyInitialized || (isFullyInitialized && !requireLoginOrUnlock)) {
// Global loading spinner will be shown by the parent component.
- console.log('Home: not fully initialized');
return null;
}
setIsInitialLoading(false);
if (!isAuthenticated) {
- console.log('Home: not authenticated');
return ;
}
if (!isDatabaseAvailable) {
- console.log('isFullyInitialized', isFullyInitialized);
- console.log('isAuthenticated', isAuthenticated);
- console.log('isDatabaseAvailable', isDatabaseAvailable);
- console.log('isInlineUnlockMode', isInlineUnlockMode);
- console.log('requireLoginOrUnlock', requireLoginOrUnlock);
- console.log('Home: not database available');
return ;
}
if (isInlineUnlockMode) {
- console.log('Home: inline unlock mode');
return setIsInlineUnlockMode(false)} />;
}
diff --git a/browser-extensions/chrome/src/app/pages/Login.tsx b/browser-extensions/chrome/src/app/pages/Login.tsx
index c4f12058c..62f582f57 100644
--- a/browser-extensions/chrome/src/app/pages/Login.tsx
+++ b/browser-extensions/chrome/src/app/pages/Login.tsx
@@ -167,7 +167,6 @@ const Login: React.FC = () => {
return;
}
-
// All is good. Store auth info which is required to make requests to the web API.
await authContext.setAuthTokens(credentials.username, validationResponse.token.token, validationResponse.token.refreshToken);
diff --git a/browser-extensions/chrome/src/app/pages/Unlock.tsx b/browser-extensions/chrome/src/app/pages/Unlock.tsx
index a8c25055b..34b286d78 100644
--- a/browser-extensions/chrome/src/app/pages/Unlock.tsx
+++ b/browser-extensions/chrome/src/app/pages/Unlock.tsx
@@ -28,9 +28,11 @@ const Unlock: React.FC = () => {
* Make status call to API which acts as health check.
*/
const checkStatus = async () : Promise => {
- const status = await webApi.getStatus();
- if (!status.clientVersionSupported) {
- authContext.logout('The browser extension is outdated. Please update to the latest version.');
+ const statusResponse = await webApi.getStatus();
+ const statusError = webApi.validateStatusResponse(statusResponse);
+ if (statusError !== null) {
+ authContext.logout(statusError);
+ return;
}
};
diff --git a/browser-extensions/chrome/src/background/VaultMessageHandler.ts b/browser-extensions/chrome/src/background/VaultMessageHandler.ts
index 95d97dcb5..22d3dbfde 100644
--- a/browser-extensions/chrome/src/background/VaultMessageHandler.ts
+++ b/browser-extensions/chrome/src/background/VaultMessageHandler.ts
@@ -45,10 +45,10 @@ export async function handleSyncVault(
sendResponse: (response: any) => void
) : Promise {
const webApi = new WebApiService(() => {});
- const response = await webApi.getStatus();
-
- if (!response.clientVersionSupported) {
- sendResponse({ success: false, error: 'The browser extension is outdated. Please update to the latest version.' });
+ const statusResponse = await webApi.getStatus();
+ const statusError = webApi.validateStatusResponse(statusResponse);
+ if (statusError !== null) {
+ sendResponse({ success: false, error: statusError });
return;
}
@@ -56,7 +56,7 @@ export async function handleSyncVault(
'vaultRevisionNumber'
]);
- if (response.vaultRevision > result.vaultRevisionNumber) {
+ if (statusResponse.vaultRevision > result.vaultRevisionNumber) {
// Retrieve the latest vault from the server.
const vaultResponse = await webApi.get('Vault');
diff --git a/browser-extensions/chrome/src/shared/AppInfo.ts b/browser-extensions/chrome/src/shared/AppInfo.ts
index 32453e0de..c79576321 100644
--- a/browser-extensions/chrome/src/shared/AppInfo.ts
+++ b/browser-extensions/chrome/src/shared/AppInfo.ts
@@ -2,14 +2,20 @@
* AppInfo class which contains information about the application version.
*/
export class AppInfo {
- // Current extension version - should be updated with each release.
+ /**
+ * The current extension version. This should be updated with each release of the extension.
+ */
public static readonly VERSION = '0.12.0';
- // Minimum supported AliasVault server (API) version. If the server version is below this, the
- // client will throw an error stating that the server should be updated.
- public static readonly MIN_SERVER_VERSION = '0.13.0';
+ /**
+ * The minimum supported AliasVault server (API) version. If the server version is below this, the
+ * client will throw an error stating that the server should be updated.
+ */
+ public static readonly MIN_SERVER_VERSION = '0.12.0-dev';
- // Minimum supported AliasVault client vault version.
+ /**
+ * The minimum supported AliasVault client vault version.
+ */
public static readonly MIN_VAULT_VERSION = '1.4.1';
/*
@@ -65,8 +71,7 @@ export class AppInfo {
if (part1 < part2) return false;
}
- // If core versions are equal, check pre-release versions
- // No pre-release > pre-release
+ // If core versions are equal, check pre-release versions.
if (!preRelease1 && preRelease2) return true;
if (preRelease1 && !preRelease2) return false;
if (!preRelease1 && !preRelease2) return true;
diff --git a/browser-extensions/chrome/src/shared/WebApiService.ts b/browser-extensions/chrome/src/shared/WebApiService.ts
index 99611754e..93eac7714 100644
--- a/browser-extensions/chrome/src/shared/WebApiService.ts
+++ b/browser-extensions/chrome/src/shared/WebApiService.ts
@@ -218,6 +218,21 @@ export class WebApiService {
return await this.get('Auth/status');
}
+ /**
+ * Validates the status response and returns an error message if validation fails.
+ */
+ public validateStatusResponse(statusResponse: StatusResponse): string | null {
+ if (!statusResponse.clientVersionSupported) {
+ return 'This version of the AliasVault browser extension is outdated. Please update your browser extension to the latest version.';
+ }
+
+ if (!AppInfo.isServerVersionSupported(statusResponse.serverVersion)) {
+ return 'The AliasVault server needs to be updated to a newer version in order to use this browser extension. Please contact support if you need help.';
+ }
+
+ return null;
+ }
+
/**
* Validates the vault response and returns an error message if validation fails
*/
diff --git a/browser-extensions/chrome/src/shared/__tests__/AppInfo.test.ts b/browser-extensions/chrome/src/shared/__tests__/AppInfo.test.ts
index 5c09cb06c..caa6f464c 100644
--- a/browser-extensions/chrome/src/shared/__tests__/AppInfo.test.ts
+++ b/browser-extensions/chrome/src/shared/__tests__/AppInfo.test.ts
@@ -1,7 +1,6 @@
import { AppInfo } from '../AppInfo';
import { describe, it, expect } from 'vitest';
-
describe('AppInfo', () => {
describe('isVersionSupported', () => {
it('should support exact version match', () => {
diff --git a/src/Shared/AliasVault.Shared.Core/AppInfo.cs b/src/Shared/AliasVault.Shared.Core/AppInfo.cs
index 8361817a1..33a40564b 100644
--- a/src/Shared/AliasVault.Shared.Core/AppInfo.cs
+++ b/src/Shared/AliasVault.Shared.Core/AppInfo.cs
@@ -25,12 +25,12 @@ public static class AppInfo
///
/// Gets the minor version number.
///
- public const int VersionMinor = 11;
+ public const int VersionMinor = 12;
///
/// Gets the patch version number.
///
- public const int VersionPatch = 1;
+ public const int VersionPatch = 0;
///
/// Gets a dictionary of minimum supported client versions that the WebApi supports.