I'm new to firebase, and I'm trying to add a Date Of Birth field to a form and save it to Firebase.
The input field in the form looks like this:
<label for="birthdate">Date of Birth</label>
<input type="date" id="birthdate" name="birthdate"
ng-model="user.birthdate" ng-required="true" placeholder="Last Name">
<p class="error validationerror"
ng-show="myform.birthdate.$invalid && myform.birthdate.$touched">
Birthdate is required</p>
Following a lynda.com tutorial, a working register function was created like this:
register : function(user) {
return simpleLogin.$createUser(user.email, user.password)
.then(function(regUser){
var ref = new Firebase(FIREBASE_URL + 'users');
var firebaseUsers = $firebase(ref);
var userInfo = {
date: Firebase.ServerValue.TIMESTAMP,
regUser: regUser.uid,
firstname: user.firstname,
lastname: user.lastname,
email: user.email
}
firebaseUsers.$set(regUser.uid, userInfo);
}); //add user
}, //register
I tried to simply add another birthdate: user.birthdate key:value pair to the end after email: user.email but that didn't work.
register : function(user) {
return simpleLogin.$createUser(user.email, user.password)
.then(function(regUser){
var ref = new Firebase(FIREBASE_URL + 'users');
var firebaseUsers = $firebase(ref);
var userInfo = {
date: Firebase.ServerValue.TIMESTAMP,
regUser: regUser.uid,
firstname: user.firstname,
lastname: user.lastname,
email: user.email,
birthdate: user.birthdate
}
firebaseUsers.$set(regUser.uid, userInfo);
}); //add user
}, //register
Nothing gets added to firebase for the birthdate.
If I do console.log("user.birthdate: "+ user.birthdate); right after var userInfo I can see the date that was chosen in the date picker... so I know its getting from the form into that register function.
I'm guessing that simpleLogin can only have firstname, lastname, and email?
A few helpful notes:
Firebase Simple Login has been deprecated by Firebase, in favor of the native authentication methods built into each of the Firebase client libraries. That said, it will continue to work.
Both Firebase Simple Login, and the native Firebase authentication, are merely delegated authentication services. That is, they only store credentials to make authentication easier in your app, but they do not store arbitrary user data. Your Firebase is the best play for that.
In the above example, writing to new Firebase(.../users) is writing to Firebase, not the authentication service, and you can write any arbitrary data of your choosing there. However, check the type of the birthdate that you're writing. Firebase leaf values can be of type string, number, boolean, or null - but it is likely that your datepicker might be returning an Object that just happens to toString() correctly.
Related
This question already has answers here:
Username authentication instead of email
(4 answers)
Closed 3 years ago.
Hello Im doing an app in angular, firebase and ionic. I have used a login starter in my app and I want my app to register with a username, email and password. I need the username for later in the app to put Hello [username]. I have the option to register firebase with the property .createUserWithEmailAndPassword(email, password)this property only allows the registration of email and password, how can I add a parameter for username? I would appreciate detailed explanation I am a noob.
I have the code divided into a page and a service and the html part.
-HTML PAGE
<ion-item lines="none">
<ion-input class="placeholdertext inputField" type="text" placeholder="Username" [(ngModel)]="name" autofocus="true" padding-start></ion-input>
</ion-item>
<ion-item lines="none">
<ion-input class="placeholdertext inputField" type="text" placeholder="nombre#dominio.com" [(ngModel)]="email" autofocus="true" padding-start></ion-input>
</ion-item>
<ion-item lines="none">
<ion-input class="placeholdertext inputField" type="password" placeholder="ContraseƱa" [(ngModel)]="password" padding-start clearInput></ion-input>
</ion-item>
-REGISTER PAGE TS
register() {
this.spinner = true;
this.disabled = true;
this.auth
.signupUser(this.email, this.password)
.then(res => {
console.log(res);
this.auth.writeNewUser(this.email, res.user.uid)
.then(response => {
this.auth.getUser(res.user.uid).then(user => {
this.spinner = false;
this.disabled = false;
this.route.navigate(['approved']);
console.log(this.email, this.password );
});
})
})
-FINALLY THE AUTH SERVICE
signupUser(email: string, password: string): Promise<any> {
return this.afAuth.auth
.createUserWithEmailAndPassword(email, password)//In this part it does not let me add another parameter
}
writeNewUser( email: string, uid: string): Promise<any> {
console.log(name, uid, email)
return this.db
.collection('drivers')
.doc(uid)
.set({
email: email,
available: false,
approved: false
});
}
loginUser( email: string, password: string): Promise<any> {
return this.afAuth.auth.signInAndRetrieveDataWithEmailAndPassword( email, password);
}
signupUser(email: string, password: string): Promise<any> {
return this.afAuth.auth
.createUserWithEmailAndPassword(email, password)
}
As I said before I want both in the registration and login can add another password to enter a username, then when the user login start the app with your username and put hello [username]. Adjoint where this property comes out. createuserwithemailandpassword. https://firebase.google.com/docs/auth/web/manage-users?hl=en-419
I appreciate any help. I also speak Spanish
Firebase Authentication doesn't support the use of a username to identify the user. The user must provide an email address to validate their identity. If you want to assign a username later, that's fine, but they still wont' be able to sign in with it. They will always have to use their email address and password.
I am new to mongoDB and mongoose. But what I am trying to do is be able to access the users I have stored in my database by their email, if a user was successfully retrieved the I will compare the password they wrote with the hashed password stored in the database
this is what I have for my Schema
UserSchema
var UserSchema = new Schema({
firstName: { type: String, required: true }, //require makes it so that the fields can't be left blank
lastName: {type: String, required: true},
emailAddress: {type: String, required: true},
password: {type: String, required: true}
});
var User = mongoose.model("User", UserSchema);
I am using the basic-auth package in my routes.js file in order to test this api in postman, this is the part where I am stuck, const user = User.find({'emailAddress': credentials.name, user.emailAddress} ); I am having trouble putting together a query to access user email from the database
//This middle-where function will authenticate users
const authenticateUser = (req, res, next) => {
let message = null;
// Parse the user's credentials from the Authorization header.
const credentials = auth(req);
// If the user's credentials are available...
if (credentials) {
// Attempt to retrieve the user from the data store
// by their email (i.e. the user's "key"
// from the Authorization header).
const user = User.find({'emailAddress': credentials.name, user.emailAddress} );
// If a user was successfully retrieved from the data store...
if (user) {
// Use the bcryptjs npm package to compare the user's password
// (from the Authorization header) to the user's password
// that was retrieved from the data store.
const authenticated = bcryptjs
.compareSync(credentials.pass, user.password);
in this express router I will be returning a user only after being authenticated
//GET /api/users 200, THIS WORKS IN POSTMAN
//This Route returns the currently authenticated user,
router.get('/users', authenticateUser, (req, res) => {
//within the route handler, the current authenticated user's information is retrieved from the Request object's currentUser property:
const user = req.currentUser;
//we use the Response object's json() method to return the current user's information formatted as JSON:
res.json({
firstName: user.firstName,
lastName: user.lastName,
});
});
Can someone help? For reference this is my repo https://github.com/SpaceXar20/rest_api-mongo-p9
here the way you find() is wrong
it should be either a callback or a exec() with async await.. this case just use callbacks
so instead of this code,
const user = User.find({'emailAddress': credentials.name, user.emailAddress} );
use this code
User.find({emailAddress:user.emailAddress},(err,user)={
if(err) throw err;
// do what you please
if (user) {
bcrypt.compare(password,hash,function(err,isMatch){
if(err) callback(err,null);
callback(null,isMatch);
});
} );
I've been struggling with this problem for a couple of days, I am able to create a user but I cannot save their email address under a users node.
register: function(user) {
return auth.$createUser({
email: user.email,
password: user.password
}).then(function(regUser) {
var ref = new Firebase(FIREBASE_URL+'users');
var userInfo = {
key : regUser.uid, // ex: simplelogin:29
date : Firebase.ServerValue.TIMESTAMP,
email : user.email,
}; // user info
ref.child(users).set(userInfo);
});
Here are a couple issues i see:
No specific shild node for each user. You are trying to save the userInfo directly in the users node instead of making a child node under users.
Firebase rules. Without knowing the rules you use i can't know for sure if this applies but can everyone write to that specific node or do you have to be logged in first?
Making the reference. Without knowing what FIREBASE_URL exactly is i can't tell if it's an isuue but if there isn't a / at the end doing + 'users' will give a wrong reference. I suggest using child as Frank also commented.
Resulting code would be something like this (don't forget to check your firebase rules):
register: function(user) {
return auth.$createUser({
email: user.email,
password: user.password
}, function(error) {
if (error) {
//catch possible errors
} else {
//no error, user has been created
//start with logging user in to have firebase write acces
auth.$authWithPassword({
email: user.email,
password: user.password
}, function(error, authData) {
if (error === null) {
//no error so log in succesfull
//Making the firebase reference
var ref = new Firebase(FIREBASE_URL).child("users");
//Get user id
var uid = authData.uid;
//Set data in firebase making a child using the user id
ref.child(uid).set({
key: regUser.uid, // ex: simplelogin:29
date: Firebase.ServerValue.TIMESTAMP,
email: user.email,
});
});
}
)};
}
I am new to Firebase and am currently setting up user and user registration. I have got that working fine but I want to save user information to my firebase database. This is my register function
register: function(user){
return simpleLogin.$createUser(user.email, user.password)
.then(function(regUser){
var ref = new Firebase(FIREBASE_URL + 'users');
var firebaseUsers = $firebase(ref);
var userInfo = {
date: Firebase.ServerValue.TIMESTAMP,
regUser: regUser.uid,
firstname: user.firstname,
lastname: user.lastname,
email: user.email
}
firebaseUsers.$set(regUser.uid, userInfo);
});//add user
},//register
As you can see from the above, I have created a userInfo object that I want to add to my database. What I want to happen is that when you go into my database I have a tree structure of
user - uid - userinfo
Instead of the above I have users - and all you can see is the uid:
I have debugged the code and all the info is being properly saved to my userInfo object - its just doesn't seem to save to firebase properly
I'm trying to implement some simple using registration using Firebase through AngularFire and Angular.js. I'm using the SimpleLogin tool to manage the users. I can create users just fine.
var firebaseRef = new Firebase(FIREBASE_URL);
var simpleLogin = $firebaseSimpleLogin(firebaseRef);
var firebaseUsersRef = new Firebase(FIREBASE_URL + 'users');
var firebaseUsers = $firebase(firebaseUsersRef);
var myObject = {
register: function(user) {
var myDate = new Date().getTime();
return simpleLogin.$createUser(
user.email, user.password)
.then(function(regUser) {
var userInfo = {
date: myDate,
md5: regUser.md5_hash,
firstname: user.firstname,
lastname: user.lastname,
email: user.email
}
firebaseUsers.$push(userInfo).then(function(ref) {
userInfo.uid = ref.name();
$rootScope.currentUser = userInfo;
});
}); //push user
}, //register
Works like a charm. In order to get at this information when the user logs in, I've tried implementing an event handler on the $rootscope. I would like it to search through the uid that I stored and then get me record with the right user information.
$rootScope.$on('$firebaseSimpleLogin:login', function (e, authUser) {
var query = $firebase(firebaseRef.startAt(authUser.uid).endAt(authUser.uid));
console.log(query);
$location.path('/meetings');
});
In order to use startAt and endAt, do I have to establish $priority. When I try, I get an error stating that I can't have any special characters. So that never works. I don't really care about how this data stored, I just want to get the index of the data so that I can retrieve the right user.
By using $push you tell Firebase to generate a key for you.
This is great for collections where you normally access all children at the same time. But that is not the case for your user info: you want to access the info for the current user.
So instead of using $push to add your user's info, I would use the uid of the user.
In the regular Firebase JavaScript API this can be accomplish with:
firebaseUsersRef.child(reguser.uid).set(userInfo);
The equivalent in AngularFire probably uses $set, but I don't think you have any need for that in your $createUser callback.
Update
It looks like you're trying to add your info to the existing user node that Firebase creates for you. This is the example from that from the Firebase documentation on storing user data:
myRef.child('users').child(user.uid).set({
displayName: user.displayName,
provider: user.provider,
provider_id: user.id
});
You can see that they do access the user's node using child(user.uid) similar to what I proposed.
Lessons
Two relatively small mistakes here as far as I can see:
when you use push/$push, you let Firebase generate the node name for you. In cases where there already is a globally unique ID (such as the uid of a user), you're often better off using that as the node name.
If you know the name of the node you want to retrieve, you don't need a query. You can simply access the node as ref.child(user.uid).
Thanks to Frank, I was able to figure out the right way to do this. In order to make my own users object searchable, I can use the uid from the simpleLogin object. So my register function works like this:
var firebaseRef = new Firebase(FIREBASE_URL);
var simpleLogin = $firebaseSimpleLogin(firebaseRef);
var myObject = {
register: function(user) {
var myDate = new Date().getTime();
return simpleLogin.$createUser(user.email, user.password)
.then(function(regUser) {
var userInfo = {
date: myDate,
md5: regUser.md5_hash,
firstname: user.firstname,
lastname: user.lastname,
email: user.email
}
firebaseUsers.$set(regUser.uid, userInfo);
}); //add user
}, //register
} //my Object
Using set instead of push, I can store the uid from the registered user into the object and then pass along what I want to add as the second parameter. My database will now have the users organized by uid, which can be accessed via a url.
Then, when users log in, Firebase will throw up a login event along with the authenticated user, which I can catch and use to add the current user to the $rootScope that's accessible throughout my application.
$rootScope.$on('$firebaseSimpleLogin:login', function (e, authUser) {
var ref = new Firebase(FIREBASE_URL + '/users/' + authUser.uid);
var user = $firebase(ref).$asObject();
user.$loaded().then(function() {
$rootScope.currentUser = user;
});
$location.path('/meetings');
});
Thanks for pointing me in the right direction Frank.