get Client IP in Accounts.OnCreateUser Meteor JS - meteor

I am trying to get client IP address in
Accounts.onCreateUser((options, user) => {
var data = {
"updated_at" : new Date(),
"registration_ip" : user.connection.clientAddress,
"recruiter" : "SELF",
"registration_time" : new Date(),
};
_.extend(user.profile, data);
return user;
});
I get Error as :
I20170511-19:11:26.792(5.5)? Exception while invoking method 'createUser'
TypeError: Cannot read property 'clientAddress' of undefined
How can I get Client IP Address here?

This is the code I used to get user IP address.
Accounts.validateLoginAttempt(function (attempt) {
/* Before any checks save user first time login attempt IP address */
let IPAddress = Global.getNestedValue(attempt, 'connection.httpHeaders.x-forwarded-for');
if (IPAddress && attempt.user && !attempt.user.firstTimeIP) {
Meteor.users.update({ _id: attempt.user._id }, { $set: { firstTimeIP: IPAddress } })
}
}

Related

App Maker: Sending Email, client script to server script function not working. Failed due to illegal value in property: a

I am new to AppMaker but I have developer experience.
The application is a Project Tracker Application
What I expect to happen: When creating a project the user uses a User Picker to select the users associated with that project. When the project is created I want to email the users associated with that project.
The issue: On clicking the Add button addProject(addButton) client script function is called.
Inside this function sendEmailToAssignees(project, assignees) is called which should reach out to the Server script and run the notifyAboutProjectCreated(project, assignees) but that is not happening.
Things to know: With logging I never reach 'Trying to send email' so I seem to never reach my server script. Also, On client script when I comment out sendEmailToAssignees function everything runs smooth. I have looked at this documentation as a resource so I feel my implementation is okay. https://developers.google.com/appmaker/scripting/client#client_script_examples
The final error message I get is:
Failed due to illegal value in property: a at addProject
(AddProject:110:24) at
AddProject.Container.PanelAddProject.Form1.Spring.ButtonAdd.onClick:1:1
Am I missing something here? Any help would be greatly appreciated. Thank you!
Client Script
function sendEmailToAssignees(project, assignees) {
google.script.run
.withSuccessHandler(function() {
console.log('Sending Email Success');
}).withFailureHandler(function(err) {
console.log('Error Sending Email: ' + JSON.stringify(err));
})
.notifyAboutProjectCreated(project, assignees);
}
function addProject(addButton) {
if (!addButton.root.validate()) {
return;
}
addButton.datasource.createItem(function(record) {
var page = app.pages.AddProject;
var pageWidgets = page.descendants;
var trainees = pageWidgets.AssigneesGrid.datasource.items;
var traineesEmails = trainees.map(function(trainee) {
return trainee.PrimaryEmail;
});
record.Assignee = traineesEmails.toString();
var assignees = traineesEmails.toString();
var project = record;
updateAllProjects(record);
console.log('update all projects done');
sendEmailToAssignees(project, assignees);
console.log('Send Email done');
if (app.currentPage !== app.pages.ViewProject) {
return;
}
gotoViewProjectPageByKey(record._key, true);
});
gotoViewProjectPageByParams();
}
Server Script
function notifyAboutProjectCreated(project, assignees) {
console.log('Trying to send email');
if (!project) {
return;
}
var settings = getAppSettingsRecord_()[0];
if (!settings.EnableEmailNotifications) {
return;
}
var data = {
appUrl: settings.AppUrl,
assignee: project.Assignee,
owner: project.Owner,
startDate: project.StartDate,
endDate: project.EndDate,
jobType: project.Type,
jobId: project.Id
};
// Email Subject
var subjectTemplate = HtmlService.createTemplate(settings.NotificationEmailSubjectJob);
subjectTemplate.data = data;
var subject = subjectTemplate.evaluate().getContent();
// Email Body
var emailTemplate =
HtmlService.createTemplate(settings.NotificationEmailBodyJob);
emailTemplate.data = data;
var htmlBody = emailTemplate.evaluate().getContent();
console.log('About to send email to:', assignees);
sendEmail_(null, assignees, subject, htmlBody);
}
The reason you are getting this error is because you are trying to pass the client "project record" to the server. If you need to access the project, then pass the record key to the server and then access the record on the server using the key.
CLIENT:
function sendEmailToAssignees(project, assignees) {
var projectKey = project._key;
google.script.run
.withSuccessHandler(function() {
console.log('Sending Email Success');
}).withFailureHandler(function(err) {
console.log('Error Sending Email: ' + JSON.stringify(err));
})
.notifyAboutProjectCreated(projectKey , assignees);
}
SERVER:
function notifyAboutProjectCreated(projectKey, assignees) {
console.log('Trying to send email');
var project = app.models.<PROJECTSMODEL>.getRecord(projectKey);
if (!project) {
return;
}
//Rest of the logic
}
The project record object in the client is not the same as the project record object in the server; hence the ilegal property value error.

Dwolla : InvalidTokenType : The requested endpoint requires an account token

Now I am switching to production. And getting “InvalidTokenType : The requested endpoint requires an account token” error while creating new customer.
'getDwollaAccount' : function(userId) {
var dwollaCredentials = getDwollaCreden();
const client = new dwolla.Client({
key : dwollaCredentials.appKey,
secret : dwollaCredentials.appSecret,
environment : 'production' // optional - defaults to production
}); // call dwolla initial api
client.auth.client()
.then(Meteor.bindEnvironment(function(appToken) {
var userFound =
Meteor.users.findOne({'_id':userId,'profile.dwollaLocation':''});
if(userFound){
var requestBody = {
firstName : userFound.profile.firstname,
lastName : userFound.profile.lastname,
email : userFound.emails[0].address
};
appToken
.post('customers', requestBody)
.then(
(res)=> {
var dwollaLocation = res.headers.get('location');;
return Promise.resolve(dwollaLocation);
}
)
.then(
Meteor.bindEnvironment((dloc) =>{
return Promise.resolve(dloc);
})
)
.catch(Meteor.bindEnvironment((error) => {
console.log(error);
}));
} // end of user found
})
);
},
Thanks in advance!
If this code worked in the Dwolla Sandbox, it's probably not a problem with your code. Please contact your Dwolla account manager to help resolve.
If you're not in a contract with Dwolla and/or you don't have any account manager, you can use the contact form to help get that process initiated: Contact Dwolla
Thanks!

Meteor HTTP.POST call on same machine (for testing)

I have created a server side route (using iron-router). Code is as follows :
Router.route( "/apiCall/:username", function(){
var id = this.params.username;
},{ where: "server" } )
.post( function(req, res) {
// If a POST request is made, create the user's profile.
//check for legit request
console.log('post detected')
var userId = Meteor.users.findOne({username : id})._id;
})
.delete( function() {
// If a DELETE request is made, delete the user's profile.
});
This app is running on port 3000 on my local. Now I have created another dummy app running on port 5000. Frrom the dummy app, I am firing a http.post request and then listening it on the app on 3000 port. I fire the http.post request via dummy app using the below code :
apiTest : function(){
console.log('apiTest called')
HTTP.post("http://192.168.1.5:3000/apiCall/testUser", {
data: [
{
"name" : "test"
}
]
}, function (err, res) {
if(!err)
console.log("succesfully posted"); // 4
else
console.log('err',err)
});
return true;
}
But I get the following error on the callback :
err { [Error: socket hang up] code: 'ECONNRESET' }
Not able to figure out whats the problem here.
The server side route is successfully called, but the .post() method is not being entered.
Using meteor version 1.6
192.168.1.5 is my ip addr
Okay so if I use Router.map function, the issue is resolved.
Router.map(function () {
this.route("apiRoute", {path: "/apiCall/:username",
where: "server",
action: function(){
// console.log('------------------------------');
// console.log('apiRoute');
// console.log((this.params));
// console.log(this.request.body);
var id = this.params.username;
this.response.writeHead(200, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
});
if (this.request.method == 'POST') {
// console.log('POST');
var user = Meteor.users.findOne({username : id});
// console.log(user)
if(!user){
return 'no user found'
}
else{
var userId = user._id;
}
}
});
});
It looks like the content type is not set the application/json. So you should do that...
Setting the "Content-Type" header in HTTP.call on client side in Meteor

invalid_grant Google OAuth

I am trying to authentiate through Google's OAuth, but I'm having problems establishing a connection to their API
My client code:
'click #addChannel': function (event) {
event.preventDefault();
var userId = Meteor.userId();
var options = {
requestPermissions: [
'https://www.googleapis.com/auth/youtube',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/youtube.force-ssl',
'https://www.googleapis.com/auth/youtube.readonly',
'https://www.googleapis.com/auth/youtube.upload',
'https://www.googleapis.com/auth/youtubepartner',
'https://www.googleapis.com/auth/youtubepartner-channel-audit',
],
requestOfflineToken: true
};
Google.requestCredential(options, function(token) {
Meteor.call('userAddOauthCredentials', userId, token, function(error, result) {
if (error) {
throw error;
}
console.log(result);
});
});
My server code:
userAddOauthCredentials: function(userId, token) {
check(userId, String);
check(token, String);
var config = ServiceConfiguration.configurations.findOne({service: 'google'});
if (!config) {
throw new ServiceConfiguration.ConfigError();
}
console.log(token, config);
var endpoint = 'https://accounts.google.com/o/oauth2/token';
var params = {
code: token,
client_id: config.clientId,
client_secret: OAuth.openSecret(config.secret),
redirect_uri: OAuth._redirectUri('google', config),
grant_type: 'authorization_code',
};
try { <------------------------------------------------------ this fails
response = HTTP.post(endpoint, { params: params });
} catch (err) {
throw _.extend(new Error("(first) Failed to complete OAuth handshake with Google. " + err.message),
{response: err.response});
}
if (response.data.error) { // if the http response was a json object with an error attribute
throw new Error("(second) Failed to complete OAuth handshake with Google. " + response.data);
} else {
return {
accessToken: response.data.access_token,
refreshToken: response.data.refresh_token,
expiresIn: response.data.expires_in,
idToken: response.data.id_token
};
}
The above throws a [400] { "error" : "invalid_grant" } error.
Most of the above code I got from how the meteor accounts-google packages logs in a user (which works fine in my application). Link to that:
https://github.com/meteor/meteor/blob/87e3c6499d5eacce62f10faefe9ce49c77bb03ee/packages/google/google_server.js
Any advice on how to proceed from here?
Much appreciated
UPDATE1:
I get these warnings in my log
W20150318-09:11:42.532(1) (oauth_server.js:71) Unable to base64 decode state from OAuth query: undefined
W20150318-09:11:42.532(1) (oauth_server.js:71) Unable to base64 decode state from OAuth query: undefined
W20150318-09:11:42.533(1) (oauth_server.js:71) Unable to base64 decode state from OAuth query: undefined
W20150318-09:11:42.534(1) (oauth_server.js:398) Error in OAuth Server: Match error: Expected string, got undefined
You have to parse your var params to application/x-www-form-urlencoded. Please find the below code to parse as i done in php
$fields_string="";
foreach($params as $key=>$value)
{
$fields_string .= $key.'='.$value.'&';
}
rtrim($fields_string, '&');
Now the $filed_string will contained the parse of params array.

How do request to external resource in Meteor?

I need get data from external service. It has API. This is example:
http://portal.example.com/portal.api?l=username&p=keyphrase&act=brand_by_nr&nr=kl2&alt
Parameters are:
"l" - login, "p" - password, "act" - function to execute, "nr" - part number
I try connect by Meteor http.This is my server code:
var sources = {
mskv: {
url: "http://portal.example.com/portal.api",
auth: { l: "mylogin", p: "cBKoTyalCgbOQb37NG6sbb0qv2I0Q4PmWRJIJMWpOhCPFombqeDv7fBhdkjsdhkjah" },
params: { act: "brand_by_nr", nr: null }
}
};
Meteor.methods({
doRequest: function(partNumber) {
for (var key in sources) {
var url = sources[key].url;
var authData = sources[key].auth;
var paramsData = sources[key].params;
paramsData.nr = partNumber;
HTTP.call("POST", url, { auth: authData, params: paramsData }, function(err, res) {
if (err) {
throw new Meteor.Error("not-response", "Remote server not responding");
}
return res;
});
}
}
});
This is my client code:
Template.search.events({
"click .search": function(event) {
var partNumber = document.getElementsByClassName("input")[0].value;
Meteor.call("doRequest", partNumber, function(err, res) {
if(err === "not-response") return;
console.log(res);
});
}
});
I have error:
> Exception while invoking method 'doRequest' TypeError: Object
> #<Object> has no method 'indexOf' I20150227-00:01:35.455(3)? at Object._call (packages/http/httpcall_server.js:42:1)
> I20150227-00:01:35.455(3)? at Object._.extend.wrapAsync [as call]
> (packages/meteor/helpers.js:118:1) I20150227-00:01:35.455(3)? at
> [object Object].Meteor.methods.doRequest (app/server/server.js:19:18)
Can you help me, where is my error?
Try
var paramsData = [sources[key].params];
I suspect it's looking for an array there.
In my case auth field is not correct. The true way is auth:"login: password", look as simply string. Second error - auth field is not need. For this service login and password send as parameters { params: {l:"login", p: "password", act: "brand_by_nr" ....} }

Resources