Before this, we could see the "non-null user observe" error if:
- One login method ran (eg login) and it called _setLoginToken.
It stored null in userObservesForConnections and gets to the
defer/observe part
- Another login method ran (eg getNewToken) and it called
_setLoginToken. The call to removeTokenFromConnection at the top
clears the null from userObservesForConnections, and it then
stores its own null in userObservesForConnections, and defers
- One of them finishes the observe and puts its observe in
userObservesForConnections, overwriting the null which it thinks
is its alone
- The other one gets there and throws
Also, consistently use _.has when checking if userObservesForConnections
has an element.
We now wait for subscriptions to be ready before calling
methods that affect those collections. Otherwise, when the
callback fires the documents in those collections aren't
guaranteed to be available on the client.
This lets you still use C.insert from the client but reject arbitrary
client-set _id's (as opposed to _id's generated using the Random.id()
algorithm with a client-determined _id).
If you don't want clients to be able to have any control over the _id at
all for inserts, then you'll have to forbid all direct inserts and use
your own methods which explicitly do `C.insert({_id: Random.id(), ...})`
Note that allow/deny rules with transforms still see an _id, because
transforms need to have (and preserve) _id. This means that if you
really want to see the server-generated _id, you can just specify an
identity transform for your allow/deny rule.
Duplicate keys aren't expected, but in case something weird happens,
just override the previous information associated with that key. We
simply insert nothing for non-string keys (e.g. an OAuth flow with no
`state` parameter, which should never happen normally).