[Python] Routing Problem from sign in page to a users account

Discussão em 'Python' iniciado por Stack, Junho 23, 2025.

  1. Stack

    Stack Membro Participativo

    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.

    Continue reading...

Compartilhe esta Página