Error: Cannot find module 'paypal-ipn' - meteor

Am using the forum in Paypal tutorial to test the IPN listener, when i click on submit a new tab is opened and it says:
Error: Cannot find module 'paypal-ipn' at Function.Module._resolveFilename (module.js:338:15)
at Function.Module._load (module.js:280:25)
at Module.require (module.js:364:17)
at require (module.js:380:17) at Object.Npm.require (/Users/mazinalmaskari/Desktop/code/.meteor/local/build/programs/server/boot.js:150:18)
at Object.Meteor.npmRequire (packages/npm-container/index.js:2:1) at [object Object].route.action (server/routing.js:6:30) at boundNext (packages/iron_middleware-stack/lib/middleware_stack.js:251:1) at runWithEnvironment (packages/meteor/dynamics_nodejs.js:110:1)
Am not sure where the problem is exactly, I get 500 Internal Server Error in the ngrok when i click submit.
this is my IPN listener located in the server
Router.map(function () {
this.route('ipn', {
path: '/ipn',
where: 'server',
action: function() {
var ipn = Meteor.npmRequire("paypal-ipn");
var wrappedVerify = Async.wrap(ipn, "verify");
var request = this.request;
var verified;
if (request.method !== 'POST') {
this.next();
} else {
try {
verified = wrappedVerify(request.body, {"allow_sandbox" : true});
} catch (error) {
//do something with error
}
if (verified === "VERIFIED") {
var payment = request.body;
//do something with payment
Router.go('/upload');
}
this.next();
}
}
});
});
This is the form am using (from Paypal tutorial):
<form target="_new" method="post" action="https://ba13954b.ngrok.io/ipn">
<input type="hidden" name="SomePayPalVar" value="SomeValue1"/>
<input type="hidden" name="SomeOtherPPVar" value="SomeValue2"/>
<input type="submit"/>
Any idea what might be causing this problem?

Review the module as the error message indicate. But...
Try like this:
var ipn = Meteor.npmRequire('paypal-ipn');
Based on:
https://github.com/meteorhacks/npm

Related

Accounts.onLogin throws session not found error

The LoggedInUser works well as it is suppose but whenever the app starts and the URL is queried like trying to login or navigate to any other URL, the Accounts.onLogin throws the below error. I don't know what could be the reason.
var LoggedInUser = FlowRouter.group({
name: 'currentUser', triggersEnter: [function () {
if (!Meteor.loggingIn() || !Meteor.userId()) {
var currentRoute = FlowRouter.current();
if (!currentRoute.route.name === 'home') {
console.log(currentRoute.path);
Session.set('redirectAfterLogin', currentRoute.path);
}
FlowRouter.go('home');
}
}]
});
Accounts.onLogin(function () {
let redirect = Session.get('redirectAfterLogin');
if (redirect) {
if (redirect != 'home') {
FlowRouter.go(redirect);
}
}
});
Error on cmd console
I20171003-18:28:44.913(1)? Exception in onLogin callback: ReferenceError: Session is not defined
I20171003-18:28:44.919(1)? at lib/routes/routes.js:30:18
I20171003-18:28:44.921(1)? at runAndHandleExceptions (packages\callback-hook.js:152:24)
I20171003-18:28:44.926(1)? at packages\callback-hook.js:159:12
I20171003-18:28:44.931(1)? at packages/accounts-base/accounts_server.js:164:5
I20171003-18:28:44.934(1)? at [object Object]._.extend.each (packages\callback-hook.js:128:15)
I20171003-18:28:44.938(1)? at AccountsServer.Ap._successfulLogin (packages/accounts-base/accounts_server.js:163:21)
I20171003-18:28:44.943(1)? at AccountsServer.Ap._attemptLogin (packages/accounts-base/accounts_server.js:353:10)
I20171003-18:28:44.946(1)? at [object Object].methods.login (packages/accounts-base/accounts_server.js:530:21)
I20171003-18:28:44.949(1)? at packages\check.js:128:16
I20171003-18:28:44.953(1)? at [object Object].EVp.withValue (packages\meteor.js:1135:15)
The onLogin function you are using needs the Session package according to the following line :
let redirect = Session.get('redirectAfterLogin');
The error in the console states than the Session package can not be found. Please make sure of the following:
Meteor Session is installed. If not please install it with:
meteor add Session
in your terminal in your project folder.
Session is imported in the file you want to use it, if not please add at the top of your file :
import { Session } from 'meteor/session'

Prevent client from calling server-side methods

so I have a login form that accepts a username and password. When a username/password is entered and submit is clicked, the first step is to check if the account exists and is enabled. I've accomplished that using the code below. The problem is, the server-side method that does the checking, is_user_enabled, can be accessed by the client via the browser console. Usually I can prevent this by doing:
my_method : function(doc) {
if (is_admin()) {
// Only admins can run this method.
}
}
But in the case of is_user_enabled, the user is not logged in yet. So, my question is, what is the correct way to handle this situation?
My code:
client/login.html
{{#autoForm schema=get_login_form_schema id="login_form"}}
{{> flashMessages}}
<fieldset>
<!-- <legend>Create User</legend> -->
{{> afQuickField name="username" placeholder="schemaLabel" label=false}}
{{> afQuickField name="password" placeholder="schemaLabel" type="password" label=false}}
<div>
<button type="submit" class="btn btn-primary">Login</button>
</div>
</fieldset>
{{/autoForm}}
client/lib/helpers.js
AutoForm.hooks({
login_form: {
onSubmit: function (insert_doc, update_doc, current_doc) {
Meteor.call("is_user_enabled", insert_doc, function(error, result) {
if (result) {
// Try to log user in via Meteor.loginWithPassword()
}
});
}
}
});
server/lib/methods.js
Meteor.methods({
is_user_enabled : function(doc) {
// Used by the login form. Returns true if user exists and account is enabled.
check(doc, schemas.login);
var user = Meteor.users.findOne({username: doc.username}, {fields: {status: 1}});
if (user.status === "enabled") {
return true;
}
}
});
Final Solution:
client/lib/helpers.js
AutoForm.hooks({
login_form: {
onSubmit: function (insert_doc, update_doc, current_doc) {
Meteor.loginWithPassword(insert_doc.username, insert_doc.password, function(error) {
// Called with no arguments on success
// or with a single Error argument on failure.
if (error) {
FlashMessages.sendError(error);
this.done();
} else {
// Successful login. Redirect to /.
this.done();
Router.go('/');
}
});
return false; // Prevent browser submit event.
},
}
server/lib/permissions.js
Accounts.validateLoginAttempt(function (info) {
if (info.user && info.user.status === "enabled") {
return true;
} else {
throw new Meteor.Error("Invalid credentials.");
}
});
More info about [Accounts.validateLoginAttempt][1]
You can't prevent the client from calling a server method. Your checks for is_user_enabled and is_admin need to happen inside your server methods as well as on the client. You can of course have private functions inside your methods.js file that only methods on the server can access. For more tips see http://0rocketscience.blogspot.com/2015/07/meteor-security-no-1-meteorcall.html
Yes you can prevent Meteor methods from being executed from the client side. this.connection will only be set inside a method when it is called from the client. When called from the server it will be null. The enables you to do something like this:
serverOnlyMethod: function () {
if(this.connection) throw(new Meteor.Error(403, 'Forbidden.'));
}

object is not a function in iron-router routes at onBeforeAction hook's this.next()

I'm running iron-router 1.0.7, and my onBeforeAction hook is causing an exception. Here's the stack trace:
Exception in callback of async function: TypeError: object is not a function
at Router.onBeforeAction.except (http://localhost:3000/lib/router.js?ebfe803416134e7c5b16265486b3998532289c58:45:8)
at http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:1199:36
at _.extend.withValue (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:955:17)
at Router.addHook.hookWithOptions (http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:1198:27)
at boundNext (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:31)
at Meteor.bindEnvironment (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:983:22)
at Router.onBeforeAction.only (http://localhost:3000/lib/router.js?ebfe803416134e7c5b16265486b3998532289c58:28:12)
at http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:1199:36
at _.extend.withValue (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:955:17)
at Router.addHook.hookWithOptions (http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:1198:27)
and here are the hooks that are referenced:
Router.onBeforeAction(function () {
//check if it's a logged in user
if (!Meteor.userId()) {
//if they aren't redirect them to login
this.render('login');
} else {
//if they are let them through
this.next();
}
},
//the routes we want this if logged in check for
{only: ['profile', 'logout', 'users']
});
// Redirects users to the survey until they have answered all the questions
Router.onBeforeAction(function() {
Meteor.subscribe('questions');
var answered = getUserAnswers();
var unanswered = Questions.find({ _id: { $nin: answered } }, {sort: {priority: 1}}).count();
if (unanswered && Roles.userIsInRole(Meteor.user(), 'manage-users')) {
this.next();
} else if (unanswered) {
this.redirect('survey');
}
this.next();
},
{except: ['survey', 'passwordReset', 'logout', 'settings', 'login']});
It seems to be the last this.next() that's causing the exception (That's the line referenced in the first line of the trace.), but I can't tell why. If I put a breakpoint on it in DevTools, it runs twice just fine. Then, on the third stop, next is undefined. Any idea why this is happening? The routes still seem to work normally despite the exception.

"Cannot read property 'username' of undefined" in a Meteor Route?

The page still renders as it should, but this appears in my console log.
Exception in callback of async function: TypeError: Cannot read
property 'username' of undefined
at null. (http://localhost:3000/router.js?39194109cc7760190c519a386d66c807ba19230c:48:9)
at boundNext (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:31)
at Meteor.bindEnvironment (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:983:22)
at onRerun (http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:520:9)
at boundNext (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:31)
at Meteor.bindEnvironment (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:983:22)
at onRun (http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:505:11)
at boundNext (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:31)
at Meteor.bindEnvironment (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:983:22)
at dispatch (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:448:3)
Which points to the line indicated below:
var OnBeforeActions = {
loginRequired: function() {
if (!Meteor.userId()) {
this.render('hello');
} else {
this.next();
}
}
};
Router.onBeforeAction(OnBeforeActions.loginRequired, {
only: ['home']
});
Router.route('/', function() {
// this.render('homepage');
Router.go('/users/' + Meteor.userId());
});
Router.route('/users/:user_id', function() {
this.render('home', {
data: {
username: Meteor.users.findOne({
_id: this.params.user_id
}).username, // THIS LINE HERE
}
});
});
The idea is to redirect the user to his page if he is already logged in - and it appears to work as it should, but why am I getting this?
When the browser loads initially there will not be any data available (all the collections will be empty - until they are downloaded. Thus the result of the query Meteor.users.findOne({_id: this.params.user_id}) will be undefined.
This is the reason you can't read username out of undefined.
Since the query will re-run/it is reactive you just need to take account when it is null and it will sort itself out. user.username is only read if user is not null:
Router.route('/users/:user_id', function() {
var user = Meteor.users.findOne({_id :this.params.user_id});
this.render('home', {
data: {
username: user && user.username
}
});
});

Type Error Exception in Autoform (Meteor)

I am getting a client side exception (below) while using an update autoform. I have absolutely no idea how to debug this issue. Please note, the file in the collection gets created just fine. Its just that this exception in thrown in client side console. Apologies if this is a noob-question.
Client form:
{{#autoForm class="editf" id="editf" collection="ServiceProviders" type="update" doc=selectedProvider}}
{{> afQuickField name="businessname"}}
{{> afQuickField name="businessdesc"}}
<button type="submit" class="btn btn-primary">Update your profile</button>
{{/autoForm}}
Helper:
Template.createprovider.events = {
'submit .editf' : function(e) {
event.preventDefault();
Router.go('/createdprovider');
AutoForm.resetForm('editf');
}
};
collection hooks:
ServiceProviders.after.update(function (userId, doc) {
Meteor.call('UpdateAddressAndLocation', userId, doc);
});
exception:
Exception in delivering result of invoking '/serviceproviders/update': TypeError: Cannot read property 'reset' of undefined
at Object.autoFormResetForm [as resetForm] (http://localhost:3000/packages/aldeed_autoform.js?b2b90d28d5cc29be68358bb3c8bb8a337992a7dd:2127:26)
at autoFormActionCallback (http://localhost:3000/packages/aldeed_autoform.js?b2b90d28d5cc29be68358bb3c8bb8a337992a7dd:6494:22)
at CollectionHooks.defineAdvice.args.(anonymous function) (http://localhost:3000/packages/matb33_collection-hooks.js?6be355737d1b00b2f05a3c833db2d77cd78d8d47:419:23)
at wrappedCallbackForParsingServerErrors (http://localhost:3000/packages/aldeed_collection2.js?fdc7f0975dd1b3446ea4afd5f820cb1242a521af:455:15)
at _.each.Mongo.Collection.(anonymous function).wrappedCallback (http://localhost:3000/packages/mongo.js?3cfe0c5981c197df33036a37574850f057e934a6:621:9)
at Meteor.bindEnvironment [as _callback] (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:983:22)
EDIT: Working Code:
This needs to be placed along with the submit hook. this.done() calls onSuccess.
onSuccess: function(doc, result) {
Router.go('/createdprovider');
}
Autofrom has its own properties .... You cannot use autoform id to get values on submission.
Example:
AutoForm.hooks({
YourFormid: {
onSubmit: function (doc) {
PeopleSchema.clean(doc);
console.log("People doc with auto values", doc);
this.done();
return false;
}
}
});
This is the correct way to use hooks and use "doc=this"

Resources