Skip to content

Commit 120a98e

Browse files
committed
cdimascio#627 Remove readOnly properties from request instead of throwing Bad request errors
1 parent 6448f45 commit 120a98e

File tree

3 files changed

+28
-37
lines changed

3 files changed

+28
-37
lines changed

src/framework/ajv/index.ts

+4-13
Original file line numberDiff line numberDiff line change
@@ -104,23 +104,14 @@ function createAjv(
104104
ajv.removeKeyword('readOnly');
105105
ajv.addKeyword({
106106
keyword: 'readOnly',
107+
modifying: true,
107108
errors: true,
108109
compile: (sch, p, it) => {
109110
if (sch) {
110111
const validate: DataValidateFunction = (data, ctx) => {
111-
const isValid = data == null;
112-
if (!isValid) {
113-
validate.errors = [
114-
{
115-
keyword: 'readOnly',
116-
instancePath: ctx.instancePath,
117-
schemaPath: it.schemaPath.str,
118-
message: `is read-only`,
119-
params: { writeOnly: ctx.parentDataProperty },
120-
},
121-
];
122-
}
123-
return false;
112+
// Remove readonly properties in request
113+
delete ctx.parentData[ctx.parentDataProperty];
114+
return true;
124115
};
125116
return validate;
126117
}

test/read.only.spec.ts

+16-17
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ describe(packageJson.name, () => {
6262
app.server.close();
6363
});
6464

65-
it('should not allow read only properties in requests', async () =>
65+
it('should remove read only properties in requests', async () =>
6666
request(app)
6767
.post(`${app.basePath}/products`)
6868
.set('content-type', 'application/json')
@@ -72,11 +72,11 @@ describe(packageJson.name, () => {
7272
price: 10.99,
7373
created_at: new Date().toISOString(),
7474
})
75-
.expect(400)
75+
.expect(200)
7676
.then((r) => {
7777
const body = r.body;
78-
// id is a readonly property and should not be allowed in the request
79-
expect(body.message).to.contain('id');
78+
// id is a readonly property and should be allowed in the request but should be deleted before entering in route
79+
expect(body.id).to.be.undefined;
8080
}));
8181

8282
it('should allow read only properties in responses', async () =>
@@ -87,7 +87,7 @@ describe(packageJson.name, () => {
8787
expect(r.body).to.be.an('array').with.length(1);
8888
}));
8989

90-
it('should not allow read only inlined properties in requests', async () =>
90+
it('should remove read only inlined properties in requests', async () =>
9191
request(app)
9292
.post(`${app.basePath}/products/inlined`)
9393
.set('content-type', 'application/json')
@@ -97,14 +97,13 @@ describe(packageJson.name, () => {
9797
price: 10.99,
9898
created_at: new Date().toUTCString(),
9999
})
100-
.expect(400)
101100
.then((r) => {
102101
const body = r.body;
103102
// id is a readonly property and should not be allowed in the request
104-
expect(body.message).to.contain('id');
103+
expect(body.id).to.be.undefined;
105104
}));
106105

107-
it('should not allow read only properties in requests (nested schema $refs)', async () =>
106+
it('should remove read only properties in requests (nested schema $refs)', async () =>
108107
request(app)
109108
.post(`${app.basePath}/products/nested`)
110109
.set('content-type', 'application/json')
@@ -113,19 +112,19 @@ describe(packageJson.name, () => {
113112
name: 'some name',
114113
price: 10.99,
115114
created_at: new Date().toISOString(),
116-
reviews: {
117-
id: 'review_id',
115+
reviews: [{
116+
id: 2,
118117
rating: 5,
119-
},
118+
}],
120119
})
121-
.expect(400)
120+
.expect(200)
122121
.then((r) => {
123122
const body = r.body;
124-
// id is a readonly property and should not be allowed in the request
125-
expect(body.message).to.contain('id');
123+
// id is a readonly property and should be removed from the request
124+
expect(body.id).to.be.equal('test');
126125
}));
127126

128-
it('should not allow read only properties in requests (deep nested schema $refs)', async () =>
127+
it('should remove read only properties in requests (deep nested schema $refs)', async () =>
129128
request(app)
130129
.post(`${app.basePath}/products/nested`)
131130
.set('content-type', 'application/json')
@@ -139,11 +138,11 @@ describe(packageJson.name, () => {
139138
},
140139
],
141140
})
142-
.expect(400)
141+
.expect(200)
143142
.then((r) => {
144143
const body = r.body;
145144
// id is a readonly property and should not be allowed in the request
146-
expect(body.message).to.contain('request/body/reviews/0/id');
145+
expect(body.reviews[0].id).to.be.undefined;
147146
}));
148147

149148
it('should pass validation if required read only properties to be missing from request ($ref)', async () =>

test/write.only.spec.ts

+8-7
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ describe(packageJson.name, () => {
4242
app.server.close();
4343
});
4444

45-
it('should not allow ready only inlined properties in requests', async () =>
45+
it('should remove read only inlined properties in requests', async () =>
4646
request(app)
4747
.post(`${app.basePath}/products/inlined`)
4848
.set('content-type', 'application/json')
@@ -51,11 +51,12 @@ describe(packageJson.name, () => {
5151
price: 10.99,
5252
created_at: new Date().toUTCString(),
5353
})
54-
.expect(400)
54+
.expect(200)
5555
.then(r => {
5656
const body = r.body;
57-
// id is a readonly property and should not be allowed in the request
58-
expect(body.message).to.contain('created_at');
57+
// created_at is a readonly property and should be removed form the request
58+
expect(body.created_at).to.be.undefined;
59+
expect(body.name).to.be.equal('some name');
5960
}));
6061

6162
it('should not allow write only inlined properties in responses', async () =>
@@ -110,7 +111,7 @@ describe(packageJson.name, () => {
110111
expect(body.errors[0].message).to.contain('write-only');
111112
}));
112113

113-
it('should not allow read only properties in requests (deep nested schema $refs)', async () =>
114+
it('should remove read only properties in requests (deep nested schema $refs)', async () =>
114115
request(app)
115116
.post(`${app.basePath}/products/nested`)
116117
.query({
@@ -128,9 +129,9 @@ describe(packageJson.name, () => {
128129
},
129130
],
130131
})
131-
.expect(400)
132+
.expect(200)
132133
.then(r => {
133134
const body = r.body;
134-
expect(body.message).to.contain('request/body/reviews/0/id');
135+
expect(body.reviews[0].id).to.be.undefined;
135136
}));
136137
});

0 commit comments

Comments
 (0)