How to solve POST 400 {bad Request} ReactJS - javascript

I'm following a MERN Stack course & I'm quite new, in that I'm keeping backend & frontend codes separately.
when I trying to POST a request through frontend I'm getting an error as below screenshot, but when I trying that same POST request through backend using Postman I'm able passing the value to my MongoDB database. I couldn't find any code error on this. I'm stacked here almost 3 weeks please help me on this.
I tried to call backend both ways as below but the result is same.
${API}/category/create/${userId}
and
${API}category/create/${userId}
please note I'm able to see my backend error message as well.
--------------------------------------------
screenshot :
--------------------------------------------
Backend API call file | Frontend
import { API } from "../../backend"
// category call
export const createCategory = (userId, token, category) => {
return fetch(`${API}/category/create/${userId}`, {
method:"POST",
headers:{
Accept: "application/json",
"Content-Type": "appliction/json",
Authorization: `Bearer ${token}`
},
body: JSON.stringify(category)
})
.then(response => {
return response.json();
})
.catch(err => console.log(err));
};
// get all categories
export const getCategories = () => {
return fetch(`${API}/categories`, {
method: "GET"
})
.then(response => {
return response.json();
})
.catch(err => console.log(err));
};
// Product calls
export const createProduct = (userId, token, product) => {
return fetch(`${API}/product/create/${userId}`, {
method: "POST",
headers:{
Accept: "application/json",
Authorization: `Bearer ${token}`
},
body: product
})
.then(response => {
return response.json();
})
.catch(err => console.log(err));
};
// get all products
export const getProducts = () => {
return fetch(`${API}/products`, {
method: "GET"
})
.then(response => {
return response.json();
})
.catch(err => console.log(err));
};
// delete a product
// get a product
export const getProduct= () => {
return fetch(`${API}/product`)
}
// update a product
View file | Backend
import React, { useState } from "react";
import Base from "../core/Base";
import { Link } from "react-router-dom";
import { isAutheticated } from "../auth/helper";
import { createCategory } from "./helper/adminapicall";
const AddCategory = () => {
const [name, setName] = useState("");
const [error, setError] = useState(false);
const [success, setSuccess] = useState(false);
const { user, token } = isAutheticated();
const goBack = () => (
<div className="mt-3">
<Link className="btn btn-sm btn-success mb-3" to="/admin/dashboard">
Admin Home
</Link>
</div>
);
const handleChange = (event) => {
setError("");
setName(event.target.value);
};
const onSubmit = (event) => {
event.preventDefault();
setError("");
setSuccess(false);
//backend call fired
createCategory(user._id, token, {name}).then(data => {
if (data.error) {
setError(true);
} else {
setError("");
setSuccess(true);
}
})
};
const myCategoryFrom = () => (
<form>
<div className="form-group">
<p className="lead">Enter the category</p>
<input
type="text"
className="form-control my-3"
onChange={handleChange}
value={name}
required
autoFocus
placeholder="For Ex. Summer"
/>
<button onClick={onSubmit} className="btn btn-outline-info">
Create Category
</button>
</div>
</form>
);
return (
<Base
title="Create a category here"
description="Add a new category for new T-shirts"
className="container bg-info p-4 "
>
<div className="row bg-white rounded">
<div className="col-md-8 offset-md-2">
{myCategoryFrom()}
{goBack()}
</div>
</div>
</Base>
);
};
export default AddCategory;
Controller file [create category] | Backend
const Category = require('../models/category');
exports.getCategoryById = (req, res, next, id) => {
Category.findById(id).exec((err, cate) => {
if(err){
return res.status(400).json({
error: "Category is Not found in the Databse"
});
}
req.category = cate;
next();
});
};
exports.createCategory = (req, res) => {
const category = new Category(req.body);
category.save((err,category) => {
if(err){
return res.status(400).json({
error: "Not able to save Category in to the Database"
});
}
res.json({ category });
});
};
exports.getCategory = (req,res) => {
return res.json(req.category)
}
exports.getAllCategory = (req,res) => {
Category.find().exec((err,categories) => {
if(err){
return res.status(400).json({
error: "No Categories found"
})
}
res.json(categories);
});
};
exports.updateCategory = (req, res) => {
const category = req.category;
category.name = req.body.name;
category.save((err, updatedCategory) => {
if (err) {
return res.status(400).json({
error: "Failed to update category"
});
}
res.json(updatedCategory);
});
};
exports.removeCategory = (req, res) => {
const category = req.category;
category.remove((err, category) => {
if(err){
return res.satus(400).json({
error: "Failed to Delete this Category"
})
}
res.json({
message: "Successfull Deleted"
});
})
}

Related

how to write async storage value return function in react-native

how to write a method to return async storage value in react native.
I have done login authentication using Context API.
AuthContext.js
import React, { createContext } from "react";
import { useState, useEffect } from "react";
import { Alert } from "react-native";
import AsyncStorage from '#react-native-async-storage/async-storage';
import NetInfo from "#react-native-community/netinfo";
import { BASE_URL } from "../constants/Const";
export const AuthContext = createContext();
export const AuthProvider = ({ children }) => {
// loading & usertoken hooks
const [isLoading, setIsLoading] = useState(false);
const [userToken, setuserToken] = useState(null);
//login method
const login = async (email, password) => {
setIsLoading(true);
//fetch method to get access token
fetch(`${BASE_URL}/sign_in`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: email,
password: password,
})
})
.then((res) => res.json())
.then((json) => {
//console.log("login auth ", json)
if (json.responseCode == 200) {
try {
setuserToken(json.responseData.access_token);
//storing usertoken value in react-native encrypted storage
AsyncStorage.setItem("userToken", json.responseData.access_token)
//console.log("user token",userToken);
}
catch (error) {
console.log("Error while saving user token data", userToken);
}
}
//showing invalid email & password alert messaqge
else {
Alert.alert('Invalid email or password.');
return;
}
})
.catch((error) => {
console.error(error);
});
setIsLoading(false);
}
//logout method
const logout = async () => {
setIsLoading(true);
//setting user token as null
setuserToken(null);
try {
//removing usertoken value in react-native encrypted storage
await AsyncStorage.removeItem("userToken");
} catch (error) {
// There was an error on the native side
console.log("Error while removing data", error);
}
setIsLoading(false);
}
// checking user is already logged in each time when app starts
const isLoggenIn = async () => {
try {
setIsLoading(true);
//let userToken = await EncryptedStorage.getItem("userToken");
let userToken = await AsyncStorage.getItem("userToken");
//console.log("accesed user token",userToken);
setuserToken(userToken);
setIsLoading(false);
} catch (error) {
console.log("Error retrieving data", error);
}
}
const [connected, setConnected] = useState(true);
useEffect(() => {
isLoggenIn();
// Subscribe
const unsubscribe = NetInfo.addEventListener(state => {
// console.log("Connection type", state.type);
// console.log("Is connected?", state.isConnected);
setConnected(state.isConnected);
});
//clean up function
return () => unsubscribe();
}, [])
return (
<AuthContext.Provider value={{ login, logout, isLoading, userToken ,connected,}}>
{children}
</AuthContext.Provider>
)
}
in Redux slice file I want access token values to make a fetch request to a server.i defined getAccessToken Method to return accessToken value but it is not returning value
DataSlice.js
import { createSlice, createAsyncThunk } from '#reduxjs/toolkit'
import { useState } from 'react';
import { Alert } from 'react-native';
import { BASE_URL } from '../constants/Const';
import AsyncStorage from '#react-native-async-storage/async-storage';
//const accessToken = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiNjM2YTFlNTc4YWNlNTRjM2E5OWE4YWI2IiwiZW1haWwiOiJhZG1pbkBnbWFpbC5jb20iLCJpYXQiOjE2Njg0MDY2MzgsImV4cCI6MTY2ODQ2MDYzOH0.i_GHy2K91I0_159AIpQ4m2eFUmyXYFmF3_0sQ-o_x-w";
//user token function
const getAcessToken = async () => {
const token = await AsyncStorage.getItem('userToken');
return token;
}
var userToken = getAcessToken();
// get and delete method request options
const getDeleteRequestOptions = (methodType) => {
return {
method: methodType,
headers: {
'Content-Type': 'application/json',
'autherization': userToken
}
}
}
// save and edit method request options
const saveEditRequestOptions = (methodType, data) => {
console.log("img uri",data.imgUri)
const imgData = new FormData();
imgData.append('first_name', data.firstName);
imgData.append('last_name', data.lastName);
imgData.append('phone', data.phoneNo);
imgData.append('email', data.email);
imgData.append('image', { uri: data.imgUri, name: 'image', type: 'image/jpg' });
return {
method: methodType,
headers: {
'Content-Type': 'multipart/form-data',
'autherization': userToken
},
body: imgData
}
};
// fetch data
export const getData = createAsyncThunk('fetch', async ({pageNo,limit}) => {
return fetch(`${BASE_URL}/list_profile?page_number=${pageNo}&limit=${limit}`, getDeleteRequestOptions('GET'))
.then((response) => response.json())
.then((json) => {
//returning json receive array
if(pageNo === 0 && limit === 0){
return {data:json.receive,fetchAllData:true};
}
return {data:json.receive,fetchAllData:false};
})
.catch((error) => {
console.error(error);
});
});
// delete data
export const deleteData = createAsyncThunk('delete', async ({id}) => {
return fetch(`${BASE_URL}/delete_profile/${id}`, getDeleteRequestOptions('DELETE',userToken))
.then((res) => res.json())
.catch((error) => {
console.error(error);
});
});
// save data
export const saveData = createAsyncThunk('save', async (data) => {
return fetch(`${BASE_URL}/add_profile`, saveEditRequestOptions('POST', data))
.then((res) => res.json())
.then((json) => {
if (json.responseCode === 211) {
Alert.alert('Input Error', json.responseMessage, [
{ text: "OK" }
])
return;
}
console.log("save responese message ", json.responseMessage);
})
.catch((error) => {
console.error(error);
});
});
// edit data
export const editData = createAsyncThunk('edit', async (data) => {
return fetch(`${BASE_URL}/update_profile/${data.id}`, saveEditRequestOptions('PUT', data))
.then((res) => res.json())
.then((json) => {
console.log("edit data response message ", json.responseMessage);
})
.catch((error) => {
console.error(error);
});
});
const initialState = {
masterData: [],
filteredData: [], //array to implement search
allData:[],
imgurl: '',
};
export const dataSlice = createSlice({
name: 'crud',
initialState,
reducers: {
filterData: (state, action) => {
state.filteredData = action.payload;
},
selectedImage: (state, action) => {
state.imgurl = action.payload;
},
},
extraReducers: {
// get data
[getData.pending]: (state, action) => {
console.log('fetching data is pending');
},
[getData.fulfilled]: (state, action) => {
console.log('data fetched successfully')
if (!action.payload) {
Alert.alert('Network error', 'Data Fetching is Failded Please try Again later.', [
{ text: "OK" }
])
return;
}
console.log(action.payload.fetchAllData)
if(action.payload.fetchAllData){
//console.log("inside fetch all data")
state.allData = action.payload.data;
}
state.masterData = action.payload.data;
state.filteredData = action.payload.data;
},
[getData.rejected]: (state, action) => {
console.log('fetching request rejected');
},
// delete data
[deleteData.pending]: (state, action) => {
console.log('delete data is pending');
},
[deleteData.fulfilled]: (state, action) => {
console.log('data deleted successfully');
},
[deleteData.rejected]: (state, action) => {
console.log('data delete request rejected');
Alert.alert('Delete Data Failure', 'Deleting Data Failed. Please try Again later.', [
{ text: "OK" }
])
},
// save data
[saveData.pending]: (state, action) => {
console.log('saving data is pending');
},
[saveData.fulfilled]: (state, action) => {
console.log('data saved successfully');
},
[saveData.rejected]: (state, action) => {
console.log('data save request rejected');
Alert.alert('Data Save Failure', 'Data Save Failed. Please try Again later.', [
{ text: "OK" }
])
},
//edit data
[editData.pending]: (state, action) => {
console.log('edit data is pending');
},
[editData.fulfilled]: (state, action) => {
console.log('data edited successfully');
},
[editData.rejected]: (state, action) => {
console.log('edit data request rejected');
Alert.alert('Data Edit Failure', 'Edit data Failed. Please try Again later.', [
{ text: "OK" }
])
},
},
})
// Action creators are generated for each case reducer function
export const { filterData, selectedImage } = dataSlice.actions;
export default dataSlice.reducer
i want to get access token values
The reason is that you are not calling getAccessToken() with await like this:
var userToken = await getAcessToken();
since it is asynchronous function.

Nodejs MongoDB - add new entry Post()

so trying to post new entry into MongoDB. but getting this error in Redux Product validation failed: name: Path 'name' is required., description: Path 'description' is required.
nodejs version: 14.9.0
and Atlas mongodb.
frontEnd addProduct.js page:
import { createProduct } from '../redux/actions/productActions'
const [name, setName] = useState('')
const [description, setDescription] = useState('')
const createProductHandler = (e) => {
e.preventDefault()
dispatch(createProduct({
name,
description
}))
}
const nameHandler = (e) => {
setName(e.target.value)
}
const descriptionHandler = (e) => {
setDescription(e.target.value)
}
return (
<input type='text' onChange={nameHandler} />
<input type='text' onChange={descriptionHandler} />
<input type="submit" value='submit' onClick={createProductHandler} />
)
productController:
const createdProduct = asyncHandler(async (req, res) => {
const mongoProduct = async (data) => {
return new Product({
name: data.name,
description: data.description
})
}
const product = await mongoProduct(req.body)
const createdProduct = await product.save()
res.status(201).json(createdProduct)
})
productActions:
export const createProduct = () => async (dispatch, getState) => {
try {
dispatch({
type: 'PRODUCT_CREATE_REQUEST',
})
const {
userLogin: {userInfo},
} = getState()
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`,
},
}
const { data } = await axios.post(`/api/products`, {}, config)
dispatch({
type: 'PRODUCT_CREATE_SUCCESS',
payload: data
})
} catch (error) {
dispatch({
type: 'PRODUCT_CREATE_FAIL',
payload:
error.response && error.response.data.message
? error.response.data.message
: error.meessage,
})
}
}
productReducers.js:
export const productCreateReducer = (state = {}, action) => {
switch (action.type) {
case 'PRODUCT_CREATE_REQUEST':
return {loading: true}
case 'PRODUCT_CREATE_SUCCESS':
return {loading: false, success: true, product: action.payload}
case 'PRODUCT_CREATE_FAIL':
return {loading: false, error: action.payload}
default:
return state
}
}
alternatively when i try to populate the database from post-man using this code in productController.js it works fine with sample data:
const createdProduct = asyncHandler(async (req, res) => {
const product = new Product({
name: 'Sample Name',
description: 'Sample Description'
})
const createdProduct = await product.save()
res.status(201).json(createdProduct)
})
plus im getting POST ipadress/api/products 500 (Internal Server Error) in console
You can config your axios api service config to separate file and use axios
const request = axios.create({
// baseURL: 'https://mock-api.com',
baseURL: BASE_URL ,
timeout: 5000
})
request.interceptors.request.use(
config => {
// get token
if (// check your token) {
config.headers["Authorization"] = "Bearer ${your-token}"
}
return config
},
error => {
// Do something with request error
console.log(error) // for debug
Promise.reject(error)
}
)
// Can also config axios response interceptors to handle API error
Your redux action
import axiosInstance from './your-axios-config-path'
export const createProduct = (product) => async (dispatch, _getState) => {
try {
dispatch({ type: 'PRODUCT_CREATE_REQUEST' })
const response = await axiosInstance.post(`/api/products`, {...product})
dispatch({
type: 'PRODUCT_CREATE_SUCCESS',
payload: response?.data ?? {}
})
} catch (error) {
dispatch({
type: 'PRODUCT_CREATE_FAIL',
payload: // error message,
})
}
}
Alternatively, you can use Redux Toolkit, It much easier to setup store and using. It includes createAsyncThunk, RTK Query to handle side effect.

401 Unauthorized, SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data

Hi all I'm new to authentication. I was building an app where a user can login and create a story using an api, and the story is sent to the backend using a POST request. The app was authenticating fine, until I built the app. Now when I sign in and try to add a story, I get 401 Unauthorized and SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data in actions.js.
Then if I refresh the page, the errors go away and the app is working.
I am able to logout and login again normally.
I have no idea why that's happening. Any help will be appreciated.
The backend server does say Error in authorization JsonWebTokenError: jwt malformed
actions.js
import * as t from './actionTypes';
import { setUserSession } from '../utils/Common';
import { getToken } from '../utils/Common'
const token = getToken();
// this is what our action should look like which dispatches the "payload" to reducer
const setLoginState = (loginData) => {
return {
type: t.SET_LOGIN_STATE,
payload: loginData, //{ ...json, userId: email }
};
};
const setStoryState = (storyData) => {
return {
type: t.CREATE_STORY,
payload: storyData, //storyData is the object with summary, description, type, etc.
};
};
const getStoryState = (storyData) => {
return {
type: t.GET_STORIES,
payload: storyData, //storyData is the object with summary, description, type, etc.
};
};
const getSingleStoryState = (storyData) => {
return {
type: t.GET_STORY,
payload: storyData, //storyData is the object with summary, description, type, etc.
};
};
export const login = (loginInput) => { //our login action
const { email, password, isAdmin } = loginInput;
return (dispatch) => { // don't forget to use dispatch here!
return fetch('http://localhost:3000/api/v1/signin', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify(loginInput),
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
// console.log(json)
dispatch(setLoginState({ ...json, userId: email, isAdmin: isAdmin })); // our action is called here with object as parameter, this is our payload
//we appended json object to our state
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
setUserSession(json.token, json.lastName)
})
.catch((err) => {
alert('Login Failed', 'Some error occured, please retry');
console.log(err);
});
};
};
export const getStories = () => {
return (dispatch) => { // don't forget to use dispatch here!
return fetch('http://localhost:3000/api/v1/stories', {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
console.log(json)
dispatch(getStoryState( [...json ])); // our action is called here with object as parameter, this is our payload
//we appended json object to our state
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
})
.catch((err) => {
alert('Login Failed', 'Some error occured, please retry');
console.log(err);
});
};
}
export const viewStory = id => {
return (dispatch) => { // don't forget to use dispatch here!
return fetch(`http://localhost:3000/api/v1/stories/${id}`, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
console.log(json)
dispatch(getSingleStoryState( {...json } )); // our action is called here with object as parameter, this is our payload
//we appended json object to our state
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
})
.catch((err) => {
alert('Login Failed', 'Some error occured, please retry');
console.log(err);
});
};
}
export const roleChange = () => {
return {
type: t.SET_ROLE_STATE,
//payload: role
};
}
export const logout = () => {
return {
type: t.LOGOUT,
};
}
export const createStory = storyInput => {
console.log(token)
const { summary, description, type, complexity, time, cost } = storyInput;
return (dispatch) => { // don't forget to use dispatch here!
return fetch('http://localhost:3000/api/v1/stories', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`,
},
body: JSON.stringify(storyInput),
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
console.log(json)
//dispatch(setStoryState( [...json ]));
dispatch(setStoryState({ // our action is called here with object as parameter, this is our payload
summary: summary,
description: description,
type: type,
complexity: complexity,
time: time,
cost: cost
})); // our action is called here
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
})
.catch((err) => {
alert('Some error occured, please retry');
console.log(err);
});
};
}
export const addStory = story => {
return {
type: t.ADD_STORY,
payload: story,
}
}
export const setStatus = (id, status) => {
return (dispatch) => { // don't forget to use dispatch here!
return fetch(`http://localhost:3000/api/v1/stories/${id}/${status}`, {
method: 'PUT',
headers: {
Accept: 'application/json',
'Content-Type': 'text/html',
'Authorization': `Bearer ${token}`
},
})
.then((response) => response.json()) //json will be the response body
.then((json) => {
// if (json.msg === 'success') { // response success checking logic could differ
console.log(json)
// dispatch(getStoryState( {...json } )); // our action is called here with object as parameter, this is our payload
//we appended json object to our state
// } else {
// alert('Login Failed', 'Email or Password is incorrect');
// }
})
.catch((err) => {
alert('Login Failed', 'Some error occured, please retry');
console.log(err);
});
};
}
CreateStory.js
import React, { useState } from 'react'
import { createStory } from '../redux/actions'
import { useDispatch, useSelector } from "react-redux";
import history from '../utils/history';
import { withRouter } from 'react-router-dom';
const CreateStory = () => {
const [summary, setSummary] = useState("");
const [description, setDescription] = useState("");
const [type, setType] = useState("");
const [complexity, setcomplexity] = useState("");
const [time, setTime] = useState("");
const [cost, setCost] = useState(0);
const usedispatch = useDispatch();
const userCreateStory = (summary, description, type, complexity) => usedispatch(createStory({
'summary': summary,
'description': description,
'type': type,
'complexity': complexity,
'time': time,
'cost': cost
}));
const handleSummaryChange = e => {
setSummary(e.target.value)
}
const handleDescriptionChange = e => {
setDescription(e.target.value)
}
const handleTypeChange = e => {
setType(e.target.value)
}
const handleComplexityChange = e => {
setcomplexity(e.target.value)
}
const handleTimeChange = e => {
setTime(e.target.value)
}
const handleCostChange = e => {
setCost(e.target.value)
}
// const currStory = useSelector((state)=> state.storyReducer.story)
const handleSubmit = e => {
e.preventDefault();
userCreateStory(summary,description,type,complexity,time,cost)
setTimeout(()=> history.push("/userStories"), 1000 );
//setTimeout(()=> console.log(currStory) ,1000)
}
return (
<div>
<form className='create-story-form'>
<label for="summary">Summary:</label>
<input name="summary" type='text' onChange={handleSummaryChange}/>
<label for="desc">Description:</label>
<textarea name="desc" type='text' onChange={handleDescriptionChange}/>
<label for="type">Type:</label>
<select name="type" onChange={handleTypeChange}>
<option value="enhancement" defaultValue>Enchancement</option>
<option value="bugfix">Bugfix</option>
<option value="development">Development</option>
<option value="qa">QA</option>
</select>
<label for="complexity">Complexity:</label>
<select name="complexity" onChange={handleComplexityChange}>
<option value="low" defaultValue>Low</option>
<option value="mid">Mid</option>
<option value="high">High</option>
</select>
<label for="time">Estimated time for completion:</label>
<input name="time" type='text' onChange={handleTimeChange}/>
<label for="cost">Cost:</label>
<input name="cost" type='number' onChange={handleCostChange}/>
<button onClick={handleSubmit}>Submit</button>
</form>
</div>
)
}
export default withRouter(CreateStory);
Login.js
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { login, roleChange } from '../redux/actions' //OUR ACTIONS
import { useSelector } from 'react-redux'
import history from '../utils/history';
import { withRouter } from 'react-router-dom';
const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [isAdmin, setIsAdmin] = useState(false);
const usedispatch = useDispatch();
const userLogin = (email, password, isAdmin) => usedispatch(login({'email': email, 'password': password, 'isAdmin': isAdmin }));
const handleRoleChange = e => {
setIsAdmin(true)
if(isAdmin)
setIsAdmin(false)
console.log(isAdmin)
}
const handleEmailChange = e => {
setEmail(e.target.value)
}
const handlePasswordChange = e => {
setPassword(e.target.value)
}
const handleSubmit = e => {
e.preventDefault();
userLogin(email, password, isAdmin)
setTimeout(()=> history.push("/user"), 1000 );
}
const disabled = () => {
return email === "" || password === ""
}
return (
<div>
<form className='login-form'>
<input type='email' name='email' placeholder='Email' onChange={handleEmailChange}/>
<input type='password' name='password' placeholder='Password' onChange={handlePasswordChange}/>
<button type='submit' disabled={disabled()} onClick={handleSubmit}>Login</button>
</form>
<button onClick={handleRoleChange}>Switch to {isAdmin ? 'user' : 'admin'}</button>
</div>
)
}
export default withRouter(Login);
reducers.js
import { initialState } from './initialState';
import * as t from './actionTypes';
export const loginReducer = (state = initialState, action) => {
switch (action.type) {
case t.SET_ROLE_STATE:
return {
...state,
isAdmin: true
};
case t.SET_LOGIN_STATE:
return {
...state,
...action.payload, // this is what we expect to get back from API call and login page input
isLoggedIn: true, // we set this as true on login
};
case t.LOGOUT:
return {
initialState
};
default:
return state;
}
};
export const storyReducer = (state = [], action) => {
switch (action.type) {
case t.CREATE_STORY:
return {
...state,
stories: [...state.stories, action.payload],
};
case t.GET_STORIES:
return {
...state,
stories: action.payload,
};
case t.GET_STORY:
return {
...state,
story: action.payload,
};
// case t.ADD_STORY:
// return {
// ...state,
// stories: [...state.stories, action.payload], //stories is an object
// };
case t.LOGOUT:
return {
stories: [{complexity: "",
cost: 0,
description: "",
summary: "",
time: "",
type: ""}]
};
default:
return state;
}
}

How to properly use DELETE by ID in Node.js/ReactJS

I would like to explain my problem of the day.
i think it's harder than usual, so let me explain
here i start by getting a get
getRandom = async () => {
const res = await axios.get(
entrypoint + "/alluserpls"
)
this.setState({ data: res.data })
}
componentDidMount() {
this.getRandom()
}
here is my method for delete
handleSubmit = (e) => {
e.preventDefault();
const config = {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
};
const url = entrypoint + "/alluserpls";
fetch(url, config)
.then(res => res.json())
.then(res => {
if (res.error) {
alert(res.error);
} else {
alert(`ajouté avec l'ID ${res}!`);
}
}).catch(e => {
console.error(e);
}).finally(() => this.setState({ redirect: true }));
}
then I map it
render() {
let datas = this.state.data.map((datass, index) => {
return (
<Col sm="12" key={index}>
<form onSubmit={this.handleSubmit}>
<button type="submit">Delete</button>
</form>
<div>{datass.name}</div>
</Col>
then i return the result on my map
return (
<div>
{datas}
</div>
so works correctly ,
but the problem is the following when I want to delete only 1 CARD it deletes all my BDD
Here is my routes on BDD
app.delete('/api/alluserpls', (req, res, ) => {
const formData = req.body;
connection.query('DELETE FROM alluserpls SET ?', formData, err => {
if (err) {
res.status(500).send("Erreur lors de la modification des users");
} else {
res.sendStatus(200);
}
});
});
I would like that when I click on delete it only deletes the card and not all of my database.
How can I fix this issue?
Here is one way to do it, assign the id of the user to button id attribute field and then call the delete API with the user id
handleSubmit = (e, id) => {
e.preventDefault();
const userIdData = { id };
const config = {
method: "DELETE",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(userIdData),
};
const url = entrypoint + "/alluserpls";
fetch(url, config)
.then(res => res.json())
.then(res => {
if (res.error) {
alert(res.error);
} else {
alert(`ajouté avec l'ID ${res}!`);
}
}).catch(e => {
console.error(e);
}).finally(() => this.setState({ redirect: true }));
, in the render method you can pass the id as variable to the handleSubmit function
render() {
let datas = this.state.data.map((datass, index) => {
return (
<Col sm="12" key={index}>
<form onSubmit={(e) => this.handleSubmit(e, datass.id)}>
<button type="submit">Delete</button>
</form>
<div>{datass.name}</div>
</Col>
and in the backend you can get the id and delete only the particular user
app.delete('/api/alluserpls', (req, res, ) => {
const formData = req.body;
const userId = req.body.id;
const deleteQuery = `DELETE from alluserpls WHERE id = ${userId}`;
connection.query(deleteQuery, err => {
if (err) {
res.status(500).send("Erreur lors de la modification des users");
} else {
res.sendStatus(200);
}
});
});

ReactJs & MSAL.js Unauthorized 401

I have a pretty basic React App which the user can login and hit some MS Graph endpoint(s), this works great no problem once consent has been approved by the user. I also have another request firing to an anonymous Azure Function that spits back some JSON, brilliant no problem.
The issue I'm having is related to when I'm trying to make a request to an Azure Function Api that is locked down using AD with the MSAL.js lib.
I'm using https://github.com/sunilbandla/react-msal-sample.
App.js
import React, { Component } from 'react';
import './App.css';
import AuthService from './services/auth.service';
import GraphService from './services/graph.service';
import HelloService from './services/hello.service';
class App extends Component {
constructor() {
super();
this.authService = new AuthService();
this.graphService = new GraphService();
this.helloService = new HelloService();
this.state = {
user: null,
userInfo: null,
apiCallFailed: false,
loginFailed: false
};
}
componentWillMount() {}
callAPI = () => {
this.setState({
apiCallFailed: false
});
this.authService.getToken().then(
token => {
this.graphService.getUserInfo(token).then(
data => {
this.setState({
userInfo: data
});
},
error => {
console.error(error);
this.setState({
apiCallFailed: true
});
}
);
},
error => {
console.error(error);
this.setState({
apiCallFailed: true
});
}
);
};
callHelloAPI = () => {
this.setState({
apiCallFailed: false
});
this.authService.getToken().then(
token => {
this.helloService.callApi(token).then(
data => {
this.setState({
userInfo: data
});
console.log(data);
},
error => {
console.error(error);
this.setState({
apiCallFailed: true
});
}
);
},
error => {
console.error(error);
this.setState({
apiCallFailed: true
});
}
);
};
getTheToken = () => {
console.log('Get Token:');
this.authService.getToken().then(token => {
console.log(token);
});
}
logout = () => {
this.authService.logout();
};
login = () => {
this.setState({
loginFailed: false
});
this.authService.login().then(
user => {
if (user) {
console.log(user);
this.setState({
user: user
});
} else {
this.setState({
loginFailed: true
});
}
},
() => {
this.setState({
loginFailed: true
});
}
);
};
render() {
let templates = [];
if (this.state.user) {
templates.push(
<div key="loggedIn">
<button onClick={this.callAPI} type="button">
Call MS Graph
</button>
<button onClick={this.callHelloAPI} type="button">
Call Azure Function
</button>
<button onClick={this.getTheToken}>
Get The Token (JWT / Cookie)
</button>
<button onClick={this.logout} type="button">
Logout
</button>
<h3>Hello {this.state.user.name}</h3>
<h4>{this.state.user.displayableId}</h4>
</div>
);
} else {
templates.push(
<div key="loggedIn">
<button onClick={this.login} type="button">
Login with Microsoft
</button>
</div>
);
}
if (this.state.userInfo) {
templates.push(
<pre key="userInfo">{JSON.stringify(this.state.userInfo, null, 4)}</pre>
);
}
if (this.state.loginFailed) {
templates.push(<strong key="loginFailed">Login unsuccessful</strong>);
}
if (this.state.apiCallFailed) {
templates.push(
<strong key="apiCallFailed">Graph API call unsuccessful</strong>
);
}
return (
<div className="App">
<header className="App-header">
<h1 className="App-title">React app with MSAL.js</h1>
</header>
{templates}
</div>
);
}
}
export default App;
auth.service
import * as Msal from 'msal';
export default class AuthService {
constructor() {
let PROD_REDIRECT_URI = 'http://localhost:3000/';
let redirectUri = window.location.origin;
if (window.location.hostname !== '127.0.0.1') {
redirectUri = PROD_REDIRECT_URI;
}
this.applicationConfig = {
clientID: 'xxxx-xxxxx-xxxxx-xxxx',
graphScopes: ['user.read','user.readbasic.all']
};
this.app = new Msal.UserAgentApplication(
this.applicationConfig.clientID,
'',
() => {
// callback for login redirect
},
{
redirectUri
}
);
}
login = () => {
return this.app.loginPopup(this.applicationConfig.graphScopes).then(
idToken => {
const user = this.app.getUser();
if (user) {
return user;
} else {
return null;
}
},
() => {
return null;
}
);
};
logout = () => {
this.app.logout();
};
getToken = () => {
return this.app.acquireTokenSilent(this.applicationConfig.graphScopes).then(
accessToken => {
return accessToken;
},
error => {
return this.app
.acquireTokenPopup(this.applicationConfig.graphScopes)
.then(
accessToken => {
return accessToken;
},
err => {
console.error(err);
}
);
}
);
};
}
graph.service
export default class GraphService {
constructor() {
this.graphUrl = 'https://graph.microsoft.com/v1.0/users';
}
getUserInfo = token => {
const headers = new Headers({ Authorization: `Bearer ${token}` });
const options = {
headers
};
return fetch(this.graphUrl, options)
.then(response => response.json())
.catch(response => {
throw new Error(response);
});
};
}
hello.service
export default class HelloService {
constructor() {
this.graphUrl = 'https://xxx.azurewebsites.net/api/Hey';
}
callApi = token => {
const headers = new Headers({ Authorization: `Bearer ${token}` });
const options = {
headers
};
return fetch(this.graphUrl, options)
.then(response => response.json())
.catch(response => {
throw new Error(response);
});
};
}
Calling this hello.service works fine anonymously but returns a 401 when locked down by an Azure AD App. I've verified the JWT token from jwt.io also. I'm guessing the problem is an auth issue (hopefully a simple one), would an issue arise depending if the app is an Azure AD only app or a converged app? I have also enabled CORS on the function app itself.
My brain has frozen at this point & I'm not sure which direction facing. Any help would be greatly appreciated thanks in advance.

Categories

Resources