REFACTOR: Removido Mock e assegurado login com JWT
This commit is contained in:
parent
eb6e4faf2c
commit
04971ca82e
@ -6,6 +6,7 @@ import {
|
|||||||
startMicrosoftLogin,
|
startMicrosoftLogin,
|
||||||
storeAuthSession,
|
storeAuthSession,
|
||||||
} from '../services/authService';
|
} from '../services/authService';
|
||||||
|
import { isAuthenticated } from '../services/sessionService';
|
||||||
|
|
||||||
function decodeAuthPayload(payload) {
|
function decodeAuthPayload(payload) {
|
||||||
const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');
|
const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');
|
||||||
@ -21,10 +22,15 @@ export function useLogin() {
|
|||||||
const [providers, setProviders] = useState({ ldap: true, microsoft: false });
|
const [providers, setProviders] = useState({ ldap: true, microsoft: false });
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!window.location.hash.includes('auth=') && isAuthenticated()) {
|
||||||
|
navigate('/home', { replace: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
getAuthConfig()
|
getAuthConfig()
|
||||||
.then((config) => setProviders(config.providers || { ldap: true, microsoft: false }))
|
.then((config) => setProviders(config.providers || { ldap: true, microsoft: false }))
|
||||||
.catch(() => setProviders({ ldap: true, microsoft: false }));
|
.catch(() => setProviders({ ldap: true, microsoft: false }));
|
||||||
}, []);
|
}, [navigate]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const hashParams = new URLSearchParams(window.location.hash.replace(/^#/, ''));
|
const hashParams = new URLSearchParams(window.location.hash.replace(/^#/, ''));
|
||||||
@ -38,23 +44,13 @@ export function useLogin() {
|
|||||||
return;
|
return;
|
||||||
} catch {
|
} catch {
|
||||||
window.history.replaceState({}, document.title, window.location.pathname);
|
window.history.replaceState({}, document.title, window.location.pathname);
|
||||||
setError('Não foi possível concluir o login Microsoft.');
|
setError('Nao foi possivel concluir o login Microsoft.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const params = new URLSearchParams(window.location.search);
|
if (window.location.search.includes('token=') || window.location.search.includes('user=')) {
|
||||||
const token = params.get('token');
|
|
||||||
const rawUser = params.get('user');
|
|
||||||
|
|
||||||
if (!token || !rawUser) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const user = JSON.parse(rawUser);
|
|
||||||
storeAuthSession({ token, user });
|
|
||||||
window.history.replaceState({}, document.title, window.location.pathname);
|
window.history.replaceState({}, document.title, window.location.pathname);
|
||||||
navigate('/home', { replace: true });
|
setError('Fluxo de login expirado. Tente novamente.');
|
||||||
} catch {
|
|
||||||
setError('Não foi possível concluir o login Microsoft.');
|
|
||||||
}
|
}
|
||||||
}, [navigate]);
|
}, [navigate]);
|
||||||
|
|
||||||
|
|||||||
@ -30,6 +30,10 @@ export function startMicrosoftLogin() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function storeAuthSession(authResult) {
|
export function storeAuthSession(authResult) {
|
||||||
|
if (!authResult?.token || !authResult?.user) {
|
||||||
|
throw new Error('Sessao de autenticacao invalida.');
|
||||||
|
}
|
||||||
|
|
||||||
window.sessionStorage.setItem('authToken', authResult.token);
|
window.sessionStorage.setItem('authToken', authResult.token);
|
||||||
window.sessionStorage.setItem('authUser', JSON.stringify(authResult.user));
|
window.sessionStorage.setItem('authUser', JSON.stringify(authResult.user));
|
||||||
window.localStorage.removeItem('authToken');
|
window.localStorage.removeItem('authToken');
|
||||||
|
|||||||
@ -22,6 +22,33 @@ function readStoredUser() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function decodeJwtPayload(token) {
|
||||||
|
const [, payload] = String(token || '').split('.');
|
||||||
|
|
||||||
|
if (!payload) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const base64 = payload.replace(/-/g, '+').replace(/_/g, '/');
|
||||||
|
const paddedBase64 = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), '=');
|
||||||
|
|
||||||
|
return JSON.parse(window.atob(paddedBase64));
|
||||||
|
} catch {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isTokenExpired(token) {
|
||||||
|
const payload = decodeJwtPayload(token);
|
||||||
|
|
||||||
|
if (!payload?.exp) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload.exp * 1000 <= Date.now();
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeProfile(value) {
|
function normalizeProfile(value) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return null;
|
return null;
|
||||||
@ -61,7 +88,14 @@ export function getCurrentUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getAuthToken() {
|
export function getAuthToken() {
|
||||||
return window.sessionStorage.getItem('authToken');
|
const token = window.sessionStorage.getItem('authToken');
|
||||||
|
|
||||||
|
if (!token || isTokenExpired(token)) {
|
||||||
|
clearSession();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isAuthenticated() {
|
export function isAuthenticated() {
|
||||||
@ -70,7 +104,7 @@ export function isAuthenticated() {
|
|||||||
|
|
||||||
export function getCurrentUserDisplay() {
|
export function getCurrentUserDisplay() {
|
||||||
const user = getCurrentUser();
|
const user = getCurrentUser();
|
||||||
const fullName = user?.name || user?.nome || user?.username || 'Ana Camolesi';
|
const fullName = user?.name || user?.nome || user?.username || user?.email || 'Usuario';
|
||||||
const nameParts = fullName.split(' ').filter(Boolean);
|
const nameParts = fullName.split(' ').filter(Boolean);
|
||||||
const name =
|
const name =
|
||||||
nameParts.length > 1 ? `${nameParts[0]} ${nameParts[nameParts.length - 1]}` : fullName;
|
nameParts.length > 1 ? `${nameParts[0]} ${nameParts[nameParts.length - 1]}` : fullName;
|
||||||
@ -94,7 +128,7 @@ export function getCurrentUserDisplay() {
|
|||||||
return {
|
return {
|
||||||
name,
|
name,
|
||||||
subtitle,
|
subtitle,
|
||||||
initials: initials || 'AM',
|
initials: initials || 'US',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,14 @@
|
|||||||
import { Navigate } from 'react-router-dom';
|
import { Navigate } from 'react-router-dom';
|
||||||
import { isAuthenticated } from '../modules/auth/services/sessionService';
|
import { getCurrentUserProfile, isAuthenticated } from '../modules/auth/services/sessionService';
|
||||||
|
|
||||||
export function ProtectedRoute({ children }) {
|
export function ProtectedRoute({ children, allowedProfiles = [] }) {
|
||||||
if (!isAuthenticated()) {
|
if (!isAuthenticated()) {
|
||||||
return <Navigate to="/login" replace />;
|
return <Navigate to="/login" replace />;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allowedProfiles.length && !allowedProfiles.includes(getCurrentUserProfile())) {
|
||||||
|
return <Navigate to="/home" replace />;
|
||||||
|
}
|
||||||
|
|
||||||
return children;
|
return children;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,8 +9,8 @@ import { AgentNewAttendancePage } from '../modules/attendance/pages/AgentNewAtte
|
|||||||
import { WhatsappAdminPage } from '../modules/management/pages/WhatsappAdminPage';
|
import { WhatsappAdminPage } from '../modules/management/pages/WhatsappAdminPage';
|
||||||
import { ProtectedRoute } from './ProtectedRoute';
|
import { ProtectedRoute } from './ProtectedRoute';
|
||||||
|
|
||||||
function privatePage(page) {
|
function privatePage(page, allowedProfiles = []) {
|
||||||
return <ProtectedRoute>{page}</ProtectedRoute>;
|
return <ProtectedRoute allowedProfiles={allowedProfiles}>{page}</ProtectedRoute>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const router = createBrowserRouter([
|
export const router = createBrowserRouter([
|
||||||
@ -48,6 +48,6 @@ export const router = createBrowserRouter([
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/admin/whatsapp',
|
path: '/admin/whatsapp',
|
||||||
element: privatePage(<WhatsappAdminPage />),
|
element: privatePage(<WhatsappAdminPage />, ['admin']),
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { API_BASE_URL } from './apiConfig';
|
import { API_BASE_URL } from './apiConfig';
|
||||||
|
import { clearSession } from '../../modules/auth/services/sessionService';
|
||||||
|
|
||||||
function getStoredToken() {
|
function getStoredToken() {
|
||||||
return window.sessionStorage.getItem('authToken');
|
return window.sessionStorage.getItem('authToken');
|
||||||
@ -16,7 +17,7 @@ export function installAuthFetchInterceptor() {
|
|||||||
|
|
||||||
const nativeFetch = window.fetch.bind(window);
|
const nativeFetch = window.fetch.bind(window);
|
||||||
|
|
||||||
window.fetch = (resource, options = {}) => {
|
window.fetch = async (resource, options = {}) => {
|
||||||
if (!shouldAttachToken(resource)) {
|
if (!shouldAttachToken(resource)) {
|
||||||
return nativeFetch(resource, options);
|
return nativeFetch(resource, options);
|
||||||
}
|
}
|
||||||
@ -27,9 +28,19 @@ export function installAuthFetchInterceptor() {
|
|||||||
headers.set('Authorization', `Bearer ${getStoredToken()}`);
|
headers.set('Authorization', `Bearer ${getStoredToken()}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nativeFetch(resource, {
|
const response = await nativeFetch(resource, {
|
||||||
...options,
|
...options,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (response.status === 401) {
|
||||||
|
clearSession();
|
||||||
|
|
||||||
|
if (window.location.pathname !== '/login') {
|
||||||
|
window.location.assign('/login');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user