8

I've tried looking for an answer all over but cannot seem to get this working. I'm using Meteor with Cordova to build a mobile app.

I want to add an attribute to my Users collection (the one Meteor creates when I'm logged in). ie. For example, I want to add {currentHotel: "Something"} to my db.Users collection.

I'm trying to do this the correct, Publish - Subscribe way. Using Meteor.methods has been quoted to not be good for real - time applications. Either way, I want to understand how to update the Users collection using Publish - Subscribe.

//On the server, I did
Meteor.publish("userData", function () {
    return Meteor.users.find({_id: this.userId},
       {fields:{services: 1, currentHotel: 1}});
});

So the currentHotel field should be accessible to the client side. Now to update the "currentHotel" field:

//On the client I do
Meteor.subscribe('userData');
var user = Meteor.users.findOne({"_id": Meteor.userId()});
Meteor.users.update({_id: user._id}, {$set:{currentHotel:'something'}});

//I tried this too
//Meteor.users.update({ _id: Meteor.userId() }, {$set: });

On the browser console I can see "currentHotel" and "services" just fine, which means the publish-subscribe worked. Yet I cannot seem to update the currentHotel. I get an Access Denied. Why is this?

Additionally, If the "currentHotel" property did not exist in the Collection at all, how can I add it using a similar publish-subscribe? Can I publish a property that isn't there and allow the client to subscribe and add that property?

I referred to the Meteor docs, this, this and this, but still cannot seem to get it to work! :-(

Thanks in advance!

Community
  • 1
  • 1
Nilay Panchal
  • 541
  • 6
  • 17

1 Answers1

8

You're not supposed to change the root fields of the user object:

Meteor.users.update(user, {$set: {"profile.currentHotel": "something"}});

Read more here: http://docs.meteor.com/#/full/meteor_users

EDIT: This answer has become irrelevant as shown in the latest documentation: https://guide.meteor.com/accounts.html#dont-use-profile

This answer is more than 1 year old :) As it turns out, forcing to write user-specific fields under a 'profile' field as some serious security implications (like I always thought) since it gives permission to the clients to modify those sub-fields. So yes, you can set fields in the root object, but be aware that fields that should not be modified by the client, should be under a field without write permissions (or else it falls under the same problem).

  • You're the best! Thank you! I assume I do not need to publish anything to add to this profile object? Edit: Ah, profile is published automatically! Thanks a tonne! – Nilay Panchal Apr 23 '15 at 22:56
  • Thanks, this was useful to me too. Just one note, I got an error by trying to update this way and I had to indicate the _id with `{ _id: Meteor.userId() }` as suggested [in this other question](http://stackoverflow.com/a/23705715/3961519). – Diego Feb 16 '16 at 16:57
  • @JoséRicardoRibeiro The doc page you link to doesn't currently mention anything about not adding root fields to the user object (that I can find). https://guide.meteor.com/accounts.html#top-level-fields says the best way is to do this. Which is correct? – mpdonadio Nov 01 '16 at 19:13
  • @mpdonadio This answer is more than 1 year old :) And yes, as it turns out, forcing to write user-specific fields under a 'profile' field as some serious security implications (like I always thought) since it gives permission to the clients to modify those sub-fields. https://guide.meteor.com/accounts.html#dont-use-profile So yes, you can set fields in the root object, but be aware that fields that should not be modified by the client should be under a field without write permissions. – José Ricardo Ribeiro Nov 15 '16 at 14:47