Skip to content

Commit 0c2e44e

Browse files
authored
Merge pull request #1458 from contentful/FUS-290
feat: allow NER resource types in allowedResources
2 parents 9730637 + 3030e4b commit 0c2e44e

File tree

3 files changed

+142
-17
lines changed

3 files changed

+142
-17
lines changed

src/lib/offline-api/validator/schema/allowed-resources-schema.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,17 @@ export const allowedResourcesSchema = Joi.array()
66
.max(MAX_ALLOWED_RESOURCES)
77
.unique('source')
88
.items(
9-
Joi.object({
10-
type: Joi.string().valid('Contentful:Entry'),
11-
source: Joi.string(),
12-
contentTypes: Joi.array().min(1).items(Joi.string())
13-
})
9+
Joi.alternatives().conditional(
10+
Joi.object({ type: Joi.string().regex(/^Contentful:/) }).unknown(),
11+
{
12+
then: Joi.object({
13+
type: Joi.string().valid('Contentful:Entry'),
14+
source: Joi.string(),
15+
contentTypes: Joi.array().min(1).items(Joi.string())
16+
}),
17+
otherwise: Joi.object({
18+
type: Joi.string().regex(/^[A-Z][a-z]*:[A-Z][a-z]*$/)
19+
})
20+
}
21+
)
1422
)

test/unit/lib/offline-api/validation/payload-validation-resource-links.spec.ts

Lines changed: 128 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ describe('payload validation (dependencies)', function () {
184184
})
185185

186186
describe('when setting a field to ResourceLink but specifying wrong resource properties', function () {
187-
it('returns errors', async function () {
187+
it('returns errors when an invalid ResourceType is provided for the Contentful: ResourceProvider', async function () {
188188
const existingCts = []
189189
const errors = await validateBatches(function (migration) {
190190
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')
@@ -194,35 +194,133 @@ describe('payload validation (dependencies)', function () {
194194
.name('Main Course')
195195
.type('ResourceLink')
196196
.allowedResources([
197-
{
198-
type: 'Contentful:Entry',
199-
source: 'crn:contentful:::content:spaces/cooking-space-1',
200-
contentTypes: []
201-
},
202197
{
203198
type: 'Contentful:Asset',
204199
source: 'crn:contentful:::content:spaces/cooking-space-2',
200+
contentTypes: ['cookingMethod']
201+
}
202+
])
203+
}, existingCts)
204+
205+
expect(errors).to.eql([
206+
[
207+
{
208+
type: 'InvalidPayload',
209+
message:
210+
'Allowed resource at index 0 on the field "mainCourse" has an invalid property: "type" must be [Contentful:Entry].'
211+
}
212+
]
213+
])
214+
})
215+
216+
it('returns errors when the allowedResources of the Contentful: Provider contains additional fields', async function () {
217+
const existingCts = []
218+
const errors = await validateBatches(function (migration) {
219+
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')
220+
221+
lunch
222+
.createField('mainCourse')
223+
.name('Main Course')
224+
.type('ResourceLink')
225+
.allowedResources([
226+
{
227+
type: 'Contentful:Entry',
228+
source: 'crn:contentful:::content:spaces/cooking-space-1',
205229
contentTypes: ['cookingMethod'],
206230
unexpectedProperty: 'someValue'
207231
}
208232
])
209233
}, existingCts)
210234

235+
expect(errors).to.eql([
236+
[
237+
{
238+
message:
239+
'Allowed resource at index 0 on the field "mainCourse" has an invalid property: "unexpectedProperty" is not allowed.',
240+
type: 'InvalidPayload'
241+
}
242+
]
243+
])
244+
})
245+
246+
it('returns errors when the contentTypes array is empty', async function () {
247+
const existingCts = []
248+
const errors = await validateBatches(function (migration) {
249+
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')
250+
251+
lunch
252+
.createField('mainCourse')
253+
.name('Main Course')
254+
.type('ResourceLink')
255+
.allowedResources([
256+
{
257+
type: 'Contentful:Entry',
258+
source: 'crn:contentful:::content:spaces/cooking-space-1',
259+
contentTypes: []
260+
}
261+
])
262+
}, existingCts)
263+
211264
expect(errors).to.eql([
212265
[
213266
{
214267
type: 'InvalidPayload',
215268
message:
216269
'Allowed resource at index 0 on the field "mainCourse" has an invalid property: "contentTypes" must contain at least 1 items.'
217-
},
270+
}
271+
]
272+
])
273+
})
274+
275+
it('returns an error when the type value is referencing a invalid type', async function () {
276+
const existingCts = []
277+
const errors = await validateBatches(function (migration) {
278+
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')
279+
280+
lunch
281+
.createField('mainCourse')
282+
.name('Main Course')
283+
.type('ResourceLink')
284+
.allowedResources([
285+
{
286+
type: 'Foo'
287+
}
288+
])
289+
}, existingCts)
290+
291+
expect(errors).to.eql([
292+
[
218293
{
219-
type: 'InvalidPayload',
220294
message:
221-
'Allowed resource at index 1 on the field "mainCourse" has an invalid property: "type" must be [Contentful:Entry].'
222-
},
295+
'Allowed resource at index 0 on the field "mainCourse" has an invalid property: "type" with value "Foo" fails to match the required pattern: /^[A-Z][a-z]*:[A-Z][a-z]*$/.',
296+
type: 'InvalidPayload'
297+
}
298+
]
299+
])
300+
})
301+
302+
it('returns an error when the type value is referencing custom ResourceProvider:ResourceType pair with additional properties', async function () {
303+
const existingCts = []
304+
const errors = await validateBatches(function (migration) {
305+
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')
306+
307+
lunch
308+
.createField('mainCourse')
309+
.name('Main Course')
310+
.type('ResourceLink')
311+
.allowedResources([
312+
{
313+
type: 'Foo:Bar',
314+
source: 'crn:contentful:::content:spaces/cooking-space-2'
315+
}
316+
])
317+
}, existingCts)
318+
319+
expect(errors).to.eql([
320+
[
223321
{
224322
message:
225-
'Allowed resource at index 1 on the field "mainCourse" has an invalid property: "unexpectedProperty" is not allowed.',
323+
'Allowed resource at index 0 on the field "mainCourse" has an invalid property: "source" is not allowed.',
226324
type: 'InvalidPayload'
227325
}
228326
]
@@ -245,6 +343,25 @@ describe('payload validation (dependencies)', function () {
245343

246344
expect(errors).to.eql([[]])
247345
})
346+
347+
it('should not return an error when the type value is referencing a custom ResourceProvider:ResourceType pair', async function () {
348+
const existingCts = []
349+
const errors = await validateBatches(function (migration) {
350+
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')
351+
352+
lunch
353+
.createField('mainCourse')
354+
.name('Main Course')
355+
.type('ResourceLink')
356+
.allowedResources([
357+
{
358+
type: 'Foo:Bar'
359+
}
360+
])
361+
}, existingCts)
362+
363+
expect(errors).to.eql([[]])
364+
})
248365
})
249366

250367
describe('when setting a field to ResourceLink with duplicate sources in allowedResources', function () {

test/unit/lib/offline-api/validation/payload-validation-rich-text-resource-link-embeds.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ describe('payload validation (dependencies)', function () {
184184
])
185185
})
186186

187-
it('should return an error when the type value is not one of the supported values', async function () {
187+
it('should return an error when the type value is not one of the supported values for the Contentful: Provider', async function () {
188188
const existingCts = []
189189
const errors = await validateBatches(function (migration) {
190190
const lunch = migration.createContentType('lunch').name('Lunch').description('A Lunch')

0 commit comments

Comments
 (0)