I am building a simple flashcard program using the MERN stack that allows users to add, edit and remove flashcards. Everything is working fine, except my deleteCards function isn't working and is throwing an error.
I can't for the life of me work out why, though, because the function is structured exactly the same as all of the others.
The problem seems to be in my auth middleware, but as far as I can tell it's being passed the same header authorization details.
The middleware function in question is this, and you can see that it's causing the error in the no token conditional:
const protect = asyncHandler(async (req, res, next) => {
let token
if(req.headers.authorization && req.headers.authorization.startsWith('Bearer')) {
try {
//get token from header
token = req.headers.authorization.split(' ')[1]
//verify token
const decoded = jwt.verify(token, process.env.JWT_SECRET)
//get user from the token
req.user = await User.findById(decoded.id).select('-password')
next()
} catch (error) {
console.log(error)
res.status(401)
throw new Error('not authorised')
}
}
if (!token) {
res.status(401)
throw new Error('not authorised, no token')
}
})
However, if I put console logs in, I can see that the first try/catch is finding the token, so I don't understand why the second error is being called at all.
The backend function works fine when I call it in postman, so my assumption is that something is going wrong on the front end when it's passed to the server.
That is happening with this slice:
//delete user card
export const deleteCard = createAsyncThunk(
"cards/deleteCard",
async (cardData, thunkAPI) => {
try {
const token = thunkAPI.getState().auth.user.token;
return await cardService.deleteCard(cardData, token);
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
}
);
And then this service:
//delete card
const deleteCard = async (cardData, token) => {
const config = {
headers: {
Authorization: `Bearer ${token}`,
},
};
const response = await axios.delete(API_URL, cardData, config);
return response.data;
};
If I console.log either config in the later, or token and cardData in the former, it displays exactly what I'd expect.
And as I say, I have an almost identical 'updateCard' function that works absolutely fine - so I can't tell what is different. That one, for reference, is here:
//slice
export const updateCard = createAsyncThunk(
"cards/updateCard",
async (cardData, thunkAPI) => {
try {
const token = thunkAPI.getState().auth.user.token;
return await cardService.updateCard(cardData, token);
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
}
);
//service
const updateCard = async (cardData, token) => {
const config = {
headers: {
Authorization: `Bearer ${token}`,
},
};
const response = await axios.put(API_URL, cardData, config);
return response.data;
};
The full code is on GitHub here if it seems like there's maybe something going on somewhere else! https://github.com/gordonmaloney/cairtean