Meteor: callLoginMethod not found error - meteor

I'm having difficulty invoking a login method, it follows
$ meteor list
Accounts-base 1.2.14 A user account system
Ecmascript 0.6.1 Compiler plugin that supports ES2015 + in all .js files
Meteor-base 1.0.4 Packages that every Meteor app needs
React 15.0.1 Everything you need to use React with Meteor.
Static-html 1.1.13 Defines static page content in .html files
/server/main.js
import { Accounts } from 'meteor/accounts-base'
Accounts.registerLoginHandler('simples', (ttt) => {
console.log(ttt);
});
/client/main.js
autenticar(){
Accounts.callLoginMethod({
methodName: 'simples',
methodArguments: [{ tipo : 'simples' }],
validateResult: function (result) {
console.log('result', result);
},
userCallback: function(error) {
if (error) {
console.log('error', error);
}
}
})
}
When calling authenticar(), I get this error:
errorClass
  Details: undefined
  Error: 404
  ErrorType: "Meteor.Error"
  Message: "Method 'simples' not found [404]"
  Reason: "Method 'simples' not found"
Where is the error?

I've never used this API personally, but from a quick glance through the Meteor internals, I see a couple issues.
Accounts.registerLoginHandler only adds an additional handler to an array of built-in handlers which are called as part of the default Meteor login process.
If you are trying to plug in an additional handler into the existing process, you should call Accounts.callLoginMethod without the methodName key.
Calling Accounts.callLoginMethod with methodName will bypass the built-in handlers completely and replace them with your custom method, however this method needs to be declared separately by you with Meteor.methods, not registerLoginHandler.
So, that's probably your error -- you need to define your simples method with Meteor.methods. Also, you should check the code for the requirements of this method, see the comments in the code here:
https://github.com/meteor/meteor/blob/devel/packages/accounts-base/accounts_client.js

Only to complement and keep as a referral for someone else to get here. That way it's working
client.js
Accounts.callLoginMethod({
methodArguments: [{tipo: 'simples'}],
validateResult: (result) => {
console.log('success', result);
},
userCallback: function(error) {
if (error) {
console.log('error', error);
}
}
});
server.js
Meteor.startup(function () {
var config = Accounts.loginServiceConfiguration.findOne({
service : 'simples'
});
if (!config) {
Accounts.loginServiceConfiguration.insert({ service: 'simples' });
}
});
Accounts.registerLoginHandler((opts) => {
if(opts.tipo === 'simples'){
return Accounts.updateOrCreateUserFromExternalService ('simples', {
id: 0 // need define something
}, {
options : 'optional'
})
}
});

Related

Meteor methods returning undefined on client even after using callback

I am trying to get data from AirVisual API using meteor methods on the server and passing it to the client. The data is successfully received on the server. However, the template helper gets undefined when the method is called in it.
Client Helper:
Template.index.helpers({
getCityDataOnClient: function(city, state) {
Meteor.call('getCityData', city.toLowerCase(), state.toLowerCase(), function(error, result) {
if(!error) {
console.log(result); //returns undefined
}
else {
console.log(error);
}
});
}
});
Meteor methods.js in lib folder:
Meteor.methods({
getCityData : function(city, state) {
var data = [];
const result = HTTP.call('GET', 'http://api.airvisual.com/v2/city', {
params: {
state: state,
city : city,
country: 'pakistan',
key: 'xxxxxxxxxx'
}
}, function(err, res) {
if (!err) {
data = res.data.data;
//console.log(data); //prints correct data on the server and client
return data;
}
else {
console.log(err);
return err;
}
});
}
});
I have already looked up answers on similar questions. Nothing seems to work, including Tracker, reactive-var, and reactive-methods.
The problem here is that you are trying to return data from inside a callback to a function that 1. isn't waiting for you, and 2. has already returned.
Thankfully, Meteor does some magic on the server to make asynchronous calls like HTTP.call appear synchronous.
Your method can be done like so:
Meteor.methods({
getCityData : function(city, state) {
const result = HTTP.call('GET', 'http://api.airvisual.com/v2/city', {
params: {
state: state,
city : city,
country: 'pakistan',
key: 'xxxxxxxxxx'
}
});
return result.data.data;
}
});
By excluding the callback on Meteor's HTTP module, Meteor will run it in a Fiber and wait for the result before continuing execution (like with async/await)
If you were using a third party library for HTTP requests, you would need to wrap the function using Meteor.wrapAsync to get the benefit of running in a fiber. Or you could wrap it in a promise and return the promise from the method

Meteor Method w/ Mongo Aggregation returning Undefined on Client but not on Server

So I've just started with Meteor and really JavaScript so forgive the messy coding as I am new to all of this please. I'm using a Mongo Aggregation to do some server side math and the method is returning undefined on the client but the server-side console log is returning the correct information. Here is the server method...
Meteor.methods({
'schoolHealth': function() {
var pipeline = [
{
"$group": {
"_id": null,
"total": { "$avg": "$roomHealth"}
}
}
];
Equipment.aggregate(pipeline, function(err, result) {
if (err) {
throw err;
console.log("Error in finding school health average:" + result);
} else {
console.log(result[0].total)
return result[0].total;
}
});
}
});
And on the client...
Meteor.call('schoolHealth', function(error, result) {
if (error) {
console.log(error);
} else {
console.log(result);
Session.set('health', result);
}
});
I'm calling the Session on a blaze template but the method is failing before that happens. Also, I have tried not using a Session and the result is the same. I have read into Sync vs. Async but I don't know enough about it to know if I am doing something wrong there. Thanks ahead of time for the help.

Remove all data in a collection relating to user

I'm trying to remove data in a collection, however, I'm getting remove failed: Access denied. I'm not sure what I'm doing wrong.
DB - Files.find
"_id": "",
"url": "",
"userId": "",
"added": ""
Path: file.js
Template.file.events = {
"click .delete-photo" : function () {
Files.remove(this._id);
}
};
If you are uninstall autopublish package use method as above answer:
Meteor.methods({
removePhoto: function (photoId) {
check(photoId, Meteor.Collection.ObjectID);
Files.remove(photoId);
});
And on your client:
Meteor.call("removePhoto", this._id, function(error, affectedDocs) {
if (error) {
console.log(error.message);
} else {
// Do whatever
console.log("success");
}
});
and if you uninstall insecure package please publishand subscribe the collection.
Meteor.publish('collectionname',function(){
return collectionname.find();
}
and subscribe:
Meteor.subscribe('collectionname);
You should consider making this into a Meteor method.
Server side code:
Meteor.methods({
removePhoto: function (photoId) {
check(photoId, Meteor.Collection.ObjectID);
Files.remove(photoId);
});
You should consider to remove the insecure and autopublish packages by typing these commands in your console:
meteor remove autopublish
meteor remove insecure
Below there is an example of how to publish the Files collection (here you also could add security features, such as only find and publish files belonging to user with correct id):
Meteor.publish('files',function(){
return Files.find();
}
And on your client:
Meteor.call("removePhoto", this._id, function(error, affectedDocs) {
if (error) {
console.log(error.message);
} else {
// Do whatever
console.log("success");
}
});
Here is the code for subscribing to the Files collection:
Meteor.subscribe('collectionname');
Read about methods, publish and subscribe over at Meteor docs. Links: http://guide.meteor.com/methods.html, https://www.meteor.com/tutorials/blaze/security-with-methods, https://www.meteor.com/tutorials/blaze/publish-and-subscribe

Meteor 1.3 + React: detect subscription failure?

I have a simple Meteor subscription, and I display a loading message while the data is being loaded. But I don't know how to display error message if subscription failed.
export const MyAwesomeComponent = createContainer(() => {
let sub = Meteor.subscribe('some-data');
if (!sub.ready()) return { message: 'Loading...'};
if (sub.failed()) return { message: 'Failed.' }; // How to do this?
return {
data: Data.find().fetch()
}
}, MyInternalRenderComponent);
Problem is, the subscription object doesn't have a failed() method, only a ready() query. How to pass the failure of a subscription as props in a createContainer() method?
I know the Meteor.subscribe method has an onStop callback for this case, but I don't know how to glue it toghether that to pass a property.
After a lot of researching I managed to get this working and I think it answers your question.
Bear in mind I'm using Meteor 1.6, but it should give you the info to get it working on your side.
On the publication/publish:
try {
// get the data and add it to the publication
...
self.ready();
} catch (exception) {
logger.error(exception);
// send the exception to the client through the publication
this.error(new Meteor.Error('500', 'Error getting data from API', exception));
}
On the UI Component:
const errorFromApi = new ReactiveVar();
export default withTracker(({ match }) => {
const companyId = match.params._id;
let subscription;
if (!errorFromApi.get()) {
subscription = Meteor.subscribe('company.view', companyId, {
onStop: function (e) {
errorFromApi.set(e);
}
});
} else {
subscription = {
ready: () => {
return false;
}
};
}
return {
loading: !subscription.ready(),
company: Companies.findOne(companyId),
error: errorFromApi.get()
};
})(CompanyView);
From here all you need to do is get the error prop and render the component as desired.
This is the structure of the error prop (received on the onStop callback from subscribe):
{
error: String,
reason: String,
details: String
}
[Edit]
The reason there is a conditional around Meteor.subscribe() is to avoid an annoying infinite loop you'd get from the natural withTracker() updates, which would cause new subscriptions / new errors from the publication and so on.

Meteor accounts verifyEmail

I am trying to make email verification that with the accounts-password package work however I have come across a weird problem.
It seems the # in the email verification URL is causing an issue. The verification email URL usually looks like : http://localhost:3000/#/verify-email/cnaTqQSCgYAksIsFo5FgmV94NHwrfaM2g5GvdZDUMlN
When I click on this, nothing seems to happen; it just re-directs to localhost:3000/#
However when I remove the # (http://localhost:3000/verify-email/cnaTqQSCgYAksIsFo5FgmV94NHwrfaM2g5GvdZDUMlN) this seems to work perfectly.
The URL (http://localhost:3000/#/verify-email/cnaTqQSCgYAksIsFo5FgmV94NHwrfaM2g5GvdZDUMlN) comes from Meteor so it's not something I create.
Here are my routes and controllers (using iron-router)
Router.route('/verify-email/:_token', {
controller : 'AccountController',
action : 'verifyEmail'
});
AccountController = RouteController.extend({
fastRender: true,
data: function () {},
onBeforeAction: function () {
this.render('Loading');
this.next();
},
verifyEmail: function() {
var verificationToken = this.params._token;
console.log(verificationToken);
Accounts.verifyEmail(verificationToken, function(error) {
if (error) {
console.log(error);
} else {
Router.go('/');
}
});
}
});
Any help is appreciated.
The conflict might be connected to the accounts-password package together with iron:router as outlined here:
...add a server file that overrides the urls with # paths that Meteor creates, so that the Iron-Router can work:
(function () {
"use strict";
Accounts.urls.resetPassword = function (token) {
return Meteor.absoluteUrl('reset-password/' + token);
};
Accounts.urls.verifyEmail = function (token) {
return Meteor.absoluteUrl('verify-email/' + token);
};
Accounts.urls.enrollAccount = function (token) {
return Meteor.absoluteUrl('enroll-account/' + token);
};
})();
Hope it will guide you in the right direction.

Resources