Search code examples
sequelize.jsfeathersjsfeathers-sequelize

How to access the user object when it's in a feathers-sequelize many-to-many association?


I'm trying to build a hook that will restrict certain user actions to specified security roles. But I'm having trouble accessing the user record from a second hook, when the users model is associated with another table.

Inside my users 'before: get' hook, I've currently got a simple test, like this:

authenticate('jwt'),
context => {
    if(context.params.user){
        console.log('TESTING:', context.params.user);
    }
}

and it works, displaying the user details:


TESTING: {
    id: 12,
    firstname: 'David',
    lastname: 'Hoare',
    systemrole: '1-admin',
    createdAt: 2022-10-24T20:53:44.000Z,
    updatedAt: 2022-10-24T20:53:44.000Z
}

And when I add the associations,


//just testing
context => {
    if(context.params.user){
        console.log('TESTING:', context.params.user);
    }
},

// this adds the associations
context => {
    const sequelize = context.params.sequelize || {};
    sequelize.raw = false;
    sequelize.include = [
        {
            model: context.app.services['groups'].Model,
            as: 'groups'
        }
    ];
    context.params.sequelize = sequelize;
    return context;
},

I get the full related groups associated under the user record like this:

TESTING: users {
    dataValues: {
        id: 12,
        firstname: 'David',
        lastname: 'Hoare',
        systemrole: '1-admin',
        createdAt: 2022-10-24T20:53:44.000Z,
        updatedAt: 2022-10-24T20:53:44.000Z,
        groups: [ [groups], [groups] ]
    },
    _previousDataValues: {
        id: 12,
        firstname: 'David',
        lastname: 'Hoare',
        systemrole: '1-admin',
        createdAt: 2022-10-24T20:53:44.000Z,
        updatedAt: 2022-10-24T20:53:44.000Z,
        groups: [ [groups], [groups] ]
    },
    uniqno: 1,
    _changed: Set(0) {},
    _options: {
    isNewRecord: false,
    _schema: null,
    _schemaDelimiter: '',
    include: [ [Object] ],
    includeNames: [ 'groups' ],
    includeMap: { groups: [Object] },
    includeValidated: true,
    attributes: [
        'id',
        'firstname',
        'lastname',
        'systemrole',
        'createdAt',
        'updatedAt'
    ],
    raw: true
    },
    isNewRecord: false,
    groups: [
        groups {
            dataValues: [Object],
            _previousDataValues: [Object],
            uniqno: 1,
            _changed: Set(0) {},
            _options: [Object],
            isNewRecord: false,
            group_users: [group_users]
        },
        groups {
            dataValues: [Object],
            _previousDataValues: [Object],
            uniqno: 1,
            _changed: Set(0) {},
            _options: [Object],
            isNewRecord: false,
            group_users: [group_users]
        }
    ]
}

This has been working in my app so far without problems, allowing me to 'get' a particular user, and see all the groups they are also a part of.

However, when I try to access that user record in a different hook, (eg. to throw an error for the wrong 'systemrole' value) it tells me the user.users object is 'undefined'...

So clearly, the sequelize 'include' associations code is changing the 'context.params.user' object... but I can't seem to access the new object from other hooks... eg.:

//just testing
context => {
    if(context.params.user){
        console.log('TESTING:', context.params.user.users); //TRY TO ACCESS THE "USERS" sub-object
    }
},

// this adds the associations
context => {
    const sequelize = context.params.sequelize || {};
    sequelize.raw = false;
    sequelize.include = [
        {
            model: context.app.services['groups'].Model,
            as: 'groups'
        }
    ];
    context.params.sequelize = sequelize;
    return context;
},

just yields:

TESTING: undefined

The order of the hooks doesn't appear to matter... Is it possible to keep the association, but also access the associated records (or at least the main authorized context.params.user object) in a different hook?

Thanks!


Solution

  • Sequelize will return the sequilize object when you do a find call , if you want to get the raw object where you can access the items inside your result as object literal, convert it using

    raw : true

    or you can covert using

    data = JSON.parse(JSON.stringify(data))