问题
I've built a user profile page for an app that I'm developing, the page works fine when an user is logged in, but when nobody is logged in the templates are empty. My goal is that anyone (even if it isn't registered in the app) is able to see the user profiles.
Here is the code:
Publication:
Meteor.publish('singleUser', function(userId) {
if (this.userId) {
var findById = Meteor.users.find(userId);
return findById.count() ? findById : 'undefined';
}
return [];
});
Router:
this.route('user_profile', {
path: '/users/:_id',
waitOn: function() {
return Meteor.subscribe('singleUser', this.params._id);
},
data: function() {
return Meteor.users.findOne({_id: this.params._id});
}
});
Profile template:
<template name="user_profile">
<h4>Username</h4>
<p>{{username}}</p>
<h4>User since:</h4>
<p>{{createdAtFormatted}}</p>
</template>
Profile helpers:
Template.user_profile.helpers({
createdAtFormatted: function(){
return moment(this.createdAt).fromNow();
}
});
I don't know what's missing in my code.
Thanks!
回答1:
You almost got it - you just need to fix the publish function. Your approach of only publishing the necessary user when you navigate to the profile page is correct.
Inside of a publish function, this.userId
refers to the calling user's id. Because a client which hasn't logged in does not have a userId
, it stands to reason that your publish function will return []
and the client will be unable to render the profile page. The rest of your publish function is unnecessary - it should return a cursor and not have to handle every possibility of data not being found. I think you want something like this:
Meteor.publish('userForProfilePage', function(userId) {
check(userId, String);
return Meteor.users.find(userId, {
fields: {createdAt: 1, username: 1}
});
});
Note the following:
- I used an explicit name for the function to clearly identify what I'm doing. I find
userForProfilePage
more clear thansingleUser
, but this is a matter of taste. Be sure to change your subscribe as appropriate. - I used a simple check on the
userId
input. This validates that it is a string and not undefined. You can add more sophisticated checks as needed. - Only if the check passed, will we return a cursor for the
userId
. The documents returned by the cursor will only contain the_id
,createdAt
, andusername
fields (this is done for security).
回答2:
I am not quite sure, whether you want to show all users' profiles or only a profile of one user, because if you are logged out the system will not know which user it is currently talking to. I assume this, because you said that you want to "see the user profiles".
Try this:
Meteor.publish('allUsers', function() {
return Meteor.users.find();
});
You could also use Meteor.methods()
.
Meteor.methods({
allUsers: function () {
return Meteor.users.find();
}
});
And do not forget to wrap your template into a {{#each allUsers}}{{/each}}
block.
Edit: Concerning security issues, map the values before passing them to the client.
Meteor.methods({
allUsers: function () {
return Meteor.users.find().fetch().map(function(user) {
return {
"name": user.username,
"createdAt": user.createdAt
};
});
}
});
来源:https://stackoverflow.com/questions/20734732/unable-to-view-user-profiles-when-logged-out-meteoriron-router