How to list users in Meteor 1.4

I’m trying to list all users in the client in Meteor 1.4.2.3. But, I’m not able to get any to the client.

In /imports/api/users.js:


import { Meteor } from 'meteor/meteor';
import { Mongo } from 'meteor/mongo';
import { check } from 'meteor/check';
 
export const Users2 = new Mongo.Collection('users2');

if (Meteor.isServer) {
	Meteor.publish('users2', function usersPublication(){

console.log("Trying to publish: " + Meteor.users.find().count() + " users");

		return Meteor.users.find({});
	});
}

in /server/main.js:

import '../imports/api/users.js';

in /imports/ui/body.js:

import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { ReactiveDict } from 'meteor/reactive-dict';

import { Users2 } from '../api/users.js';

import './body.html';

Template.mainLayout.onCreated(function bodyOnCreated() {
	this.state = new ReactiveDict();

	Meteor.subscribe('users2');
});
 
Template.mainLayout.helpers({
	users() {
		console.log("User count: " + Users2.find().count());
		return Users2.find();	
	},
});

In /imports/ui/body.html:

users?
{{#each users}}
  hahaha
{{/each}}

In the server console, the number of users is correctly reported by “Trying to publish: //number of users// users”.
But, the client console reports 0 users.

What am I missing?

You publish documents from Meteor.users collection and subscribe to it, but you try to receive documents from Users2 collection. That’s why, in short.

Just use return Meteor.users.find(); in your mainLayout helper.

Thanks. Pardon my ignorance, but isn’t the point of “Meteor.publish(‘users2’, fun…” exactly to publish the users collection as users2 (and thus ‘Users2’)?

Your solution does work, but doesn’t this mean the whole users collection is available to every user, including all related email addresses?

My /imports/ui/body.js is now:

import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { ReactiveDict } from 'meteor/reactive-dict';

//import { Users2 } from '../api/users.js';

import './body.html';
Template.mainLayout.onCreated(function bodyOnCreated() {
	this.state = new ReactiveDict();

//	Meteor.subscribe('users2');
});
 
Template.mainLayout.helpers({
	users() {
		Meteor.users.find().forEach(function(oneUser) {
			console.log(oneUser);
		})
		
		return Meteor.users.find();
		
//		return Users2.find();	
	},
})

And, this works fine. But, makes each user’s email address available to the current user. :confused:

No. Meteor.publish('users2') will just make the users2 publication available to use with Meteor.subscribe('users2'). But whatever is in MyCollection will be passed to Minimongo’s MyCollection regardless of how you name your publication. This way you can use same queries on both server and client. And in fact, you should be.

But with your code, the same will happen. It doesn’t matter if you provide it as Meteor.users or Users2 - the clients will get full access to all private data, because in your publication, you publish whole user documents. Instead of find(), you should be returning only certain fields of each document in your publish function. As long as you don’t return the user’s email address in your publication, it won’t be available on the client.

Your code shouldn’t work without this line. The default subscription returns only data of the logged in user. It won’t grab any other data from Meteor.users collection.

If your code does work, it most probably mean that you have autopublish package in your project. Be sure to do meteor remove autopublish insecure as a first step after creating new projects - these two packages are evil and imho should be removed from the default Meteor project a long time ago.

Thanks again.

No, I have neither ‘autopublish’ nor ‘insecure’ as packages within my app.

Yes, my example code also publishes the email addresses, but my objective was to indeed limit what was to be returned for that particular subscription, based on the user doing the request. (Admins see all, regular users only themselves.) Hence why I tried to set up ‘users2’, such that I could limit what was going to be in that collection.

So, I’m still quite confused:

I have the following helper:

	users() {
		Meteor.users.find().forEach(function(oneUser) {
			console.log(oneUser);
		})
		
		return Meteor.users.find();
	},

The ‘console.log’ in this helper logs all my users, with their email addresses. But, not only is the app not subscribed to ‘users2’, ‘users2’ is also not publishing anything.

I agree that it looks like autopublish is running, but it is not. This is my package list:

accounts-base            1.2.14  A user account system
accounts-password        1.3.3  Password support for accounts
accounts-ui              1.1.9  Simple templates to add login widgets to an app
alanning:roles           1.2.15  Authorization package for Meteor
blaze-html-templates     1.1.0  Compile HTML templates into reactive UI with Meteor Blaze
ecmascript               0.6.1  Compiler plugin that supports ES2015+ in all .js files
es5-shim                 4.6.15  Shims and polyfills to improve ECMAScript 5 support
fortawesome:fontawesome  4.7.0  Font Awesome (official): 500+ scalable vector icons, customizable via CSS, Retina friendly
jquery                   1.11.10  Manipulate the DOM using CSS selectors
kadira:blaze-layout      2.3.0  Layout Manager for Blaze (works well with FlowRouter)
kadira:flow-router       2.12.1  Carefully Designed Client Side Router for Meteor
meteor-base              1.0.4  Packages that every Meteor app needs
mobile-experience        1.0.4  Packages for a great mobile user experience
mongo                    1.1.14  Adaptor for using MongoDB and Minimongo over DDP
reactive-dict            1.1.8  Reactive dictionary
reactive-var             1.0.11  Reactive variable
shell-server             0.2.1  Server-side component of the `meteor shell` command.
standard-minifier-css    1.3.2  Standard css minifier used with Meteor apps by default.
standard-minifier-js     1.2.1  Standard javascript minifiers used with Meteor apps by default.
tracker                  1.1.1  Dependency tracker to allow reactive callbacks
twbs:bootstrap           3.3.6  The most popular front-end framework for developing responsive, mobile first projects on the web.

How to proceed?

There is no need to create a seperate users collection like you do with users2.

Meteor.users is already a collection which will be used for logging in etc.

In your first code you published the collection of Meteor.users but tried querying the Users2 collection which wasn’t published.

I’m still not completely following. :confused:

But, either way, I started a project from scratch and was unable to recreate this issue. That is, I can now publish a subset of the users collection based on who is logged in, which is what my intention was to begin with.

Thanks for the help, @henribeck and @gusto!

1 Like

From what you say, that could be simply a caching problem. It’s possible that clearing the cache from .meteor/local would solve it too.

That might just be the golden tip I needed. Will keep that in mind next time.