How to store chrome identity api response in vuejs component - javascript

I'm passing the response from chrome identity api to the tab that will run my vue powered chrome extension. I need to store this information inside my vue instance tu use it inside a component. I've tried to assign the info to a variable using this.username but it will result in undefined in console. What's wrong with the code and what's the best way to accomplish this?
component code
<script>
import { EventBus } from '../../event-bus';
export default {
data () {
return {
socket: null,
isRegistered: false,
isConnected: false,
username: null,
message: '',
}
},
created() {
},
mounted() {
chrome.runtime.onMessage.addListener(
function(request, sender){
console.log(request);
this.username = request.name;
this.isRegistered = true;
});
EventBus.$emit('open-connection')
// the variable is undefined and also the open-connection event are not emitted?
console.log(this.username)
EventBus.$on('connected', (socket) => {
console.log(socket)
this.socket = socket;
this.isConnected = true;
console.log(this.socket.id)
})
},
methods: {
// I was using this method but the function isn't called inside mounted, result in an error :(
connect(){
//if( this.isRegistered === false){
//this.username = this.username;
//this.isRegistered = true;
//EventBus.$emit('open-connection')
//return this.username;
// }
}
// methods here
}
}
</script>
<style scoped>
</style>
The response from identity api (I will omit the fields value for privacy):
{
"id": "100xxxxxx",
"name": "xxx",
"given_name": "xxxx",
"family_name": "xxxx",
"picture": "https://lh4.googleusercontent.com/xxxxx.jpg",
"locale": "xx"
}
NB: the response object is not accessible in this way key.val
EDIT
After some debug I've finally found a solution. The response information retrived by the api isn't really an object but a JSON. I've used the JSON.parse() function to make it an object and now I'm able to access to the fields using key.value syntax.

Perhaps you could use the chrome.storage to set/get the data rather than rely on the components state.
Otherwise can you share what the console.log(request) is giving you and what the background script looks like?

Related

Websockets in Vue/Vuex (how to receive emissions from server)

So until now I just socket.io-client to do communication to a WebSocket in my Vue component.
Now I am adding Vuex to the project and declared a Websocket like this
Vue.use(new VueSocketIO({
debug: true,
connection: 'http://192.168.0.38:5000',
}));
new Vue({
router,
store,
render: (h) => h(App),
}).$mount('#app');
1) Should i have stuff like emitting some messages in the component themselves now or in the store?
2) Before I introduced the changes I could do something like this:
socket.on('connect', function () {
console.error('connected to webSocket');
socket.emit('my event', { data: 'I\'m connected!' });
});
socket.on('my response', function(data){
console.log('got response');
console.log(data.data);
});
When sending the "my event", the flask server would respond with "my response". Now I am trying the same thing from a component after the changes like this.
this.$socket.emit('my_event', { data: 'I\'m connected!' });
console.error('send to websocket ');
this.$options.sockets.my_event = (data) => {
console.error('received answer ');
console.error(data);
};
The my_event reaches my flask server however I don't get the response receiving to work. What am I doing wrong?
Also because I was asking about whether I should put this in the component or the store, I found stuff like this for the store:
SOCKET_MESSAGECHANNEL(state, message) {
state.socketMessage = message
}
The explanation was "So, for example, if your channel is called messageChannel, the corresponding Vuex mutation would be SOCKET_MESSAGECHANNEL" and it is from this site https://alligator.io/vuejs/vue-socketio/.
I think I don't really get what a channel is at this point. Is the my_response I emit from the flask server also a channel?
Thanks for your help in advance!
EDIT: So now I am trying to listen and emit to a websocket from my store. For this I tried the following: In main.js I have this part:
Vue.use(new VueSocketIO({
debug: true,
connection: SocketIO('http://192.168.0.38:5000'),
vuex: {
store,
actionPrefix: 'SOCKET_',
mutationPrefix: 'SOCKET_',
},
}));
Then in my store.js I have the following:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0,
title: 'title from vuex store',
isConnected: false,
},
mutations: {
increment(state) {
state.count += 1;
},
emitSth(state) {
this.sockets.emit('my_event', { data: 'I\'m connected!' });
console.log(state.count);
},
SOCKET_my_response(state) {
state.isConnected = true;
alert(state.isConnected);
},
SOCKET_connect(state) {
state.isConnected = true;
alert(state.isConnected);
},
},
});
And in my component I have this script:
export default {
name: 'ControlCenter',
data() {
return {
devices: [{ ip: 'yet unknown' }], // placeholder so line 12 does not throw error before actual device info fetched
thisDeviceIndex: 0,
currentLayoutIndex: 0,
layouts: [],
};
},
computed: mapState([
'title',
'count',
]),
components: {
DNDAssign,
FirstPage,
},
methods: {
// mapMutation helper let's us use mutation from store via this instead of this.$store
...mapMutations([
'increment',
'emitSth',
]),
incrementMutation() {
this.increment();
},
emitEvent() {
this.emitSth();
},
// some other stuff here
},
created() {
// inital fetching of layouts
console.log('fetching layouts from backend');
this.getAllLayouts();
console.log(this.$socket);
},
};
I also have a button for the triggering of the emit which is
<b-button
type="button"
variant="success"
v-on:click="emitEvent()"
>
emit event
</b-button>
The connected in the store gets triggered, however I get the following errors for the emitting:
"TypeError: Cannot read property 'emit' of undefined"
"Cannot read property 'emit' of undefined"
Also I am not sure about the naming in the mutations. If I have this mutationPrefix, shouldn't it be enough to just use connect instead of SOCKET_connect?
First of all, if you are using Vue-Socket.io version 3.0.5>, uninstall it and install version 3.0.5
npm uninstall vue-socket.io
npm install vue-socket.io#3.0.5
then lock the version in packege.json: "vue-socket.io": "3.0.5", latest update seems to breaks the library, read more here
Now to receive events from socket.io server, you can do:
this.sockets.subscribe("my response", (data) => {
console.log(data);
});
or if want put listener on component level, you need to add sockets object on the component export, for example:
export default {
...
sockets: {
"my response": function (data) {
console.log(data);
}
}
...
}
Since you are not using Vuex Integration on the VueSocketIO, you dont need to put additional function in store mutation. If you want to use Vuex integration on VueSocketIO, you need to add vuex object when declaring the VueSocketIO class.
Here's the basic example for main.js
// Set Vue to use Vuex
Vue.use(Vuex);
// Create store
const store = new Vuex.Store({
state: {
someData: null
},
getters: {},
actions: {
"SOCKET_my response"(context, data) {
// Received `my response`, do something with the data, in this case we are going to call mutation "setData"
context.commit("setData", data);
}
}
mutations: {
["setData"](state, data) {
state.someData = data; // Set it to state
}
}
});
// Set Vue to use VueSocketIO with Vuex integration
Vue.use(new VueSocketIO({
debug: true,
connection: 'http://192.168.0.38:5000',
vuex: {
store,
actionPrefix: "SOCKET_"
}
}));
new Vue({
router,
store
render: h => h(App)
}).$mount("#app");
If you need example on Vuex Integration, you can check my example app that uses Vue and Vue-Socket.io with Vuex integration.te

Exported data is null when using it in another javascript vue js file

i am developing a shopify theme, currently i am working on shopping cart page, i have CartForm.js file where i am importing data from cartData.js file. This is CartForm.js...
import { store } from "./../shared/cartData.js";
if (document.querySelector('.cart-form')) {
let productForm = new Vue({
el:".cart-form",
delimiters: ['${', '}'],
data(){
return{
cart:null,
}
},
created(){
this.getCart();
},
methods:{
getCart(){
store.getCart();
this.cart=store.state.cartData;
console.log("cart data: "+this.cart);
},
and this is cartData.js file
export const store = {
state: {
cartData:null
},
getCart(){
alert("store get cart called!...")
axios.get('/cart.js')
.then( response => {
this.state.cartData=response.data;
console.log("Responsed data="+this.state.cartData);
})
.catch( error => {
new Noty({
type: 'error',
layout: 'topRight',
text: 'There was an error !!'
}).show();
});
}
}
As you can see i am explicitly calling store.getCart(); in CartForm's getCart() method, and when "Responsed data" gets printed it shows that this.state.cartData filled with data, but when i am using it like this: this.cart=store.state.cartData; this.cart is null, why is null? Any help is appreciated
This happens because your API takes a while to respond, but JavaScript continues running the function in parallel. Your state is still 'null' while the call hasn't returned, thus this.cart will be set to null, unless you tell JavaScript to wait until the call is finished.
Try making the getCart() method an asynchronous function:
methods:{
async getCart(){
await store.getCart();
this.cart=store.state.cartData;
console.log("cart data: "+this.cart);
},
If cart should always be the same as the data in your store, a better way to do this might be to use a computed property for cart. This returns the store.state directly and will help you keep a single source of truth for your data.
computed: {
cart() {
return store.state.cartData
}
}

ScopeKey doesn't work in nuxt.js auth module

Recently i started to learn how to use Nuxtjs and while learning how to use its Auth module i came across a problem.
I'm able to log in and I want to check the scope of the accounts, i tried doing it using the "scopeKey" property of "Auth". From the back end i get the "scope" from the databse and it can either be "user" or "admin".
I have tried to set the scope with
scopeKey: 'scope'
But I get that scope is "undefined"/"null" when checking with
this.$auth.hasScope('admin') / this.$auth.hasScope('user')
or "this.$auth.hasScope(admin)" return an empty value when setting "scopeKey" to
scopeKey: 'data.scope'
or
scopeKey: 'user.scope'
Here is my auth strategy:
auth: {
strategies: {
local: {
scopeKey: 'scope',
endpoints: {
login: {
url: 'api/auth/login',
method: 'post',
propertyName: 'token',
},
logout: {
url: 'api/auth/logout',
method: 'get'
},
user: {
url: 'api/me',
method: 'get',
propertyName: data
}
}
}
},
redirect: {
login: '/auth/login',
logout: '/',
callback: '/auth/login',
home: '/dash/'
}
}
and here it is an example of the json that the auth module reads when i log in:
"data": {
"id": 2,
"name": "test1",
"email": "test#test.com",
"email_verified_at": null,
"scope": "admin",
"created_at": "2019-08-01 13:11:49",
"updated_at": "2019-08-01 13:11:49"
},
I can access the scope value on the front end page with
$auth.user.scope
or with
$auth.$state.user.scope
But how can I give the "scope" to the "scopeKey" property in the nuxt.config.js file while setting the "auth" properties/strategy?
edit:
I have tried moving it inside the auth object or deleting the property and I still get false on $auth.hasScope('admin') and $auth.hasScope('user') which means scopeKey is still undefined and i'm not sure why.
The scopeKey is 'scope' by default. You don't need to set it again.
For me it worked by doing server side change.
When I put string value in scope, it does not work
$data['scope'] = "admin";
But when I changed it to array, $auth.hasScope('admin') works;
$data['scope'] = array("admin", "test");
Hope it helps.
scopeKey: 'scope' should not be placed inside strategies object.
Put it directly in the auth object.
Take a look at default config.
P.S. You can even delete this property from your auth config object, because 'scope' is default value for scopeKey.
Somehow hasScope() is not working for me too, so I directly checked the user object, I also has token in my response.
I am having a type variable in my response that tells me if the user is admin or someone else.
add this into your middleware
export default function ({ $auth, redirect }) {
if (!$auth.loggedIn) {
return redirect('/')
}
if ($auth.user.type != 'Super Admin') { // Super Admin or whatever the user you want to check
return redirect('/')
}
}

Run computed function after mounted - VUE

I'm trying to run a function that needs some data that I get back from the mounted method. Right now I try to use computed to create the function but unfortunately for this situation computed runs before mounted so I don't have the data I need for the function. Here is what I'm working with:
computed: {
league_id () {
return parseInt(this.$route.params.id)
},
current_user_has_team: function() {
debugger;
}
},
mounted () {
const params = {};
axios.get('/api/v1/leagues/' +this.$route.params.id, {
params,
headers: {
Authorization: "Bearer "+localStorage.getItem('token')
}
}).then(response => {
debugger;
this.league = response.data.league
this.current_user_teams = response.data.league
}).catch(error => {
this.$router.push('/not_found')
this.$store.commit("FLASH_MESSAGE", {
message: "League not found",
show: true,
styleClass: "error",
timeOut: 4000
})
})
}
As you can see I have the debugger in the computed function called current_user_has_team function. But I need the data I get back from the axios call. Right now I don't have the data in the debugger. What call back should I use so that I can leverage the data that comes back from the network request? Thank You!
If your computed property current_user_has_team depends on data which is not available until after the axios call, then you need to either:
In the current_user_has_team property, if the data is not available then return a sensible default value.
Do not access current_user_has_team from your template (restrict with v-if) or anywhere else until after the axios call has completed and the data is available.
It's up to you how you want the component to behave in "loading" situations.
If your behavior is synchronous, you can use beforeMount instead of mounted to have the code run before computed properties are calculated.

How to use servicebus topic sessions in azure functionapp using javascript

I have an Azure Functionapp that processes some data and pushes that data into an Azure servicebus topic.
I require sessions to be enabled on my servicebus topic subscription. I cannot seem to find a way to set the session id when using the javascript functionapp API.
Here is a modified extract from my function app:
module.exports = function (context, streamInput) {
context.bindings.outputSbMsg = [];
context.bindings.logMessage = [];
function push(response) {
let message = {
body: CrowdSourceDatum.encode(response).finish()
, customProperties: {
protoType: manifest.Type
, version: manifest.Version
, id: functionId
, rootType: manifest.RootType
}
, brokerProperties: {
SessionId: "1"
}
context.bindings.outputSbMsg.push(message);
}
.......... some magic happens here.
push(crowdSourceDatum);
context.done();
}
But the sessionId does not seem to get set at all. Any idea on how its possible to enable this?
I tested sessionid on my function, I can set the session id property of a message and view it in Service Bus explorer. Here is my sample code.
var connectionString = 'servicebus_connectionstring';
var serviceBusService = azure.createServiceBusService(connectionString);
var message = {
body: '',
customProperties:
{
messagenumber: 0
},
brokerProperties:
{
SessionId: "1"
}
};
message.body= 'This is Message #101';
serviceBusService.sendTopicMessage('testtopic', message, function(error)
{
if (error)
{
console.log(error);
}
});
Here is the test result.
Please make sure you have enabled the portioning and sessions when you created the topic and the subscription.

Categories

Resources