nestjsx / crud

NestJs CRUD for RESTful APIs
https://github.com/nestjsx/crud/wiki
MIT License
4.01k stars 526 forks source link

using $or in ?s ignores auth filter #815

Open matan1905 opened 1 year ago

matan1905 commented 1 year ago

Bug Report

Current behavior

When I use the following search query, I receive results from all userId's, despite setting a filter for userId:

{
    "tip.type": {
        "$or": [
            "Connection",
            "Info"
        ]
    }
}

for your convenience, a Curl:

curl --request GET \
  --url 'http://127.0.0.1:3000/user-tips?s=%7B%0A%09%09%09%22tip.type%22%3A%20%7B%0A%09%09%09%09%22%24or%22%3A%20%5B%0A%09%09%09%09%09%22Connection%22%2C%0A%09%09%09%09%09%22Info%22%0A%09%09%09%09%5D%0A%09%09%09%7D%0A%09%09%7D' 

Input Code

Controller:

@Crud({
  model: { type:UserTip },
  routes:{
    only:[]
  },
  query:{
    join:{
      tip:{eager:true},
    }
  }
})
@CrudAuth({
  filter:(req)=>{
    return {'userId':req?.auth?.id}
  },
  persist: (req: any) => {
    return {
      userId: req?.auth?.id ?? undefined
    };
  }
})
@Controller("user-tips")
export class UserTipsController implements CrudController<UserTip>{
  constructor(public service: UserTipsService) {
  }

  get base(): CrudController<UserTip> {
    return this;
  }

  @Override()
  async getMany(
    @ParsedRequest() req: CrudRequest,
  ) {
    // todo - figure out why search = tip.type:{or:[1,2]  gives away all tips, and remove the filter fix
    const  result= (await this.base.getManyBase(req))
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    return { tips: result?.filter(tip=>tip.userId == req.parsed.authPersist.userId) };
  }
}

UserTip Entity:

@Entity()
export class UserTip extends CommonEntity{

  @ManyToOne(()=>Tip,)
  tip:Tip;

  @Column()
  userId:string;

  @Column()
  isLiked:boolean;
}

Tip entity:

enum TipType {
  Info = "Info",
  Activity = "Activity",
  Resource = "Resource",
  Inspiration = "Inspiration",
  Connection = "Connection",
}

@Entity()
export class Tip extends CommonEntity {
  @Column({type:'enum',enum:TipType, default:TipType.Info})
  type: TipType;
  @Column()
  content: string;
}

The generated SQL:

"UserTip_id", "UserTip"."id" AS "UserTip_id", "UserTip"."createdAt" AS "UserTip_createdAt", "UserTip"."userId" AS "UserTip_userId", "UserTip"."isLiked" AS "UserTip_isLiked", "tip"."id" AS "tip_id", "tip"."id" AS "tip_id", "tip"."createdAt" AS "tip_createdAt", "tip"."type" AS "tip_type", "tip"."content" AS "tip_content", "UserTip"."tipId" FROM "user_tip" "UserTip" LEFT JOIN "tip" "tip" ON "tip"."id"="UserTip"."tipId" WHERE ("UserTip"."userId" = $1  OR ("tip"."type" = $3 OR "tip"."type" = $4)

Expected behavior

I would expect to only receive entities with the specified userId. (WHERE ("UserTip"."userId" = $1 AND ("tip"."type" = $3 OR "tip"."type" = $4))

Possible Solution

Environment


Package version: tried both 4.6.2 and 5.0.0-alpha.3

For Tooling issues:
- Node version: v16.17.0
- Platform: Mac
- Database:  PostgreSQL 15.0 (Debian 15.0-1.pgdg110+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit

Repository with minimal reproduction

repo

imnotjames commented 1 year ago

I'm using 4.6.2 and postgres and cannot replicate this. Commenting and subscribing for when the minimal repo is up!

matan1905 commented 1 year ago

@imnotjames Sorry, completely forgot about it, I added it now.