feathersjs-ecosystem / feathers-vuex

Integration of FeathersJS, Vue, and Nuxt for the artisan developer

Home Page:https://vuex.feathersjs.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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?

Screen Shot 2020-12-03 at 5 06 32 PM

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!