Delete route not overrided

Hi Forest,

I used to override a route to delete an object. That has been working perfectly until now.

image

However, I never enter anymore in the handleDeleteSubscriptionPromotionCode handler to override the request.

Expected behavior

Override the request

Actual behavior

The request directly delete the object without being overrided

Failure Logs

api_forest_1  | info:    ┏ OPTIONS /forest/subscriptionPromotionCode?timezone=Europe%2FLondon 204 0ms +15s
api_forest_1  | info:    ┃ [ 1] {
api_forest_1  | info:    ┃ [ 2]   http: {
api_forest_1  | info:    ┃ [ 3]     request: {
api_forest_1  | info:    ┃ [ 4]       method: 'OPTIONS',
api_forest_1  | info:    ┃ [ 5]       url: 'http://api-forest.dev.localhost/forest/subscriptionPromotionCode?timezone=Europe%2FLondon',
api_forest_1  | info:    ┃ [ 6]       path: '/forest/subscriptionPromotionCode',
api_forest_1  | info:    ┃ [ 7]       query: { timezone: 'Europe/London' },
api_forest_1  | info:    ┃ [ 8]       headers: {},
api_forest_1  | info:    ┃ [ 9]       source_ip: '172.23.0.1'
api_forest_1  | info:    ┃ [10]     },
api_forest_1  | info:    ┃ [11]     responseTime: 0,
api_forest_1  | info:    ┃ [12]     response: { status: 204, message: 'No Content', type: undefined, headers: {} }
api_forest_1  | info:    ┃ [13]   },
api_forest_1  | info:    ┃ [14]   service: 'api_forest',
api_forest_1  | info:    ┃ [15]   env: 'development',
api_forest_1  | info:    ┃ [16]   version: 'v2.0.3',
api_forest_1  | info:    ┃ [17]   context: { message: 'OPTIONS /forest/subscriptionPromotionCode?timezone=Europe%2FLondon 204 0ms' },
api_forest_1  | info:    ┃ [18]   timestamp: '2021-06-14T11:28:20.089Z'
api_forest_1  | info:    β”— [19] }
api_forest_1  | debug:   ┏ mongo query +13ms
api_forest_1  | debug:   ┃ [ 1] {
api_forest_1  | debug:   ┃ [ 2]   service: 'api_forest',
api_forest_1  | debug:   ┃ [ 3]   env: 'development',
api_forest_1  | debug:   ┃ [ 4]   version: 'v2.0.3',
api_forest_1  | debug:   ┃ [ 5]   context: {
api_forest_1  | debug:   ┃ [ 6]     collection: 'subscriptionPromotionCode',
api_forest_1  | debug:   ┃ [ 7]     method: 'deleteMany',
api_forest_1  | debug:   ┃ [ 8]     'query._id.$in': [ 60c73d3d3792be14b27360d8 ],
api_forest_1  | debug:   ┃ [ 9]     doc: {},
api_forest_1  | debug:   ┃ [10]     options: undefined,
api_forest_1  | debug:   ┃ [11]     message: 'mongo query'
api_forest_1  | debug:   ┃ [12]   },
api_forest_1  | debug:   ┃ [13]   timestamp: '2021-06-14T11:28:20.103Z'
api_forest_1  | debug:   β”— [14] }
api_forest_1  | info:    ┏ DELETE /forest/subscriptionPromotionCode?timezone=Europe%2FLondon 204 15ms +4ms
api_forest_1  | info:    ┃ [ 1] {
api_forest_1  | info:    ┃ [ 2]   http: {
api_forest_1  | info:    ┃ [ 3]     request: {
api_forest_1  | info:    ┃ [ 4]       method: 'DELETE',
api_forest_1  | info:    ┃ [ 5]       url: 'http://api-forest.dev.localhost/forest/subscriptionPromotionCode?timezone=Europe%2FLondon',
api_forest_1  | info:    ┃ [ 6]       path: '/forest/subscriptionPromotionCode',
api_forest_1  | info:    ┃ [ 7]       query: { timezone: 'Europe/London' },
api_forest_1  | info:    ┃ [ 8]       headers: {},
api_forest_1  | info:    ┃ [ 9]       source_ip: '172.23.0.1'
api_forest_1  | info:    ┃ [10]     },
api_forest_1  | info:    ┃ [11]     responseTime: 15,
api_forest_1  | info:    ┃ [12]     response: { status: 204, message: 'No Content', type: undefined, headers: {} }
api_forest_1  | info:    ┃ [13]   },
api_forest_1  | info:    ┃ [14]   service: 'api_forest',
api_forest_1  | info:    ┃ [15]   env: 'development',
api_forest_1  | info:    ┃ [16]   version: 'v2.0.3',
api_forest_1  | info:    ┃ [17]   context: { message: 'DELETE /forest/subscriptionPromotionCode?timezone=Europe%2FLondon 204 15ms' },
api_forest_1  | info:    ┃ [18]   timestamp: '2021-06-14T11:28:20.111Z'
api_forest_1  | info:    β”— [19] }

Context

image

Has anything changed with overriding behaviour ?

Best
Guillaume

Hi @Guiguijo :wave: Have you recently upgrade the forest-express-mongoose to v6?
According to the documentation, since the v6 the override of the delete record route should be like this Default routes - Documentation.
let me know if that help.

To add a precision it depend on where you call the delete action.
If you call this action on the detail record view your implementation is correct.
If you call this action by selecting a record on the table view you need to implement / override the delete route like as suggest you in my previous message.

1 Like

Hi @Arnaud_Moncel ,

Ok. Thanks for this precision. I am currently upgrading to the v7 version and check what I missed on v6.

Thanks

1 Like

@Arnaud_Moncel ,

I have implemented the overriding function as it is described in the documentation but something goes wrong even if I call the delete action from the detail record view.

The route called is this one:

api_forest_1  | info:    DELETE /forest/subscriptionPromotionCode/60d06665750195007e42afdb?timezone=Europe%2FLondon 204 20ms +14ms

If I set the route as follow:

router.delete('/subscriptionPromotionCode', permissionMiddlewareCreator.delete(), handleDeleteSubscriptionPromotionCode)

The delete is never overrided.

If I set the route as follow:

router.delete('/subscriptionPromotionCode/:id', permissionMiddlewareCreator.delete(), handleDeleteSubscriptionPromotionCode)

I get this error:

error:   Cannot read property 'ids' of undefined

Here are the logs of the error:

api_forest_1  | error:   ┏ Cannot read property 'ids' of undefined +6s
api_forest_1  | error:   ┃ [ 1] {
api_forest_1  | error:   ┃ [ 2]   service: 'api_forest',
api_forest_1  | error:   ┃ [ 3]   env: 'development',
api_forest_1  | error:   ┃ [ 4]   version: 'v2.0.2-4-g99e948a3',
api_forest_1  | error:   ┃ [ 5]   context: { message: "Cannot read property 'ids' of undefined" },
api_forest_1  | error:   ┃ [ 6]   manager: 'subscription-promotion-code',
api_forest_1  | error:   ┃ [ 7]   error: TypeError: Cannot read property 'ids' of undefined
api_forest_1  | error:   ┃ [ 8]       at _callee2$ (/srv/app/node_modules/forest-express/dist/services/ids-from-request-retriever.js:34:60)
api_forest_1  | error:   ┃ [ 9]       at tryCatch (/srv/app/node_modules/regenerator-runtime/runtime.js:45:40)
api_forest_1  | error:   ┃ [10]       at Generator.invoke [as _invoke] (/srv/app/node_modules/regenerator-runtime/runtime.js:274:22)
api_forest_1  | error:   ┃ [11]       at Generator.prototype.<computed> [as next] (/srv/app/node_modules/regenerator-runtime/runtime.js:97:21)
api_forest_1  | error:   ┃ [12]       at asyncGeneratorStep (/srv/app/node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24)
api_forest_1  | error:   ┃ [13]       at _next (/srv/app/node_modules/@babel/runtime/helpers/asyncToGenerator.js:25:9)
api_forest_1  | error:   ┃ [14]       at /srv/app/node_modules/@babel/runtime/helpers/asyncToGenerator.js:32:7
api_forest_1  | error:   ┃ [15]       at new Promise (<anonymous>)
api_forest_1  | error:   ┃ [16]       at IdsFromRequestRetriever.<anonymous> (/srv/app/node_modules/@babel/runtime/helpers/asyncToGenerator.js:21:12)
api_forest_1  | error:   ┃ [17]       at IdsFromRequestRetriever.perform (/srv/app/node_modules/forest-express/dist/services/ids-from-request-retriever.js:135:19)
api_forest_1  | error:   ┃ [18]       at _callee3$ (/srv/app/node_modules/forest-express/dist/services/exposed/records-getter.js:170:129)
api_forest_1  | error:   ┃ [19]       at tryCatch (/srv/app/node_modules/regenerator-runtime/runtime.js:45:40)
api_forest_1  | error:   ┃ [20]       at Generator.invoke [as _invoke] (/srv/app/node_modules/regenerator-runtime/runtime.js:274:22)
api_forest_1  | error:   ┃ [21]       at Generator.prototype.<computed> [as next] (/srv/app/node_modules/regenerator-runtime/runtime.js:97:21)
api_forest_1  | error:   ┃ [22]       at asyncGeneratorStep (/srv/app/node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24)
api_forest_1  | error:   ┃ [23]       at _next (/srv/app/node_modules/@babel/runtime/helpers/asyncToGenerator.js:25:9)
api_forest_1  | error:   ┃ [24]       at /srv/app/node_modules/@babel/runtime/helpers/asyncToGenerator.js:32:7
api_forest_1  | error:   ┃ [25]       at new Promise (<anonymous>)
api_forest_1  | error:   ┃ [26]       at RecordsGetter.<anonymous> (/srv/app/node_modules/@babel/runtime/helpers/asyncToGenerator.js:21:12)
api_forest_1  | error:   ┃ [27]       at RecordsGetter.getIdsFromRequest (/srv/app/node_modules/forest-express/dist/services/exposed/records-getter.js:181:35)
api_forest_1  | error:   ┃ [28]       at /srv/app/joinly-forest/dist/joinly-forest/manager/subscription-promotion-code/subscription-promotion-code.handler.js:68:97
api_forest_1  | error:   ┃ [29]       at Generator.next (<anonymous>)
api_forest_1  | error:   ┃ [30]       at /srv/app/joinly-forest/dist/joinly-forest/manager/subscription-promotion-code/subscription-promotion-code.handler.js:7:71
api_forest_1  | error:   ┃ [31]       at new Promise (<anonymous>)
api_forest_1  | error:   ┃ [32]       at __awaiter (/srv/app/joinly-forest/dist/joinly-forest/manager/subscription-promotion-code/subscription-promotion-code.handler.js:3:12)
api_forest_1  | error:   ┃ [33]       at handleDeleteSubscriptionPromotionCode (/srv/app/joinly-forest/dist/joinly-forest/manager/subscription-promotion-code/subscription-promotion-code.handler.js:65:12)
api_forest_1  | error:   ┃ [34]       at Layer.handle [as handle_request] (/srv/app/node_modules/express/lib/router/layer.js:95:5)
api_forest_1  | error:   ┃ [35]       at next (/srv/app/node_modules/express/lib/router/route.js:137:13)
api_forest_1  | error:   ┃ [36]       at _callee$ (/srv/app/node_modules/forest-express/dist/middlewares/permissions.js:111:19)
api_forest_1  | error:   ┃ [37]       at tryCatch (/srv/app/node_modules/regenerator-runtime/runtime.js:45:40)
api_forest_1  | error:   ┃ [38]       at Generator.invoke [as _invoke] (/srv/app/node_modules/regenerator-runtime/runtime.js:274:22)
api_forest_1  | error:   ┃ [39]       at Generator.prototype.<computed> [as next] (/srv/app/node_modules/regenerator-runtime/runtime.js:97:21)
api_forest_1  | error:   ┃ [40]       at asyncGeneratorStep (/srv/app/node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:24)
api_forest_1  | error:   ┃ [41]       at _next (/srv/app/node_modules/@babel/runtime/helpers/asyncToGenerator.js:25:9),
api_forest_1  | error:   ┃ [42]   controller: 'handleDeleteSubscriptionPromotionCode',
api_forest_1  | error:   ┃ [43]   controller_type: 'handler',
api_forest_1  | error:   ┃ [44]   timestamp: '2021-06-21T11:17:40.442Z'
api_forest_1  | error:   β”— [45] }

Here are some data about of the request:

api_forest_1  |   params: { id: '60d0754aac721a01363b1544' },

…

api_forest_1  |   body: {},
api_forest_1  |   secret: undefined,
api_forest_1  |   cookies: [Object: null prototype] {},
api_forest_1  |   signedCookies: [Object: null prototype] {},
api_forest_1  |   user: {
api_forest_1  |     id: '37263',
api_forest_1  |     email: 'gjauffret@joinly.com',
api_forest_1  |     firstName: 'Guillaume',
api_forest_1  |     lastName: 'Jauffret',
api_forest_1  |     team: 'Admins',
api_forest_1  |     renderingId: 62017,
api_forest_1  |     iat: 1624271886,
api_forest_1  |     exp: 1624275486
api_forest_1  |   },
api_forest_1  |   route: Route {
api_forest_1  |     path: '/subscriptionPromotionCode/:id',
api_forest_1  |     stack: [ [Layer], [Layer] ],
api_forest_1  |     methods: { delete: true }
api_forest_1  |   },

As requested in the doc, my handler retrieve the ids with the getIdsFromRequest() function from the RecordGetter

async function handleDeleteSubscriptionPromotionCode(request, response) {
  console.log('----> handleDeleteSubscriptionPromotionCode', request)
  try {
    const subscriptionPromoCodeIds = await new RecordsGetter(SubscriptionPromotionCode).getIdsFromRequest(request)
    await DeleteSubPromoCode.init(subscriptionPromoCodeIds)
    response.send({ success: 'Code promo supprimΓ© en DB et sur Stripe!' })
  } catch (error) {
    response.status(400).send(error.message)
  }
}

So I don’t understand how Forest function looks for the ids because we have a Cannot read property 'ids' of undefined. Forest should be looking it the params property of the request.

Moreover, I don’t understand why the route is automatically overrided from the moment I write my own middleware handling function, regardless of how I deal with the ids or any other data inside my handler, such as:

router.delete('/subscriptionPromotionCode/:id', permissionMiddlewareCreator.delete(), handleDeleteSubscriptionPromotionCode)

For your understanding :

  • When you are in the record details view and you call the delete action
    => forest call

    delete('/entity/:entityId')
    

    On this route you cannot use getIdsFromRequest the id you want is in req.params.entityId

  • When you select some records and you call the delete action
    => forest call

    delete('/entity')
    

    And in this case we provide all the information in the request.body related to your selection.
    To extract all the ids you are selected, you need to use getIdsFromRequest.

So in your case, I think you need to override the two routes for those cases.
Let me know if that help.

All right @Arnaud_Moncel . I will try later. I did a smart action to bypass the problem :slight_smile: