You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On a typescript setup using sequelize ORM
Populating context.params.sequelize on any service that uses hook all: [authenticate('jwt')] results in a broken query
I'm using a hook to implement $include[]=someAssociation that basically populates context.params.sequelize
then using association on requests with authentication
if request didn't include users it adds users table into the query linking whatever (out of commented query below ON "users"."id" = "parents->tags_tags"."tagId")
or tries users.userId (of course doesn't exist) when $include[]=user ex: accounts.belongsTo(users, {as: 'user'})
as a workaround I proxy the authenticate('jwt') with a hook that hides context.params.sequelize.include from authenticate()
hooks/fix-authentication-sequelize.ts
// Use this hook to manipulate incoming or outgoing data.// For more information on hooks see: http://docs.feathersjs.com/api/hooks.htmlimport{Hook,HookContext}from'@feathersjs/feathers';import*asauthenticationfrom'@feathersjs/authentication';import{AuthenticateHookSettings}from'@feathersjs/authentication/lib/hooks/authenticate';const{ authenticate }=authentication.hooks;/*When calling authenticate (strategy 'jwt')and that context.params has a sequelize include in my case a service (tags) including a model alias 'parents' of type belongsToMany(tags, through: tagsTags)tags and tagsTags have in the model description (but wasn't included in the current call) a relations belongsTo(users, as: author)then an error would emerge out of users serviceerror: 'invalid reference to FROM-clause entry for table "tags"'error: error app.service('users').get()here part of the SQLFROM "users" AS "users" LEFT OUTER JOIN ( "tags_tags" AS "parents->tags_tags" INNER JOIN "tags" AS "parents" ON "parents"."id" = "parents->tags_tags"."parentTagId" ) ON "users"."id" = "parents->tags_tags"."tagId" AND "parents"."id" != "tags"."id" LEFT OUTER JOIN "media" AS "parents->featuredImage" ON "parents"."featuredMediumId" = "parents->featuredImage"."id"WHERE ("users"."id" = '1');So on querying users it would try to link to the models included in the request to 'tags' serviceAs a workaround I 'proxied' the authenticate() hook with this one, it basically deletes context.params.sequelize.include import authenticate from '../../hooks/fix-authenticate-sequelize-include';that I then use as I would normally use authenticate('jwt')*/exportdefault(originalSettings: string|AuthenticateHookSettings, ...originalStrategies: string[]): Hook=>{returnasync(context: HookContext)=>{if(context.params&&context.params.sequelize&&context.params.sequelize.include){const{ sequelize }=context.params;const{ include }=sequelize;letcontextWithoutInclude=context;deletecontextWithoutInclude.params.sequelize.include;letauthContext=awaitauthenticate(originalSettings, ...originalStrategies)(contextWithoutInclude);authContext.params.sequelize.include=include;returnauthContext;}else{returnauthenticate(originalSettings, ...originalStrategies)(context);}};};
not sure it's realy relevant, but putting it too
hooks/include-associated-models.ts
import{Hook,HookContext}from'@feathersjs/feathers';importloggerfrom'../logger';import{merge}from'lodash';consthydrate=require('feathers-sequelize/hooks/hydrate');// inspired by https://stackoverflow.com/questions/48602085/using-feathers-client-and-sequelize-many-to-many-relationexportdefault(options={}): any=>{returnasyncfunction(this: any,context: HookContext){switch(context.type){case'before':
if(context.params&&context.params.query){if('$include'incontext.params.query){const{ $include, ...query}=context.params.query;// Update the query to not include `$include`context.params.query=query;context.params.sequelize=context.params.sequelize||{};letinclude: any=[];// see https://jsperf.com/array-coerce(Array.isArray($include) ? $include : [$include]).forEach((name: string)=>{if(nameincontext.service.Model.associations){include.push({association: context.service.Model.associations[name],as: name,});}else{logger.warn(`Requested association '${name}' of model '%s' doesn't exist. Available associations are: %O`,context.service.Model.name,context.service.Model.associations);}});if(include){merge(context.params.sequelize,{
include,raw: false,});}}if('$scope'incontext.params.query){const{ $scope, ...query}=context.params.query;// Update the query to not include `$scope`context.params.query=query;context.params.sequelize=context.params.sequelize||{};merge(context.params.sequelize,{scope: $scope,});}if('$raw'incontext.params.query){const{ $raw, ...query}=context.params.query;// Update the query to not include `$raw`context.params.query=query;context.params.sequelize=context.params.sequelize||{};Object.assign(context.params.sequelize,{raw: !!$raw});}}break;case'after':
// I still don't understand why we have to do this as I didn't see any difference using it (yet)// they say so here:// https://github.com/feathersjs-ecosystem/feathers-sequelize#working-with-sequelize-model-instancesif(context.params&&context.params.sequelize&&context.params.sequelize.include&&!context.params.sequelize.raw){hydrate().call(this,context);}break;}returncontext;};};
Expected behavior
authentication not to change/look at context.params.sequelize.include
Actual behavior
resulting query generated by sequelize gets all broken
This discussion was converted from issue #2051 on March 31, 2021 05:25.
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Steps to reproduce
On a typescript setup using sequelize ORM
Populating
context.params.sequelize
on any service that uses hookall: [authenticate('jwt')]
results in a broken queryI'm using a hook to implement $include[]=someAssociation that basically populates
context.params.sequelize
then using association on requests with authentication
users
it adds users table into the query linking whatever (out of commented query belowON "users"."id" = "parents->tags_tags"."tagId"
)users.userId
(of course doesn't exist) when $include[]=user ex:accounts.belongsTo(users, {as: 'user'})
as a workaround I proxy the
authenticate('jwt')
with a hook that hidescontext.params.sequelize.include
fromauthenticate()
hooks/fix-authentication-sequelize.ts
not sure it's realy relevant, but putting it too
hooks/include-associated-models.ts
Expected behavior
authentication not to change/look at
context.params.sequelize.include
Actual behavior
resulting query generated by sequelize gets all broken
System configuration
Module versions
"@feathersjs/authentication": "^4.5.8",
"@feathersjs/authentication-local": "^4.5.8",
NodeJS version:
10..12
Operating System:
OSX / Linux
Beta Was this translation helpful? Give feedback.
All reactions