I'm working on a component that takes care of registering my users to Sinch (voip platform). In order for my registration to work I need to have some variables that are accessible throughout my component methods. I'm wondering how this should be done using vue.
I need my variable sinchClient to be accessible in my methods newUserRequest() and loginRequest()
Any tips?
Sinch variable
var sinchClient = new SinchClient({
applicationKey: "My-Key",
capabilities: {
messaging: true,
calling: true
},
supportActiveConnection: true,
onLogMessage: function(msg) {
console.log(msg);
}
});
Methods
<script>
export default {
data() {
return {
username: null,
name: null,
password: null,
loggedIn: false
};
},
mounted() {},
methods: {
newUserRequest() {
console.log(this.name, this.password);
if (this.name && this.password) {
var handleSuccess = () => {
console.log("User created");
this.loggedIn = true;
this.name = sinchClient.user.userId;
};
var handleFail = error => {
console.log(error.message);
};
var signUpObject = { username: this.name, password: this.password };
sinchClient
.newUser(signUpObject)
.then(sinchClient.start.bind(sinchClient))
.then(() => {
localStorage[
"sinchSession-" + sinchClient.applicationKey
] = JSON.stringify(sinchClient.getSession());
})
.then(handleSuccess)
.fail(handleFail);
}
},
logInRequest() {
if (this.name && this.password) {
var handleSuccess = () => {
console.log("User logged in");
this.loggedIn = true;
this.name = sinchClient.user.userId;
};
var handleFail = error => {
console.log(error.message);
};
var signUpObject = { username: this.name, password: this.password };
sinchClient
.start(signUpObject)
.then(() => {
localStorage[
"sinchSession-" + sinchClient.applicationKey
] = JSON.stringify(sinchClient.getSession());
})
.then(handleSuccess)
.fail(handleFail);
}
}
}
};
</script>
You can define sinchClient globally and access it using window (window.sinchClient). Better you can create a Vue plugin and inject it in the app context:
var sinchClient = new SinchClient({
applicationKey: "My-Key",
capabilities: {
messaging: true,
calling: true
},
supportActiveConnection: true,
onLogMessage: function(msg) {
console.log(msg);
}
})
Vue.use({
install: function(Vue) {
Object.defineProperty(Vue.prototype, '$sinchClient', {
get () { return sinchClient }
})
}
})
And access it with this.$sinchClientin Vue context
Related
I am trying to make a site in Vue and backend on Spring. I want to use rsocket to transfer data, but as soon as I add rsocket seurity in spring, I get :
'metadata is malformed'
Would like to take a look at a working example using jwt/simpleauth
I solved the issue with Simple Auth, now I would like to synchronize this authorization with spring websecurity.
Those. so that routing in rsocket checks authorization via websecurity. I know that this can be implemented through the jwt token, i.e. send a jwt token to a client via rest, but how can I do this in code? JS client (browser) and Spring, how do I generate userdetails token?
Just in case, I'll leave an example of the simpleauth implementation:
// METADATA BUILDER
import {encodeRoute, encodeBearerAuthMetadata, encodeSimpleAuthMetadata, encodeAndAddCustomMetadata, encodeAndAddWellKnownMetadata, MESSAGE_RSOCKET_ROUTING, MESSAGE_RSOCKET_AUTHENTICATION} from "rsocket-core";
export default class Metadata {
constructor(json) {
this.route = json['route'];
this.auth = json['auth'];
}
toMetadata() {
let metadata = Buffer.alloc(0);
if (this.auth) {
if (this.auth["type"] === 'bearer') {
metadata = encodeAndAddCustomMetadata(
metadata,
MESSAGE_RSOCKET_AUTHENTICATION.string,
encodeBearerAuthMetadata(this.auth["token"]),
);
}
if (this.auth["type"] === 'simple') {
metadata = encodeAndAddCustomMetadata(
metadata,
MESSAGE_RSOCKET_AUTHENTICATION.string,
encodeSimpleAuthMetadata(this.auth["username"], this.auth["password"]),
);
}
}
if (this.route) {
metadata = encodeAndAddWellKnownMetadata(
metadata,
MESSAGE_RSOCKET_ROUTING,
encodeRoute(this.route)
);
}
return metadata;
}
}
// RSOCKET CLIENT CLASS
import RSocketWebSocketClient from "rsocket-websocket-client";
import {BufferEncoders, MESSAGE_RSOCKET_COMPOSITE_METADATA, RSocketClient,toBuffer} from "rsocket-core";
import Metadata from "./metadata";
export default class SpringClient {
constructor(wsUrl, keepAlive = 60000, lifetime = 180000, dataMimeType = "application/json") {
this.client = new RSocketClient({
"setup": {
"keepAlive": keepAlive,
"lifetime": lifetime,
"dataMimeType": dataMimeType,
"metadataMimeType": MESSAGE_RSOCKET_COMPOSITE_METADATA.string
},
"transport": new RSocketWebSocketClient({
"url": wsUrl
}, BufferEncoders)
});
}
bearerAuth(token) {
this.auth = {type: "bearer", token: token}
}
simpleAuth(username, password) {
this.auth = {type: "simple", username: username, password: password}
}
logout() {
this.auth = null;
}
connect(
completeCallback = (socket) => {
}, errorCallback = (error) => {
}, subscribeCallback = (cancel) => {
}
) {
this.client.connect().subscribe({
onComplete: socket => {
this.socket = socket;
completeCallback(socket);
},
onError: error => {
errorCallback(error);
},
onSubscribe: cancel => {
subscribeCallback(cancel);
}
});
}
requestResponse(data, route,
completeCallback = (data) => {
},
errorCallback = (error) => {
},
subscribeCallback = (cancel) => {
}
) {
if (this.socket) {
const metadata = new Metadata({
route: route,
auth: this.auth
}).toMetadata();
data = toBuffer(data);
this.socket.requestResponse({
data,
metadata
}).subscribe({
onComplete: data => {
completeCallback(data);
},
onError: error => {
errorCallback(error);
},
onSubscribe: cancel => {
subscribeCallback(cancel);
}
});
}
}
}
// EXAMPLE, HOW TO USE
import SpringClient from "./springclient";
this.client = new SpringClient("ws://localhost:7000/", 5000, 15000, "text/plain");
this.client.connect(
(socket) => {
console.log("got connection complete");
this.socket = socket;
},
(error) => {
console.log("got connection error");
console.error(error);
},
(cancel) => {
console.log("got connection subscribe");
/* call cancel() to abort */
}
)
this.client.simpleAuth("LOGIN", "PASSWORD");
this.client.requestResponse("MESSAGE", "ROUTE",
(data) => {
console.log("got response with requestResponse");
console.log(data.data);
},
(error) => {
console.log("got error with requestResponse");
console.error(error);
},
(cancel) => {
console.log(message);
/* call cancel() to stop onComplete/onError */
}
);
My component script is:
export default {
name: "Authenticate",
data: () => {
return {
validationFailed: {}
};
},
methods: {
validateForm() {
this.validationFailed = {};
if (this.createEmail.trim().length === 0) {
this.validationFailed.createEmailField = "Email cannot be blank. ";
}
if (this.createPassword.trim().length === 0) {
this.validationFailed.createPasswordField =
"Password cannot be blank. ";
}
if (Object.keys(this.validationFailed).length === 0) {
return true;
}
return false;
},
handleSubmit() {
const that = this;
axios
.request({
url: `${process.env.VUE_APP_API_URL}/users`,
method: "POST",
data: {
email: this.createEmail,
password: this.createPassword
}
})
.then(response => {
console.log(response);
})
.catch(err => {
that.validationFailed.createEmailField = "something";
});
}
}
};
But inside the catch, with a debugger, I can see that the value gets set. But in my template, the validationFailed doesn't get updated. What am I doing wrong?
It's Vue reactivity problem. You need to assign this.validationFailed to new object. You can try ES6 syntax in catch block:
that.validationFailed = {
...that.validationFailed,
createEmailField: 'something'
}
The code below handles authentication for a Vue.js application. It stores and retrives some important values in local storage. How do I refactor this code so as to get and set the values expiresAt, idToken, accessToken and user from memory instead of local storage?
import auth0 from 'auth0-js'
import Vue from 'vue'
let webAuth = new auth0.WebAuth({
domain: 'your_auth0_domain',
clientID: 'your_auth0_client',
redirectUri: 'http://localhost:8080/callback',
audience: 'https://' + 'your_auth0_domain' + '/api/v2/',
responseType: 'token id_token',
scope: 'openid profile' // define the scopes you want to use
})
let auth = new Vue({
computed: {
token: {
get: function () {
return localStorage.getItem('id_token')
},
set: function (id_token) {
localStorage.setItem('id_token', id_token)
}
},
accessToken: {
get: function () {
return localStorage.getItem('access_token')
},
set: function (accessToken) {
localStorage.setItem('access_token', accessToken)
}
},
expiresAt: {
get: function () {
return localStorage.getItem('expires_at')
},
set: function (expiresIn) {
let expiresAt = JSON.stringify(expiresIn * 1000 + new Date().getTime())
localStorage.setItem('expires_at', expiresAt)
}
},
user: {
get: function () {
return JSON.parse(localStorage.getItem('user'))
},
set: function (user) {
localStorage.setItem('user', JSON.stringify(user))
}
}
},
methods: {
login() {
webAuth.authorize()
},
logout() {
return new Promise((resolve, reject) => {
localStorage.removeItem('access_token')
localStorage.removeItem('id_token')
localStorage.removeItem('expires_at')
localStorage.removeItem('user')
webAuth.authorize()
})
},
isAuthenticated() {
return new Date().getTime() < this.expiresAt
},
handleAuthentication() {
return new Promise((resolve, reject) => {
webAuth.parseHash((err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
this.expiresAt = authResult.expiresIn
this.accessToken = authResult.accessToken
this.token = authResult.idToken
this.user = authResult.idTokenPayload
resolve()
} else if (err) {
this.logout()
reject(err)
}
})
})
}
}
})
export default {
install: function (Vue) {
Vue.prototype.$auth = auth
}
}
I have this Javascript code to handle ActiveDirectory authentication.
I need to create a React component that uses this code, what is the best way to achieve this in React?
var config = { url: 'ldap://compandomain.com:389',
baseDN: 'dc=domainname,dc=com',
username: 'user',
password: 'pass' };
var ad = new ActiveDirectory(config);
var username = 'john.smith#domain.com';
var password = 'password';
ad.authenticate(username, password, function(err, auth) {
if (err) {
console.log('ERROR: '+JSON.stringify(err));
return;
}
if (auth) {
console.log('Authenticated!');
}
else {
console.log('Authentication failed!');
}
});
The React component looks like this:
export default class ActiveDirectory extends React.Component {
..
......
.........
render() {
return <div ..../>;
}
}
you should be abler to handle this authentication in the componentDidMount lifecycle method. it should probably look like this.
import React from 'react';
import ActiveDirectory from 'activedirectory';
export default class ActiveDirectoryComponent extends React.Component {
state = {
authResponse: undefined
};
componentDidMount() {
var config = {
url: 'ldap://compandomain.com:389',
baseDN: 'dc=domainname,dc=com',
username: 'user',
password: 'pass'
};
var ad = new ActiveDirectory(config);
var username = 'john.smith#domain.com';
var password = 'password';
ad.authenticate(username, password, function (err, auth) {
if (err) {
this.setState({ authResponse: { error: JSON.stringify(err) } });
return;
}
if (auth) {
this.setState({ authResponse: auth });
} else {
console.log('Authentication failed!');
this.setState({ authResponse: { authFailed: true } });
}
});
}
render() {
if (!this.state.authResponse) {
return <div>Authenticating....</div>;
}
if (this.state.authResponse.error) {
return <div>{this.state.authResponse.error}</div>
}
if (this.state.authResponse.authFailed) {
return <div>Authentication Failed</div>
}
return <div>.....</div>
}
}
I am trying to make login with google in vue by following google document and everything worked but i cant access method inside attachClickHandler.
new Vue({
el: '#loginModal',
data: { ...
},
methods: {
gInit: function() {
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: 'MY-Client-id.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin',
//scope: 'additional_scope'
});
auth2.attachClickHandler(document.getElementById('googleBtn'), {},
function(googleUser) {
const profile = googleUser.getBasicProfile();
const gplusObj = {
name: profile.getName(),
email: profile.getEmail(),
provider: 'google',
image: profile.getImageUrl(),
provider_user_id: profile.getId()
};
this.socialLogin(gplusObj);
},
function(error) {
alert(JSON.stringify(error, undefined, 2));
});
});
},
socialLogin: function(data) {
axios.post(`${this.api}/api/sociallogin`, data)
.then(res => {
console.log(res);
}).catch(err => {
console.log(err);
});
},
},
mounted: function() {
this.gInit();
}
})
Here calling a function socialLogin() inside attachClickHandler() is giving error this.socialLogin is not a function is not defined. Why this is not working?
It's because the this.socialLogin call is located in a callback function. This function creates a new context so this changes and won't be your component anymore.
Use arrow functions. They won't change this.
Edit: Change your code like this:
gInit() {
gapi.load('auth2', () => {
...
auth2.attachClickHandler(document.getElementById('googleBtn'), {}, (googleUser) => {
...
this.socialLogin(gplusObj);
}, (error) => {
alert(JSON.stringify(error, undefined, 2));
});
});
},
More on that topic: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions, see "No separate this".
Because you didn't save this,try :
new Vue({
el: '#loginModal',
data: { ...
},
methods: {
gInit: function() {
let self = this // new added
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: 'MY-Client-id.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin',
//scope: 'additional_scope'
});
auth2.attachClickHandler(document.getElementById('googleBtn'), {},
function(googleUser) {
const profile = googleUser.getBasicProfile();
const gplusObj = {
name: profile.getName(),
email: profile.getEmail(),
provider: 'google',
image: profile.getImageUrl(),
provider_user_id: profile.getId()
};
console.log(e);
self.socialLogin(gplusObj); //updated
},
function(error) {
alert(JSON.stringify(error, undefined, 2));
});
});
},
socialLogin: function(data) {
axios.post(`${this.api}/api/sociallogin`, data)
.then(res => {
console.log(res);
}).catch(err => {
console.log(err);
});
},
},
mounted: function() {
this.gInit();
}
})
this wouldn't be passed automatically and you should already know this before learning vue.
Also,you can use arrow function to avoid this being changed:
new Vue({
el: '#loginModal',
data: { ...
},
methods: {
gInit: function() {
gapi.load('auth2', function() {
auth2 = gapi.auth2.init({
client_id: 'MY-Client-id.apps.googleusercontent.com',
cookiepolicy: 'single_host_origin',
//scope: 'additional_scope'
});
auth2.attachClickHandler(document.getElementById('googleBtn'), {},
(googleUser) => { //updated
const profile = googleUser.getBasicProfile();
const gplusObj = {
name: profile.getName(),
email: profile.getEmail(),
provider: 'google',
image: profile.getImageUrl(),
provider_user_id: profile.getId()
};
console.log(e);
this.socialLogin(gplusObj);
},
function(error) {
alert(JSON.stringify(error, undefined, 2));
});
});
},
socialLogin: function(data) {
axios.post(`${this.api}/api/sociallogin`, data)
.then(res => {
console.log(res);
}).catch(err => {
console.log(err);
});
},
},
mounted: function() {
this.gInit();
}
})