skip to Main Content

I am developing this project using Spring Boot for backend and react for frontend, I connected this front end and back end. Then Sign Up and Sign in is working without any error but when I am going to get login information to display front end the error message is showing. I created function of the front end. when clicked Login/Sign Up button then it going to user profile that function based on role (USER/OWNER/ADMIN). but related login user details cannot display. The special thing is when I run that API in postman that function is working without any error.

error message in console

import axios from 'axios';
import React, { useState } from 'react';
import { useNavigate, useLocation } from 'react-router-dom'; // Import useNavigate hook
import ForgotPasswordPopup from '../components/ForgotPasswordPopup';
import EnterCodePopup from '../components/EnterCodePopup';
import ChangePasswordPopup from '../components/ChangePasswordPopup';
import './login.css';
import MailOutlineIcon from '@mui/icons-material/MailOutline';
import LockIcon from '@mui/icons-material/Lock';
import CloseIcon from '@mui/icons-material/Close';
import { GoogleLogin } from '@react-oauth/google'; // Import from @react-oauth/google

export default function Login() {
  const [step, setStep] = useState(null);
  const navigate = useNavigate(); // Initialize navigate function
  const [email, setEmail] = useState(''); // State for email input
  const [password, setPassword] = useState('');
  const location = useLocation(); 
  const [error, setError] = useState(''); // State to show login errors

   // Get the page the user was trying to access before being redirected to login
   const redirectTo = location.state?.from?.pathname || '/';  // Defaults to home page if no previous page

  const openForgotPassword = () => setStep('forgot');
  const openEnterCode = () => setStep('code');
  const openChangePassword = () => setStep('change');
  const closePopup = () => setStep(null);
    
 // Navigate to the signup page when the signup button is clicked
 const handleSignup = () => {
   navigate('/signup'); // Navigate to your signup page
  };
    

  // Function to handle Google Login success
  const handleGoogleSuccess = (response) => {
    console.log('Google login successful:', response);
    localStorage.setItem('authToken', 'google-auth-token');
    navigate(redirectTo);  // Navigate to the intended page after successful login
  };

  // Function to handle Google Login failure
  const handleGoogleFailure = (error) => {
    console.log('Google login failed:', error);
    // Handle failed login here
  };

  // Function to go back to the previous page
  const handleClose = () => {
    navigate(-1); // Navigates back to the previous page
  };

      // Handle email/password form submission
const handleSignIn = async (e) => {
  e.preventDefault();
  setError(''); // Reset error message

  try {
      // Send a POST request to the backend API
      const response = await axios.post(${process.env.REACT_APP_API_URL}/SignInUser/SignIn, {
          email,
          password,
      });

      const { role, token } = response.data; // Assuming your backend returns a user object with a role

      console.log('Email login successful');

      // Store authentication token in localStorage
      localStorage.setItem('authToken',token); // Assuming the token is returned

      // Redirect based on user role
      switch (role) {
        case 'User':
          navigate('/userprofile');
          break;
        case 'Owner':
          navigate('/ownerprofile');
          break;
        case 'Admin':
          navigate('/adminprofile');
          break;
        default:
          navigate('/'); // Fallback in case role is unrecognized
      }
  } catch (error) {
      if (error.response) {
          // Handle specific errors based on the response from the backend
          if (error.response.status === 401) {
              setError('Incorrect email or password');
          } else {
              setError('Login failed. Please try again.');
          }
      } else {
          setError('Login failed. Please try again.');
      }
  }
};

  return (
    <div className="login-container">
      <div className="login">
        <div className="login-left">
          <img src="/images/1.png" alt="logo" className="logo"/>
          <p className="signup-text">Don't have an account?</p>
          <button className="signup-button" onClick={handleSignup}>SIGN UP</button>
          <img src="/images/1.1.png" alt="login vector" className='vectorimage1'/>
        </div>

        <div className="login-right">
          {/* Update CloseIcon to use handleClose on click */}
          <CloseIcon className="close-icon" onClick={handleClose} />
          <div className="login-right-signup">
            <p className="signup-text">Don't have an account?</p>
            <button className="signup-button" onClick={handleSignup}>SIGN UP</button>
          </div>
          <h2 className="signin-header">Sign in Here</h2>
          <form onSubmit={handleSignIn}>
            <div className="input">
              <input type="email" placeholder="Email" className="input-field" value={email}
              onChange={(e) => setEmail(e.target.value)} // Update email state
              />
              <MailOutlineIcon className="icon"/>
              <input type="password" placeholder="Password" className="input-field" 
              value={password}
              onChange={(e) => setPassword(e.target.value)} // Update password state
            />
              <LockIcon className="icon"/>
            </div>
            <div className="input-field-container">
              <button type="button" className="forgot-password" onClick={openForgotPassword}>Forget Your Password?</button>
            </div>
            <button type="submit" className="signin-button">SIGN IN</button>
          </form>
          {error && <p style={{ color: 'red' }}>{error}</p>}
          <div className="or-divider"><span>OR</span></div>
          
          {/* Use GoogleLogin from @react-oauth/google */}
          <GoogleLogin
            onSuccess={handleGoogleSuccess}
            onError={handleGoogleFailure}
            render={({ onClick, disabled }) => (
              <button onClick={onClick} disabled={disabled} className="google-signin-button">
                <img src="/images/1.2.png" alt="Google logo" className="googlelogo"/>
                Google
              </button>
            )}
          />
        </div>
      </div>

      {step === 'forgot' && <ForgotPasswordPopup onClose={closePopup} onNext={openEnterCode} />}
      {step === 'code' && <EnterCodePopup onClose={closePopup} onNext={openChangePassword} />}
      {step === 'change' && <ChangePasswordPopup onClose={closePopup} />}
    </div>
  );
}
import React,{useState} from 'react';
import NavigationBar from '../../components/NavigationBar';
import Footer from '../../components/Footer';
import UserContent from '../../components/UserProfile/UserContent';
import {Avatar,Typography} from '@mui/material';
import ChatBubbleOutlineIcon from '@mui/icons-material/ChatBubbleOutline';
import StarOutlineIcon from '@mui/icons-material/StarOutline';
import PersonOutlineIcon from '@mui/icons-material/PersonOutline';
import MenuIcon from '@mui/icons-material/Menu';
import './userProfile.css';

const UserProfile = () => {
  const [activeMenuItem, setActiveMenuItem] = useState('Profile');
  const [isSidebarVisible, setSidebarVisible] = useState(false);

  const toggleSidebar = () => {
    setSidebarVisible(!isSidebarVisible);
  };


  return (
    <div className="userprofile">
      {/* Navigation bar at the top */}
      <div className="nav">
        <NavigationBar />
      </div>

      {/* Menu icon for small screens */}
      <div className="menu-icon" onClick={toggleSidebar}>
        <MenuIcon />
      </div>

      {/* Main container with sidebar and content */}
      <div className={userprofile-container ${isSidebarVisible ? 'show-sidebar' : ''}}>
        {/* Sidebar Section */}
        <div className={userprofile-sidebar ${isSidebarVisible ? 'show-sidebar' : ''}}>
        <div className="sidebar-header">
          <Avatar className="avatar" />
          <Typography variant="h6" className="sidebar-title"sx={{margin:'2px',fontFamily:'"Josefin Sans", sans-serif'}} >User</Typography>
        </div>
        <ul className="sidebar-menu">
            <li
              className={sidebar-menu-item ${activeMenuItem === 'Profile' ? 'active' : ''}}
              onClick={() => setActiveMenuItem('Profile')}
            >
              <PersonOutlineIcon className="menu-icon" />
              <span className="menu-text">Profile</span>
            </li>
            <li
              className={sidebar-menu-item ${activeMenuItem === 'Chats' ? 'active' : ''}}
              onClick={() => setActiveMenuItem('Chats')}
            >
              <ChatBubbleOutlineIcon className="menu-icon" />
              <span className="menu-text">Chats</span>
            </li>
            <li
              className={sidebar-menu-item ${activeMenuItem === 'Ratings' ? 'active' : ''}}
              onClick={() => setActiveMenuItem('Ratings')}
            >
              <StarOutlineIcon className="menu-icon" />
              <span className="menu-text">Ratings</span>
            </li>
          </ul>

      </div>

        {/* Main Content Section */}
        <div className="userprofile-content">
          {/* Content can go here */}
          <UserContent 
          activeMenuItem={activeMenuItem} 
          setActiveMenuItem={setActiveMenuItem} 
        />
      </div>
    </div>
    <div className='footer'>
    <Footer/>
    </div>
  </div>
  );
};
export default UserProfile;
import axios from 'axios';

// Create an Axios instance with a base URL
const api = axios.create({
  baseURL: process.env.REACT_APP_API_URL,
});

// Request interceptor for adding token
api.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem('token');
    if (token) {
      config.headers.Authorization = Bearer ${token};
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// Function to fetch all boarding places
export const fetchBoardingPlaces = async () => {
  try {
    const response = await api.get('/boarding-places');
    return response.data;
  } catch (error) {
    console.error('Error fetching boarding places:', error);
    throw new Error('Unable to fetch boarding places. Please try again later.');
  }
};

// Function to fetch a boarding place by ID
export const fetchBoardingPlaceById = async (id) => {
  try {
    const response = await api.get(/boarding-places/${id});
    return response.data;
  } catch (error) {
    console.error(Error fetching boarding place ${id}:, error);
    throw new Error(Unable to fetch boarding place ${id}.);
  }
};

// Change user password
export const changePassword = async (newPassword) => {
  const token = localStorage.getItem('token'); // Retrieve token
  const response = await api.put('/change-password', { password: newPassword }, {
    headers: {
      Authorization: Bearer ${token},
    },
  });
  return response.data; // Return success message or user data if needed
};

// Fetch user data
export const fetchUserData = async (token, userId) => {
  try {
    const response = await api.get(/loginuser/${userId}, {
      headers: {
        Authorization: Bearer ${token},
      },
    });
    return response.data; // Return user data
  } catch (error) {
    console.error('Error fetching user data:', error);
    throw error; // Propagate the error for further handling
  }
};
import React from 'react';
import UserAccount from './UserAccount';
import UserChats from './UserChats';
import UserRatings from './UserRatings';

const UserContent = ({ activeMenuItem }) => {
  return (
    <div>
      {activeMenuItem === 'Profile' && <UserAccount/>}
      {activeMenuItem === 'Chats' && <UserChats />}
      {activeMenuItem === 'Ratings' && <UserRatings />}
    </div>
  );
};

export default UserContent;
import React, { useState, useEffect } from 'react';
import { TextField, Button, Typography, Container, Grid } from '@mui/material';
import { fetchUserData, changePassword } from '../../apiService'; // Import the API functions

const UserAccount = () => {
  const [userData, setUserData] = useState({
    userId: '',
    email: '',
    name: '',
  });
  const [newPassword, setNewPassword] = useState('');
  const [confirmPassword, setConfirmPassword] = useState('');
  const [error, setError] = useState('');
  const [successMessage, setSuccessMessage] = useState('');

  useEffect(() => {
    const fetchUserDetails = async () => {
      try {
        const data = await fetchUserData(); // Call API to get user data
        setUserData(data);
      } catch (error) {
        console.error('Error fetching user data:', error);
      }
    };

    fetchUserDetails();
  }, []);

  const handleChangePassword = async (e) => {
    e.preventDefault();
    setError('');
    setSuccessMessage('');

    // Basic validation for password change
    if (!newPassword || !confirmPassword) {
      setError('Both password fields are required.');
      return;
    }
    if (newPassword !== confirmPassword) {
      setError('Passwords do not match.');
      return;
    }

    try {
      await changePassword(newPassword); // Call API to update the password
      setSuccessMessage('Password changed successfully!');
      setNewPassword('');
      setConfirmPassword('');
    } catch (error) {
      setError('Error changing password. Please try again.');
    }
  };

  return (
    <Container maxWidth="sm" style={{ padding: '20px', backgroundColor: '#f5f5f5', borderRadius: '8px' }}>
      <Typography variant="h5" gutterBottom style={{ color: 'gray', fontSize: '36px' }}>
        User Account
      </Typography>

      {/* Display user details */}
      <Grid container spacing={1}>
        <Grid item xs={12}>
          <Typography variant="h6">User ID: {userData.userId}</Typography>
        </Grid>
        <Grid item xs={12}>
          <Typography variant="h6">Email: {userData.email}</Typography>
        </Grid>
        <Grid item xs={12}>
          <Typography variant="h6">Name: {userData.name}</Typography>
        </Grid>
      </Grid>

      <Typography variant="h6" style={{ marginTop: '20px', color: '#72d6c9' }}>Change Password</Typography>
      <form onSubmit={handleChangePassword}>
        <TextField
          label="New Password"
          type="password"
          fullWidth
          value={newPassword}
          onChange={(e) => setNewPassword(e.target.value)}
          required
        />
        <TextField
          label="Confirm Password"
          type="password"
          fullWidth
          value={confirmPassword}
          onChange={(e) => setConfirmPassword(e.target.value)}
          required
        />
        {error && <Typography color="error">{error}</Typography>}
        {successMessage && <Typography color="primary">{successMessage}</Typography>}
        <Button type="submit" variant="contained" color="primary" fullWidth style={{ marginTop: '20px', backgroundColor: '#72d6c9' }}>
          Change Password
        </Button>
      </form>
    </Container>
  );
};

export default UserAccount;
package com.example.testing.controller;

import com.example.testing.dto.LoginUserDto;
import com.example.testing.dto.ReturnLoginUserDto;
import com.example.testing.service.LoginUserService;
import com.example.testing.utill.JWTAuthenticator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@CrossOrigin(origins = "http://localhost:3000")
@RestController
@RequestMapping("/loginuser")
public class LoginUserController {
    @Autowired
    LoginUserService service;

    @Autowired
    JWTAuthenticator jwtAuthenticator;

    @PostMapping("/saveLoginUser")
    public ResponseEntity<Object> saveLoginUser(@RequestBody LoginUserDto loginUserDto){
                ReturnLoginUserDto returnLoginUserDto = service.saveLoginUser(loginUserDto);
                if (returnLoginUserDto != null) {
                    return new ResponseEntity<>("Register Success", HttpStatus.OK);
                } else {
                    return new ResponseEntity<>("Already regitered with this Email", HttpStatus.CREATED);
                }
    }
    @GetMapping("/{id}")
    public ResponseEntity<Object> getLoginUserById(@PathVariable Integer id) {
        LoginUserDto loginUserDto = service.getLoginUserById(id);
        if (loginUserDto != null) {
            return new ResponseEntity<>(loginUserDto, HttpStatus.OK);
        }
        return new ResponseEntity<>("User not found", HttpStatus.NOT_FOUND);
    }
}
package com.example.testing.service;

import com.example.testing.dto.LoginUserDto;
import com.example.testing.dto.ReturnLoginUserDto;
import com.example.testing.entity.LoginUser;
import com.example.testing.repo.LoginUserRepo;
import com.example.testing.utill.SignInMail;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service

public class LoginUserService {
    @Autowired
    LoginUserRepo loginUserRepo;
    @Autowired
    SignInMail signInMail;
    @Autowired
    PasswordEncoder passwordEncoder;

    public ReturnLoginUserDto saveLoginUser(LoginUserDto loginUserDto) {
        String encodedPassword = passwordEncoder.encode(loginUserDto.getPassword());

        if (loginUserRepo.existsLoginUserByEmail(loginUserDto.getEmail())) {
            return null;
        }

        LoginUser save = loginUserRepo.save(
                new LoginUser(loginUserDto.getContactNo(),encodedPassword,loginUserDto.getEmail(),loginUserDto.getRole()));
        signInMail.sendEmail(loginUserDto);
        return new ReturnLoginUserDto(save.getEmail(), save.getId());
    }
public List<LoginUserDto> getAllLoginUser(){
        List<LoginUser> all = loginUserRepo.findAll();

        List<LoginUserDto> loginUserDtos = new ArrayList<>();
        for(LoginUser loginUser : all){
            loginUserDtos.add(new LoginUserDto(loginUser.getId(), loginUser.getContactNo(), loginUser.getPassword(), loginUser.getEmail(), loginUser.getRole()));
        }
        return loginUserDtos;
    }
}
package com.example.testing.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class LoginUser {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private Integer contactNo;
    private String password;
    private String email;
    private String role;

    @OneToOne(mappedBy = "loginUser", cascade = CascadeType.ALL)
    private BoardingOwner boardingOwner;

    public LoginUser(Integer contactNo, String password, String email, String role) {
        this.contactNo = contactNo;
        this.password = password;
        this.email = email;
        this.role = role;
    }

    public LoginUser(Integer id, Integer contactNo, String password, String email) {
    }
}
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class LoginUserDto {
    private Integer id;
    private Integer contactNo;
    private String password;
    private String email;
    public String role;
}

we need to show the details of login user its own profile, we need to know, how to integrate correctly.

2

Answers


  1. Since the API is working without issues in Postman but your front-end application is encountering CORS errors (As the console suggest) it suggests that you need to configure CORS (Cross-Origin Resource Sharing) to allow requests from your front end.

    Here is a sample CORS configuration that you can add to your Spring Boot application.

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.cors.CorsConfiguration;
    import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
    import org.springframework.web.filter.CorsFilter;
    
    @Configuration
    public class CorsConfig {
    
        @Bean
        public CorsFilter corsFilter() {
            CorsConfiguration corsConfig = new CorsConfiguration();
            corsConfig.addAllowedOrigin("http://localhost:3000"); // Allow requests from the specified origin
            corsConfig.addAllowedHeader("*"); // Allow all headers
            corsConfig.addAllowedMethod("*"); // Allow all HTTP methods
    
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", corsConfig);
    
            return new CorsFilter(source);
        }
    }
    

    Note that additionally, as the console logs show some undefined values in the URLs, you may want to verify that all URL paths are constructed correctly on the front end. Check that any dynamic parameters are properly initialized before making the API requests.

    Login or Signup to reply.
  2. There is an API issue while accessing through different origins, it is followed for best security practice, to fix this, you can use the @CrossOrigin Annotation. This can be applied to controller or specific methods to allow access.

    @CrossOrigin(origins = "http://localhost:3000")
    @RestController
    public class YourController {
        // Your endpoint logic
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search