ForestAdmin / agent-nodejs

🌱 Node.js agent for Forest Admin
GNU General Public License v3.0
67 stars 8 forks source link

Context filter contains invalid additional condition tree branch #515

Closed Segfaultd closed 1 year ago

Segfaultd commented 2 years ago

Introduction

On a custom smart action, the filter contained in the context argument contains an additional unknown filter that breaks the whole implementation.

Code sample

collection.addAction('Export V2', {
        scope: 'Global',
        generateFile: true,
        execute: async (ctx, resultBuilder) => {
            try {
                const results: Order[] = [];
                let skip = 0;
                const limit = 15;
                console.log(ctx.filter);
                console.log(ctx.filter.conditionTree);
                while (true) {
                    const orders: Order[] = await ctx.collection.list({
                        conditionTree: ctx.filter.conditionTree,
                        page: {
                            skip,
                            limit
                        }
                    }, ['order_id']);

                    if (!orders.length) {
                        break;
                    }

                    results.push(...orders);
                    skip += limit;
                }
                console.log(results.length);

            } catch (err) {
                captureException(err, {
                    user: {
                        id: String(ctx.caller.id),
                        email: ctx.caller.email,
                        team: ctx.caller.team,
                        role: ctx.caller.role
                    }
                });
                return resultBuilder.error("Failed to process the action: " + err.message);
            }
        }
    });

With filters on the created_at field (before & after), a empty and unknown "Or" ConditionTreeBranch is injected and breaks the whole query.

Payload sent by UI

Filter {
  conditionTree: ConditionTreeBranch {
    aggregator: 'And',
    conditions: [ [ConditionTreeBranch], [ConditionTreeLeaf], [ConditionTreeLeaf] ]
  },
  search: null,
  searchExtended: false,
  segment: null
}
ConditionTreeBranch {
  aggregator: 'And',
  conditions: [
    ConditionTreeBranch { aggregator: 'Or', conditions: [] },
    ConditionTreeLeaf {
      field: 'created_at',
      operator: 'After',
      value: '2022-01-31T23:00:00.000Z'
    },
    ConditionTreeLeaf {
      field: 'created_at',
      operator: 'Before',
      value: '2022-04-13T22:00:00.000Z'
    }
  ]
}

Debug hint

If I actually cheat the querier by manually placing the information inside, everything works as intended.

collection.addAction('Export V2', {
        scope: 'Global',
        generateFile: true,
        execute: async (ctx, resultBuilder) => {
            try {
                const results: Order[] = [];
                let skip = 0;
                const limit = 15;
                console.log(ctx.filter);
                console.log(ctx.filter.conditionTree);
                while (true) {
                    const orders: Order[] = await ctx.collection.list({
                        conditionTree: {
                            aggregator: 'And',
                            conditions: [
                                {
                                    field: 'created_at',
                                    operator: 'After',
                                    value: '2022-01-31T23:00:00.000Z'
                                },
                                {
                                    field: 'created_at',
                                    operator: 'Before',
                                    value: '2022-04-13T22:00:00.000Z'
                                }
                            ]
                        },
                        page: {
                            skip,
                            limit
                        }
                    }, ['order_id']);

                    if (!orders.length) {
                        break;
                    }

                    results.push(...orders);
                    skip += limit;
                }
                console.log(results.length);

            } catch (err) {
                captureException(err, {
                    user: {
                        id: String(ctx.caller.id),
                        email: ctx.caller.email,
                        team: ctx.caller.team,
                        role: ctx.caller.role
                    }
                });
                return resultBuilder.error("Failed to process the action: " + err.message);
            }
        }
    });
jeffladiray commented 2 years ago

Hello again @Segfaultd :wave:

Totally able to reproduce this one, I'll file a bug report in our issue tracker.

In the meantime, I can suggest the following implementation:

Your workaround is also a valid one though, but it will prevent you from using the currently set frontend filter. If you set a frontend filter on your table view, you'll not be able to retrieve it from the smart action.

We will let you know once the fix is released and available 👍

Segfaultd commented 2 years ago

Hello @jeffladiray any chance your team had the time to work on that point?

Thanks!

jeffladiray commented 2 years ago

Looks like a fix was merged yesterday, and as the issue wasn't mentioned in the PR, our forest bot didn't notify you.

It should be fixed in @forestadmin/agent@1.4.1, via this contribution.

Let me know if it fixes your issue.

romain-gilliotte commented 1 year ago

Closing this, as the bug is fixed