I recently migrated to new joi repo (#hapi/joi => joi)
Now I am getting error when running server
throw new AssertError([result.error.details[0].message]);
^
Error: "language" is not allowed
I searched google and SO , but cant find solution
This is my code :
forgetUser: {
query: {
email: Joi.string().regex(/^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/)
.required()
.options({ language: { string: { regex: { base: 'must be valid' } } } })
.label('Email')
}
},
Please help me?
This is caused when you are passing an unknown field to a Joi schema.
for example, you have this Joi schema:
Joi.object({
name: Joi.string().required(),
email: Joi.string().required(),
});
and you pass this object to validate:
{
name: "John Doe",
email: "johndoe#gmail.com",
language: "en"
}
The validation will throw an error / failed because language is not allowed inside the schema.
To prevent this, you can pass stripUnknown options on the Joi Schema so it will strip unknown fields
Joi.object({
name: Joi.string().required(),
email: Joi.string().required(),
}).options({ stripUnknown: true });
or you can pass allowUnknown so it will ignore unknown fields
Joi.object({
name: Joi.string().required(),
email: Joi.string().required(),
}).options({ allowUnknown: true });
You can read more about validation options here
It is not clear from the question what you are trying to achieve (maybe add more details?).
If you are trying to validate email, there is already a built-in function to do so: string.email().
If you still want to do a custom regex matching, there is an built-in function for this too: string.pattern().
If you want to replace the built-in error messages to custom error messages, Joi provides that by using .messages(). Check the answer here: https://stackoverflow.com/a/58234246/1499476.
Basically, you can do something like:
forgetUser: {
query: {
email: Joi.string().pattern(/^(([^<>()[\]\\.,;:\s#\"]+(\.[^<>()[\]\\.,;:\s#\"]+)*)|(\".+\"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/)
.required()
.label('Email')
.messages({
'string.pattern.base': '{#label} must be valid', // --> Email must be valid.
'string.base': '{#label} should be a type of "text"',
... // other customisations
})
}
},
string.pattern() can also be used as alias string.regex() (as you are already doing).
Related
Sometimes when using MikroORM entities with Jest (TS) in this way:
const ads = await repo.findAll({
orderBy: {
providerId: 'asc'
}
})
expect(ads).toMatchObject([
{
providerId: 'a',
title: 'a-changed',
createdBy: {
id: firstJobId
},
updatedBy: {
id: secondJobId
},
removed: false
}])
it causes this error to be thrown:
Cannot redefine property: __helper TypeError: Cannot redefine
property: __helper
When I try to use wrap(entity).toPOJO() a reference to another entity is no longer an object but is converted to an id. In my case the createdBy and updatedBy becomes a number.
Is there a way around this problem?
A user will be sending contact information as an array of objects like the following, with the phone number being optional and the email being required:
{
"contact": [{
"type": "phone",
"value": "555-555-5555"
}, {
"type": "email",
"value": "test#test.com"
}]
}
I would like to ensure there is an email object inside the array. I tried a Joi validation like this:
contact: Joi.array().items(Joi.object().keys({
type: Joi.string().valid('phone', 'email'),
value: Joi.string()
.when('contact.type', { is: 'phone', then: Joi.string() })
.when('contact.type', { is: 'email', then: Joi.string().email().required() })
}))
.when('contact.type', { is: 'phone', then: Joi.array().min(2).required() }),
But I get the following error:
Error: Item cannot come after itself: contact
It seems it doesn't like me giving it a length in this manner but I can't figure out any other way to do it. Any help would be appreciated. Thanks.
This schema combining .when, .has, and .unique, should work:
Joi.object({
contact: Joi.array().items(
Joi.object().keys({
type: Joi.string().valid('phone', 'email').required(),
value: Joi.string().when('type', { is: 'email', then: Joi.required() })
}).required(),
)
.has(Joi.object({ type: 'email', value: Joi.exist() }))
.unique('type').min(1).max(2)
})
Let's see the rules:
the object with the type 'email' must exist;
That's why I've added
.has(Joi.object({ type: 'email', value: Joi.exist() }))
This means that the array must have at least one of these elements.
We don't want duplicates, right?
.unique('type').min(1).max(2)
The array will have either 1 element, or 2, with different types.
When the type is 'email', the value should be required, and optional otherwise. That's what we are saying here:
value: Joi.string().when('type', { is: 'email', then: Joi.required() })
Thank you #soltex for your answer.
First I'm not sure we should exclude duplicates. Some people have multiple phone numbers.
Second, your answer did not quite work. Here is my updated answer based on what you wrote:
contact: Joi.array().items(Joi.object().keys({
type: Joi.string().valid('phone', 'email').required(),
value: Joi.string().required(),
}))
.has(Joi.object({ type: 'email', value: Joi.string().email() }))
Once I include the .has method then there is no reason to include the .when method. I also want the email to be a valid email not just that it exists. I changed value to required because if the user sends type phone I still want them to include the value.
Once again thanks for your guidance.
I have following validation schema, and sample data.
var schema = Joi.alternatives().try(
Joi.object().keys({
searchTerm: Joi.string().trim().min(3).label('Search Term').options({ language: { any: { empty: 'should not be empty' } } }),
location: Joi.string().allow(''),
searchType: Joi.string().valid('people')
}),
Joi.object().keys({
searchTerm: Joi.string().allow(''),
location: Joi.string().trim().min(3).label('Location').options({ language: { any: { empty: 'should not be empty' } } }),
searchType: Joi.string().valid('people')
})
);
Sample data is:
{searchTerm: "", searchType: "people", location: ""}
Should not pass and show a message Please enter either search term or location. Make sure it contains 3 characters at least
{searchTerm: "as", searchType: "people", location: ""}
Should not pass and show a message Search term must contain 3 characters at least
{searchTerm: "test", searchType: "people", location: ""} // Should pass
My validation schema shows both message in failure situations
You can simplify your joi schema to this
const schema = Joi.object().keys({
searchTerm: Joi.string().trim().min(3),
location: Joi.string().allow(''),
searchType: Joi.string().valid('people'),
}).or('searchTerm', 'location').error(new Error('Please enter either search term or location. Make sure it contains 3 characters at least'));
However this will not meet your second condition(Search term must contain 3 characters at least) as there can be only one error message.
Planning to use AJV
for validating user inputs. AJV needs data model JSON Schema to validate user inputs. So, we need to derive JSON Schema from Sequelize model. Is there a way to get JSON schema from Sequelize model programatically?
A late answer, but I ended up creating sequelize-to-json-schema to solve this for our needs.
It offers more customisation in terms of which attributes you include in your schema and adding virtual attributes that might be used by your create method or similar.
Example
// assuming you have a user model with the properties
// name (string) and status (enum: real, imagined)
const schemaFactory = require('sequelize-to-json-schema');
const factory = new SchemaFactory({
customSchema: {
user: {
name: { description: "The user's name" },
status: { description: 'Was it all just a dream?' },
},
}
hrefBase: 'http://schema.example',
});
const schemaGenerator = factory.getSchemaGenerator(User);
const schema = schemaGenerator.getSchema();
// Results in
schema = {
{
title: 'User',
'$id': 'http://schema.example/user.json',
type: 'object',
'$schema': 'http://json-schema.org/draft-06/schema#',
properties: {
name: {
'$id': '/properties/fullname',
type: 'string',
examples: [],
title: 'Name',
description: "The user's name",
},
status: {
'$id': '/properties/status',
type: 'string',
examples: ['REAL', 'IMAGINED'],
enum: ['REAL', 'IMAGINED'],
title: 'Status',
description: 'Was it all just a dream?'
}
}
}
}
Note: sequelize-to-json-schema generates draft-06 schemas, to use that with AJV, their README says you'll need to do:
ajv.addMetaSchema(require('ajv/lib/refs/json-schema-draft-06.json'));
I am trying to create a simple server application in Node.js using the waterline-orientdb package where there are several users who can invoke several methods. Before a user can do anything, the user needs to authenticate with his username and password. Within this authentication the user object is given a token that will be piggybacked with the future requests.
When a user is given a token, an update query is invoked. When invoking the update request I get the following error:
ERROR err: { [OrientDB.RequestError: expression item ']' cannot be resolved because current record is NULL]
name: 'OrientDB.RequestError',
message: 'expression item \']\' cannot be resolved because current record is NULL',
data: {},
previous: [],
id: 1,
type: 'com.orientechnologies.orient.core.exception.OCommandExecutionException',hasMore: 0 }
The strange thing is that the update is executed, so this error doesn't have influence on the update request. But because I want to catch all errors, I can't just ignore this.
My model looks like this:
module.exports = {
tableName: 'User',
identity: 'dbuser',
schema: true,
attributes: {
id: {
type: 'string',
primaryKey: true,
columnName: '#rid'
},
username: {
type: 'string',
required: true,
unique: true
},
password: {
type: 'string',
required: false
},
token: {
type: 'string'
},
follows: {
collection: 'dbuser',
via: 'followed',
dominant: true
},
followed: {
collection : 'dbuser',
via: 'follows'
}
};
As you can see, I'm associating two users with eachother so that one user can follow the activities of the other user. When I delete the association (so follows and followed) the error also dissapears.
The piece of code where the updates happens looks like this:
user[0].token = generateToken(user[0])
dbuser.update({
id: user[0].id
}, user[0]).exec(function (error, data) {
if (error) res.json(401, {
code: 401,
error: "Token could not be updated"
})
res.json(user);
});
Does anyone has an idea on how to avoid this behavior or what the error even means?
It seems to be a bug in the adapter.
You could try using:
npm install appscot/waterline-orientdb#refactor_collection
Apparently will be resolved in v.0.10.40
More info about it: https://github.com/appscot/waterline-orientdb/issues/43#issuecomment-75890992