Computed object is undefined when post requesting via axios (Vuex) - vuejs2

I've set up a node express server with post method on localhost/send and vue app on localhost.
Vue app is working perfect, even on remote machine.
Post request requires json object and it sends an mail via nodemailer.
It works when I make post request via postman app.
Problem appears when I want to send email making post request via Vue app (axios). I store whole email data in Vuex and use "computed" to use it in my component. I can render data, but in my email whole data is undefined.
What am I doing wrong?
Code below:
node server
const express = require('express');
const bodyParser = require('body-parser');
const nodemailer = require('nodemailer');
const path = require('path');
const app = express();
app.use('/', express.static(path.join(__dirname, 'render')));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname+'/render/index.html'));
});
app.post('/send', (req, res) => {
const email = {
name: req.body.name,
email: req.body.email,
phone: req.body.phone,
startPoint: req.body.startPoint,
endPoint: req.body.endPoint,
dateTime: req.body.dateTime
};
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: 'mail.advertidea.pl',
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: 'emailIsCorrect', // generated ethereal user
pass: 'passIsCorrect' // generated ethereal password
},
tls:{
rejectUnauthorized:false
}
});
// mail for admin
// setup email data with unicode symbols
let adminMailOptions = {
from: '"GoodTransfer" <test#advertidea.pl>', // sender address
to: 'kamil.grzaba#gmail.com', // list of receivers
subject: 'New transfer request', // Subject line
html: `<p>${email.name}, asks for transfer.<p><br>
<p>Transfer details:</p><br><br>
<p>starting point: ${email.startPoint}</p>
<p>ending point: ${email.endPoint}</p>
<p>date and time: ${email.dateTime}</p><br><br>
<p>clients email: ${email.email}</p>
<p>phone number: ${email.phone}</p>` // html body
};
// send mail with defined transport object
transporter.sendMail(adminMailOptions, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
});
Vuex store
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
email: {
name: '',
email: 'test#test.pl',
phone: '',
startPoint: '',
endPoint: '',
date: new Date().toISOString().substr(0, 10),
},
},
getters: {
email: state => state.email,
},
mutations: {
updateEmail(state, email) {
this.state.email = email;
},
},
actions: {
},
});
Vue component
import axios from 'axios';
export default {
name: 'Book',
data() {
return {
newEmail: '',
valid: false,
emailRules: [
v => !!v || 'E-mail is required',
v => /.+#.+/.test(v) || 'E-mail must be valid',
],
};
},
computed: {
email: {
get() {
return this.$store.state.email;
},
set(value) {
this.$store.commit('updateMessage', value);
},
/* return this.$store.getters.email; */
},
},
methods: {
submitForm() {
console.log(JSON.stringify(this.email));
axios.post('http://goodtransfer.pixelart.pl/send', JSON.stringify(this.email), 'json')
.then((res) => {
console.log(res);
console.log(res.data);
});
},
},
};

Ok, I just found out what was the problem. When You make request via axios You should use object as a payload, not already strigified data.

Related

Is Auth.js compatible with Sveltekit SSR?

I am trying to create a Sveltekit app where users can log in. The login process is handled by a self-created API, so I would like to use the Auth.js Credentials Provider.
When I call the SignIn method as the FormAction in the +page.server.ts file, I get the error message 'window is not defined', which makes sense. Does this mean that Auth.js is not compatible with server-side rendering, or is there something else that I can adjust?
My Code:
//hooks.server.ts
SvelteKitAuth({
providers: [
// #ts-ignore
Credentials({
name: "credentials",
async authorize(credentials, req) {
// TODO: Call Api
const user = { id: "1", name: "J Smith", email: "jsmith#example.com" }
if (user) {
return user
} else {
return null
}
}
})
],
});
//+page.server.ts
export const actions = {
default: async ({ cookies, request }: { cookies: any, request: any }) => {
const data = await request.formData();
const credentials = {
username: data.get('username'),
password: data.get('password')
};
signIn('credentials', credentials)
.then(response => {
console.log('Success');
})
.catch(error => {
console.error('error', error);
});
}
};

how to pass token to browser url in vue js

i've an app whcih sends email to users to reset their passwords
this is the link i send to the user email to be able to do password reset
http://localhost:8081/reset/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfaWQiOiI2MmU2YWJmMmMzMzI0Mjk1NGQyNmVjZjIiLCJpYXQiOjE2NTk0ODkzODEsImV4cCI6MTY1OTQ5MDI4MX0.6omB-TkXXcwrjv0MaJQxltyERIoJZmkm8sY74AAqgxo
but each time i try to access the link i get
Cannot GET /reset/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
this is my route
{ name: "reset", path: "/reset/:token", component: Reset },
this is my script tag
<script>
import axios from "axios";
export default {
data: () => ({
valid: true,
password: "",
}),
mounted() {
console.log("the id is :" + this.$route.params.token);
},
methods: {
async handleSubmit() {
const response = await axios
.post("http://localhost:5000/api/auth/reset-password", {
newPassword: this.password,
token: this.$route.params.token
})
.then(res => {
console.log(res);
})
.catch(error => {
console.log(error);
});
},
}
};
</script>
please how can i go about these

How to get user info after a successful authentication with nuxt-auth

I'm using nuxt.js, after I send a login request with email and password to the backend I get a response which contains a message, token and user informations, how can I access user informations in the response and save it inside some state in store.js after a successful login?
I wanted to save user object in user state down in store/index.js using an action saveUserAction which might be dispatched after a successful login, i dont know if thats right or not, any advise would be very helpful
Response
{
"message":"success",
"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIxIiwianRpIjoiNzFkYjA1MWM2MTYxMmE4YzAyNWI2YjU3N2xMzJiNzJjMjI0MzRlY2IzNzYwNTg2N2NjOWQ5ZWEwY2MiMJM3uYEiZ8GSlPlQhIctVErO2KzwXOBxifWWoM7et_qT-mgvfsk3ljwiQF9iPQw-WeekBx8J8lcmxDLESa3tfE1Re1Xk2flkcBLmiI4JN2YHh08U1U",
"user":{
"id":1,
"role_id":4587,
"firstname":"Hans",
"lastname":"newman",
"email":"newman#gmail.com",
"email_verified_at":null,
"phone":"89498",
"skype":"gdgdfg",
"birthdate":"2021-05-02",
"address":"asdfaf",
"postalcode":14984,
"city":"jisf",
"country":"isfisf",
"status":"mfof",
"created_at":"2021-06-16T09:33:08.000000Z",
"updated_at":"2021-06-16T09:39:41.000000Z",
"image":"1623835988-carlsen.png",
"description":"sfdgg",
"geo_lat":5.5,
"geo_lng":8.1
}
}
login.vue
<script>
import { mapActions } from 'vuex'
export default {
data() {
return {
auth: false,
email: '',
password: '',
}
},
methods: {
async login() {
const succesfulLogin = await this.$auth.loginWith('local', {
data: {
email: this.email,
password: this.password,
},
})
if (succesfulLogin) {
await this.$auth.setUser({
email: this.email,
password: this.password,
})
this.$router.push('/profile')
}
},
},
}
</script>
store/index.js
export const state = () => ({
user:{}
})
export const mutations = {
saveUser(state, payload) {
state.user=payload;
}
}
export const actions = {
saveUserAction({commit}, UserObject){
commit('saveUser');
}
}
Go to your vue devtools, vuex tab and look for auth, it should already be available. This answer may help you during your debugging: https://stackoverflow.com/a/68081536/8816585
Since you do have your user object in the response, this kind of configuration should do it, as shown in the documentation. No need to make some other vuex actions.
auth: {
strategies: {
local: {
token: {
property: 'token',
global: true,
},
user: {
property: 'user', // the name of your object in your backend response payload
},
endpoints: {
[...]
}
}
}
}

Access Vue app (this) from non vue file

I'm new to vue (started using vue 2) I'm using Store (vuex) and I'm trying to acheive something.
basically I managed to install the vue-auth plugin : I have this.$auth that I can call from within .vue files.
Now using the store I wanna call the userLogin function by dispatching the call like this from a vue file :
<script>
export default {
computed: {
comparePasswords() {
return this.password === this.passwordConfirm
? true
: "Passwords don't match";
}
},
methods: {
userSignUp() {
if (this.comparePasswords !== true) {
return;
}
this.$store.dispatch("userSignUp", {
email: this.email,
password: this.password
});
}
},
data() {
return {
email: "",
password: "",
passwordConfirm: ""
};
}
};
</script>
in the store/index I'm trying to access the 'this.$auth' I do understand is some kind of context switching but I don't know how to access the vue app instance. :
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let app = this
export const store = new Vuex.Store({
state: {
appTitle: 'LiveScale Dashboard',
user: null,
error: null,
loading: false
},
mutations: {
setUser(state, payload) {
state.user = payload
},
setError(state, payload) {
state.error = payload
},
setLoading(state, payload) {
state.loading = payload
}
},
actions: {
userLogin({ commit }, payload) {
commit('setLoading', true)
var redirect = this.$auth.redirect(); // THIS IS WRONG.
this.$auth.login({ // THIS IS WRONG.
body: payload, // Vue-resource
data: payload, // Axios
rememberMe: this.data.rememberMe,
redirect: { name: redirect ? redirect.from.name : 'account' },
fetchUser: this.data.fetchUser
})
.then(() => {
commit('setUser', this.context)
commit('setLoading', false)
router.push('/home')
}, (res) => {
console.log('error ' + this.context);
commit('setError', res.data)
commit('setLoading', false)
});
},
userSignUp({ commit }, payload) {
// ...
}
},
getters: {}
})
Thanks for your help
try using Vue.$auth in index.js it should work
The idea (so far) is to pass the instance as an argument to the function as follows :
this.$store.dispatch("userSignUp", {
email: this.email,
password: this.password,
auth: this.$auth //added this line
});
and then in the store -> actions , payload.auth will contain my auth plugin :
userLogin({ commit }, payload) {
commit('setLoading', true)
var redirect = payload.auth.redirect();
payload.auth.login({
body: payload, // Vue-resource
data: payload, // Axios
rememberMe: this.data.rememberMe,
redirect: { name: redirect ? redirect.from.name : 'account' },
fetchUser: this.data.fetchUser
})
.then(() => {
commit('setUser', this.context)
commit('setLoading', false)
router.push('/home')
}, (res) => {
console.log('error ' + this.context);
commit('setError', res.data)
commit('setLoading', false)
});
},
I don't know if it's the best practice or not, but this is how I managed to do it. Please feel free to suggest anything.

Nuxt Auth Module Authenticated User Data

I have an API api/auth that is used to log users in. It expects to receive an access_token (as URL query, from Headers, or from request body), a username, and a password. I've been using the Vue Chrome Developer Tool and even though I get a 201 response from the server, the auth.loggedIn state is still false. I think that might be the reason why my redirect paths on the nuxt.config.js isn't working as well. Can anyone point me to the right direction on why it doesn't work?
This is a screenshot of the Vue Chrome Developer Tool
This is the JSON response of the server after logging in. The token here is different from the access_token as noted above.
{
"token": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"user": {
"user_name": "xxxxxxxxxxxxxxxxxx",
"uid": "xxxxxxxxxxxxxxxxxx",
"user_data": "XXXXXXXXXXXXXXXXXXXXXXXXX"
}
}
Here is the relevant part of nuxt.config.js
export default {
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth',
['bootstrap-vue/nuxt', { css: false }]
],
router: {
middleware: [ 'auth' ]
},
auth: {
strategies: {
local: {
endpoints: {
login: {
url: '/api/auth?access_token=XXXXXXXXXXXXXXXXXXXXXX',
method: 'post',
propertyName: 'token'
},
logout: {
url: '/api/auth/logout',
method: 'post'
},
user: {
url: '/api/users/me',
method: 'get',
propertyName: 'user'
}
}
}
},
redirect: {
login: '/',
logout: '/',
home: '/home'
},
token: {
name: 'token'
},
cookie: {
name: 'token'
},
rewriteRedirects: true
},
axios: {
baseURL: 'http://localhost:9000/'
}
}
And my store/index.js
export const state = () => ({
authUser: null
})
export const mutations = {
SET_USER: function (state, user) {
state.authUser = user
}
}
export const actions = {
nuxtServerInit ({ commit }, { req }) {
if (req.session && req.user) {
commit('SET_USER', req.user)
}
},
async login ({ commit }, { username, password }) {
const auth = {
username: username,
password: password
}
try {
const { user } = this.$auth.loginWith('local', { auth })
commit('SET_USER', user)
} catch (err) {
console.error(err)
}
}
}
The login action in the store is triggered by this method in the page:
export default {
auth: false,
methods: {
async login () {
try {
await this.$store.dispatch('login', {
username: this.form.email,
password: this.form.password
})
} catch (err) {
this.alert.status = true
this.alert.type = 'danger'
this.alert.response = err
}
}
}
}
P.S. I realize I'm explicitly including the access_token in the URL. Currently, I don't know where a master_key or the like can be set in the Nuxt Auth Module.
Try this in your store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = () => new Vuex.Store({
state: {
authUser: null
},
mutations: {
SET_USER: function (state, user) {
state.authUser = user
}
},
actions: {
CHECK_AUTH: function(token, router) {
if (token === null) {
router.push('/login')
}
}
}
})
export default store
And for the router, this should work globally:
$nuxt._router.push('/')