Dispatcharr/frontend/src/store/auth.jsx
2025-03-11 17:43:16 -04:00

132 lines
3.8 KiB
JavaScript

import { create } from 'zustand';
import API from '../api';
import useChannelsStore from './channels';
import useUserAgentsStore from './userAgents';
import usePlaylistsStore from './playlists';
import useEPGsStore from './epgs';
import useStreamProfilesStore from './streamProfiles';
import useSettingsStore from './settings';
const decodeToken = (token) => {
if (!token) return null;
const payload = token.split('.')[1];
const decodedPayload = JSON.parse(atob(payload));
return decodedPayload.exp;
};
const isTokenExpired = (expirationTime) => {
const now = Math.floor(Date.now() / 1000);
return now >= expirationTime;
};
const useAuthStore = create((set, get) => ({
accessToken: localStorage.getItem('accessToken') || null,
refreshToken: localStorage.getItem('refreshToken') || null,
tokenExpiration: localStorage.getItem('tokenExpiration') || null,
superuserExists: true,
isAuthenticated: false,
setIsAuthenticated: (isAuthenticated) => set({ isAuthenticated }),
setSuperuserExists: (superuserExists) => set({ superuserExists }),
initData: async () => {
await Promise.all([
useChannelsStore.getState().fetchChannels(),
useChannelsStore.getState().fetchChannelGroups(),
useUserAgentsStore.getState().fetchUserAgents(),
usePlaylistsStore.getState().fetchPlaylists(),
useEPGsStore.getState().fetchEPGs(),
useStreamProfilesStore.getState().fetchProfiles(),
useSettingsStore.getState().fetchSettings(),
]);
},
getToken: async () => {
const tokenExpiration = localStorage.getItem('tokenExpiration');
let accessToken = null;
if (isTokenExpired(tokenExpiration)) {
accessToken = await get().refreshToken();
} else {
accessToken = localStorage.getItem('accessToken');
}
return accessToken;
},
// Action to login
login: async ({ username, password }) => {
try {
const response = await API.login(username, password);
if (response.access) {
const expiration = decodeToken(response.access);
set({
accessToken: response.access,
refreshToken: response.refresh,
tokenExpiration: expiration, // 1 hour from now
isAuthenticated: true,
});
// Store in localStorage
localStorage.setItem('accessToken', response.access);
localStorage.setItem('refreshToken', response.refresh);
localStorage.setItem('tokenExpiration', expiration);
}
} catch (error) {
console.error('Login failed:', error);
}
},
// Action to refresh the token
refreshToken: async () => {
const refreshToken = localStorage.getItem('refreshToken');
if (!refreshToken) return;
try {
const data = await API.refreshToken(refreshToken);
if (data.access) {
set({
accessToken: data.access,
tokenExpiration: decodeToken(data.access),
isAuthenticated: true,
});
localStorage.setItem('accessToken', data.access);
localStorage.setItem('tokenExpiration', decodeToken(data.access));
return true;
}
} catch (error) {
console.error('Token refresh failed:', error);
get().logout();
}
return false;
},
// Action to logout
logout: () => {
set({
accessToken: null,
refreshToken: null,
tokenExpiration: null,
isAuthenticated: false,
});
localStorage.removeItem('accessToken');
localStorage.removeItem('refreshToken');
localStorage.removeItem('tokenExpiration');
},
initializeAuth: async () => {
const refreshToken = localStorage.getItem('refreshToken') || null;
if (refreshToken) {
const loggedIn = await get().refreshToken();
if (loggedIn) {
return true;
}
}
return false;
},
}));
export default useAuthStore;