Routing Problem from sign in page to a users account
The Issues is routing a user after creating an account on the webapp platform to the users dashboard created for the user.
I can provide with the sign in and authcontext.js page which helps with this.
signin.js
import React, { useState, useEffect } from 'react';
import { Link, useNavigate, useLocation } from 'react-router-dom';
import { useAuth } from '../../../contexts/AuthContext';
import './Login.css';
const Login = () => {
const [formData, setFormData] = useState({
email: '',
password: ''
});
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const { login, isAuthenticated } = useAuth();
const navigate = useNavigate();
const location = useLocation();
// Redirect if already logged in
useEffect(() => {
if (isAuthenticated) {
const from = location.state?.from?.pathname || '/';
navigate(from, { replace: true });
}
}, [isAuthenticated, navigate, location]);
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({
...prev,
[name]: value
}));
// Clear error when user starts typing
if (error) setError('');
};
const handleSubmit = async (e) => {
e.preventDefault();
setError('');
setLoading(true);
try {
const { email, password } = formData;
const result = await login(email, password);
if (result.success) {
// Redirect to the dashboard or previous page
const from = location.state?.from?.pathname || '/dashboard';
navigate(from, { replace: true });
} else {
setError(result.error || 'Login failed. Please try again.');
}
} catch (err) {
console.error('Login error:', err);
setError('An unexpected error occurred. Please try again.');
} finally {
setLoading(false);
}
};
return (
<div className="auth-page">
<nav className="navbar">
<div className="container">
<div className="logo">EnergyAI</div>
<div className="nav-links">
<Link to="/">Home</Link>
<Link to="/features">Features</Link>
<Link to="/contact">Contact</Link>
<div className="auth-buttons">
<Link to="/login" className="btn btn-outline active">Sign In</Link>
<Link to="/register" className="btn btn-primary">Sign Up</Link>
</div>
</div>
</div>
</nav>
<div className="auth-container">
<div className="auth-card">
<div className="auth-header">
<h1>Welcome Back</h1>
<p>Sign in to your EnergyAI account</p>
</div>
{error && (
<div className="alert alert-error">
{error}
</div>
)}
<form onSubmit={handleSubmit} className="auth-form">
<div className="form-group">
<label>Email Address</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
placeholder="Enter your email"
required
disabled={loading}
/>
</div>
<div className="form-group">
<div className="form-label-row">
<label>Password</label>
<Link to="/forgot-password" className="forgot-password">
Forgot password?
</Link>
</div>
<input
type="password"
name="password"
value={formData.password}
onChange={handleChange}
placeholder="••••••••"
required
disabled={loading}
/>
</div>
<div className="form-options">
<label className="checkbox-container">
<input
type="checkbox"
disabled={loading}
/>
<span className="checkmark"></span>
Remember me
</label>
</div>
<button
type="submit"
className="btn btn-primary btn-block"
disabled={loading}
>
{loading ? (
<>
<span className="spinner-border spinner-border-sm me-2" role="status" aria-hidden="true"></span>
Signing in...
</>
) : 'Sign In'}
</button>
<div className="auth-footer">
<p>Don't have an account? <Link to="/register">Sign up</Link></p>
</div>
</form>
</div>
</div>
</div>
);
};
export default Login;
authcontext.js
import { createContext, useContext, useState, useEffect } from 'react';
import axios from 'axios';
const ROLES = {
ADMIN: 'admin',
ENERGY_MANAGER: 'energy_manager',
FACILITY_MANAGER: 'facility_manager',
IT_ADMIN: 'it_admin',
VIEWER: 'viewer'
};
const PERMISSIONS = {
VIEW_DASHBOARD: 'view_dashboard',
MANAGE_ENERGY: 'manage_energy',
CONFIGURE_SYSTEM: 'configure_system',
MANAGE_USERS: 'manage_users',
VIEW_REPORTS: 'view_reports',
GENERATE_REPORTS: 'generate_reports'
};
const AuthContext = createContext(null);
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
const [token, setToken] = useState(localStorage.getItem('token'));
const [loading, setLoading] = useState(true);
const [permissions, setPermissions] = useState([]);
// Set axios default headers
useEffect(() => {
if (token) {
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
localStorage.setItem('token', token);
} else {
delete axios.defaults.headers.common['Authorization'];
localStorage.removeItem('token');
}
}, [token]);
// Load user data on mount and when token changes
useEffect(() => {
let isMounted = true;
const source = axios.CancelToken.source();
const loadUser = async () => {
if (!token) {
setLoading(false);
return;
}
// Skip if we already have user data
if (user && user.id) {
setLoading(false);
return;
}
try {
console.log('Loading user profile...');
const response = await axios.get('/api/auth/profile/', {
cancelToken: source.token,
headers: {
'Authorization': `Bearer ${token}`,
'Accept': 'application/json'
}
});
console.log('User profile loaded:', response.data);
if (isMounted && response.data) {
setUser(response.data);
setPermissions(getPermissionsForRole(response.data.role || 'viewer'));
}
} catch (error) {
if (axios.isCancel(error)) {
console.log('Profile request canceled:', error.message);
} else {
console.error('Failed to load user profile:', error);
// Log detailed error info
if (error.response) {
console.error('Response status:', error.response.status);
console.error('Response data:', error.response.data);
console.error('Response headers:', error.response.headers);
} else if (error.request) {
console.error('No response received:', error.request);
} else {
console.error('Error setting up request:', error.message);
}
// If token is invalid (401) or other auth error, clear it
if (isMounted && (!error.response || error.response.status === 401)) {
console.log('Clearing invalid token');
setToken(null);
setUser(null);
localStorage.removeItem('token');
}
}
} finally {
if (isMounted) {
setLoading(false);
}
}
};
// Only load user if we have a token
if (token) {
loadUser();
} else {
setLoading(false);
}
return () => {
isMounted = false;
source.cancel('Operation canceled by component unmount.');
};
}, [token]);
// Helper function to get permissions for a role
const getPermissionsForRole = (role) => {
const rolePermissions = {
[ROLES.ADMIN]: Object.values(PERMISSIONS),
[ROLES.ENERGY_MANAGER]: [
PERMISSIONS.VIEW_DASHBOARD,
PERMISSIONS.MANAGE_ENERGY,
PERMISSIONS.VIEW_REPORTS,
PERMISSIONS.GENERATE_REPORTS
],
[ROLES.FACILITY_MANAGER]: [
PERMISSIONS.VIEW_DASHBOARD,
PERMISSIONS.VIEW_REPORTS
],
[ROLES.IT_ADMIN]: [
PERMISSIONS.VIEW_DASHBOARD,
PERMISSIONS.CONFIGURE_SYSTEM
],
[ROLES.VIEWER]: [
PERMISSIONS.VIEW_DASHBOARD,
PERMISSIONS.VIEW_REPORTS
]
};
return rolePermissions[role] || [];
};
// Check if user has a specific permission
const hasPermission = (permission) => {
return permissions.includes(permission);
};
// Check if user has any of the given permissions
const hasAnyPermission = (requiredPermissions) => {
return requiredPermissions.some(permission =>
permissions.includes(permission)
);
};
// Check if user has all of the given permissions
const hasAllPermissions = (requiredPermissions) => {
return requiredPermissions.every(permission =>
permissions.includes(permission)
);
};
// Login function
const login = async (email, password) => {
// Prevent multiple login attempts
if (loading) {
return {
success: false,
error: 'Login in progress. Please wait...'
};
}
setLoading(true);
try {
console.log('Attempting login with email:', email);
const response = await axios.post('/api/auth/login/', {
email: email.trim(),
password: password
}, {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
withCredentials: true
});
console.log('Login response received:', response.data);
const { access, refresh, user: userData } = response.data;
if (!access) {
throw new Error('No access token received in login response');
}
console.log('Login successful, access token received');
// Set the auth token for future requests
const authHeader = `Bearer ${access}`;
axios.defaults.headers.common['Authorization'] = authHeader;
// Store tokens first
localStorage.setItem('token', access);
if (refresh) {
localStorage.setItem('refresh_token', refresh);
}
// If we have user data in the response, use it
if (userData) {
console.log('Using user data from login response');
setUser(userData);
setPermissions(getPermissionsForRole(userData.role || 'viewer'));
} else {
console.log('No user data in login response, will load profile separately');
// The profile will be loaded by the useEffect that watches the token
}
// Set the token last to trigger the profile load
setToken(access);
return {
success: true,
user: userData
};
} catch (error) {
console.error('Login failed:', error);
// Clear any invalid tokens
localStorage.removeItem('token');
localStorage.removeItem('refresh_token');
delete axios.defaults.headers.common['Authorization'];
let errorMessage = 'Login failed. Please check your credentials and try again.';
if (error.response) {
console.error('Login error response:', {
status: error.response.status,
statusText: error.response.statusText,
data: error.response.data,
headers: error.response.headers
});
// Handle different error statuses
if (error.response.status === 400) {
errorMessage = 'Invalid request. Please check your input.';
} else if (error.response.status === 401) {
errorMessage = 'Invalid email or password. Please try again.';
} else if (error.response.status === 403) {
errorMessage = 'Access denied. Please contact support.';
} else if (error.response.status >= 500) {
errorMessage = 'Server error. Please try again later.';
}
// Use server-provided error message if available
if (error.response.data?.detail) {
errorMessage = error.response.data.detail;
} else if (error.response.data?.message) {
errorMessage = error.response.data.message;
} else if (typeof error.response.data === 'string') {
errorMessage = error.response.data;
}
} else if (error.request) {
console.error('No response received from server:', error.request);
errorMessage = 'No response from server. Please check your internet connection.';
} else {
console.error('Error setting up login request:', error.message);
errorMessage = `Login failed: ${error.message}`;
}
return {
success: false,
error: errorMessage,
status: error.response?.status
};
} finally {
setLoading(false);
}
};
// Register function
const register = async (userData) => {
try {
// Create a new axios instance without the auth header for registration
const registrationAxios = axios.create();
console.log('Sending registration data:', userData);
// Make the registration request
const response = await registrationAxios.post('/api/auth/register/', userData);
// If we get a 201 status, registration was successful
if (response.status === 201) {
console.log('Registration successful, response:', response.data);
// If the response includes tokens and user data, use them directly
if (response.data.tokens && response.data.user) {
const { tokens, user } = response.data;
// Set the auth token for future requests
axios.defaults.headers.common['Authorization'] = `Bearer ${tokens.access}`;
// Update auth state
setToken(tokens.access);
setUser(user);
setPermissions(getPermissionsForRole(user.role || 'viewer'));
// Store tokens in local storage
localStorage.setItem('token', tokens.access);
if (tokens.refresh) {
localStorage.setItem('refresh_token', tokens.refresh);
}
return {
success: true,
tokens,
user,
autoLoggedIn: true
};
}
// If no tokens in response, try to log in the user automatically
try {
console.log('No tokens in response, attempting auto-login...');
const loginResponse = await axios.post('/api/auth/login/', {
email: userData.email,
password: userData.password
});
if (loginResponse.data.token && loginResponse.data.user) {
const { token, user } = loginResponse.data;
// Update auth state
setToken(token);
setUser(user);
setPermissions(getPermissionsForRole(user.role || 'viewer'));
// Store token in local storage
localStorage.setItem('token', token);
return {
success: true,
tokens: { access: token },
user,
autoLoggedIn: true
};
}
} catch (loginError) {
console.error('Auto-login after registration failed:', loginError);
// Continue with normal flow - user will need to log in manually
}
// If auto-login fails, return success but indicate manual login is needed
return {
success: true,
autoLoggedIn: false
};
}
// Handle other success cases if needed
if (response.data) {
console.log('Registration successful, but unexpected response format:', response.data);
return {
success: true,
...response.data,
autoLoggedIn: false
};
}
// If we get here, the response didn't contain the expected data
console.error('Unexpected registration response:', response);
return {
success: false,
error: 'Invalid response from server. Please try again.'
};
} catch (error) {
console.error('Registration failed:', {
message: error.message,
response: error.response?.data,
status: error.response?.status
});
// Extract error details from the response if available
let errorMessage = 'Registration failed. Please try again.';
let errorDetails = {};
const errorData = error.response?.data;
if (errorData) {
// Handle Django REST framework validation errors
if (typeof errorData === 'object') {
// Handle specific field errors
if (errorData.details) {
// Handle our custom error format
errorMessage = errorData.error || errorMessage;
errorDetails = errorData.details;
} else if (errorData.error) {
// Handle error object format
errorMessage = errorData.error;
if (errorData.message) {
errorMessage += `: ${errorData.message}`;
}
errorDetails = errorData;
} else {
// Handle field validation errors
const errorMessages = [];
for (const [field, messages] of Object.entries(errorData)) {
if (Array.isArray(messages)) {
errorMessages.push(...messages);
errorDetails[field] = messages;
} else if (typeof messages === 'string') {
errorMessages.push(messages);
errorDetails[field] = [messages];
} else if (typeof messages === 'object') {
const flatMessages = Object.values(messages).flat();
errorMessages.push(...flatMessages);
errorDetails[field] = flatMessages;
}
}
errorMessage = errorMessages.join(' ');
}
} else if (typeof errorData === 'string') {
errorMessage = errorData;
}
}
// Return the error message for display in the UI
return {
success: false,
error: errorMessage,
errorDetails: error.response?.data,
autoLoggedIn: false
};
}
};
// Logout function
const logout = () => {
setToken(null);
setUser(null);
setPermissions([]);
localStorage.removeItem('token');
};
// Value to be provided by context
const value = {
user,
token,
loading,
permissions,
login,
register,
logout,
hasPermission,
hasAnyPermission,
hasAllPermissions,
ROLES,
PERMISSIONS
};
return (
<AuthContext.Provider value={value}>
{!loading && children}
</AuthContext.Provider>
);
};
// Custom hook to use the auth context
export const useAuth = () => {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
};
export default AuthContext;
please what might be the cause of this error it's just registering on my browser dev console showing the credentials I used for registering the user account and this response on my server terminal
HTTP GET /api/auth/profile/ 200 [0.08, 127.0.0.1:57736]
I tried changing the token hoping it would help with the redirection issues but whenever I do that it affects the signin.js page making it turn to a white screen page i.e. intended form to sign-in is not visible to users just a white screen.