samedi 12 décembre 2020

JWT Auth giving error when attempting to login user

Im using JWT with a Rails backend/React frontend. Im attempting to have my user redirected when they log into their account to the /home page of the site. The error I am receiving is

TypeError: Cannot read property 'push' of undefined
Login.<anonymous>
src/components/Login.js:20
 17 |   if(res.user){
 18 |     localStorage.token = res.token
 19 |     this.setState({user:{id:res.user.id, username:res.user.username, token:res.token}, home:res.user.home}, () => {
> 20 |     this.props.history.push('/home')
    | ^  21 |   })
 22 | } else {
 23 |     alert(res.error)

Ive did make a change, to the home component but since reverted back to what it was but still having issues....

my controllers...

class ApplicationController < ActionController::API
  def encode_token(payload)
      JWT.encode(payload, "coffee")
  end 

def auth_header
  # { Authorization: 'Bearer <token>' }
  request.headers['Authorization']
end

def decoded_token
  if auth_header
    token = auth_header.split(' ')[1]
    # header: { 'Authorization': 'Bearer <token>' }
    begin
      JWT.decode(token,'coffee', true, algorithm: 'HS256')
    rescue JWT::DecodeError
      nil
    end
  end
end

def current_user
  if decoded_token
    user_id = decoded_token[0]['user_id']
    @user = User.find_by(id: user_id)
  end
end

def logged_in?
  !!current_user
end

def authorized
  render json: { message: 'Please log in' }, status: :unauthorized unless logged_in?
end
end
----
class UsersController < ApplicationController
    before_action :authorized, only:[:persist]

    def create
        @user = User.create(user_params)
        if @user.valid?
            token = encode_token({user_id: @user.id})   
            render json: @user
        else 
            render json: {error:'failed to create a user'}
        end
    end 

    def login
        @user = User.find_by(username:params[:username])
        if @user && @user.authenticate(params[:password])
            token = encode_token({user_id: @user.id})
            render json: {user:UserSerializer.new(@user), token:token}
        else
            render json: {error:"wrong user or password"}
        end 
        
    end 
    
    def index 
        @user = User.all
        render json: @user
    end
    def persist
        token = encode_token({user_id: @user.id})
        render json: {user:UserSerializer.new(@user), token:token} 
    end 

    private 
    def user_params
        params.permit(:username, :password)
    end 
end

my user_serializer...

class UserSerializer < ActiveModel::Serializer
    attributes :id, :username
    has_many :favorites
    has_many :favorite_coffee_shops, through: :favorites, source: :coffee_shop
    has_many :reviews
    has_many :coffee_shops, through: :reviews
  end

my login component...

import React from 'react';
import SignUp from './SignUp';

class Login extends React.Component{

    state={
      user:{
        id:0,
        username:"",
        token:""
      },
      home:[]
    }
     

       handleAuthResponse = (res) => {
         if(res.user){
           localStorage.token = res.token
           this.setState({user:{id:res.user.id, username:res.user.username, token:res.token}, home:res.user.home}, () => {
           this.props.history.push('/home')
         })
       } else {
           alert(res.error)
         }
       }

       handleLogin = (e, userInfo) =>{
        e.preventDefault()
        console.log(e)
     
        fetch('http://localhost:3000/login',{
         method:"POST",
         headers:{
           'Content-Type':'application/json'
         },
         body:JSON.stringify(userInfo)
       })
       .then(res => res.json())
       .then(json => {
         console.log(json)
         if(!json.error){
           this.handleAuthResponse(json)
         }else {
           alert(json.error)
         }
       })
       .catch(err => console.log(err))
      }
     
      
handleChange = (e) => {
  let {name, value} = e.target
  this.setState({
    [name]: value
  })
}


render(){
  return (
    <div className="login">Welcome Back!
     <form onSubmit={(e) => this.handleLogin(e, this.state)}>
       <div>
         <label>UserName</label>
         <br></br>
         <input type="text" name="username" value={this.state.username} onChange={this.handleChange}/>
         </div>
         <div>
         <label>Password</label>
         <br></br>
         <input type="password" name="password" value={this.state.password} onChange={this.handleChange}/>
         </div>
         <input type="submit" value="Submit" className="sl-btn" />
      </form>
      <div></div>
      <SignUp />
    </div>
  );
}
}

export default Login;

and my home component im attempting to push the user to once logged-in

import React from 'react'
import MapContainer  from '../containers/MapContainer'
import NavBar from './NavBar'
import FavoritesContainer  from './FavoritesContainer'

class Home extends React.Component {

    state = {
        reviews: [],
        favorites: [],
    }

    componentDidMount(){
    fetch('http://localhost:3000/reviews')
    .then(res => res.json())
    .then(reviews => this.setState({ reviews }))
    }
              
    addReview = (review) => {
        fetch('http://localhost:3000/reviews',{
            method: "POST",
            headers: {
                "Content-Type" : "application/json",
                Accept: "application/json",
                Authorization: `bearer ${localStorage.token}`
            },
            body: JSON.stringify({ review: review }
            ),
        })
        .then(res => res.json())
        .then(( json => {
            this.setState(prevState => ({
                reviews: [...prevState.reviews, json ]
               }))
        }))
    }
  
    render() {
        return (
               <div className="home">
                   <NavBar />
                   <MapContainer />
                   <FavoritesContainer />
           </div>
        )
}
}

export default Home

I am pretty new dev, please let me know if there is anymore info needed to help diagnose the problem. any advice would be helpful, thank you!!

Aucun commentaire:

Enregistrer un commentaire