Hello!
Im with a strange behavior when I sanitize user input.
I have a custom sanitizer that transforms metadatas arrays into dynamic jsons.
Custom sanitizor:
sanitizor.jsonInput = value => {
const metadata = {};
value.forEach(element => {
const [k, v] = element;
metadata[k] = v;
});
return metadata;
};
My validator:
'use strict';
class StorePlan {
get validateAll() {
return true;
}
get sanitizationRules() {
return {
accept_boleto: 'to_boolean',
accept_credit_card: 'to_boolean',
metadata: 'json_input'
};
}
get rules() {
return {
name: 'required',
gateway: 'required',
amount: 'required|number',
trial_period_days: 'required|number',
interval: 'required|in:day,week,month,year',
interval_count: 'required|number',
metadata: 'array'
};
}
}
My controller:
async store({ response, request, params, session }) {
const application = await Application.findOrFail(params.applications_id);
const planParams = await this.planParams(request);
const plan = await Plan.create(planParams);
await plan.application().associate(application);
session.flash({ alert: 'Plan created successfully' });
response.route('Admin/Application/PlanController.edit', {
applications_id: params.applications_id,
id: plan.id
});
}
async planParams(request) {
return request.only([
'name',
'description',
'gateway',
'amount',
'trial_period_days',
'interval',
'interval_count',
'metadata',
'accept_boleto',
'accept_credit_card'
]);
}
When I submit the form, the sanitize works, but it does not replace the metadata content. Instead, it merges the old content with the new content. Like this:
app_1 | {
app_1 | name: 'Test',
app_1 | description: 'Test description',
app_1 | gateway: 'paypal',
app_1 | amount: '50',
app_1 | trial_period_days: '15',
app_1 | interval: 'week',
app_1 | interval_count: '1',
app_1 | metadata: [
app_1 | [ 'foo', 'bar' ],
app_1 | [ 'bar', 'foo' ],
app_1 | [ 'acme', 'inc' ],
app_1 | foo: 'bar',
app_1 | bar: 'foo',
app_1 | acme: 'inc'
app_1 | ],
app_1 | accept_boleto: true,
app_1 | accept_credit_card: true
app_1 | }
But if I use the validator/sanitizor in a specific field in my controller, all works fine:
async store({ response, request, params, session }) {
const { sanitizor } = use('Validator');
const application = await Application.findOrFail(params.applications_id);
const planParams = await this.planParams(request);
if (planParams.metadata) {
planParams.metadata = sanitizor.jsonInput(planParams.metadata);
}
const plan = await Plan.create(planParams);
await plan.application().associate(application);
session.flash({ alert: 'Plan created successfully' });
response.route('Admin/Application/PlanController.edit', {
applications_id: params.applications_id,
id: plan.id
});
}
Output:
app_1 | {
app_1 | name: 'Test',
app_1 | description: 'Test description',
app_1 | gateway: 'paypal',
app_1 | amount: '50',
app_1 | trial_period_days: '15',
app_1 | interval: 'week',
app_1 | interval_count: '1',
app_1 | metadata: { foo: 'bar', bar: 'foo', acme: 'inc' },
app_1 | accept_boleto: true,
app_1 | accept_credit_card: true
app_1 | }
Package version: 4.1.0;
Node version: v12.4.0;
NPM version: 6.9.0