First Sign-in after Signup Show Config Page Once Effectively - meteor

I'm trying to show a popup or a template page if user has signed in for the first time after sign up basically allowing them configure some stuff on that page before going to dashboard home, It's only needed for convenience and here is what I got (telescope code)
Router.onBeforeAction(hasCompletedChannels);
hasCompletedChannels: function() {
if(!this.ready()) return;
var user = Meteor.user();
if (user && ! userCompletedChannels(user)){
this.render('connectChannels');
} else {
this.next();
}
}
Which I don't really like because this will always run every time, I want it to run just once, And don't even execute the check function. Is it possible to detect first sign in? (After signup)

I think you could just tie it to the specific route. Right now you're tying it to the Router object (every render forces that check as you point out). So if you define your login function to send someone to a specific route after sign-in, you could just verify on that route.
The function Accounts.onLogin gives you a way to do stuff after the login.
Something like
Router.route('profile', {
path: '/profile',
onBeforeAction: function() {
// Check some stoof
// If first time logged in
// render first time template
// else
// this.next() will render the profile page
},
waitOn: function() {
return [
// some subs
];
},
data: function() {
// some data
}
});
I'm assuming that its going to get routed to a page called profile (seems to make sense). You could check for first time logged in by some attribute you use in the user object and the fields you want filled out and force a render of a different template, or a subtemplate. Check out the Iron Router guide for more ideas on ways to configure it.
Best of luck

Related

How to clear Meteor's user even offline

I don't know why, the logout button in my Meteor App often fails to callback. the code is simple:
$scope.logout = function () {
Accounts.logout(function () {
// the code often fails to come here
$state.go('login');
});
}
maybe the network's problem? so I added some code to ensure my logout button won't look like frozen:
$scope.logout = function () {
Accounts.logout(function () {
// the code often fails to come here
$state.go('login');
});
$timeout(function () {
$state.go('login');
}, 2000);
}
The redirection to login page succeeded, but because Meteor.userId() still have value, the login page still shows the App user someone is logged on.
I want to know if there is a way to delete Meteor.userId / Meteor.user family even when failed connecting to the server.
I know it is not a complete solution, the App user will probably failed to do the next login at that state, but at least they won't complain the App even cannot logout.
The function you're looking for is Meteor.logout() not Accounts.logout()

Displaying form on first login

I'm trying to work out how I can display a form to a user upon their first login to my app ( to fill in profile information) after which they can proceed to the regular site.
Could anyone point me in the right direction?
Thanks
You can make the trick using app startup script:
https://devsite.googleplex.com/appmaker/settings#app_start
Assuming that you have Profile model/datasource, code in your startup script will look similar to this:
loader.suspendLoad();
var profileDs = app.datasources.Profile;
// It would be more secure to move this filtering to the server side
profileDs.query.filters.UserEmail._equals = app.user.email;
profileDs.load({
success: function() {
if (profileDs.item === null) {
app.showPage(app.pages.CreateProfile);
} else {
app.showPage(app.pages.HomePage);
}
loader.resumeLoad();
},
failure: function() {
loader.resumeLoad();
// your fallback code goes here
}
});
If profile is absolute must, I would also recommend to enforce the check in onAttach event for every page but CreateProfile (to prevent navigation by direct link):
// Profile datasource should be already loaded by startup script
// when onAttach event is fired
if (app.datasources.Profile.item === null) {
throw new Error('Invalid operation!');
}
I suggest checking the user profile upon login. If the profile is not present, display the profile form, otherwise, proceed to the regular site.

Meteor: How do I only allow the user to access on page?

I am using iron router, and I have a special type of account (certain value in Meteor.user().profile) and I am wondering if there is a way using iron router, that instead of having to put a restriction in every single route (except for home. login, etc) that I can simply only allow them one page?
Is there a way to do this?
Check out this page... http://www.manuel-schoebel.com/blog/meteorjs-iron-router-filters-before-and-after-hooks
Basically, you can setup a global onBeforeAction hook that will run before each route, then redirect the user if needed to a default route. You can also use before for specific routes, here's the example from the page...
////////////////
// BeforeHooks
////////////////
// I use an object that contains all before hooks
var IR_BeforeHooks = {
isLoggedIn: function(pause) {
if (!(Meteor.loggingIn() || Meteor.user())) {
Notify.setError(__('Please login.'));
this.render('login');
pause();
}
},
somethingForAnyRoute: function() { ... },
...
// add more before hooks here
}
// (Global) Before hooks for any route
Router.onBeforeAction(IR_BeforeHooks.somethingForAnyRoute);
...
// Before hooks for specific routes
// Must be equal to the route names of the Iron Router route map
Router.before(IR_BeforeHooks.isLoggedIn, {only: ['userAreaA', 'userAreaB']});
Also, triggering your route protection from something in Meteor.user().profile can be a bad idea, since the user can access and change anything in profile from the client console. This should be directly in the Meteor.user() object for security, then it is looked at server side. I'm not an expert in this area, so more research might be required if security is a concern.

Meteor router force rerender

I have the following routs
/product/123
/product/456
the template renders the product data and allows the user to drag things around
when I make a redirect to another product like that
Router.go("product",{_id:"456"});
the template updates the data but does not re-render the html. that means that what the user dragged stays in place. this is good for some cases but not for mine
the only solution that worked for me was to redirect to another page that sets clear template and it redirects to the product page
my router function:
Router.route('product/:_id/', {
name:"product",
data:function(){
var data = {product: Products.findOne({_id:objectId(this.params._id)})}
return data;
},
waitOn:function(){
return Meteor.subscribe('Products',this.params._id);
},
yieldTemplates: {'product': {to: 'mainArea'}},
});
I need a way to tell the router or template to reset the html
One solution is to set up an autorun in the template's onRendered function that looks for changes to the URL parameters and the resets the template as needed. Something like this:
Template.myTemplate.onRendered(function() {
var controller = Router.current()
this.autorun(function() {
var params = controller.getParams() // Reactive
// Clear up your drag interface here
});
});
By accessing controller.getParams() (the route controllers reactive parameter list) the outrun will be called when you move between routes on the same template.

Iron:router landing page AFTER login

Folks, I am making progress, but I am certain that there is a better, more elegant way to accomplish this functionality. As before, I want users to "always" be directed to a welcome page once they log into the application, even if they were previously signed-out at a different page. What trips me up is the "this.next()" requirement for iron Router's onBeforeAction.
Briefly a scenario:
1) User navigates to the application and is prompted with a "Welcome but please sign-in/up" page.
2) User signs in, and the router directs the user to a "welcome to the application" page
3) User navigates through the application to "pageOne" and then decides to sign out, and is again presented with the "Welcome but please sign-in/up" page being rendered. (However, the URL still reads http://xxx.xxx.xxx.xxx/pageOne)
4) User signs-in again, where now the application should instead of rendering the "pageOne" page, which is the behavior of this.next(), be presented with the "welcome to the application" page.
I was able to get to this functionality with the code below:
Router.configure({
layoutTemplate: 'layout',
});
Router.route('/', {name: 'welcome'});
Router.route('/pageOne', {name: 'pageOne'});
Router.route('/pageTwo', {name: 'pageTwo'});
var requireLogin = function() {
if (! Meteor.user()) {
if (Meteor.loggingIn()) {
Router.go('welcome');
} else {
this.render('welcomeButLogin');
}
} else {
this.next();
}
}
Router.onBeforeAction(requireLogin, {except: ['blah']});
This works, but I am getting a warning message of:
Route dispatch never rendered. Did you forget to call this.next() in an onBeforeAction?
Thank you for taking the time, any feedback would be much appreciated.
Gene.
Problem solved.
I changed:
Router.onBeforeAction(requireLogin, {except: ['blah']});
to:
Router.onBeforeAction(requireLogin);
per suggested code by solarc on the meteor forum (thanks solarc). I don't quite understand how this changes the routing specific behavior, since I interpreted that "{except" ['blah']}" would mean all routes since I did not have a "blah" route. I'll investigate further, but for now it works as expected, and I am not getting the warning message.
Thanks!

Resources