mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: add forced password change page on first login
The backend sets mustChangePassword=true for all new accounts and blocks API calls until the password is changed. The frontend was not handling this flag - it logged the user in and redirected to the dashboard where every API call silently failed with 403. Add a /change-password page that is shown when mustChangePassword is true. The login page now redirects there instead of home, and the AuthGuard intercepts any direct navigation to force the change first.
This commit is contained in:
@@ -4,6 +4,7 @@ interface AuthState {
|
||||
loading: boolean;
|
||||
authEnabled: boolean;
|
||||
isAuthenticated: boolean;
|
||||
mustChangePassword: boolean;
|
||||
}
|
||||
|
||||
export function useAuth(): AuthState {
|
||||
@@ -11,6 +12,7 @@ export function useAuth(): AuthState {
|
||||
loading: true,
|
||||
authEnabled: false,
|
||||
isAuthenticated: false,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
@@ -21,14 +23,24 @@ export function useAuth(): AuthState {
|
||||
const config = await configRes.json();
|
||||
|
||||
if (!config.authEnabled) {
|
||||
setState({ loading: false, authEnabled: false, isAuthenticated: true });
|
||||
setState({
|
||||
loading: false,
|
||||
authEnabled: false,
|
||||
isAuthenticated: true,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Auth is enabled — check if we have a valid session
|
||||
const token = localStorage.getItem("stirling-token");
|
||||
if (!token) {
|
||||
setState({ loading: false, authEnabled: true, isAuthenticated: false });
|
||||
setState({
|
||||
loading: false,
|
||||
authEnabled: true,
|
||||
isAuthenticated: false,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -37,14 +49,31 @@ export function useAuth(): AuthState {
|
||||
});
|
||||
|
||||
if (sessionRes.ok) {
|
||||
setState({ loading: false, authEnabled: true, isAuthenticated: true });
|
||||
const session = await sessionRes.json();
|
||||
const mustChange = session.user?.mustChangePassword === true;
|
||||
setState({
|
||||
loading: false,
|
||||
authEnabled: true,
|
||||
isAuthenticated: true,
|
||||
mustChangePassword: mustChange,
|
||||
});
|
||||
} else {
|
||||
localStorage.removeItem("stirling-token");
|
||||
setState({ loading: false, authEnabled: true, isAuthenticated: false });
|
||||
setState({
|
||||
loading: false,
|
||||
authEnabled: true,
|
||||
isAuthenticated: false,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
// Can't reach API — assume no auth needed (dev mode)
|
||||
setState({ loading: false, authEnabled: false, isAuthenticated: true });
|
||||
setState({
|
||||
loading: false,
|
||||
authEnabled: false,
|
||||
isAuthenticated: true,
|
||||
mustChangePassword: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user