How to compare Inputs and JSON data - javascript

I'm working on a school project and I need to validate some users without making a real Database. My problem is that when I compare the information entered in the inputs with the information storaged in JSON, it pops an error for every option that doesn't match. What I want is to reduce the multiple errors into only one (in case that the username or the password doesn't matches with the information storaged in JSON). Here is My JavaScript:
const form = document.querySelector('form');
form.addEventListener('submit', function(e){
e.preventDefault();
const emailInput = document.querySelector('#email').value;
const pwdInput = document.querySelector('#pwd').value;
const object = {
email: emailInput,
pwd: pwdInput
};
fetch('users.json')
.then(res => res.json())
.then(data => {
data.forEach(function(user) {
const userInfo = JSON.stringify(user);
const databaseInfo = JSON.stringify(object);
if(userInfo === databaseInfo) {
console.log('success');
} else {
console.log('err');
}
});
})
.catch(error => console.log('error'));
});
And here is the fake database made with JSON:
[
{"email": "James", "pwd": "1111"},
{"email": "Peter", "pwd": "2222"},
{"email": "Josh", "pwd": "3333"}
]

Using vanilla JavaScript :
// This is only to simulate your fetch from JSON
function fakeFetch ()
{
return Promise.resolve([
{"email": "James", "pwd": "1111"},
{"email": "Peter", "pwd": "2222"},
{"email": "Josh", "pwd": "3333"}
]);
}
const form = document.querySelector('form');
form.addEventListener( 'submit', function(e){
e.preventDefault();
const emailInput = document.querySelector('#email').value;
const pwdInput = document.querySelector('#pwd').value;
const object = {
email: emailInput,
pwd: pwdInput
};
fakeFetch()
.then( users => {
// Check each user in users and try to find a match
for ( let user of users )
{
// Destructuring email and password from the current user
let { email, pwd } = user;
// Comparing email and pwd from active user with the ones in object
if ( email === object.email && pwd === object.pwd )
{
// Found, do something
console.log( 'found!' );
return;
}
}
// Not found, do something else
console.log( 'Not found...' );
})
.catch(error => console.log( error ) );
});
<form>
<input type="text" id="email"/>
<input type="test" id="pwd"/>
<input type="submit"/>
</form>

I tried explaining in the comments, but its probably easier to show you. I think its better to compare the smallest amount of data possible (rather than a big JSON string), like email to email and password to password.
So I changed your if to do a more simpler compare.
To condense all your errors into one, you can include a flag and set it to true if a match is found. Then outside the forEach loop you can check that flag and log just 1 error (if there is no match)
var users = [{
email: "user1",
pwd: "pass1"
}, {
email: "user2",
pwd: "pass2"
}];
var object = {
email: "user3",
pwd: "pass3"
};
var isMatch = false;
users.forEach(function(user) {
if (user.email === object.email && user.pwd === object.pwd) {
console.log("success");
isMatch = true;
}
});
if (!isMatch) {
// only logs once even though there are multiple users
console.log("No Match!");
}

The main idea of your function is to, given a tuple (username, password), check if it exists in your database, which is an array of objects in this case.
You could say you want to filter from the array the entries whose username and password match what was inserted by the user. Since there should be no repeated tuples of username/password, your filter should either return the matching tuple or null.
An approach for this could be the following:
function verifyLogin(loginObject) {
return new Promise((resolve, reject) => {
fetch('users.json')
.then(res => res.json())
.then(data => data.filter(entry => entry.email ===
loginObject.email && loginObject.pwd === object.pwd).length > 0 ? resolve(true) : resolve(false))
.catch(error => reject(error));
});
})
}
verifyLogin(loginObject)
.then(result => result === true ? console.log('Login successful!') : console.log('Login failed'))
.catch(error => console.log(error))
This way the code shows what you are trying to accomplish and does it with no side effects.

Related

Error: Firebase reCAPTCHA placeholder element must be empty

I am using firebase authentication with phone number, and that requires Recaptcha verification. I had initially used the normal visible recaptcha, and that worked fine, but a need came in to make the recaptcha an invisible one.
I used Firebase's documentations on this and here's my code below:
const generateRecaptcha = () => {
window.recaptchaVerifier = new RecaptchaVerifier(
"signin_btn",
{
size: "invisible",
callback: (response) => {
onSignInSubmit();
},
},
auth
);
};
const onSignInSubmit = async () => {
setLoading(true);
const q = query(doc(db, "users", phone));
const querySnapshot = await getDoc(q);
console.log("Snapshot", querySnapshot.exists());
if (
phone === "" ||
password === "" ||
repeatPassword === "" ||
lastname === "" ||
firstname === ""
) {
setLoading(false);
setErrors("Please fill the needed fields.");
} else if (password !== repeatPassword) {
setErrors("Passwords do not match.");
setLoading(false);
} else if (querySnapshot.exists()) {
setErrors(
"This phone number already exists on the server. Please try another number."
);
setLoading(false);
} else {
setErrors("Complete ReCaptcha to get verification code");
generateRecaptcha();
let appVerifier = window.recaptchaVerifier;
console.log("Did we get here?");
signInWithPhoneNumber(auth, phone, appVerifier)
.then((confirmationResult) => {
console.log("We got here..!!");
window.confirmationResult = confirmationResult;
setLoading(false);
})
.catch((err) => {
console.error(err);
});
}
};
I end up getting this error though
Please I need help on this issue.

Best way to define a subarray of state with consideration of react/destructuring-assignment

I'd like to define an new array containing two values of state. This array will be send to the api. My first approach which was working fine, at first, was:
const userRoles = {
userName: this.state.userName,
roles: this.state.userRoles
};
putData('api/User/EditUserRoles', userRoles).then((result) => {
const responseJson = result;
if (responseJson) {
this.setState({ msg: "User's roles updated successfully!" });
}
});
but after i've enabled eslint - react/destructuring-assignment the following errors appeared:
(property) userName: string Must use destructuring state
assignmenteslintreact/destructuring-assignment
(property) userRoles: string[]
Must use destructuring state assignmenteslintreact/destructuring-assignment
so i changed the code to
const { userName, userRoles } = this.state;
const userNameBuffer = userName;
const userRolesBuffer = userRoles;
const userRolesArrayBuffer = {
userName: userNameBuffer,
roles: userRolesBuffer
};
putData('api/User/EditUserRoles', userRolesArrayBuffer).then((result) => {
const responseJson = result;
if (responseJson) {
this.setState({ msg: "User's roles updated successfully!" });
}
});
which workes, but i'm not happy about using the additional "buffer" variables. Is there a way to write this code more "handsome" (e.g. no "buffer" variables) with consideration of react/destructuring-assignment?
Thank you for every answer and sorry for any mistakes in my english that may occur.
you dont need to save vars in buffer, more elegant and common way is:
const { userName, userRoles } = this.state;
const userRolesBuffer = {
userName, // its not mistake, in object variables with same name can be assigned like this
roles: userRoles
};
putData('api/User/EditUserRoles', userRolesBuffer).then((result) => {
const responseJson = result;
if (responseJson) {
this.setState({ msg: "User's roles updated successfully!" });
}
});
Well the answer seems pretty easy and i misunderstood something.
I thought it's necessary to declare an array like
const exampleArray = {
key1: "value1",
key2: "value2"
}
that the result of JSON.stringify(exampleArray); looks like
{
"key1": "value1",
"key2": "value2"
}
but it seems like that
const key1 = "value1";
const key2 = "value2";
const exampleArray = {
key1,
key2,
}
does return the the same result...
so my code, matching react/destructuring-assignment finally looks like
const { userName, userRoles } = this.state;
const roles = userRoles;
putData('api/User/EditUserRoles', { userName, roles }).then((result) => {
const responseJson = result;
if (responseJson) {
this.setState({ msg: "User's roles updated successfully!" });
}
});
Thank you for your answers... especially Pavlo Demydiuk ^^

Validation of username OR phone number - compare

I am currently just doing a very simple and basic login system with either a email address or a phone number. No password.
Nothing major to hide, just an information hub.
What i want to achieve:
Check if user entered email exists within users array.
Check if users entered phone exists within users array. Check if both email and phone match the same user.
Check if email is wrong and phone is drop (or vice versa) - it still finds the right user.
Whats currently happening:
It finds the right user if the email is entered in.
If email is entered in wrong and phone number is correct, i get a undefined error.
If both are wrong i get a server error stating email is undefined.
The code:
Users object
const users = [
{
email: "jon#doe.com",
phone: "0798888888",
name: "John Doe",
access: ["home", "blah", "etc"]
},
{
email: "fakedoe#john.com",
phone: "079000000",
name: "Fake Doe",
access: ["home", "etc"]
}
];
Main code:
app.post("/in", async (req, res) => {
let email = req.body.email,
phone = req.body.phone;
let conditions = !!email ? { email } : { phone };
let data = users.find((x) => x.email === conditions.email || x.phone === conditions.phone);
let pass = data.email || data.phone !== undefined;
console.log(pass);
if (pass) {
if (conditions.email && conditions.email === data.email) {
pass = true;
}
if (conditions.phone && conditions.phone === data.phone) {
pass = true;
}
}
if (pass) {
res.cookie("JWT", jwtSign(req.body.email, data.name, data.access));
res.status(200);
res.send("OK");
} else {
res.status(200);
res.send("Invalid user/password");
}
});
login system with either a email address or a phone number
Had to find a way to play around with the code. Here is a working version!
const users = [{
email: "fakedoe#john.com",
phone: "079000000",
name: "Fake Doe",
access: ["home", "etc"]
}
];
function checkUserExists(email, phone) {
return !!users.find((x) => x.email === email || x.phone === phone);
}
console.log(checkUserExists('fakedoe#john.com', '0490')); //email
console.log(checkUserExists('fakedoe#joh.com', '079000000')); //phone
console.log(checkUserExists('fakedoe#john.com', '079000000')); //both
console.log(checkUserExists('fakedoe#joh.com', '0490')); //none
So replace this:
app.post("/in", async (req, res) => {
let email = req.body.email,
phone = req.body.phone;
let conditions = !!email ? { email } : { phone };
let data = users.find((x) => x.email === conditions.email || x.phone === conditions.phone);
let pass = data.email || data.phone !== undefined;
console.log(pass);
if (pass) {
if (conditions.email && conditions.email === data.email) {
pass = true;
}
if (conditions.phone && conditions.phone === data.phone) {
pass = true;
}
}
if (pass) {
res.cookie("JWT", jwtSign(req.body.email, data.name, data.access));
res.status(200);
res.send("OK");
} else {
res.status(200);
res.send("Invalid user/password");
}
});
with this:
function userExists(email, phone) {
return !!users.find((x) => x.email === email || x.phone === phone);
}
app.post("/in", async (req, res) => {
if (userExists(req.body.email, req.body.phone)) {
res.cookie("JWT", jwtSign(req.body.email, data.name, data.access));
res.status(200);
res.send("OK");
} else {
res.status(200);
res.send("Invalid user/password");
}
});

Valdaition for user exist or not using nodejs

I'm working on a project in React and ran into a problem that has me stumped.
I want to add new user but want to check if user is present or not I tried to give custom message but still not giving me my custom message.
so here is my code and i am not able to figure out how to give custom message.
if any one have some solution it will be really great if you help me
const Employee = require("../models/employeeSchema");
//custom imports
const AppError = require("../helpers/appErrorClass");
const sendErrorMessage = require("../helpers/sendError");
const sendResponse = require("../helpers/sendResponse");
const addEmployees = async (req, res, next) => {
try {
let data = req.body;
let newEmployee = {};
newEmployee.firstName = data.firstName.trim();
newEmployee.lastName = data.lastName.trim();
newEmployee.company = data.company.trim();
newEmployee.email = data.email.trim();
newEmployee.contact = data.contact;
newEmployee.skills = data.skills.split(",").map((skill) => {
return skill.trim();
});
newEmployee.altDescription = data.altDescription.trim();
newEmployee.hobbies = data.hobbies.split(",").map((hobby) => {
return hobby.trim();
});
newEmployee.socialLinks = [
{
gitHub: data.gitHub,
linkedIn: data.linkedIn,
website: data.website,
},
];
newEmployee.imageUrl = req.image;
let employee = await Employee.find({ email: newEmployee.email });
if (employee.email === newEmployee.email) {
return sendErrorMessage(
new AppError(
400,
"Unsuccessful",
"Email already exist try with another Email id"
),
req,
res
);
} else {
let data = await Employee.create(newEmployee);
sendResponse(200, "Employee added Succesfully", data, req, res);
}
} catch (err) {
return sendErrorMessage(new AppError(400, "unsuccessful", err), req, res);
}
};
module.exports.addEmployees = addEmployees;
I have no idea why this is happening, if anyone has experienced this I would be grateful.
Edit:
console.log(employee) outputs the following:
[{
employeeId: 'c88wgb4ocuw01609613746852',
contact: 123456789,
imageUrl: 'http://res.cloudinary.com/altafshaikh/image/upload/v1609613765/qbl7ujyz0wi6cy0xt3rf.jpg',
skills: [ 'sleep', 'laziness' ],
altDescription: 'Hello Saurav',
hobbies: [ 'Nautanki', 'doubtfull' ],
socialLinks: [ {} ],
_id: 5ff0c1c5327f300a55f6259a,
firstName: 'Saurav',
lastName: 'Upadhyay',
company: 'Raw',
email: 'sourav23#gmail.com',
__v: 0
}]
It's because employee is an array. You need to access the first element.
if (employee.length && employee[0].email === newEmployee.email) {
return sendErrorMessage(
new AppError(
400,
"Unsuccessful",
"Email already exist try with another Email id"
),
req,
res
);
}
Since the db query condition is email, we can assume that it will return empty array if no matches are found. It also means that the array will be populated only if a match is found. So we can also avoid the unnecessary check of emails being equal. You can do this.
if (employee.length) {
return sendErrorMessage(
new AppError(
400,
"Unsuccessful",
"Email already exist try with another Email id"
),
req,
res
);
}

While loop is not generating data randomly

I'm creating API tests with async-await using Supertest and Mocha.
In the accountsData.js file I created a function to generate random test accounts.
In the accountsHelper.js file I created a function to create unlimited accounts using a while loop
When I run tests on the post_accounts.js file, the first account is created successfully, but from the second account, the data generated in the accountsData.js file is already repeated.
Why isn't data randomly generated when I create more than one account using data from the accountsData.js file?
accountsData.js
const casual = require('casual');
function randomAccount() {
return {
'email': casual.email,
'password': '123456',
};
}
module.exports = {
randomAccount,
};
accountsHelper.js
const request = require('supertest');
const commonData = require('../data/commonData');
/* eslint-disable no-console */
const accountList = [];
let counterAccounts;
module.exports = {
async createAccount(account, accountsToCreate = 2, validateResponse = true) {
counterAccounts = 0;
while (counterAccounts < accountsToCreate) {
try {
const res = await request(commonData.environment.staging)
.post(commonData.endpoint.accounts)
.send(account);
if (validateResponse === true) {
if (res.status === commonData.statusCode.ok) {
accountList.push(res.body);
} else {
throw new Error('Email already exists\n\n' + JSON.stringify(res.body, null, ' '));
}
} else {
return res.body;
}
} catch (err) {
console.log(err);
}
counterAccounts++;
}
return accountList;
},
};
post_accounts.js
const accountsData = require('../../data/accountsData');
const accountsHelper = require('../../helpers/accountsHelper');
const account = accountsData.randomAccount();
describe('Create accounts with email and password', () => {
context('valid accounts', () => {
it('should create an account successfully', async() => {
const res = await accountsHelper.createAccount(account);
// eslint-disable-next-line no-console
console.log(res);
});
});
});
API response:
Create accounts with email and password
valid accounts
Error: Email already exists
{
"error": {
"statusCode": 422,
"name": "ValidationError",
"message": "The `account` instance is not valid. Details: `email` Email already exists (value: \"Lemuel.Lynch#Susan.net\").",
"details": {
"context": "account",
"codes": {
"email": [
"uniqueness"
]
},
"messages": {
"email": [
"Email already exists"
]
}
}
}
}
at Object.createAccount (/Users/rafael/Desktop/projects/services/test/helpers/accountsHelper.js:24:19)
at process._tickCallback (internal/process/next_tick.js:68:7)
[ { 'privacy-terms': false,
'created-date': '2019-08-24T10:00:34.094Z',
admin: false,
isQueued: false,
lastReleaseAttempt: '1970-01-01T00:00:00.000Z',
'agreed-to-rules': { agreed: false },
email: 'Lemuel.Lynch#Susan.net',
id: '5d610ac213c07d752ae53d91' } ]
✓ should create an account successfully (2243ms)
1 passing (2s)
The code that you posted doesn't correspond to the code that you're describing in prose.
However, I tested your accountsData.js file, in the way that your words (but not your code) say that you're using it, and it works fine.
// main.js
const { createPerson } = require(__dirname + '/accountsData')
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
Output from running it once:
$ node main.js
{ email: 'Anne_Ebert#Macie.com', password: '123456' }
{ email: 'Manley.Lindgren#Kshlerin.info', password: '123456' }
{ email: 'McClure_Thurman#Zboncak.net', password: '123456' }
{ email: 'Breitenberg.Alexander#Savannah.com', password: '123456' }
{ email: 'Keely.Mann#Stark.io', password: '123456' }
And again:
$ node main.js
{ email: 'Destany_Herman#Penelope.net', password: '123456' }
{ email: 'Narciso_Roob#gmail.com', password: '123456' }
{ email: 'Burnice_Rice#yahoo.com', password: '123456' }
{ email: 'Roma_Nolan#yahoo.com', password: '123456' }
{ email: 'Lilla_Beier#yahoo.com', password: '123456' }
Nothing in the code that you posted is actually requiring or using accountsData.js. If you change your code to use it, I think you'll see, like I do, that it works.
Problem is, you are generating the random account and storing it in a variable 'post_accounts.js(line 3)'. So, when you create an account, you are using the same payload to create multiple accounts, which obviously throws an error.
I just modified the accountHelper to properly handle your scenario. Hope this helps.
Note: The code is not tested, I just wrote it from my mind. Please test and let me know if it works.
// accountsHelper.js
const request = require('supertest');
const commonData = require('../data/commonData');
const accountsData = require('../../data/accountsData');
/* eslint-disable no-console */
const accountList = [];
module.exports = {
async createAccount(account, accountsToCreate = 1, validateResponse = true) {
// creates an array of length passed in accountsToCreate param
return (await Promise.all(Array(accountsToCreate)
.fill()
.map(async () => {
try {
const res = await request(commonData.environment.staging)
.post(commonData.endpoint.accounts)
// takes account if passed or generates a random account
.send(account || accountsData.randomAccount());
// validates and throw error if validateResponse is true
if (validateResponse === true && (res.status !== commonData.statusCode.ok)) {
throw new Error(
'Email already exists\n\n' +
JSON.stringify(res.body, null, ' ')
);
}
// return response body by default
return res.body;
} catch (e) {
console.error(e);
// return null if the create account service errors out, just to make sure the all other create account call doesnt fail
return null;
}
})))
// filter out the null(error) responses
.filter(acc => acc);
}
};
//post_accounts.js
const accountsHelper = require('../../helpers/accountsHelper');
const accountsData = require('../../data/accountsData');
const GENERATE_RANDOM_ACCOUNT = null;
describe('Create accounts with email and password', () => {
context('valid accounts', () => {
it('should create an account successfully', async () => {
const result = await accountsHelper.createAccount();
expect(result.length).toEquals(1);
});
it('should create 2 accounts successfully', async () => {
const result = await accountsHelper.createAccount(GENERATE_RANDOM_ACCOUNT, 2);
expect(result.length).toEquals(2);
});
it('should not create duplicate accounts', async () => {
const account = accountsData.randomAccount();
// here we are trying to create same account twice
const result = await accountsHelper.createAccount(account, 2);
// expected result should be one as the second attempt will fail with duplicate account
expect(result.length).toEquals(1);
});
});
});

Categories