mirror of
				https://github.com/strapi/strapi.git
				synced 2025-10-31 09:56:44 +00:00 
			
		
		
		
	implement new findAvailable route
This commit is contained in:
		
							parent
							
								
									1200e43618
								
							
						
					
					
						commit
						241393eaa3
					
				| @ -26,31 +26,29 @@ module.exports = { | |||||||
| 
 | 
 | ||||||
|     // idsToOmit: used to exclude relations that the front already added but that were not saved yet
 |     // idsToOmit: used to exclude relations that the front already added but that were not saved yet
 | ||||||
|     // idsToInclude: used to include relations that the front removed but not saved yes
 |     // idsToInclude: used to include relations that the front removed but not saved yes
 | ||||||
|     const { component, entityId, idsToOmit, idsToInclude, _q, ...query } = ctx.request.query; |     const { entityId, idsToOmit, idsToInclude, _q, ...query } = ctx.request.query; | ||||||
| 
 | 
 | ||||||
|     const sourceModelUid = component || model; |     const modelSchema = strapi.getModel(model); | ||||||
| 
 |     if (!modelSchema) { | ||||||
|     const sourceModel = strapi.getModel(sourceModelUid); |  | ||||||
|     if (!sourceModel) { |  | ||||||
|       return ctx.badRequest("The model doesn't exist"); |       return ctx.badRequest("The model doesn't exist"); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     const attribute = modelSchema.attributes[targetField]; | ||||||
|  |     if (!attribute || attribute.type !== 'relation') { | ||||||
|  |       return ctx.badRequest("This relational field doesn't exist"); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const isComponent = modelSchema.modelType === 'component'; | ||||||
|  | 
 | ||||||
|  |     // RBAC checks when it's a content-type
 | ||||||
|  |     // TODO: do RBAC check for components too
 | ||||||
|  |     if (!isComponent) { | ||||||
|       const permissionChecker = getService('permission-checker').create({ |       const permissionChecker = getService('permission-checker').create({ | ||||||
|         userAbility, |         userAbility, | ||||||
|         model, |         model, | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|     if (permissionChecker.cannot.read()) { |       if (permissionChecker.cannot.read(null, targetField)) { | ||||||
|       return ctx.forbidden(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     const attribute = sourceModel.attributes[targetField]; |  | ||||||
|     if (!attribute || attribute.type !== 'relation') { |  | ||||||
|       return ctx.badRequest("This relational field doesn't exist"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // TODO: find a way to check field permission for component
 |  | ||||||
|     if (!component && permissionChecker.cannot.read(null, targetField)) { |  | ||||||
|         return ctx.forbidden(); |         return ctx.forbidden(); | ||||||
|       } |       } | ||||||
| 
 | 
 | ||||||
| @ -63,20 +61,17 @@ module.exports = { | |||||||
|           return ctx.notFound(); |           return ctx.notFound(); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|       if (!component && permissionChecker.cannot.read(entity, targetField)) { |         if (permissionChecker.cannot.read(entity, targetField)) { | ||||||
|           return ctx.forbidden(); |           return ctx.forbidden(); | ||||||
|         } |         } | ||||||
|       // TODO: find a way to check field permission for component
 |  | ||||||
|       if (component && permissionChecker.cannot.read(entity)) { |  | ||||||
|         return ctx.forbidden(); |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const targetedModel = strapi.getModel(attribute.target); |     const targetedModel = strapi.getModel(attribute.target); | ||||||
| 
 | 
 | ||||||
|     const modelConfig = component |     const modelConfig = isComponent | ||||||
|       ? await getService('components').findConfiguration(sourceModel) |       ? await getService('components').findConfiguration(modelSchema) | ||||||
|       : await getService('content-types').findConfiguration(sourceModel); |       : await getService('content-types').findConfiguration(modelSchema); | ||||||
|     const mainField = prop(`metadatas.${targetField}.edit.mainField`, modelConfig) || 'id'; |     const mainField = prop(`metadatas.${targetField}.edit.mainField`, modelConfig) || 'id'; | ||||||
| 
 | 
 | ||||||
|     const fieldsToSelect = ['id', mainField]; |     const fieldsToSelect = ['id', mainField]; | ||||||
| @ -101,7 +96,7 @@ module.exports = { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (entityId) { |     if (entityId) { | ||||||
|       const subQuery = strapi.db.queryBuilder(sourceModel.uid); |       const subQuery = strapi.db.queryBuilder(modelSchema.uid); | ||||||
| 
 | 
 | ||||||
|       const alias = subQuery.getAlias(); |       const alias = subQuery.getAlias(); | ||||||
| 
 | 
 | ||||||
| @ -153,10 +148,6 @@ module.exports = { | |||||||
|         model, |         model, | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       if (permissionChecker.cannot.read()) { |  | ||||||
|         return ctx.forbidden(); |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (permissionChecker.cannot.read(null, targetField)) { |       if (permissionChecker.cannot.read(null, targetField)) { | ||||||
|         return ctx.forbidden(); |         return ctx.forbidden(); | ||||||
|       } |       } | ||||||
|  | |||||||
| @ -84,19 +84,7 @@ module.exports = { | |||||||
|       path: '/relations/:model/:targetField', |       path: '/relations/:model/:targetField', | ||||||
|       handler: 'relations.findAvailable', |       handler: 'relations.findAvailable', | ||||||
|       config: { |       config: { | ||||||
|         policies: [ |         policies: ['admin::isAuthenticatedAdmin'], | ||||||
|           'admin::isAuthenticatedAdmin', |  | ||||||
|           { |  | ||||||
|             name: 'plugin::content-manager.hasPermissions', |  | ||||||
|             config: { |  | ||||||
|               actions: [ |  | ||||||
|                 'plugin::content-manager.explorer.create', |  | ||||||
|                 'plugin::content-manager.explorer.update', |  | ||||||
|               ], |  | ||||||
|               hasAtLeastOne: true, |  | ||||||
|             }, |  | ||||||
|           }, |  | ||||||
|         ], |  | ||||||
|       }, |       }, | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|  | |||||||
| @ -180,25 +180,25 @@ describe.each([[false], [true]])('Relations, with d&p: %p', (withDraftAndPublish | |||||||
|       ['products_mw', false], |       ['products_mw', false], | ||||||
|       ['compo_products_ow', true], |       ['compo_products_ow', true], | ||||||
|       ['compo_products_mw', true], |       ['compo_products_mw', true], | ||||||
|     ])('Relation not in a component (%s)', (fieldName, isComponent) => { |     ])('Relation (%s) (is in component: %s)', (fieldName, isComponent) => { | ||||||
|       let entityId; |       let entityId; | ||||||
|       let entityIdEmptyShop; |       let entityIdEmptyShop; | ||||||
|  |       let modelUID; | ||||||
| 
 | 
 | ||||||
|       beforeAll(() => { |       beforeAll(() => { | ||||||
|         entityId = isComponent ? data.shops[0].myCompo.id : data.shops[0].id; |         entityId = isComponent ? data.shops[0].myCompo.id : data.shops[0].id; | ||||||
|         entityIdEmptyShop = isComponent ? data.shops[1].myCompo.id : data.shops[1].id; |         entityIdEmptyShop = isComponent ? data.shops[1].myCompo.id : data.shops[1].id; | ||||||
|  |         modelUID = isComponent ? 'default.compo' : 'api::shop.shop'; | ||||||
|       }); |       }); | ||||||
| 
 | 
 | ||||||
|       test('Can retrieve available relation(s) for an entity that have some relations', async () => { |       test('Can retrieve available relation(s) for an entity that have some relations', async () => { | ||||||
|         let res = await rq({ |         let res = await rq({ | ||||||
|           method: 'GET', |           method: 'GET', | ||||||
|           url: `/content-manager/relations/api::shop.shop/${fieldName}`, |           url: `/content-manager/relations/${modelUID}/${fieldName}`, | ||||||
|           qs: { |           qs: { | ||||||
|             entityId, |             entityId, | ||||||
|             ...(isComponent ? { component: 'default.compo' } : {}), |  | ||||||
|           }, |           }, | ||||||
|         }); |         }); | ||||||
| 
 |  | ||||||
|         expect(res.status).toBe(200); |         expect(res.status).toBe(200); | ||||||
| 
 | 
 | ||||||
|         expect(res.body.results).toMatchObject([ |         expect(res.body.results).toMatchObject([ | ||||||
| @ -212,11 +212,10 @@ describe.each([[false], [true]])('Relations, with d&p: %p', (withDraftAndPublish | |||||||
|         // can omitIds
 |         // can omitIds
 | ||||||
|         res = await rq({ |         res = await rq({ | ||||||
|           method: 'GET', |           method: 'GET', | ||||||
|           url: `/content-manager/relations/api::shop.shop/${fieldName}`, |           url: `/content-manager/relations/${modelUID}/${fieldName}`, | ||||||
|           qs: { |           qs: { | ||||||
|             entityId, |             entityId, | ||||||
|             idsToOmit: [data.products[1].id], |             idsToOmit: [data.products[1].id], | ||||||
|             ...(isComponent ? { component: 'default.compo' } : {}), |  | ||||||
|           }, |           }, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
| @ -226,10 +225,9 @@ describe.each([[false], [true]])('Relations, with d&p: %p', (withDraftAndPublish | |||||||
|       test("Can retrieve available relation(s) for an entity that don't have relations yet", async () => { |       test("Can retrieve available relation(s) for an entity that don't have relations yet", async () => { | ||||||
|         let res = await rq({ |         let res = await rq({ | ||||||
|           method: 'GET', |           method: 'GET', | ||||||
|           url: `/content-manager/relations/api::shop.shop/${fieldName}`, |           url: `/content-manager/relations/${modelUID}/${fieldName}`, | ||||||
|           qs: { |           qs: { | ||||||
|             entityId: entityIdEmptyShop, |             entityId: entityIdEmptyShop, | ||||||
|             ...(isComponent ? { component: 'default.compo' } : {}), |  | ||||||
|           }, |           }, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
| @ -251,11 +249,10 @@ describe.each([[false], [true]])('Relations, with d&p: %p', (withDraftAndPublish | |||||||
|         // can omitIds
 |         // can omitIds
 | ||||||
|         res = await rq({ |         res = await rq({ | ||||||
|           method: 'GET', |           method: 'GET', | ||||||
|           url: `/content-manager/relations/api::shop.shop/${fieldName}`, |           url: `/content-manager/relations/${modelUID}/${fieldName}`, | ||||||
|           qs: { |           qs: { | ||||||
|             entityId, |             entityId, | ||||||
|             idsToOmit: [data.products[1].id], |             idsToOmit: [data.products[1].id], | ||||||
|             ...(isComponent ? { component: 'default.compo' } : {}), |  | ||||||
|           }, |           }, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
| @ -265,10 +262,7 @@ describe.each([[false], [true]])('Relations, with d&p: %p', (withDraftAndPublish | |||||||
|       test('Can retrieve available relation(s) without entity', async () => { |       test('Can retrieve available relation(s) without entity', async () => { | ||||||
|         let res = await rq({ |         let res = await rq({ | ||||||
|           method: 'GET', |           method: 'GET', | ||||||
|           url: `/content-manager/relations/api::shop.shop/${fieldName}`, |           url: `/content-manager/relations/${modelUID}/${fieldName}`, | ||||||
|           qs: { |  | ||||||
|             ...(isComponent ? { component: 'default.compo' } : {}), |  | ||||||
|           }, |  | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         expect(res.status).toBe(200); |         expect(res.status).toBe(200); | ||||||
| @ -289,10 +283,9 @@ describe.each([[false], [true]])('Relations, with d&p: %p', (withDraftAndPublish | |||||||
|         // can omitIds
 |         // can omitIds
 | ||||||
|         res = await rq({ |         res = await rq({ | ||||||
|           method: 'GET', |           method: 'GET', | ||||||
|           url: `/content-manager/relations/api::shop.shop/${fieldName}`, |           url: `/content-manager/relations/${modelUID}/${fieldName}`, | ||||||
|           qs: { |           qs: { | ||||||
|             idsToOmit: [data.products[0].id], |             idsToOmit: [data.products[0].id], | ||||||
|             ...(isComponent ? { component: 'default.compo' } : {}), |  | ||||||
|           }, |           }, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
| @ -311,11 +304,10 @@ describe.each([[false], [true]])('Relations, with d&p: %p', (withDraftAndPublish | |||||||
|         test("search ''", async () => { |         test("search ''", async () => { | ||||||
|           const res = await rq({ |           const res = await rq({ | ||||||
|             method: 'GET', |             method: 'GET', | ||||||
|             url: `/content-manager/relations/api::shop.shop/${fieldName}`, |             url: `/content-manager/relations/${modelUID}/${fieldName}`, | ||||||
|             qs: { |             qs: { | ||||||
|               _q: '', |               _q: '', | ||||||
|               ...(withEntity ? { entityId } : {}), |               ...(withEntity ? { entityId } : {}), | ||||||
|               ...(isComponent ? { component: 'default.compo' } : {}), |  | ||||||
|             }, |             }, | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
| @ -331,11 +323,10 @@ describe.each([[false], [true]])('Relations, with d&p: %p', (withDraftAndPublish | |||||||
|         test("search 'Can'", async () => { |         test("search 'Can'", async () => { | ||||||
|           const res = await rq({ |           const res = await rq({ | ||||||
|             method: 'GET', |             method: 'GET', | ||||||
|             url: `/content-manager/relations/api::shop.shop/${fieldName}`, |             url: `/content-manager/relations/${modelUID}/${fieldName}`, | ||||||
|             qs: { |             qs: { | ||||||
|               _q: 'Can', |               _q: 'Can', | ||||||
|               ...(withEntity ? { entityId } : {}), |               ...(withEntity ? { entityId } : {}), | ||||||
|               ...(isComponent ? { component: 'default.compo' } : {}), |  | ||||||
|             }, |             }, | ||||||
|           }); |           }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Pierre Noël
						Pierre Noël