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();
}
})
Related
I created a Lambda function using Amplify CLI, when executing the Lambda function executes without errors but the Cognito User isn't created.
What am I missing here?
I have checked the CloudWatch Logs but not errors that I can pick up either.
I have been following this documentation: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html#adminCreateUser-property
/* Amplify Params - DO NOT EDIT
AUTH_XXXXXXXXXXXXXXXXXXXX_USERPOOLID
ENV
REGION
Amplify Params - DO NOT EDIT */
const AWS = require('aws-sdk');
AWS.config.update({ region: process.env.AWS_REGION,accessKeyId: process.env.AWS_ACCESS_KEY_ID, secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY });
const cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider({ apiVersion: '2016-04-18' });
//console.log(process.env);
exports.handler = async (event) => {
let retailerid = event.pathParameters.retailerid;
let params = {
UserPoolId: process.env.AUTH_XXXXXXXXXXXXXXXXXXXX_USERPOOLID, /* required */
Username: 'testtest', /* required */
ClientMetadata: {
},
DesiredDeliveryMediums: [
'EMAIL'
],
ForceAliasCreation: false,
MessageAction: 'SUPPRESS',
TemporaryPassword: 'mynuw000000000TTS',
UserAttributes: [
{
Name: 'custom:app_role', /* required */
Value: 'retail'
},
{
Name: 'email_verified', /* required */
Value: 'true'
},
{
Name: 'email', /* required */
Value: 'usersname#someemail.co.za'
},
{
Name: 'phone_number', /* required */
Value: '27833260000'
},
/* more items */
],
ValidationData: [
/* more items */
]
};
await cognitoidentityserviceprovider.adminCreateUser(params, function (err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log('SUCCESS', data); // successful response
});
// TODO implement
const response = {
statusCode: 200,
// Uncomment below to enable CORS requests
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(retailerid),
};
return response;
};
Test event
{
"request": {
"userAttributes": {
"custom:name": "Ajay",
"email": "ajay#gmail.com",
"custom:role": "Admin"
}
},
"response": {}
}
Lambda Function
var AWS = require('aws-sdk');
var resp200ok = { statusCode: 200, headers: {'Content-Type': 'application/json'}, body: {} };
var cognitoidentityserviceprovider = new
AWS.CognitoIdentityServiceProvider({apiVersion: '2016-04-18'});
exports.handler = function(event, context, callback){
const attributes = event.request.userAttributes; // read user attributes from event
console.log('User Role : ',attributes['custom:role'])
var params = {
UserPoolId:'*********',
Username: attributes.email,
//TemporaryPassword: 'Password!1',
DesiredDeliveryMediums: ["EMAIL"],
UserAttributes: [
{
Name: "email",
Value: attributes.email
},
{
Name: 'email_verified', /* required */
Value: 'true'
},
{
Name: 'custom:name', /* required */
Value: attributes['custom:name']
},
{
Name: 'custom:role', /* required */
Value: attributes['custom:role']
},
],
};
cognitoidentityserviceprovider.adminCreateUser(params, function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log('SUCCESS', data); // successful response
});
};
I'm not sure that await is working. How about this.
var createUserPromise = cognitoidentityserviceprovider.adminCreateUser(params).promise();
createUserPromise.then(results => {
// TODO implement
const response = {
statusCode: 200,
// Uncomment below to enable CORS requests
headers: {
"Access-Control-Allow-Origin": "*"
},
body: JSON.stringify(retailerid),
};
return response;
})
.catch(err => {
console.log("Error: ", err);
return "err"
});
await cognitoidentityserviceprovider.adminCreateUser(params).promise()
.then((data) => {
console.log('SUCCESS', data);
})
.catch((error) => {
console.log('ERROR', error);
});
This will work
I need your help with this issue that I am having while unit testing a Got client hook
where I do logging of HTTP requests. I am using Jest.
I am getting an expectations error that is seeing the argument to .toBeCalledWith as object whereas it is a string when I console log it. Maybe I am doing something wrong here. Please let me know.
got-client.js below
const http = require('http');
const https = require('https');
const got = require('got');
const _ = require('lodash');
const { name: packageName, version: packageVersion } = require('../../package.json');
const keepAliveOptions = { keepAlive: true, keepAliveMsecs: 20000 };
let clients = {};
const allowedHeaders = ['user-agent', 'x-forwarded-for', 'referer', 'content-length'];
const filterHeaders = headers => _.pick(headers, allowedHeaders);
const gotLoggingHooks = (name, logger) => ({
hooks: {
beforeRequest: [
options => {
const { url, method, headers } = options;
logger.debug({
message: `${name} request ${options.method} ${options.url}`,
http_request: {
method,
target: url,
direction: 'OUT',
headers: filterHeaders(headers)
},
request: _.pick(options, ['url', 'method', 'headers', 'body', 'json'])
});
}
],
beforeRetry: [
(options, error, retryCount) => {
const {
response: { statusCode, ip } = {},
request: { options: { method, headers = {} } = {}, requestUrl: url } = {},
timings: {
// eslint-disable-next-line camelcase
phases: { total: duration_ms } = {}
} = {}
} = error;
logger.warn({
message: `${name} will retry request, attempt ${retryCount}/${options.retry.limit} ${method} ${url} (${error.code} ${error.message})`,
err: error,
http_request: {
method,
target: url,
status: statusCode,
server_ip: ip,
duration_ms,
direction: 'OUT',
protocol: headers.via,
headers: filterHeaders(headers)
}
});
}
],
beforeError: [
error => {
const {
response: { statusCode, ip } = {},
request: { options: { method, headers } = {}, requestUrl: url } = {},
timings: {
// eslint-disable-next-line camelcase
phases: { total: duration_ms } = {}
} = {}
} = error;
if (!statusCode) {
logger.error({
message: `${name} request error ${method} ${url} (${error.code} ${error.message})`,
err: error,
http_request: {
method,
target: url,
status: statusCode,
server_ip: ip,
duration_ms,
direction: 'OUT',
protocol: headers.via,
headers: filterHeaders(headers)
}
});
}
// eslint-disable-next-line no-param-reassign
error.serviceName = name;
return error;
}
],
afterResponse: [
response => {
const {
statusCode,
body,
url,
ip,
headers = {},
request: { options: { method } = {} } = {},
timings: {
// eslint-disable-next-line camelcase
phases: { total: duration_ms } = {}
} = {},
retryCount
} = response;
logger.debug({
message: `${name} response ${method} ${url}`,
response: { body, retryCount, headers },
http_request: {
method,
target: url,
status: statusCode,
server_ip: ip,
duration_ms,
direction: 'OUT',
protocol: headers.via,
headers: filterHeaders(_.get(response, 'request.options.headers'))
}
});
return response;
}
]
}
});
const gotClient = ({ name, logger, keepAlive = true, gotOptions = {} }) => {
if (!clients[name]) {
clients[name] = got
.extend({
headers: {
'user-agent': `${packageName} ${packageVersion}`
},
...(keepAlive && {
agent: {
http: new http.Agent(keepAliveOptions),
https: new https.Agent(keepAliveOptions)
}
}),
responseType: 'json',
timeout: 5000
})
.extend(gotLoggingHooks(name, logger))
.extend(gotOptions);
}
return clients[name];
};
gotClient.clearAll = () => {
clients = {};
};
module.exports = gotClient;
got-client.spec.js below
const nock = require('nock');
const { name: packageName, version: packageVersion } = require('../../../package.json');
const gotClient = require('../../../src/lib/got-client');
const BASE_URL = 'https://subdomain.domain.com/';
const BASE_ENDPOINT = 'path';
const logger = {
error: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
log: jest.fn(),
warn: jest.fn(),
};
describe('got client', () => {
afterEach(gotClient.clearAll);
test('should log requests', async () => {
const client = gotClient({
name: 'test',
logger,
gotOptions: {
prefixUrl: BASE_URL,
},
});
nock(BASE_URL).get(`/${BASE_ENDPOINT}`).reply(200, { success: true });
await client.get(BASE_ENDPOINT);
// console.log('mock call 0', logger.debug.mock.calls[0][0]);
// TODO: match message
expect(logger.debug).toBeCalled();
expect(logger.debug).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`request GET ${BASE_URL}${BASE_ENDPOINT}`),
})
);
expect(logger.debug).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`response GET ${BASE_URL}${BASE_ENDPOINT}`),
})
);
nock(BASE_URL).get(`/${BASE_ENDPOINT}/error`).reply(500, { success: false });
try {
await client.get(`${BASE_ENDPOINT}/error`, { retry: 0 });
} catch (e) {}
expect(logger.error).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`request error GET ${BASE_URL}${BASE_ENDPOINT}/error`),
})
);
});
});
Failing Test Error below
Error: expect(jest.fn()).toBeCalledWith(...expected)
Expected: ObjectContaining {"message": StringContaining "request error GET https://subdomain.domain.com/path/error"}
Number of calls: 0
at Object.<anonymous> (/Users/user/Documents/company/teams/team/project/test/unit/lib/got-clients.spec.js:62:26)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
I will really appreciate help with this. Thank you very much in advance.
Working got-client.spec.js
const nock = require('nock');
const { name: packageName, version: packageVersion } = require('../../../package.json');
const gotClient = require('../../../src/lib/got-client');
const BASE_URL = 'https://subdomain.domain.com/';
const BASE_ENDPOINT = 'path';
const logger = {
error: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
log: jest.fn(),
warn: jest.fn(),
};
const defaultClient = gotClient({
name: 'test',
logger,
gotOptions: {
prefixUrl: BASE_URL,
},
});
describe('got client', () => {
afterEach(gotClient.clearAll);
test('should log requests', async () => {
nock(BASE_URL).get(`/${BASE_ENDPOINT}`).reply(200, { success: true });
await defaultClient.get(BASE_ENDPOINT);
expect(logger.debug).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`request GET ${BASE_URL}${BASE_ENDPOINT}`),
})
);
});
test('should log responses', async () => {
nock(BASE_URL).get(`/${BASE_ENDPOINT}`).reply(200, { success: true });
await defaultClient.get(BASE_ENDPOINT);
expect(logger.debug).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`response GET ${BASE_URL}${BASE_ENDPOINT}`),
})
);
});
test('should log errors', async () => {
const endpoint = `${BASE_ENDPOINT}/error`;
nock(BASE_URL).get(`/${endpoint}`).replyWithError({
message: 'something awful happened',
code: 'ECONNRESET',
});
try {
await defaultClient.get(endpoint, { retry: 0 });
} catch (e) {}
expect(logger.error).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`request error GET ${BASE_URL}${endpoint}`),
})
);
});
test('should log retries', async () => {
nock(BASE_URL)
.get(`/${BASE_ENDPOINT}`)
.replyWithError({
message: 'something awful happened',
code: 'ECONNRESET',
})
.get(`/${BASE_ENDPOINT}`)
.reply(500, { success: false })
.get(`/${BASE_ENDPOINT}`)
.reply(500, { success: false })
.get(`/${BASE_ENDPOINT}`)
.reply(200, { success: true });
await defaultClient.get(BASE_ENDPOINT, { retry: { limit: 3, calculateDelay: () => 1 } });
expect(logger.warn).toBeCalledTimes(3);
expect(logger.warn).toBeCalledWith(
expect.objectContaining({
message: expect.stringContaining(`will retry request`),
})
);
});
});
I'm trying to get the response object resulting of calling a vuex action with axios, I need the response in my object but it says undefined for some reason.
In my component method:
mounted()
{
console.log(this.$options.name+' component successfully mounted');
this.$store.dispatch(this.module+'/'+this.action, this.payload)
.then((response) =>
{
console.log(response);
this.items = response.data.data;
this.pagination = response.data.pagination;
});
},
My vuex action:
list({ commit }, payload)
{
commit( 'Loader/SET_LOADER', { status:1 }, { root: true });
return axios.get('/api/posts', { params: payload })
.then((response) => {
commit('Loader/SET_LOADER', { status:2, response:response }, { root: true });
console.log(response);
commit('SET_POSTS', response.data.data.data );
commit('SET_PAGINATION', response.data.pagination );
})
.catch((error) => {
commit('Loader/SET_LOADER', { status:3, errors: error }, { root: true });
throw error;
});
},
Using vuex state is not an option, I want to use the component data properties items and pagination instead.
Return promise to get the response in the component
list({ commit }, payload)
{
commit( 'Loader/SET_LOADER', { status:1 }, { root: true });
return new Promise((resolve,reject)=>{
axios.get('/api/posts', { params: payload })
.then((response) => {
commit('Loader/SET_LOADER', { status:2, response:response }, { root: true });
console.log(response);
commit('SET_POSTS', response.data.data.data );
commit('SET_PAGINATION', response.data.pagination );
resolve(response);
})
.catch((error) => {
commit('Loader/SET_LOADER', { status:3, errors: error }, { root: true }); reject(error);
throw error;
});
})
},
Using async
async list({commit}, payload) {
commit('Loader/SET_LOADER', {status: 1}, {root: true});
try {
let response = await axios.get('/api/posts', {params: payload});
commit('Loader/SET_LOADER', {status: 2, response: response}, {root: true});
console.log(response);
commit('SET_POSTS', response.data.data.data);
commit('SET_PAGINATION', response.data.pagination);
return response;
} catch (e) {
commit('Loader/SET_LOADER', {status: 3, errors: error}, {root: true});
throw error;
}
}
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
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
}
}