I don't get redirected to login page when the role is "user".I have two getters in my route. One getter to check if the user is authenticated and another getter to get userRole. The userRole contains this: [“user”]. When i console log the getter i get the correct values but when i console.log a string, I don't see it as an orange string value in my console.
name: "GrantQuotes",
component: GrantQuotes,
beforeEnter: (to, from, next) => {
const authStatus = store.getters["auth/userRole"];
const myArrStr = JSON.stringify(authStatus);
const obj = JSON.parse(myArrStr);
console.log(obj);
console.log("user");
if (!store.getters["auth/authenticated"] && obj.includes("user")) {
return next({
name: "Login",
});
}
next();
},
},
Also my obj.includes("user")returns true.
export default {
namespaced: true,
state: {
accessToken: null,
user: null,
roles: null,
},
getters: {
authenticated(state) {
return state.accessToken && state.user;
},
user(state) {
return state.user;
},
userRole(state) {
console.log("test");
return state.roles;
},
},
mutations: {
SET_TOKEN(state, accessToken) {
state.accessToken = accessToken;
},
SET_USER(state, data) {
state.user = data;
},
SET_ROLE(state, data) {
state.roles = data;
console.log(data, "hej");
},
},
actions: {
async register({ dispatch }, credentials) {
let response = await axios.post(
"http://localhost:3000/api/auth/signup",
credentials
);
return dispatch("attempt", response.data.accessToken);
},
async signIn({ dispatch }, credentials) {
let response = await axios.post(
"http://localhost:3000/api/auth/signin",
credentials
);
return dispatch("attempt", response.data.accessToken);
},
async attempt({ commit, state }, accessToken) {
if (accessToken) {
commit("SET_TOKEN", accessToken);
}
if (!state.accessToken) {
return;
}
try {
let response = await axios.get(
"http://localhost:3000/api/auth/userMe",
{
headers: {
"x-access-token": accessToken,
},
}
);
console.log(response.data);
commit(
"SET_ROLE",
response.data.roles.map((role) => role.name)
);
commit("SET_USER", response.data);
} catch (e) {
commit("SET_TOKEN", null);
commit("SET_USER", null);
}
},
signOut({ commit }) {
commit("SET_TOKEN", null);
commit("SET_USER", null);
},
},
};
This is my user object
1. {roles: Array(1), quotes: Array(5), _id: "6089da8bd846c7e42a196ac5", username: "jon", email: "jon#gmail.com", …}
1. email: "jon#gmail.com"
2. quotes: (5) ["6089e8346dba89414317e646", "6089e8d96dba89414317e647", "608abd11462bf51a1583ab05", "60c5e89d1a6cfb0f3b16f51f", "60c62dc21a6cfb0f3b16f520"]
3. roles: Array(1)
1. 0: {_id: "607a0a5d102d2f5ad7738adf", name: "user", __v: 0}
2. length: 1
3. __proto__: Array(0)
4. username: "jon"
5. __v: 10
6. _id: "6089da8bd846c7e42a196ac5"
7. __proto__: Object
Related
I'm using Sequelize with expressjs for my api, I have a model named "Order" for the orders of the website im currently making, this is my model order:
module.exports = (sequelize, Sequelize) => {
const Order = sequelize.define("order", {
uid: {
type: Sequelize.STRING
},
author: {
type: Sequelize.TEXT('long'),
get: function() {
return JSON.parse(this.getDataValue('author'));
},
set: function(author) {
this.setDataValue('author', JSON.stringify(author));
}
},
cart: {
type: Sequelize.TEXT('long'),
get: function() {
return JSON.parse(this.getDataValue('cart'));
},
set: function(cart) {
this.setDataValue('cart', JSON.stringify(cart));
}
},
delivery: {
type: Sequelize.TEXT('long'),
get: function() {
return JSON.parse(this.getDataValue('delivery'));
},
set: function(delivery) {
this.setDataValue('delivery', JSON.stringify(delivery));
}
},
shipmethod: {
type: Sequelize.STRING
},
paymethod: {
type: Sequelize.STRING
},
totalprice: {
type: Sequelize.DECIMAL
},
cryptoprice: {
type: Sequelize.DECIMAL
},
payed: {
type: Sequelize.DECIMAL
},
promoCode: {
type: Sequelize.STRING
},
status: {
type: Sequelize.STRING
}
});
return Order;
}
All was working good, until I try to update an order, like this:
router.post('/payment/crypto', async (req, res) => {
const {order, currency} = req.body;
if (!order, !currency) return res.status(404).json({error: 'not found'});
console.log(order);
console.log(currency);
try {
const orderDb = await db.orders.findOne({where:{uid: order}});
if (!orderDb) return res.status(404).json({error: 'not found'});
const cryptoPrice = await crypto.convertPrice(currency, (parseFloat(orderDb.totalPrice) + 5));
// HERE
await db.orders.update({cryptoprice: cryptoPrice}, { where: {uid: order}});
const wallet = await crypto.generateWallet(currency, '1P5ZEDWTKTFGxQjZphgWPQUpe554WKDfHQ', 'https://google.fr');
return res.status(200).json({address: wallet.address, price: cryptoPrice});
} catch (error) {
console.error(error);
return res.status(404).json({error: error});
}
});
The findOne method works correctly, but when just after I update this order, I got this error:
SyntaxError: "undefined" is not valid JSON
at JSON.parse (<anonymous>)
at model.get (shopapp\back\src\database\models\Order.model.js:9:29)
at model.get (shopapp\back\node_modules\sequelize\lib\model.js:2116:41)
at model.get (shopapp\back\node_modules\sequelize\lib\model.js:2138:33)
at order.update (shopapp\back\node_modules\sequelize\lib\model.js:1877:44)
at shopapp\back\src\routes.js:132:29
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
The line number 9 of my Order.model.js is :
get: function() {
return JSON.parse(this.getDataValue('author'));
},
I dont understand cause the author column is not null, and even with the findOne I can get it
I have a function to get the logged in user details and check for the 'permissions' in the 'teams array'.
However, after running the code, I got two errors, and after the UI is loaded, the currentUser displays null until any component in the UI is selected. See the image, currentUser is null when UI is loaded but as soon as I click on a component, it prints the currentUser. I do not understand how to get through these errors.
This is a part of the vue-store code from which I am getting the currentUser array:
state(){
return currentUser: null
}
mutations: {
setCurrentUser(state, payload) {
// console.log("set current user", payload);
state.currentUser = payload;
}
},
actions: {
loadCurrentUser(context, data) {
// console.log("loadcurrentuser");
return new Promise((resolve, reject) => {
axiosService({ requiresAuth: true })
.get(`/administration/users/${data.id}`)
.then(response => {
context.commit("setCurrentUser", response.data);
resolve(response.data);
})
.catch(error => reject(error));
});
},
}
getters: {
isCurrentUser(state){
return state.currentUser;
}
}
here is the code from the router.js
{
path: "/administration",
name: "Administration",
component: PageAdministration,
meta: {
requiresAuth: true,
neededPermissions: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11],
},
function authorizeUser(to, from,next) {
let isAllowed = true;
const currentUser = store.getters["auth/isCurrentUser"];
console.log(currentUser);
for(let i = 0;i<currentUser.teams.length;i++){
const team = currentUser.teams[i]
const validPermissions = team.permissions.filter((item) => { return to.meta.neededPermissions.includes(item.permissionType); }); //returns array of objects
const mappedValidPermissions = validPermissions.map((item) => { return item.permissionType; });// returns array with permissionType
if (!to.meta.neededPermissions.every(i=>mappedValidPermissions.includes(i))) {
isAllowed = false;
next({ path: "/:notFound(.*)" });
break;
}
}
if(isAllowed) next();
}
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !store.getters["auth/isLoggedIn"]) {
next({
name: "Authentication",
params: {
desiredRoute: to.fullPath,
},
});
} else {
authorizeUser(to,next)
}
});
These are the two errors
I've had for months a login page with Next 12.0.10 and next-auth 4.1.2 working perfectly, but lately it stopped working.
I sign in with:
const onSubmit = async ({ email, password }) => {
try {
const { ok, error } = await signIn("normal-login", { redirect: false, email: email, password: password, callbackUrl: process.env.LOGIN_CALLBACK_URL})
console.log('ok, error: ', ok, error)
if(ok) {
console.log('Sesión iniciada correctamente')
} else {
console.log('error: ', error)
setCredentialError('Email o contraseña inválidos')
}
} catch (error) {
console.log('error: ', error)
}
}
But now { ok, error } returns false and sessionRequired respectively. And setCredentialError('Email o contraseña inválidos') is triggered. But the weird thing is that when I refresh the page the login is successful and I'm redirected to my main page. That makes me think that the cookies are set correctly, but something is wrong with my signIn function.
This is my [...nextauth].js file:
import NextAuth from "next-auth"
import CredentialsProvider from "next-auth/providers/credentials"
import { login } from "../axios/auth"
import jwt_decode from "jwt-decode";
export default NextAuth({
// Configure one or more authentication providers
providers: [
CredentialsProvider({
id: "normal-login",
name: "normal credentials",
credentials: {
email: {
label: "Email",
type: "email"
},
password: {
label: "Password",
type: "password"
}
},
async authorize(credentials) {
try {
const res = await login({
user: {
email: credentials.email,
password: credentials.password
}
})
const { token } = res.data
const token_decoded = jwt_decode(token)
const user = {
id: token_decoded.id,
email: credentials.email,
name: token_decoded.full_name,
role: token_decoded.role,
image: token_decoded.avatar,
token: token
}
return user
} catch(error) {
console.log("error: ", error)
}
return null
}
}),
CredentialsProvider({
id: "admin-login",
name: "admin credentials",
credentials: {
username: {
label: "Email",
type: "email",
placeholder: "nombre#test.com"
},
password: {
label: "Password",
type: "password"
}
},
async authorize(credentials) {
try {
const res = await login({
user: {
email: credentials.email,
password: credentials.password
}
})
const { token } = res.data
const token_decoded = jwt_decode(token)
const user = {
id: token_decoded.id,
email: credentials.email,
name: token_decoded.full_name,
role: token_decoded.role,
image: token_decoded.avatar,
token: token
}
return user
} catch(error) {
console.log("error: ", error)
}
return null
}
})
// ...add more providers here
],
callbacks: {
jwt: ({ token, user }) => {
// first time jwt callback is run, user object is available
if (user) {
token.token = user.token
token.uid = user.id
}
if (user?.role) {
token.role = user.role
}
if (user?.image) {
token.image = user.image
}
return token
},
session: ({ session, token }) => {
// session callback is called whenever a session for that particular user is checked
if (token) {
session.token = token.token
session.user.uid = token.uid
}
if (token?.role) {
session.user.role = token.role
}
if (token?.image) {
session.user.image = token.image
}
console.log('session: ', session)
return session
},
},
session: {
strategy: "jwt",
// Seconds - How long until an idle session expires and is no longer valid.
maxAge: 30 * 24 * 60 * 60, // 30 days
},
secret: process.env.NEXTAUTH_SECRET,
pages: {
signIn: "/user/login" || "/admin/login"
}
})
I've looked if something change with next-auth, but couldn't find anything.
Any help would be appreciated. Thank you!
I fixed it by upgrading the next-auth library to version 4.18.5.
I write test in Jest for my app trying to test if the data downloads correctly from the api. These are the data of the movies.
export const programsMock: FetchProgramsParameters = {
meta: {
status: 200,
pagination: {
page: 1,
perPage: 15,
hasNext: true,
},
},
data: [
{
id: "1",
title: "No Abras la Puerta",
genres: ["Drama", "Komedi", "Komedi", "Drama", "Romantik"],
imdb: {
rating: "7.1",
},
playProviders: [],
},
]}
jest.mock("./server/services/api");
render(<App />);
const fetchProgramsMocked = jest.mocked(fetchAllProgramsParameters);
describe("GET ", () => {
it("responds with 200", async () => {
fetchProgramsMocked.mockResolvedValueOnce(programsMock);
expect(fetchProgramsMocked).toHaveBeenCalledTimes(1);
expect(screen.getByText(/No Abras la Puerta/i)).toBeTruthy();
});
But I get error in getData: Cannot destructure property 'data' of '(intermediate value)' as it is undefined.
getData:
export const getAllPrograms = async (category: string) => {
const { data } = await fetchAllProgramsParameters(category);
const programs: TVProgram[] = data.map((program) => {
return {
id: program.id,
title: program.title,
imageLandscape: program.imageLandscape,
genres: program.genres,
playProviders: program.playProviders,
imdb: program.imdb,
};
});
return programs;
};
async function fetchApi<T>(pathname: string, filter?: string) {
const response = await fetch(`${pathname}${filter}`);
if (response.status === 404) {
throw new NotFoundError();
}
if (response.status >= 400) {
throw new HttpError("Bad response", response.status);
}
return response.json() as Promise<T>;
}
async function fetchAllProgramsParameters(category: string) {
return fetchApi<FetchProgramsParameters>(
API_URL,
["orderBy=views", "programType=" + category].join("&")
);
}
Please help how to solve it
I trying to implement a favorite toggle where it saves the favorites in an array, I create a Schema and a router, the code you can see below the problem is when I try to test it on insomnia I'm getting undefined on my console.log(isFavorite). I don't know what could be wrong.
const userSchema = new Schema({
username: String,
email: String,
password: String,
favorites: [{ type: Schema.Types.ObjectId, ref: "Places" }],
},
{
timestamps: true,
});
// route
router.put("/favorites/:placeId", (req, res) => {
const userId = "5ebd13df31430045957db8c3";
User.findById(userId).then( (user) => {
const isFavorite = user.favorites.find( (favorite) => {
return favorite === req.params.placeId;
});
console.log(isFavorite);
console.log(req.params.placeId);
if (isFavorite) {
User.findOneAndUpdate(
{ _id: userId },
{
$pull: { favorites: req.params.placeId },
},
{
new: true,
})
.then((user) => res.json(user))
.catch((err) => res.status(400).json(err));
} else {
User.findOneAndUpdate(
{ _id: userId },
{
$push: { favorites: req.params.placeId },
},
{
new: true,
})
.then((user) => res.json(user))
.catch((err) => res.status(400).json(err));
}
});
});
this chunk is bad:
User.findById(userId).then((user) => {
const isFavorite = user.favorites.find((favorite) => {
return favorite === req.params.placeId;
});
instead must use populate():
let favorites = await User.findById(userId).populate('favorites');
and then filter favorites by placeId