Validator always return empty in graphql - javascript

the problem is, I am not able to make a request to MongoDB after validating the request with the following code:
module.exports.validateRegisterInput = (
username,
email,
password,
confirmPassword
) => {
const errors = {};
if (username.trim() === "") {
errors.username = "Username must be provided";
}
if (email.trim() === "") {
errors.email = "Email must be provided";
} else {
const validEmail =
/^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*#([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/;
if (!email.match(validEmail)) {
errors.email = "Email must be valid";
}
}
if (password === "") {
errors.password = "Password must be provided";
}
if (password !== confirmPassword) {
errors.password = "Passwords must match";
}
return {
errors,
vaild: Object.keys(errors).length < 1,
};
};
the validators work fine and check the request for any mistakes but once there is no issue with the request it does not let me send a request and raises an error anyway, also I am using the validators in the following way:
module.exports = {
Mutation: {
async register(
parent,
{ registerInput: { username, email, password, confirmPassword } }
) {
const { valid, errors } = validateRegisterInput(
username,
email,
password,
confirmPassword
);
if (!valid) {
throw new UserInputError("Errors", { errors });
}
...

so, I solved the problem, the problem was I was not calling the question directly and changed it to:
validateRegisterInput(username, email, password, confirmPassword);
and add errors in the validators and not in the index
const { UserInputError } = require("apollo-server");
module.exports.validateRegisterInput = (
username,
email,
password,
confirmPassword
) => {
if (username.trim() === "") {
throw new UserInputError("Username must be provided", {
errors: {
username: "Username must be provided",
},
});
}
if (email.trim() === "") {
throw new UserInputError("Email must be provided", {
errors: {
email: "Email must be provided",
},
});
} else {
const validEmail =
/^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*#([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9})$/;
if (!email.match(validEmail)) {
throw new UserInputError("Email must be correct", {
errors: {
email: "Email must be correct",
},
});
}
}
if (password === "") {
throw new UserInputError("Password must be provided", {
errors: {
password: "Password must be provided",
},
});
}
if (password !== confirmPassword) {
throw new UserInputError("Passwords must match", {
errors: {
password: "Password must match",
},
});
}
};

Related

Submit form if all fields are valid

I have created a Javascript form validator.
What I would like to do if if all the fields are valid, I would like to be able to submit the form.
I am checking the validity of the fields both on entry and onSubmit.
My thoughts are to use an onClick handler.
For example:
document.getElementById("submit-button").addEventListener("click", submitForm);
submitForm(e) {
e.preventDefault();
form.submit();}
But I am unsure on the best way to implement this with the below validator. For example, should this be used outside of the class validator or within it?
Here is my validator code:
class FormValidator {
constructor(form, fields) {
this.form = form;
this.fields = fields;
}
initialize() {
this.validateOnEntry();
this.validateOnSubmit();
}
validateOnSubmit() {
let self = this;
this.form.addEventListener("submit", (e) => {
e.preventDefault();
self.fields.forEach((field) => {
const input = document.querySelector(`#${field}`);
self.validateFields(input);
});
});
}
validateOnEntry() {
let self = this;
this.fields.forEach((field) => {
const input = document.querySelector(`#${field}`);
input.addEventListener("input", (event) => {
self.validateFields(input);
});
});
}
validateFields(field) {
// Check presence of values
if (field.value.trim() === "") {
this.setStatus(
field,
`${field.previousElementSibling.innerText} cannot be blank`,
"error"
);
} else {
this.setStatus(field, null, "success");
}
// check for a valid email address
if (field.type === "email") {
const re = /\S+#\S+\.\S+/;
if (re.test(field.value)) {
this.setStatus(field, null, "success");
} else {
console.log("ERROR", field.value);
this.setStatus(field, "Please enter valid email address!", "error");
}
}
// Check for valid password
if (field.id === "password") {
if (field.value.trim() == "") {
this.setStatus(field, "Password required!", "error");
} else if (field.value.length <= 10) {
this.setStatus(field, "Password too short!", "error");
} else if (field.value.length >= 50) {
this.setStatus(field, "Password too long!", "error");
} else {
this.setStatus(field, null, "success");
}
}
console.log("We're valid");
}
setStatus(field, message, status) {
const successIcon = field.parentElement.querySelector(".icon-success");
const errorIcon = field.parentElement.querySelector(".icon-error");
const errorMessage = field.parentElement.querySelector(".error-message");
if (status === "success") {
if (errorIcon) {
errorIcon.classList.add("hidden");
}
if (errorMessage) {
errorMessage.innerText = "";
}
successIcon.classList.remove("hidden");
field.classList.remove("input-error");
}
if (status === "error") {
if (successIcon) {
successIcon.classList.add("hidden");
}
field.parentElement.querySelector(".error-message").innerText = message;
errorIcon.classList.remove("hidden");
}
}
}
const form = document.querySelector(".form");
const fields = ["email", "password"];
const validator = new FormValidator(form, fields);
validator.initialize();

How to only log in using admin. Angular

Email:
Invalid email!
Password:
Password need 10 characters!
Submit
I would suggest you to do a serverside authentication, but if you are practicing the authentication from mockdata then you can do the following on your onSubmit:
onSubmit(): void {
var res = this.authservice.admins.filter(data => data.email === this.model.email && data.password === this.model.password);
if (res.length > 0) {
this.authservice.adminFull = true;
this.authservice.isUserLoggedIn = true;
this.route.navigate(['/dashboard']);
this.text = null;
}else{
//do whatever you want for unauthenticated
alert('user not found');
}
}

how to refactor this with ternary operator?

I might not need to refactor this code but now I'm just curious how to do it.
handleError: ({ error, email, password }, props) => authError => {
if (email === "" || password === "") {
return {
error: `Fields can't be empty`
};
} else {
return {
error: authError
};
}
}
this doesn't provide the same functionality as the code above:
handleError: ({ error, email, password }, props) => authError => {
email === "" || password === ""
? { error: `Fields can't be empty` }
: { error: authError };
}
You don't need any return. Since the only conditional logic is the message, it can be simplified as below.
handleError: ({ error, email, password }, props) => (authError) => ({
error: email === "" || password === "" ? `Fields can't be empty` : authError
})
Instead of return, you can wrap your object in parenthesis.
You just forgot the return
It should be:
handleError: ({ error, email, password }, props) => authError => {
return email === "" || password == ""
? { error: `Fields can't be empty` }
: { error: authError };
};
Something like this?
handleError: ({ error, email, password }, props) => authError => {
return email === "" || password === "" ? {error: "Fields can't be empty"} : {error: authError};
}

express validator - custom password validator cannot read property of undefined

I have a simple validator that checks if "password" = "passwordconf"
exports.RegisterUser = [
check('username').isLength({ min: 1 , max: 10}).trim().withMessage("Length 1-10"),
check('password').isLength({ min: 6 , max: 10}).trim().withMessage("Length 6-10"),
check('passwordconf').isLength({ min: 6 , max: 10}).trim().withMessage("Length 6-10"),
check('passwordconf').custom((value , { req }) => {
if (value !== req.body.password) {
throw new Error('Password confirmation is incorrect');
}
}),
sanitizeBody('*').trim().escape(),
function ( req , res ) {
//check for errors
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
} else {
var user = new User({
username : req.body.username,
password : req.body.password
});
var username = req.body.username;
//check if user is in DB
User.findOne({ 'username' : username})
.exec(( err , docs) => {
if (err) {
res.send('There was an error');
return err;
} else if (!docs) {
//username does not exist
user.save((err) => {
if (err) {
return next(err)
} else {
//saved it
res.send('saved a new user!')
}
})
} else {
res.send('Username exists!')
}
})}
}]
if i comment out this statement,
check('passwordconf').custom((value , { req }) => {
if (value !== req.body.password) {
throw new Error('Password confirmation is incorrect');
}
})
the code works.I copied this statement from the official docs https://express-validator.github.io/docs/custom-validators-sanitizers.html
I gives me this error when saving a new user
{"errors":[{"location":"body","param":"passwordconf","value":"password1","msg":"Cannot read property 'then' of undefined"}]}
What is missing here?
This is a known bug, and will be fixed in the next release (current one being v5.2.0).
Custom validators that return nothing fail with that error.
To work around this, you can simply return true from your validator:
check('passwordconf').custom((value , { req }) => {
if (value !== req.body.password) {
throw new Error('Password confirmation is incorrect');
}
return true;
})

Function returns a promise rather than the object it should return

I was writing a MEAN stack application when I came across a rather peculiar error that I don't quite understand.
One of the functions I wrote should return a regular JSON object with certain parameters that will be set in the execution of the function. However, that is not what happens. It instead returns a promise object.
I created a user model, and then created some methods/functions for it. The function in question that returns a promise is the validate function.
What this function does is simply that it makes sure that the data the user entered is in check! You can tell from the code in user.js that it merely checks the length of the input data as well as match it to some predefined regular expressions to see if the data is within acceptable limits (in order not to cause problems later).
I call this function when a user registers which happens in the register function in registerController.js which also should find if the user already exists (has created an account before) or if the username he chose is taken (username exists) after that it sends them a confirmation email containing a link that is their temporaryToken. The route that leads the user to register is in registerRoutes.js. I tried logging the value of the objects received from the functions checkData and validate. checkData returns a normal object while validate returns a promise even though it shouldn't.
Here is the user file user.js
const mongoose = require('mongoose');
var userSchema = new mongoose.Schema({
username: {
type: String,
required: true,
unique: true
},
email:{
type: String,
required: true,
unique: true
},
password:{
type: String,
required: true
},
firstName:{
type: String,
required: true
},
lastName:{
type: String,
required: true
},
confirmed:{
type: Boolean,
default:false,
required: true
},
temporaryToken:{
type: String,
default: "NO_TOKEN",
required: true
}
});
userSchema.method({
checkData: function() {
let checkData = {};
checkData.missing = [];
checkData.wrongType = [];
checkData.success = true;
if(!this.username)
{
checkData.success = false;
checkData.missing.push("username");
}
if(!this.email)
{
checkData.success = false;
checkData.missing.push("email");
}
if(!this.password)
{
checkData.success = false;
checkData.missing.push("password");
}
if(!this.firstName)
{
checkData.success = false;
checkData.missing.push("firstName");
}
if(!this.lastName)
{
checkData.success = false;
checkData.missing.push("lastName");
}
return checkData;
},
validate: function() {
let validation = {};
validation.errors = [];
validation.success = true;
if(this.username.length < 2 || this.username.length > 35)
{
validation.success = false;
validation.errors.push({
"field": "username",
"message": "Invalid length of username. Username must be between 2 and 35 characters long."
});
}
if(this.email.length < 6 || this.username.length > 256)
{
validation.success = false;
validation.errors.push({
"field": "email",
"message": "Invalid length of email. Email must be between 6 and 256 characters long."
});
}
if(this.password.length < 8 || this.password.length > 50)
{
validation.success = false;
validation.errors.push({
"field": "password",
"message": "Invalid length of password. Password must be between 6 and 256 characters long."
});
}
if(this.firstName.length < 2 || this.firstName.length > 35)
{
validation.success = false;
validation.errors.push({
"field": "firstName",
"message": "Invalid length of first name. First name must be between 2 and 35 characters long."
});
}
if(this.lastName.length < 2 || this.lastName.length > 35)
{
validation.success = false;
validation.errors.push({
"field": "lastName",
"message": "Invalid length of last name. Last name must be between 2 and 35 characters long."
});
}
let usernameRegex = /^[a-zA-Z0-9$##%`'"\.]+$/
if(!usernameRegex.test(this.username))
{
validation.success = false;
validation.errors.push({
"field": "username",
"message": "Invalid format of username. Username can only contain Alphanumeric characters and $ # # % ` ' \" and .."
});
}
let emailRegex = /^(([^<>()\[\]\\.,;:\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,}))$/;
if(!emailRegex.test(this.email))
{
validation.success = false;
validation.errors.push({
"field": "email",
"message": "Invalid format and email. Email has to be in the form example#domain.com."
})
}
let passwordRegex = /^[A-Za-z0-9$##%`'"\.]+$/;
if(!passwordRegex.test(this.password))
{
validation.success = false;
validation.errors.push({
"field": "email",
"message": "Invalid format of password. Password an only contain Alphanumeric characters and $ # # % ` ' \" and .."
});
}
let nameRegex = /^[A-Z][a-z-]+$/;
if(!nameRegex.test(this.firstName))
{
validation.success = false;
validation.errors.push({
"field": "firstName",
"message": "Invalid format of first name. First Name can only contain English letters and hyphens (-)."
});
}
if(!nameRegex.test(this.middleName))
{
validation.success = false;
validation.errors.push({
"field": "middleName",
"message": "Invalid format of middle name. Middle Name can only contain English letters and hyphens (-)."
});
}
if(!nameRegex.test(this.lastName))
{
validation.success = false;
validation.errors.push({
"field": "lastName",
"message": "Invalid format of last name. Last Name can only contain English letters and hyphens (-)."
});
}
return validation;
},
capitalizeNames: function() {
this.firstName = this.firstName.charAt(0).toUpperCase() + this.firstName.slice(1);
this.lastName = this.lastName.charAt(0).toUpperCase() + this.lastName.slice(1);
}
});
const UserModel = mongoose.model("user", userSchema);
module.exports = UserModel;
Here is the register controller file registerController.js
const User = require("../model/user.js");
const system = require("../middleware/system.js");
const mails = require("../../config/mails.js");
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
const nodemailer = require('nodemailer');
let registerController = {
register: function(req, res, next) {
let newUser = new User ({
"username": req.body.username,
"email": req.body.email,
"password": req.body.password,
"firstName": req.body.firstName,
"lastName": req.body.lastName,
});
let check = newUser.checkData();
if(!check.success)
{
res.status(400).json(check);
next();
return;
}
newUser.capitalizeNames();
let validity = newUser.validate();
console.log(validity); // "Promise { <pending> }"
if(!validity.success)
{
res.status(400).json(validity);
next();
return;
}
newUser.findOne({"username": newUser.username}, function(err, foundUser1) {
if(err)
{
system.handleServerError(res);
next();
return;
}
if(foundUser1)
{
res.status(403).json({
"success": false,
"message": "The user with the name " + newUser.username + " already exists. Please choose another name."
});
next();
return;
}
newUser.findOne({"email": newUser.email}, function(err, foundUser2) {
if(err)
{
system.handleServerError(res);
next();
return;
}
if(foundUser2)
{
res.status(403).json({
"success": false,
"message": "The user with the email " + newUser.email + " already exists. If you already have an account, please log in."
});
next();
return;
}
bcrypt.hash(newUser.password, saltRounds, function(err, hash) {
newUser.password = hash;
newUser.temporaryToken = jwt.sign({
"email": newUser.email
}, "confirm", {
expiresIn: 60*60*24*365
});
newUser.save(function(err, product, numAffected) {
if(err)
{
system.handleServerError(res);
next();
return;
}
// SEND EMAIL TO USER
res.status(200).json({
"success": true,
"message": "Your registration has been completed successfully. A confirmation link has been sent to your email. Please use that link to actvate your account and login."
});
next();
return;
});
});
});
});
}
};
module.exports = registerController;
Here is the routes file registerRoutes.js
const express = require("express");
const router = express.Router();
const registerController = require("../controllers/registerController.js")
router.post("/api/register", registerController.register);
module.exports = router;
Please tell me if there is anything other information that I can provide or clarify. And thank you all for your time. :)
The error is in the naming of the function.
validate() is already defined in the mongoose module. Calling it on an instance of the user model called the native mongoose function that expected a callback, and therefore returned a promise.
Thankfully, changing validate() to validator() solved the problem.

Categories