How to add phone number validation in AJV - javascript

I have a form field called phone number with country code. So when the user inputs the phone, it is required to validate the phone number with its country code. I did it before with Yup and yup-phone libraries which use google's libphonenumber. However, I found no way to do it with AJV. Here is my schema.
export const ProfileRequestSchema = {
type: "object",
properties: {
firstName: {
type: "string",
minLength: 1,
},
lastName: {
type: "string",
minLength: 1,
},
countryCode: {
minLength: 1,
type: "string",
},
phoneNumber: {
minLength: 1,
type: "string",
},
},
//additionalProperties: false,
required: [
"firstName",
"lastName",
"countryCode",
"phoneNumber",
],
errorMessage: {
type: "should be an object",
properties: {
firstName: t`First name is required and must be a string`,
lastName: t`Last name is required and must be a string`,
countryCode: t`Country Code is required and must be a string`,
phoneNumber: t`Phone number is required and must be a string`,
},
},
};
export const ProfileRequestValidator = ajv.compile(ProfileRequestSchema);
So, is there any way to integrate phone number validator library like libphonenumber-js with AJV?
TIA

Related

How Save Nested Array into Mongodb Using Mongoose schema?

Actually, Only allFacilities field makes an error in Schema, Please Someone help by making sure the correct format of the mongoose schema allFacilities field for allFacilities array data
Actually, Only allFacilities field makes an error in Schema, Please Someone help by making sure the correct format of the mongoose schema allFacilities field for allFacilities array data
My data Look Like That
{
"name": "This is Name countru",
"type": "Hotel",
"country": "Bangladesh",
"city": "Chittagong",
"address": "22 D Block, Kolpolok Residense, Bakulia,",
"distance": "Chittagong",
"title": "tis is best hotel",
"desc": "Pamper yourself with a visit to the spa, which offers massages, body treatments, and facials. You can take advantage of recreational amenities such as an outdoor pool, a spa tub, and a sauna. Additional features at this hotel include complimentary wireless Internet access, concierge services, and a banquet hall. Grab a bite at The Exchange, one of the hotel's 3 restaurants, or stay in and take advantage of the 24-hour room service. Relax with your favorite drink at the bar/lounge or the poolside bar. Featured amenities include a business center, dry cleaning/laundry services, and a 24-hour front desk. Free valet parking is available onsite. Make yourself at home in one of the 241 air-conditioned rooms featuring LED televisions. Complimentary wireless Internet access keeps you connected, and satellite programming is available for your entertainment. Private bathrooms with separate bathtubs and showers feature hair dryers and slippers. Conveniences include phones, as well as safes and coffee/tea makers. Distances a",
"cheapestPrice": "105",
"rooms": [
"629dd3bae549560b971612da",
"629dd418e549560b971612df",
"629dd481e549560b971612ea",
"629dd4b3e549560b971612f0",
"629dd4b4e549560b971612f6",
"629dec61e549560b9716139f"
],
"photos": [
"http://res.cloudinary.com/cloudmonzu/image/upload/v1655222493/upload/jxsbi7r26cyqgnwg65ni.jpg",
"http://res.cloudinary.com/cloudmonzu/image/upload/v1655222494/upload/bybbcdb8iluy0t7smf1u.jpg",
"http://res.cloudinary.com/cloudmonzu/image/upload/v1655222493/upload/pzfzk3umv5agumt30ygo.jpg"
],
"allFacilities": [
{
"hotelfacilities": [
"dsds",
" sdsd",
" sdd"
]
},
{
"roomfacilities": [
"sdsd",
" dss",
" dss"
]
},
{
"wellnessSpa": [
"sds",
" dsd",
" sdsd",
" sds"
]
}
]
}
My Mongoose Schema Look Like That
import mongoose from "mongoose";
const HotelSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
type: {
type: String,
required: true,
},
country: {
type: String,
required: true,
},
city: {
type: String,
required: true,
},
address: {
type: String,
required: true,
},
distance: {
type: String,
required: true,
},
title: {
type: String,
required: true,
},
desc: {
type: String,
required: true,
},
cheapestPrice: {
type: Number,
required: true,
},
rooms: {
type: [String],
},
photos: {
type: [String],
},
allFacilities: {
type: [String],
required: true,
},
rating: {
type: Number,
min: 0,
max: 5,
},
featured: {
type: Boolean,
default: false,
},
});
export default mongoose.model("Hotel", HotelSchema)
use "type: Array" for rooms, photos and allFacilities
name: {
type: String,
required: true,
},
type: {
type: String,
required: true,
},
country: {
type: String,
required: true,
},
city: {
type: String,
required: true,
},
address: {
type: String,
required: true,
},
distance: {
type: String,
required: true,
},
title: {
type: String,
required: true,
},
desc: {
type: String,
required: true,
},
cheapestPrice: {
type: Number,
required: true,
},
rooms: {
type: Array,
},
photos: {
type: Array,
},
allFacilities: {
type: Array,
required: true,
},
rating: {
type: Number,
min: 0,
max: 5,
},
featured: {
type: Boolean,
default: false,
},
});

Updating the field of a nested object property inside an array of objects in mongodb

I have created the following schema in MongoDB. It is a customer schema with a sub-schema for storing the transactions. Each transaction is an object and each object(a transaction) contains a field called "transactionDetails", which is an object as well.
const transactionSchema = new Schema(
{
transactionType: {
type: String,
},
transactionDetails: {
transferredFrom: {
type: String,
default: "",
},
transferredTo: {
type: String,
default: "",
},
balance:{
type: Number,
default:0,
min: 0,
},
amount:{
type:Number,
default:0
}
},
},
{
timestamps: true,
}
);
const customerSchema = new Schema(
{
name: {
type: String,
required: [true, "Please provide a customer name"],
},
dob: {
type: Date,
required: [true, "Please provide a Date of Birth"],
},
address: {
type: String,
default: "India",
},
accNo: {
type: String,
required: true,
default: mongoose.Types.ObjectId,
},
email: {
type: String,
required: [true, "Please provide an email address"],
},
phone: {
type: String,
required: [true, "Please provide a phone number"],
},
transactions: [transactionSchema],
currentBal: {
type: Number,
required: [true, "Please provide valid balance"],
default: 0,
min:0
},
},
{
timestamps: true,
}
);
All I want to do is to set the value of a field to an existing field in the document while updating it. I want to set the value of "balance" field to the current updated value of the "currentBal" after the "currentBal" field has been updated.
The problem is that the no matter what I did, the value of "balance" field always set to default value without throwing any error
Customer.findOneAndUpdate(
{ accNo: id },
{
$inc: { currentBal: Number(amount),
},
$push: {
transactions: {
transactionType: "deposit",
transactionDetails: {
transferredFrom: "Self",
transferredTo: "Self",
balance:{currentBal} ,
amount: Number(amount),
},
},
},
},
(err, customer) => {
if (err !== null && err.name === "ValidationError") {
res.json({ message: err._message });
} else {
console.log("Balance has been updated successfully");
// console.log(customer.currentBal);
res.redirect(`/customers/${id}`);
}
}
);

How to change the HTTP error about the password length in loopback 4?

I am using loopback 4 authentication and I have this credential schema.
In my register method I am getting this http error response when giving a password shorter than 8 characters.
I'm trying to avoid error message in the response that the password should be shorter than 8 characters, instead respond with an http error response without that details. How can I replace this default error with a custom one?
I tried something like this
if (credential.password.length < 8) {
throw new HttpErrors.NotFound;
}
in the register method but it did not work.
I could delete the minLength limit 8 in the schema but I want that error response in that case.
export const CredentialsSchema = {
type: 'object',
required: ['email', 'password'],
properties: {
email: {
type: 'string',
format: 'email',
},
password: {
type: 'string',
minLength: 8,
},
},
};
async register(
#requestBody() credential: CredentialPassword,
): Promise<AccessToken> {
return this.userRegistration(credential);
}
{
"error": {
"statusCode": 422,
"name": "UnprocessableEntityError",
"message": "The request body is invalid. See error object `details` property for more info.",
"code": "VALIDATION_FAILED",
"details": [
{
"path": ".password",
"code": "minLength",
"message": "should NOT be shorter than 8 characters",
"info": {
"limit": 8
}
}]
}
}
Thank's for your help !
You can do this like following way:
export const CredentialsSchema = {
type: 'object',
required: ['email', 'password'],
properties: {
email: {
type: 'string',
format: 'email',
},
password: {
type: 'string',
minLength: 8,
errors: {
minLength: "Should be at least 8 characters long."
}
},
},
};

Mongoose/Mongodb: Index Already Exists With Different Options

I am using Mongoose 5.1.7 and attempting to create a compound index across multiple text indexes in my defined schema. Here is my schema definition:
const mongoose = require('mongoose');
const alumniSchema = mongoose.Schema({
firstName: {
type: [String],
required: true
},
lastName: {
type: [String],
required: true
},
classYear: {
type: Number,
required: true
},
photoURL: {
type: String,
},
education: [
{
school: {
type: String,
required: true
},
gradYear: {
type: Number,
required: true
},
degreeType: String,
degreeSubject: String,
}
],
jobs: [
{
employer: {
type: String,
required: true
},
position: String,
startDate: Date,
endDate: Date,
isCurrent: Boolean
}
],
contactInfo: {
phoneNumber: {
type: String,
},
email: {
type: String,
}
},
})
alumniSchema.index({ firstName: 'text', lastName : 'text', email: 'text' });
module.exports = mongoose.model('Alumni', alumniSchema);
When I boot up the server, I receive the following error:
MongoError: Index: { v: 2, key: { _fts: "text", _ftsx: 1 }, name: "firstName_text_lastName_text_email_text", ns: "5b3be578c0c6e317f7c1bc2b_test.alumnis", background: true, weights: { email: 1, firstName: 1, lastName: 1 }, default_language: "english", language_override: "language", textIndexVersion: 3 } already exists with different options: { v: 2, key: { _fts: "text", _ftsx: 1 }, name: "firstName_text_lastName_text_classYear_text_education.school_text", background: true, weights: { classYear: 1, education.school: 1, firstName: 1, lastName: 1 }, default_language: "english", language_override: "language", ns: "5b3be578c0c6e317f7c1bc2b_test.alumnis", textIndexVersion: 3 }
I have been messing around with this for a while and evidently previously created an index. When I use the mongo shell to check the indexes that I currently have set up, however, I cannot find the index "firstName_text_lastName_text_classYear_text_education.school_text" referenced by the error message:
> db
test
> db.collection.getIndexes()
[ ]
I am at an impasse--I'm not sure if I've incorrectly created the index, or if I am supposed to drop the index (it doesn't look like Mongoose natively supports a dropIndex() function).
Has anyone else dealt with this issue? Thanks!
Looks like Mongoose dynamically creates the index at runtime. The trick for me was adding:
var Alumni = mongoose.model('Alumni', alumniSchema);
Alumni.collection.dropIndex('firstName_text_lastName_text_classYear_text_education.school_text', function(err, result) {
if (err) {
console.log('Error dropping index!', err);
}
});
and then restarting the server.
THEN I was able to change the index to whatever I wanted. Note that I still needed to add the above code segment and restart the server every time I wanted to update the index.

Simple Schema error in Meteor

I am using the meteor accounts and simple schema for users to register and enter their profile information in my app. I defined a schema for users and attached a schema for address to it. However, when I go to register an account, I keep getting the error "Address required" although I filled out all the required fields for address. Here's my schema:
Schemas.UserAddress = new SimpleSchema({ //UserAddress schema defined
streetAddress: {
type: String,
max: 100,
optional: false
},
city: {
type: String,
max: 50,
optional: false
},
state: {
type: String,
regEx: /^A[LKSZRAEP]|C[AOT]|D[EC]|F[LM]|G[AU]|HI|I[ADLN]|K[SY]|LA|M[ADEHINOPST]|N[CDEHJMVY]|O[HKR]|P[ARW]|RI|S[CD]|T[NX]|UT|V[AIT]|W[AIVY]$/,
optional: false
},
zipCode: {
type: String,
regEx: /^[0-9]{5}$/,
optional: false
}
});
var Schemas = {};
Schemas.UserProfile = new SimpleSchema({
companyName: {
type: String,
regEx: /^[a-zA-Z-]{2,25}$/,
optional: false
},
tireMarkup: {
type: Number,
optional: true,
min: 1
},
phoneNum: {
type: String,
regEx: /^[(]{0,1}[0-9]{3}[)]{0,1}[-\s\.]{0,1}[0-9]{3}[-\s\.]{0,1}[0-9]{4}$/,
optional: false
},
confirmed: {
type: Boolean,
optional: true
},
});
Schemas.User = new SimpleSchema({
emails: {
type: [Object],
optional: false
},
"emails.$.address": {
type: String,
regEx: SimpleSchema.RegEx.Email
},
"emails.$.verified": {
type: Boolean
},
createdAt: {
type: Date
},
profile: {
type: Schemas.UserProfile,
optional: false
},
address: { //Attach user address schema
type: Schemas.UserAddress,
optional: false
},
services: {
type: Object,
optional: true,
blackbox: true
}
});
Meteor.users.attachSchema(Schemas.User);
Here is my accounts config which creates the sign up form:
Meteor.startup(function () {
AccountsEntry.config({
logo: '', // if set displays logo above sign-in options
termsUrl: '/terms-of-use', // if set adds link to terms 'you agree to ...' on sign-up page
homeRoute: '/', // mandatory - path to redirect to after sign-out
dashboardRoute: '/dashboard/', // mandatory - path to redirect to after successful sign-in
profileRoute: '/profile',
passwordSignupFields: 'EMAIL_ONLY',
showOtherLoginServices: true, // Set to false to hide oauth login buttons on the signin/signup pages. Useful if you are using something like accounts-meld or want to oauth for api access
extraSignUpFields: [
{
field: "companyName",
label: "Company Name",
placeholder: "Petrocon",
type: "text",
required: true
},
{
field: "firstName",
label: "First Name",
placeholder: "John",
type: "text",
required: true
},
{
field: "lastName",
label: "Last Name",
placeholder: "Nguyen",
type: "text",
required: true
},
{ field: "streetAddress",
label: "Street Address",
placeholder: "12345 Main Street",
type: "text",
required: true
},
{ field: "city",
label: "City",
placeholder: "Springfield",
type: "text",
required: true
},
{ field: "state",
label: "State",
placeholder: "Missouri",
type: "text",
required: true
},
{ field: "zipCode",
label: "Zip Code",
placeholder: "65801",
type: "text",
required: true
},
{
field: "phoneNum",
label: "Contact Number",
placeholder: "316-000-0000",
type: "text",
required: true
}
]
});
});
As you can see, I defined all of the fields in the address schema in AccountsEntry.config.. therefore I don't know why when I enter all the information in the form, I get the error 'address required'. Does anyone know what's going on? Thank you in advance!
Looks like you're using the accounts-entry package. You can see the code where the account is created in this file:
https://github.com/Differential/accounts-entry/blob/9aac00cb3c67afcbb1cc990c7af1f2c7607a2337/server/entry.coffee
Line 29 looks like this:
profile: _.extend(profile, user.profile)
If you debug and look at the value of profile after the extend method is called, you'll see this:
{
"companyName": "Petrocon",
"firstName": "John",
"lastName": "Nguyen",
"streetAddress": "12345 Main Street",
"city": "Springfield",
"state": "Missouri",
"zipCode": "65801",
"phoneNum": "316-000-0000"
}
There is no property named "address" for your Schemas.User schema.
There might be some slick way to do what you're looking for, but the easiest approach is to just get rid of the Schemas.UserAddress schema. Move those properties (streetAddress, city, state, zipCode) into the Schemas.UserProfile schema and it will work.

Categories