Auth user is not updating on a find
Thomas-git opened this issue · comments
Steps to reproduce
First use the Auth plugin to authenticate to a feathers server.
Let the server only return basic user data: Let's say the server respond with id
and displayname
fields only.
Setup your User model so that instanceDefault add a email
property with default value null
Later in the app, if you need all user data, using User.get(AUTH_USER_ID)
it will populate auth user with his email.
But if you use User.find({query:{id:AUTH_USER_ID}})
, email won't get updated.
So, to give a small example, this is not working:
const users = (await Users.find({
query: {
$select: ['id', 'displayname', 'email'],
id: {
$in: userIds
}
}
})).data
whereas this one works (but it's obviously not optimal)
const users = await Promise.all(userIds.map(async id => {
return await Users.get(id, {
query: {
$select: ['id', 'displayname', 'email']
}
})
}))
Expected behavior
User used in Auth plugin should have his properties updated on a find
as it does on a get
.
Actual behavior
The find query with the Auth user is like a No-op.
System configuration
NodeJS version: Electron 9.3
Operating System: Archlinux
Browser Version: Electron 9.3
React Native Version: No. Using Quasar 1.14
Module Loader: Webpack 4.44
@Thomas-git could you please verify that you are using the user
getter and not the one from the auth state?
Here is how I get the Users model:
import { models } from 'feathers-vuex'
const { Users } = models.profile // I use more than one server.
I'm not using the Auth service outside of login/logout needs.
In the case we're talking about, the Administrator list all Users, including himself. And 'himself' is not updated with more details. Note that I do not checked if the user from Auth service if uptodate.
Note that I do not checked if the user from Auth service if uptodate.
Ok, good. Because the value in the auth state won't ever update unless you re-authenticate.
The steps that you mention are exactly how it should work.
- Setup your User model so that instanceDefault add a email property with default value null. Return any subset of data in initial requests, as the defaults will/should serve as placeholders.
- Later in the app, if you need all user data, using User.get(AUTH_USER_ID) it will populate auth user with his email.
- But if you use User.find({query:{id:AUTH_USER_ID}}), email won't get updated.
Records should definitely update whether they come in across find
or get
requests. The responses all pass through the same function, here: https://github.com/feathersjs-ecosystem/feathers-vuex/blob/master/src/service-module/service-module.mutations.ts#L71
And here is the code that routes them all to that function: https://github.com/feathersjs-ecosystem/feathers-vuex/blob/master/src/service-module/service-module.mutations.ts#L144-L153
@Thomas-git, could you try setting breakpoints in the updateItems
function in that first link and see if the data is following a different code path for find
than it is for get
?
Ok, I'll do that as soon as possible and report to you.
@marshallswain Ok, I finally took time to investigate this. And it's happening on other Models...
So, in updateItems
func:
- On Find :
never called and request not issued to server !
- On Get:
state.ids
includes id
replaceItems
is false
and updateOriginal
gets called
where to look at next ? what can prevent Model.find call to be issued ?
I finally found the Bug. And it's not related to feathers-vuex. I post here the solution because it may affect others.
Sometimes my backend server was sending "id" as Number
and sometimes as String
.
It turns out that's because I use knex with postgresql. And Int8 field, Count and other functions return an int8 : 2^64 max value. As JS max int is 2^53, knex return thoses numbers as String
to avoid an overflow.
Solution is as easy as doing
const pg = require('pg')
pg.types.setTypeParser(pg.types.builtins.INT8, (value) => {
return parseInt(value)
})
pg.types.setTypeParser(pg.types.builtins.FLOAT8, (value) => {
return parseFloat(value)
})
pg.types.setTypeParser(pg.types.builtins.NUMERIC, (value) => {
return parseFloat(value)
})
But be aware that an overflow become possible... if you have more that 9 Petabytes of entries in a single table!