Create new item in Firebase using form - javascript

I am building a web app for a party planning iOS app and I want to have a form where users can create new events through a web form that is submitted using that data.(Sounds better in my head :/ )
In our database there is a tree called "events" where all the events and their details are stored. As an example let's say that I want a form to post the name of the event and the date of the event then have it be stored under the event tree.
After looking at the firebase documentation for a while it seemed like using the update/add user snippet could be the framework for this project.
user.updateProfile({
displayName: "Jane Q. User",
photoURL: "https://example.com/jane-q-user/profile.jpg"
}).then(function() {
// Update successful.
}, function(error) {
// An error happened.
});
But instead of using "Jane Q. User" I would want to call a form field and its data. Am I going about this the right direction or am I up the wrong tree?

Related

Passing User Credentials between Vue-Router Components

I'm new in front-end development and learning Vue 3. I'm currently working on a user Login and Registration pages and I have a problem that I don't know how to solve properly.
The application has a Login page (with Email and Password fields) and a Registration page (with Email, Name, Password and Repeat password fields). Everywhere APIs are connected that check user data when clicking on the Submit button.
Now I have the following task: if the user enters an Email address that has already been registered before, then a pop-up window appears, which says: "Email is already in use. Sing Up to continue."
If the user clicks on Sing Up, then he should be routed to the Login page, in which the data that he just entered on the registration page will be automatically entered into the Email and Password fields.
For routing, I use Vue Router. I have read in the documentation that it is possible to pass props between components, however I am not sure if this is the safest and most correct method.
PS I can't use global state managers like Pinia or Vuex (the team I work for told me to not using them).
Thanks for your help and attention!
I tried using props method but I got problems during compilation
What kinda problem are you facing ? you need to insert the part of code at least or screenshot your problem.
If you want to pass data, you just add props in your route file, example :
{
path: "/example",
name: "example",
props: true,
}
And for sending a data, you need to pass data to params.
Example for option API:
this.$router.push('example', {
params: {email:email, pass:pass};
})
Example for composition API:
router.push({
name: 'example',
params: {email:email, pass:pass},
})
Dont forget to import router. Now you just add props variable:
props: ['email', 'pass']
//or composition API
const props = defineProps({
email: String, pass:String
})
const { email, pass } = toRefs(props)

Proper way to have initial properties for users in Firebase [with react]

I want to build an application where the users could login with Github (as of now, and probably Facebook, Google+ in the future).
I'm wondering how could I have initial properties when the user logs in first time, which would be modified in the future?
In my App component I have an onAuthStateChanged function which will push the users info into the database, but the issue is (obviously) that it will do this every time:
firebaseAuth.onAuthStateChanged((user) => {
if (user) {
this.setState({
user
});
usersRef.push({
id: user.uid,
displayName: user.displayName,
coins: 3000
});
} else {
this.setState({
user: undefined
});
}
});
Is there a way I could check if the user logged in before? Is there a better way to achieve what I want?
Perhaps you can use a Firebase Authentication Trigger as documented at https://firebase.google.com/docs/functions/auth-events.
You could set up a trigger that runs once on the Firebase servers just after a user is created; that trigger can update data in the database for the user, which could include defaulting certain values. Your React app would then be able to read that data when it needs it.

Update Firebase with dynamic state properties

I have a Firebase database structure like this:
-KrVtLbX7w8LKHC888cx
siteInfo
description: "Udemy is an online learning and teaching market..."
siteName: "Udemy"
title: "Udemy Online Courses - Learn Anything, On Your ..."
type: "video_lecture"
url: "https://www.udemy.com/"
Each of these siteInfo nodes could potentially contain different keys (ie. one might not have a type and another could have an img). This makes the data keys relatively dynamic so I can't explicitly set them in firebase.update.
On the frontend, I have a form for the user to edit the site information. The form displays the data in individual input fields for the user to edit depending on which site the user has selected and this is working great.
My problem is submitting an update to the data node that the user is updated.
Right now I'm setting the state for the inputs that have changes like this:
handleChange = ({target}) => {
this.setState({
[target.name]: target.value
});
}
And updating the node like this:
firebase.database().ref().child(`paths/${this.props.uid}/${key}`);
let siteInfo = this.state;
firebaseRef.update({
siteInfo
});
What this is doing is deleting the entire siteInfo node and adding only those fields that the user has edited. So instead of getting this where only the description has been updated:
-KrVtLbX7w8LKHC888cx
siteInfo
description: "The updated description!"
siteName: "Udemy"
title: "Udemy Online Courses - Learn Anything, On Your ..."
type: "video_lecture"
url: "https://www.udemy.com/"
I'm getting this where it's updating the edits made by the user but everything else is deleted:
-KrVtLbX7w8LKHC888cx
siteInfo
description: "The updated description!"
siteName: "The updated site name!"
I want it to only update those keys that have been updated though. This is my understanding of how the .update method for Firebase is supposed to work but for some reason it's just overwriting everything here.
This was actually a pretty silly oversite on my part. State is already submitting the data as an object so instead of doing this (with the extra object wrapper):
firebaseRef.update({
siteInfo
});
I should have just done this:
firebaseRef.update(siteInfo);

firebase javascript injection

I want ask something about firebase security. How to handle following situations?
User is creating account with createUserWithEmailAndPassword() function, then i save his username,email,created_at...to realtime db. But what if data are not saved correctly. His account is created and he is logged in automatically but data is not stored.
I have some registration logic... for example unique usernames... so before creating acc i check if this username exist in realtime db. But he still can call createUserWithEmailandPassword() from js console and account is created.
For situation one:
According to the firebase docs (https://www.firebase.com/docs/web/api/firebase/createuser.html), creating a user does not automatically authenticate them. An additional call to authWithPassword() is required first. In order to ensure that a user isn't authenticated without valid data, you could run a check to the server to make sure the data is saved correctly before authenticating.
Edit: Nevermind that; looks like firebase does auto-auth now - take a look at what I wrote below.
Now a concern with this approach would be if your app allowed people to authenticate with an OAuth provider like gmail, then there is no function for creating the user before authenticating them. What you may need to do is pull the user data from the firebase, determine if it's valid, and if its not valid show a popup or redirect that lets the user fix any invalid data.
For situation two:
If you wanted to make sure that in the case of them calling createUserWithEmailAndPassword() from the console a new user is not created, you could try something like this with promises;
var createUserWithEmailAndPassword = function(username, password) {
var promise = isNewUserValid(username, password);
promise.then(function() {
// Code for creating new user goes here
});
}
In this way, you never expose the actual code that makes a new user because it exists within an anonymous function.
I don't think that this could solve the problem entirely though because firebases API would let anyone create an account using something
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
ref.createUser({
email: "bobtony#firebase.com",
password: "correcthorsebatterystaple"
}
(Taken from https://www.firebase.com/docs/web/api/firebase/createuser.html)
If you wanted to make sure that server side you can't ever create a user with the same user name, you'd need to look into firebases's rules, specifically .validate
Using it, you could make sure that the username doesn't already exist in order to validate the operation of creating a username for an account.
Here's the firebase doc on rules: https://www.firebase.com/docs/security/quickstart.html
And this is another question on stack overflow that is quite similar to yours. Enforcing unique usernames with Firebase simplelogin Marein's answer is a good starting point for implementing the server side validation.
First save the user credentials in the realtime database before you create the user:
var rootRef = firebase.database().ref('child');
var newUser = {
[name]: username,
[email]: useremail,
[joined]: date
};
rootRef.update(newUser);
After adding the Usersinfo into the realtime database create a new user:
firebase.auth().createUserWithEmailAndPassword(useremail, userpassword).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
When an error occured while inserting the data in the realtime database, it will skip the createuser function.
This works fine for me, hope this helps!

Updating Meteor.users from client

I have a form that tried to update meteor.users with extra information about users with the following helper
Template.Profile.events({
'submit form': function(e) {
e.preventDefault();
var post = {
firstName: $(e.target).find('[name=firstname]').val()
};
Meteor.users.update( { _id: Meteor.userId() }, { $set: { 'firstName': post.firstName }} );
}
});
however, i get update failed: Access denied
Another question is, I am wondering whether I should do extra update straight to Meteor.users collection or should I have a seperate collection to store these data.
thanks
Due to the fact that you are trying to set an attribute directly on the base user object, you are receiving the 'Access denied' error. According to the Meteor documentation for Meteor.users:
By default, the current user's username, emails, and profile are
published to the client.
This means that you can update any of those user attributes, but if you want to add additional ones, it is best to add them to one of these already existing fields. I would suggest adding something like `firstName' to the profile attribute. In this case, your code would look something like this:
Meteor.users.update({_id: Meteor.userId()}, {$set: {'profile.firstName': post.firstName}});

Categories