I have an Api which is fetching Email and password. After that I am seeing if that email and password exists by the following functions:
function EmailCheck(Email){
return arr.some(function(el) {return el.attributes.Email === Email;})}
And same for password just changing email to password but if email is of one object and password ob another objects it passing. Is there any way I can check if Password is in Object where Email is.
what do you mean by another object its passing? do your objects look like this
emailObject = {
'email': 'some#email.com'
}
passwordObject = {
'password': 'password'
}
or like this
authObject = {
'email':'some#email.com'
'password': 'password'
}
if it is like the latter you could just use one function
authCheck(email,password){
return arr.some((el)=>{
if(el.email != email){
return false
}
return el.password == password
})
}
however this may not be the best approach. it kind of depends on what your database looks like and how everything is strung together but what i have done in the past is something like
checkUser(email, password){
return arr.find((user)=>{
return user.email === email && user.password === password
})
}
that way it finds the first (should be only) object, and returns it to be used. this will also allow you to get the index in the array if needed or do ther checks on the same object once you have gotten it. (like removing the password check and doing that as a separate function)
checkUser(email, password){
let user = arr.find((user)=>{
return user.email === email
})
if(user){
//do password check and other operations here
}
return user // for anything that needs to be done with the user
}
Related
I have been trying to make a simple Register/Login system in JS. I tried to get the username/password values through user inputs and turn them into variables using a register() function. After that, however, these variables no longer hold any value, and I need them to compare with the new login username/password to check if they match in order to login.
Here's what I tried.
The function below attributes the user's input to the respective variables successfully. The ID's are from a text input in a HTML file.
function register () {
var user1 = window.document.getElementById('username')
var pass1 = window.document.getElementById('password')
alert('User registered, user your credentials to login')
}
When I click the 'register' button in the html page, the function is called (onclick="register()"), and I am redirected to the login page.
Here's the code for the login session:
function login () {
let userL = window.document.getElementById('usernameL')
let passL = window.document.getElementById('passwordL')
if (userL === user1 && passL === pass1) {
alert(`${userL} successfully logged`)
}
else {
alert('Invalid credentials')
}
It doesn't work because in the code above, user1 and pass1 are "not defined", according to the console. How do I keep the values of these variables stored after getting them in the first function(register) in order to use it when the second function(login) is used?
You can use Session storage to store temporary data
sessionStorage.setItem('username',username);
sessionStorage.setItem('password',password);
To retreive the data in login page
var user1 = sessionStorage.getItem('username',username);
var pass1 = sessionStorage.getItem('password',password);
then clear
sessionStorage.clear();
Please refer the below code,
<script>
const allUsers = [];
function register() {
// assuming user1 && pass1 are input elements with ids username, password
var user1 = document.getElementById("username").value;
var pass1 = document.getElementById("password").value;
// TODO: always validate the data that is taken as input from the user
// create an object containing user details
const newUser = {
username: user1,
password: pass1,
};
// push the registered user in allUsers array
allUsers.push(newUser);
alert("User registered, user your credentials to login");
}
function login() {
// assuming user1 && pass1 are input elements with ids usernameL, passwordL
let userL = document.getElementById("usernameL").value;
let passL = document.getElementById("passwordL").value;
// TODO: always validate the data that is taken as input from the user
// loop through allUsers array to check whether we already have a user registered with the details given in login form
for(let user of allUsers) {
if(user.username === userL && user.password === passL) {
alert(`${userL} successfully logged`);
return; // exit the function here
}
}
// if user detail not found in allUsers array this alert will be executed
alert("Invalid credentials");
}
</script>
Store all users in array after successful registration
While login, loop through the registered users array to check whether the user has already registered or not and decide how to handle the logic.
As PM 77-1 mentioned in the comment, please be aware that getElementById(ID) returns us the element itself (the tag itself), if we want to access it text content we can use either getElementById(ID).textContent or getElementById(ID).innerText
My overall problem is actually finding the values of the variables ''loginEmail'' and ''loginPass'' inside my ''arrayRegistros''. It only becomes TRUE when I write the email and password inside includes manually, however, it always ends up turning into FALSE when I use the variables themselves. I tried converting the variables into strings, then used document.getElementById alongside a few other ideas but until now, none of them completed the login system I had planned. The help I need is how one can find a certain variable's value/object, inside a certain array.
login(registro){
this.arrayRegistros;
var loginEmail = document.getElementById('userEmail');
var loginPass = document.getElementById('userPass');
var contaEmail = this.arrayRegistros.some((loginEmail) => {
return loginEmail.emailRegistro.includes(loginEmail)
})
var contaPass = this.arrayRegistros.some((loginPass) => {
return loginPass.passRegistro.includes(loginPass)
})
console.log(contaEmail)
console.log(contaPass)
}
you should get values from inputs like this:
const data = [
{
user : 'jhon',
password : 'asdf123'
},
{
user : 'bob',
password : 'asdf124'
}
]
const userName = document.getElementById('userEmail').value;
const passWord= document.getElementById('userPassword').value;
const findUser = data.filter( item => item.user === userName && item.password === passWord);
if(findUser.length > 0){
//user found
}
The first problem is that you are naming the parameter on the Array.prototype.some function the same as the variable you want to check outside of the predicate scope.
Second, suposing that this.arrayRegistros is a array with objects with the keys emailRegistro and passRegistro containing strings, DOM Elements CANNOT match with strings, but a element.value can.
Another thing you should have in mind is that includes is not an equality operator, 'a-very-strong-password'.includes('a'); will return true.
And, last, you should never validate login and password on the browser, because the user can edit the JavaScript code on-the-fly and get to login without any real credential.
With that in mind, I think the solution would be something like that (ignoring the browser validation problem):
const $userField = document.getElementById('userEmail');
const $passField = document.getElementById('userPass');
const registros = [
{
email: 'example#example.com',
password: 'a-very-strong-password'
},
...anotherUsers
];
function login(registro) {
const { value: user } = $userField;
const { value: pass } = $passField;
// You can use `Array.prototype.some` to just know if the specific user credentials exist, or use `Array.prototype.find` to know if exist AND grab the user, to further utilization
const item = registros.find(item => item.email === user && item.password === pass);
if (item) {
// User found
} else {
// User not found
}
}
First time on SO so I'm hoping this goes well.
I'm using Mongoose on a current project and until now I haven't had any issues. As the title states, after querying for a document and verifying that document actually exists in the database using a simple console.log, I can't get my document's object references to populate when I use the populate method.
I'm working on a simple authentication route. My client document is broken into two object references, login and user profiles. In my query I'm searching for a client document where the login profile object reference id matches a previously queried login profile's id. Then I want to populate both the user profile and login profile on the client document, then return the client document.
My console log is showing the client document but the population methods don't seem to be executing. Code is below.
const login = await LoginProfile.findOne({ email });
if (login === null) {
console.log("Account doesn't exist.");
} else {
let validPassword = await bcrypt.compare(password, login.password);
if (!validPassword) {
console.log("Email or Password is incorrect");
} else {
const clientDoc = await Client.findOne({
loginProfile: login,
});
console.log(clientDoc.populate("userProfile").populate("loginProfile");
}
}
I'm probably doing this all wrong but I'm self taught and I'm trying. Thanks for whatever solutions you may have. If you have other ways of implementing this, please share! Thanks!
Welcome to Stack Overflow, MrGeonDeaux
Instead of :
console.log(clientDoc.populate("userProfile").populate("loginProfile"));
You could populate the documents on finding, here's the full snippet:
const login = await LoginProfile.findOne({ email });
if (login === null) {
console.log('Account doesn\'t exist.');
} else {
const validPassword = await bcrypt.compare(password, login.password);
if (!validPassword) {
console.log('Email or Password is incorrect');
} else {
const clientDoc = await Client.findOne({
loginProfile: login
}).populate('userProfile loginProfile');
console.log(clientDoc);
}
}
I'm hashing passwords on a pre hook with mongoose schemas, however, the check I'm doing for isModified to know whether or not I should hash/rehash the password with isModified is always resulting in false.
await mongoose.connect(this.connUri, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true
});
const oldUser = await UserModel.findOne({ name: user.name });
oldUser.name = user.name || oldUser.name;
oldUser.password = user.password || oldUser.password;
oldUser.firstName = user.firstName || oldUser.firstName;
oldUser.lastName = user.lastName || oldUser.lastName;
oldUser.email = user.email || oldUser.email;
oldUser.status = user.status || oldUser.status;
let modified = oldUser.isModified(); // test for seeing if modified or not. Always false
await oldUser.save();
result.status = status;
result.result = oldUser;
await mongoose.disconnect();
An fyi user is passed into the method housing this. I would've thought that by changing the properties it would be marked as isModified === true so how does one get the isModified set to true/false or what actually sets it? Any tips, suggestions, or advice appreciated. Open to a different way of doing this too, thanks!
Edit - based on comments and suggested similar answer
Even with the specified object parameter my code is still only presenting as false instead of true in the isModified() method. So the suggested questions isn't helpful because it doesn't answer how the modified property gets set in the first place.
If one uses oldUser.set('password', user.password || oldUser.password); for each of the properties then the object gets isModifed() === true however, when you set it directly with document.property = 'some value' then the object doesn't get isModified() === true but insetad is false, even though it did change the property, and will save it in the DB with .save(). So why is that, and what's the better way to update a document with mongoose?
I've made a full working example from scratch to test this, you can find the repo here:
https://github.com/ZeldOcarina/mongoose-edit-example
The main takeaway is this handler:
app.patch('/user', async (req, res) => {
const { id, username, password } = req.body;
const user = await User.findById(id);
user.username = username ? username : user.username;
user.password = password ? password : user.password;
await user.save();
res.status(200).json(user);
});
If a value exists it means something came from the form thus it's changed, let me know if this works for you or I dig further into this.
The Solution is why not using conditional about changing property. Example if u want to check password isModified like this :
oldUser.pre('save', function(next) {
if(oldUser.password && oldUser.isModified('password')){
this.password = bcrypt.hashSync(oldUser.password, bcrypt.genSaltSync(8),null);
}
next() });
There are some irreversible actions that user can do in my app. To add a level of security, I'd like to verify that the person performing such an action is actually the logged in user. How can I achieve it?
For users with passwords, I'd like a prompt that would ask for entering user password again. How can I later verify this password, without sending it over the wire?
Is a similar action possible for users logged via external service? If yes, how to achieve it?
I can help with the first question. As of this writing, meteor doesn't have a checkPassword method, but here's how you can do it:
On the client, I'm going to assume you have a form with an input called password and a button called check-password. The event code could look something like this:
Template.userAccount.events({
'click #check-password': function() {
var digest = Package.sha.SHA256($('#password').val());
Meteor.call('checkPassword', digest, function(err, result) {
if (result) {
console.log('the passwords match!');
}
});
}
});
Then on the server, we can implement the checkPassword method like so:
Meteor.methods({
checkPassword: function(digest) {
check(digest, String);
if (this.userId) {
var user = Meteor.user();
var password = {digest: digest, algorithm: 'sha-256'};
var result = Accounts._checkPassword(user, password);
return result.error == null;
} else {
return false;
}
}
});
For more details, please see my blog post. I will do my best to keep it up to date.
I haven't done this before, but I think you will need something like this on your server
Accounts.registerLoginHandler(function(loginRequest) {
console.log(loginRequest)
var userId = null;
var username = loginRequest.username;
// I'M NOT SURE HOW METEOR PASSWORD IS HASHED...
// SO YOU NEED TO DO A BIT MORE RESEARCH ON THAT SIDE
// BUT LET'S SAY YOU HAVE IT NOW
var password = loginRequest.password;
var user = Meteor.users.findOne({
$and: [
{username: username},
{password: password}
]
});
if(!user) {
// ERROR
} else {
// VERIFIED
}
});
then you can call this function from the client side like this:
// FETCH THE USERNAME AND PASSWORD SOMEHOW
var loginRequest = {username: username, password: password};
Accounts.callLoginMethod({
methodArguments: [loginRequest]
});
I have a project on github for different purpose, but you can get a sense of how it is structured: https://github.com/534N/apitest
Hope this helps,
I have found the best way to validate the users password is to use the Accounts.changePassword command and
pass in the same password for old and new password. https://docs.meteor.com/api/passwords.html#Accounts-changePassword
Accounts.changePassword(this.password, this.password, (error) => {
if(error) {
//The password provided was incorrect
}
})
If the password provided is wrong, you will get an error back and the users password will not be changed.
If the password is correct, the users password will be updated with the same password as is currently set.