Here is one: onRun hook is not fired EVER AGAIN when a hot code push happens · Issue #1219 · iron-meteor/iron-router · GitHub
If MDG do provide a core router I hope it’ll be optional.
Based on one of their current projects in splitting meteor-platform into smaller packages i’m sure it will be.
But eitherway it’ll give apps time/the choice to change over to the core router.
Having to do auth at the template level with Flow Router is far from ideal for me. Iron Router works fine (use template subs) and is already on both server & client. Accounts-UI still has to be migrated I believe, there’s no oauth integration working just yet.
Though @arunoda has said that FR v3 will do serverside rendering, I just hope we won’t be forced to use React for it.
Seems like you don’t get it properly. Whenever you stop doing router level subscriptions(we’ve good reasons for that), you can’t do template level authentication, other than checking for whether user loggedIn or not. That’s because we don’t have data in the router level. (Meteor.userId()
does not need data).
This is the newest version of useraccounts core, which removes router level auth layer. Still you can flow-router specific stuff here. It uses loggedIn user checks in the router level. But it only check it with Meteor.userId()
.
UX in template level auth
Template level auth gives better UX to the user. You don’t need to render the content inside the loggedIn user. You can simply render the login form instead. This is a successful pattern used by many Meteor apps, including Telescope.
Router level is auth is proven?
In a typical PHP/Ruby kind of app, you can do auth level in the router level, because you have the data in the router layer. Client side apps are different. You don’t have the data in the router layer initially, you need to wait for that.
So, you need to show some loading screen whether you use IR, FR or anything else. So, even if you use router level auth, you need to interact with the layout layer to show the loading screen.
Even if you redirect the user, you need to show some message. Otherwise, user will get confused. Then you need to interact with the templating layer.
At the end of the day, you need to interact with the template level to do auth stuff, even you use it in the router layer. That’s why we recommend it to do it in the template level.
Decoupling Auth Logic from the Template with Router level auth
This is the one other argument for router level auth. Client side apps is all about templates and UI. You can’t decouple auth with it. With template level auth, we can implement the auth logic per componenet/template basic. That’s the same as we do it template level subs. So, we can build great reusable content with that. (That’s one way to do it, if needed)
We can also isolate auth logic into a once place and use some helpers like this:
{{#ifUserLoggedIn}}
{{> editPostForm }}
{{/ifUserLoggedIn}}
I don’t think Template level auth is far from ideal. It’s the ideal solution.
That being said, I don’t think everyone needs to follow it. We make it extremely hard to do Router level auth in FlowRouter. If you going with Router level auth, Flow Router is not the option.
Adding server side routing to FlowRouter is very simple. But we didn’t do it for a purpose. Client side routing and Server side routing is two different thing for two different purpose. Apis are different in both case. Even if the APIs are the same, semantics will be different.
We also have a lot of great packages to do server side routing, just use them.
I didn’t get this. May be you were saying we need to use React for SSR at the end. right?
Yes, FlowRouter starts with React because SSR for React easy and it’s there. We use React for https://kadira.io and I wanted to do SSR for that. That’s why I start with React.
That does not mean, we won’t have it for Blaze. We already had SSR for Blaze. But the problem is, client side templates are not available in the server by default. We don’t had a simple way to make it correct without tearing down some core packages.
But with Meteor 1.2, this will be simple. So, we’ll have Blaze SSR too.
I’ll start it once I finish based SSR apis.
If someone wanna help me, try to make Blaze templates available on the server. Write a package for that. In 1.2 there are some Apis. See.
I do “get it properly” and understand that we don’t do our subs in the routing later, hence we’ve no data in this layer to do auth checks. Doing auth checks at the template level sounds a little more attractive when we start thinking about components.
Yes, I’m well aware that there’s separate packages for this, I just don’t think it was clearly explained to the community why they weren’t combined, or I missed a blog post.
Awesome, I was worried that we’d only get SSR if using React.
One thing I did notice is a flash of the {{else}}
content until my user is logged in client side.
If I refresh the page, I see the “welcome” area for a split second until my user is logged in automatically.
Any ideas around this?
<template name="layout">
{{#if currentUser}}
{{> sAlert}}
<div class="container-fluid">
<div class="row">
<div class="col-sm-2 col-md-2 sidebar">
{{> Template.dynamic template=sidebar}}
</div>
<div class="col-sm-10 col-sm-offset-2 col-md-10 col-md-offset-2 main">
{{> Template.dynamic template=content}}
</div>
</div>
</div>
{{else}}
{{> welcomePage}}
{{/if}}
</template>
It’s because your subscriptions aren’t loaded yet.
How can I check if subscriptions have loaded in my Template?
{{#if Template.subscriptionsReady}}
flow router level subs this way in helper
FlowRouter.subsReady("currentCategory")
For template level there is premade generic helper
{{ #if Template.subscriptionsReady }}
And you can always use your own helper to monitor it, for example we have this on onCreated
var this.contentSub = this.subscribe("categoryProducts", this.slug);
And than helper
isContentReady: function(){
Template.instance().contentSub.ready();
}
Mby I have something wrong in that code, I was dumbing it down for example purposes and translating from coffee.
FWIW you should do subscriptions in the template
So am I correct in assuming that in my template or layout I should first get the user data, do an auth check - if fails, redirect, if successful then subscribe to the data the page needs? Makes sense.
Correct. You don’t need to redirect at all.
Just show the login form.
Once you user logs in back, no need to do anything. He can just use the app.
No need to mess around with the redirectUrl
kind of thing when user logged in.
Yeah the worst thing is when an app doesn’t take you to the right place after logging in, it’s much easier to just avoid the whole problem by not redirecting.
Of course, usually in other apps I’ve written with traditional server side frameworks, after login I’d redirect the user back to their intended page. The reason I suggested redirects at all was simply to ensure the url always reflects the current state eg. If the user needs to login and we’re going to show a login form, then I’d assume the url should reflect that. I think there’s valid arguments for both sides in this scenario.
Though thinking about it now, I guess we could treat login via a route param as opposed to a /login route.
A url is a shareable and immutable representation of app state. Following this logic,
Auth status is not a part of shareable app state,
Even if it were, it would not be something you’d want to expose. Imagine you distinguish between such states like /posts/whenLoggedin
vs /posts/whenLoggedout
since you won’t directly show contents of /posts/whenLoggedin
without actually checking auth, auth state in url just does not make sense
Also, a url like /login
still does not make sense. Why would any one actually want to share the login link to an app? They would need to share it in a typical request response app because that’s where any other protected link would have to redirect anyway.
But what if you could avoid that whole “redirect to login, in the meantime keep a reference to the previously requested url, then redirect the user to that url once auth completes” crap that we had to eat all these years? It turns out, we actually can avoid it.
I find route based auth to be a case of stockholm syndrome where we should break our mental/emotional chains and see it for what it is, a workaround to a problem that we could not solve more elegantly until template/layout based auth