Check if user is logged in with Meteor - node.js

How can I determine layout depending on whether the user is logged in or not in Meteor?
I have tried
Router.map(function () {
this.configure({
layoutTemplate: Meteor.userId() ? "appLayout" : "startLayout",
});
});
I get the error
Error: Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.

It seems that Meteor.user() returns undefined if it's loading and null if it's logged out, same is true of Meteor.userId().

if(Meteor.userId(){
layoutTemplate: "appLayout";
}else{
layoutTemplate: "startLayout";
}
Did you try something like this ?

You can use this.userId, as error mentioned Meteor.user() you can use in functions, otherwise use Meteor.users.findOne({_id: this.userId}) if you need any data from user collection.
Also, your iron-router structure is deprecated, here are new docs

Related

Express.js : about the behavior of next()

I'm learning to create web applications using Express.js.
In the process, we tried to implement a feature to prevent users from accessing certain pages when they are not logged in.
// teamController.redirectView : Redirect the screen according to res.locals.redirect
app.get('/user/:id/team/member', teamController.showMember, teamController.redirectView)
// The following is a middleware function written in another file(teamController.js)
showMember: (req, res, next) => {
// I want to set the redirect to the '/login' and skip the following process when no user are logging in.
if(!res.locals.loggedIn) {
res.locals.redirect = 'login'
next()
}
// access the property that is set only when the user logs in
let userID = res.locals.currentUser.userID
// Other processes...
When I accessed the URI when the user was not logged in, I was indeed taken to the login page, but I got the following error in the console.
TypeError: Cannot read property 'userID' of undefined
at // the position of 'let userID...'
Error occured: TypeError: Cannot read property 'userID' of undefined
// Abbreviated below...
Does this mean that excuting next() does not skip the following process, like 'return' does?
Or is there some fatal error that is causing this error?
Can you please help me?
I could have avoided the error by enclosing all subsequent processes in 'else', but if there is a better way, I would appreciate it if you could tell me that too.
Does this mean that executing next() does not skip the following process, like 'return' does?
Exactly. Calling next() alone doesn't stop further execution.
This is actually intentional because it allows for additional logic without making the client wait longer (especially with multiple middle-wares).
However to solve your problem, you can combine your next() and a return:
if(!res.locals.loggedIn) {
res.locals.redirect = 'login';
return next();
}
This way you don't have to warp all the code below in an else.
It's a common practice as well, as described here.
You must use return next() or the code keeps executing after you call next()

Basic GET Request using Express.js & Mongoose

I'm working on an assignment to list all of the data in a mongoDB database, and am having trouble finding where I'm going wrong. It seems like a fairly simple problem, but whenever I run the provided mocha test, it keeps throwing 404 errors. Here is the relevant portion of the test:
it('should it able to retrieve all listings', function(done) {
agent.get('/api/listings')
.expect(200)
.end(function(err, res) {
should.not.exist(err);
should.exist(res);
res.body.should.have.length(147);
done();
});
});
And here is my code for the GET request. I've tried a few different ways of coding it, but this is seems like the simplest/most direct way to return the desired data as JSON.
exports.list = function(req, res) {
Listing.find(function(err, listing){
if(err){
res.status(404).send(err);
} else {
res.json(listing);
}})
};
Is there anything else I should be doing? I've been looking at tutorials and basic examples of requests and it seems like it should work, but it doesn't. Any help would be greatly appreciated.
Make sure that the middleware function (the code for GET request) is mapped to /api/listings
I'm not sure about exports.list. It should probably be module.exports
I'm assuming, based on ur code, that ur using the mongoose ODM. In which case, I think you need to pass a query to the find method check this out
You might wanna make sure that you're connected to the database at the time of test initialization and that that completes before the test starts
It always helps to log errors
Checkout express-generator to scaffold a boilerplate express app. Might help to compare it with your app, to check if it's wired correctly
Seems like you are not passing the first parameter to the find method. Only the callback ... try this:
Listing.find({}, function(err, listing) {
if (err) {
res.status(404).send(err);
} else {
res.json(listing);
}
})
I am assuming you want all records which is why we pass an empty object {}.

Loopback beforeRemote for PUT requests

Using Loopback framework, I want to perform some operations before the Item is edited hence I am trying this but unable to bind this to the update hook.
Item.beforeRemote("update", function(ctx,myitem,next) {
console.log("inside update");
});
Instead of update I have tried with updateAttributes,updateById, create but none works. This kind of beforeRemote hook works well with create on POST, but unable to get it with PUT during edit.
The last solution left with me is again inspect the methodString with wildcard hook but I want to know if there is anything documented which I could not find.
Item.beforeRemote("**",function(ctx,instance,next){
console.log("inside update");
});
I know that two year have passed since this post was opened, but if any body have the same question and if you use the endpoint your_model/{id} the afterRemote hook is replaceById.
If you need to know which method is fired in remote hook use this code:
yourModel.beforeRemote('**', function(ctx, unused, next) {
console.info('Method name: ', ctx.method.name);
next();
});
Contrary to the comments, save is a remote hook, not an operation hook, but you want to use it as: prototype.save. The relevant operational hook would be before save. You can see a table of these on the LoopBack docs page. I would probably implement this as an operational hook though, and use the isNewInstance property on the context to only perform the action on update:
Item.observe('before save', function(ctx, next) {
if (ctx.isNewInstance) {
// do something with ctx.currentInstance
}
next();
});
Sorry for bumping into old question but its for those who are still searching.
'prototype.updateAttributes' can be used as remote hook for update requests.
and #jakerella , there is no remote hook called 'save' , i myself tried it, but didnt work.
Came here looking for another thing, guess it will be helpful to someone.
For before remote model/:id patch method you have to use "prototype.patchAttributes".
On loopback3 for PATCH you can use "prototype.patchAttributes" to sanitize your data before the update.
YourModel.beforeRemote('prototype.patchAttributes', (ctx, unused, next) => {
console.log(ctx.args.data);
next();
});

mongoose pre update not firing

I have follow the directions in mongoose here
PostSchema.pre('update', function() {
console.log('pre update');
console.log(this);
});
it is not firing this middleware. Am I missing something here?
I have added next so it looks exactly like my pre save, however that still does nothing.
Make sure you don't define this after mongoose.model() has been called. Please also take note that findOneAndUpdate / upserts or updates won't trigger this hook. Another reason why it wouldn't execute is that validation fails. Therefore you would need to setup a pre('validate') hoke
I think you have to add the await keyword before your promise.

How to access user model properties after finding?

I'm trying to implement a user search function.
I have this for for finding the user. I'm using a post request and taking the search parameter from the post request. That parameter is used to search for the username. However, when I try logging the user, nothing comes up.
router.get('/register', function(req, res) {
var tester;
User.find({username : "bob"}, function(err, p){
if (err) console.log("didn't find bob");
var lolz = p.username;
console.log(p);
tester = p;
console.log(tester);
});
console.log(tester);
res.render('register', {info : "stuff", testuser : tester});
});
And when I log tester before I render, it works. However, when I access the register page, and try to do console.log(testuser.username) I get undefined. I also get undefined for testuser,username within the posted function and on the register page.
Additionally, when I attempt to log tester.username within the routing, I get undefined.
What is the issue here? Because I would like to pass all the found usernames into rendering a page. Thanks!
Thanks!
User.find passes an error and an array of matching documents to the callback, so p is not a user object, it's an array of user objects (which could be empty if no users match). So you need to access p[0] to get the user object itself.
Your second issue if your use of the tester variable is incorrect for node's asynchronous IO. Just move your res.render call up inside the User.find callback function so the control flow and scope nesting is correct.

Resources