I have a Meteor app which works fine on my older MacBookPro (10.6.8 Snow Leopard) and also runs on a newer MacBook (10.10.5) but some of the pages don't show when I login. The same is true of my other friend who works on a similar MacBook. We get the browser warning:
Route dispatch never rendered. Did you forget to call this.next() in an onBeforeAction?
Here is a live and perfectly functional version of the app: http://sscprobs.meteor.com/
layout.js shows at all times with header, login buttons, etc.
When user is not logged in, the home route, for example, shows intro text as normal, but that text disappears upon login. It seems to me the trouble must lie with the accounts system and/or routing. Logging in with either Google or Twitter reproduces the problem equally (Facebook login is not configured for now).
I'm not sure how to troubleshoot. Here is my router.js:
Router.route('/', function() {
this.render('home');
});
Router.route('/user/:_username', {
name: 'user_profile',
data: function() { return Meteor.user();}
});
Router.route('/create', function() {
this.render('createEvent');
}, {
name: 'create'
});
Router.onBeforeAction(function () {
if (!Meteor.userId()) {
// if the user is not logged in, render the Login template
this.render('home');
} else {
// otherwise don't hold up the rest of hooks or our route/action function
// from running
this.next();
}
}, {
only: ['create']
});
Router.route('/insert', function() {
this.render('insertEvent');
});
Router.route('/events/:slug', {
name: 'event',
data: function() { return Events.findOne({slug: this.params.slug});}
});
Router.route('/useremail', function() {
this.render('userEmail');
}, {
name: 'userEmail'
});
Router._filters = {
hasCompletedProfile: function() {
if(!this.ready()) return;
var user = Meteor.user();
if (user && ! userProfileComplete(user)){
this.render('userEmail');
} else {
this.next();
}
},
};
// copied from Telesc.pe router.js
filters = Router._filters;
Router.onBeforeAction(filters.hasCompletedProfile);
Router.configure({
layoutTemplate: 'layout',
});
Here my package list:
accounts-facebook 1.0.4 Login service for Facebook accounts
accounts-google 1.0.4 Login service for Google accounts
accounts-twitter 1.0.4 Login service for Twitter accounts
aldeed:autoform 5.5.0 Easily create forms with automatic insert a...
aldeed:collection2 2.5.0 Automatic validation of insert and update o...
autopublish 1.0.3 Publish the entire database to all clients
blaze 2.1.2 Meteor Reactive Templating library
cmather:handlebars-server 2.0.0 Allows handlebars templates to be defined o...
email 1.0.6 Send email messages
insecure 1.0.3 Allow all database writes by default
iron:router 1.0.9 Routing specifically designed for Meteor
meteor-platform 1.2.2 Include a standard set of Meteor packages i...
mquandalle:jade 0.4.3_1 Jade template language
msavin:mongol 1.1.5 The insanely handy development package for ...
percolate:synced-cron 1.2.1 Allows you to define and run scheduled jobs...
service-configuration 1.0.4 Manage the configuration for third-party se...
stevezhu:fbgraph 1.2.0* Node.js module to access the Facebook graph...
todda00:friendly-slugs 0.3.4 Generate URL friendly slugs from a field wi...
twbs:bootstrap 3.3.5 The most popular front-end framework for de...
useraccounts:bootstrap 1.12.3 Accounts Templates styled for Twitter Boot...
useraccounts:iron-routing 1.12.3 UserAccounts package providing routes conf...
Any ideas?
Related
I am attempting to add Facebook authentication into an Angular2-Meteor app that started off as the Socially app from the tutorial and is slowly being modified into something less generic. There doesn't seem to be much posted on this particular use case however.
Note: I've asked in the Meteor forums and Gitter without success already.
Here are the steps I've taken:
Added Service Configuration package using
meteor add service-configuration
Created a file at server/services.ts containing (with my actual keys):
ServiceConfiguration.configurations.upsert({
"service": "facebook"
}, {
$set: {
"settings": {
"appId": “appid”,
“secret": "secret",
"loginStyle": "popup"
}
}
});
But on compile, I get an error saying
cannot find name 'ServiceConfiguration'
Which makes me think the package didn't install properly, but uninstalling/reinstalling it has not resolved the issue and it is showing in my .meteor directory.
Client side I'm calling this method with a click event on a button in a component that does have Meteor imported:
facebook() {
Meteor.loginWithFacebook((err) => {
if (err) {
//Handle error
} else {
//Handle sign in (I reroute)
this.router.navigate(['/home']);
}
})
Which throws the console error
meteor_1.Meteor.loginWithFacebook is not a function
But I suspect this is secondary to the fact that ServicesConfiguration isn't registering.
Git repo of the project is here: https://github.com/nanomoffet/ng2-starter with the referenced files being server/services.ts and client/app.ts
Currently it is not possible to use the ServiceConfiguration in TypeScript. What I did in my application was that I created a Javascript file in which I did make the ServiceConfiguration calls.
meteor add service-configuration
Create the file ./server/service-config.js
Meteor.startup(() => {
ServiceConfiguration.configurations.remove({
service: "facebook"
});
ServiceConfiguration.configurations.insert({
service: "facebook",
appId: '<APP_ID_YOU_GET_FROM FROM_FACEBOOK>',
loginStyle: "popup",
secret: '<SECRET_YOU_GET_FROM_FACEBOOK>'
});
});
I only tested it with Google and works fine for me.
Current we are using a meteor App with the iron:router package and also the spiderable and phantomjs for making this app crawlable by google.
In our special case we have some Routes where we call Meteor methods which are running async before we render the right template into our layout.
When testing spiderable on these routes the template will never get rendered and instead our "loading" template will be the rendered template.
We are testing this with /?_escaped_fragment_=
Now we are looking for a solution to tell spiderable that the page is ready or is not ready so we can control when the page has to be rendered.
Router.route('/awesome-route', function(){
// This is how it could look to tell spiderable that it has to wait
Spiderable.pleaseWait();
// Render the loading template until our route is ready
this.render('loading');
// Waiting for the response of our method
Meteor.call('data', function(err, resp){
this.render('awesome', {
data : resp
});
// This is how it could look to tell spiderable we are ready / always be polite
Spiderable.thanksForWaiting_WeAreReady();
});
}, {
name : 'awesome'
});
When opening now localhost:3000/awesome-route?_escaped_fragment_= we will just see the laoding template ...
The other option for us would be: Is there any alternatives for getting meteor apps crawled by google yet ?
Since spiderable will pre-render your template using phantomjs on server, there is no need for special methods like spiderablePleaseWaitForALittleBitMore_Please
You can just say to your iron:router that template is not rendered yet. Use onBeforeAction hook:
Router.route('/awesome-route', {
name : 'awesome',
template: "awesome",
loadingTemplate: "loading",
onBeforeAction: function(){
var next = this.next;
Meteor.call('data', function(err, resp){
next();
});
}
});
I'm struggling to get my head around the ability to edit any collection that's available to the front-end, and how to prevent it - and if this is a feature only available to Mongol.
Mongol states:
… because Mongol is a debugOnly package, it does not compile to production code.
Which is great, but as I'm new to Meteor I'm not sure if Mongol is just an interface in this scenario, or if the ability to update is something always available to the front-end (and Mongol is just making it easier).
My scenario is that I have a form submission page that grabs the profile of an associated Meteor.user to display their name along with the form:
HTML
<template name="form">
<h2>Submission for: {{ user.profile.name }}</h2>
<form id="brief">
…
</form>
</template>
Route
Router.route('/form/:_id', {
loadingTemplate: 'loading',
waitOn: function () {
return Meteor.subscribe('forms', this.params._id);
},
action: function () {
this.render('form', {
data: {
_id: this.params._id,
form: function() {
return Forms.findOne({});
},
user: function() {
return Meteor.users.findOne({});
}
}
});
}
});
Publication
Meteor.publishComposite('forms', function(formId) {
return {
find: function() {
return Forms.find({_id: formId});
},
children: [
{
find: function(form) {
return Meteor.users.find({_id: form.userId}, {fields: {profile:1}});
}
}
]
};
});
This works perfectly - however using the Mongol console I can update, duplicate and remove the user. Naturally in a production environment I wouldn't want this to be possible - is this something only available because Mongol is there, or could a determined user achieve the same thing without Mongol?
If they can, how do I prevent/work with it?
Edit: It's also elaborated on here: https://github.com/msavin/Mongol/blob/master/documentation/SECURITY.md
Given how they refer to 'special methods' I'm assuming that's what allows this to happen, and that the ability to directly update the fields isn't ordinarily available to the front-end. If anyone's able to confirm that would be ace!
Yes, Mongol uses a backdoor solution (in debug/dev only) to access and change your mongo docs in the db. This means it wont be included in your production code. As far as client side operations on the DB, Meteor restricts updating, removing, and inserting to the server although you can use Meteor's allow/deny rules to allow the client to update a DB collection. However, allow/deny rules need to be very tight to ensure the client can not alter data they should not be able to. For this reason, most people stick to using server side DB changes that are fired by meteor.methods that the client can initialize.
Since it is a debugOnly package as long as you don't deploy to production in "debug mode" it is safe.
I'm designing an administration interface with graphics and so on and I'm using the Highcharts Library (140kb). I want this file to be loaded only for admin users. What would be the best way to do it?
I just saw that we could use Iron-Router to conditionally load JavaScript but I don't like the idea to handle this kind of things inside the router as below:
Router.map ->
#route 'admin',
path: '/admin'
template: 'admin'
action: ->
$.getScript '/js/moment.min.js', (data, textStatus, jqxhr) ->
if jqxhr.status is 200
#render()
NOTE: I wrote a little blog post to load a library for only specific users with Meteor.
Does this not work (on the client)?
var loaded = false;
Deps.autorun(function() {
if (!loaded && isAdmin(Meteor.userId())) {
$.getScript("/js/moment.min.js");
loaded = true;
}
});
I develop an ASP.NET MVC solution with Durandal and Breeze. I need to translate frontend to french and dutch. How to proceed with Durandal/knockout?
In a classic ASP.NET MVC solution we have the opportunity to have the views rendered server side (thanks to razor).
Thanks for your help.
To expand on Rob's answer of trying the i18n.js plugin for require.js, here's the steps I followed (I'm working off the Durandal starter template in Visual Studio).
Download the i18n.js plugin and put it in the App folder.
Create an App/nls folder, which is where you will put the require.js resource bundles, e.g. App/nls/welcomeBundle.js.
define({
"root": {
"displayName": "Welcome to the Durandal Starter Project!"
},
"fr-fr": true
});
You'll see I added a line to tell require.js that there's a French version available. This will be created in App/nls/fr-fr/welcomeBundle.js, which I kinda did below (changed the to le :D)
define({
"displayName": "Welcome to le Durandal Starter Project!"
});
require.js needs to be configured initially with the locale (can't be done dynamically). So in the main.js file, I declare the below getLocale() function, which I use to configure the locale for require.js:
function getLocale() {
var locale = 'en-us';
if (localStorage) {
var storedLocale = localStorage.getItem('locale');
locale = storedLocale || locale;
}
return locale;
}
requirejs.config({
paths: {
'text': 'durandal/amd/text'
},
locale: getLocale()
});
In the welcome.js module I then load the bundle and use it for the displayName property:
define(function(require) {
var bundle = require('i18n!nls/welcomeBundle');
return {
displayName: bundle.displayName,
...
}
});
I then set the locale to French and reload the page via JavaScript:
localStorage.setItem('locale', 'fr-fr');
location.reload();
Hope that helps :)
Edit: 2013-04-04: I updated the above to initialize the locale in the main.js file and not in the shell.js module, as for some reason the locale wasn't being used correctly when loading the bundle in the shell module. Figure that it should be configured as soon as possible anyway.