This Firebase kindling will describe a simple recipe for creating a user profile document and upload a profile picture upon new account creation with Firebase authentication.
<p dir="auto">If you have been working with Firebase before, you might have found yourself creating a "user" object to complement the information that we retrieve from Firebase authentication. If you are new to Firebase, you are likely to find this article useful in a very near future. <h2>Preconditions <p dir="auto">You will need to install the <code>crypto-js NPM package dependency for your cloud functions. We'll be using the MD5 hash function for fetching gravatar images. <pre><code>~/awesomeproject $ cd functions ~/awesomeproject/functions $ npm i --save crypto-js <p dir="auto">Before you go any further, you need to know that your project must be on a "non-free price plan" to use the code in this example. <a href="#" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Blaze is a pretty good choice if you don't know which one to choose. And it's worth mentioning that <strong>you do not pay for your usage even if you're on the Blaze plan, iff you are below the free usage tier levels. <p dir="auto">That means that your project won't cost you anything until you reach higher usage. But instead of just hitting the breaks, which is a bad experience even in <em>Alpha testing, you will start paying some $$$. Try to have a plan to make up for that when you develop your app. <h2>What are we cooking? <p dir="auto">Here's what we'll do: for every new account that is created through Firebase authentication, we'll create a "user document" in Firestore containing the name, email and profile photo. The profile photo will be saved to <a href="https://firebase.google.com/docs/storage/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Cloud Storage for Firebase ... but not only that, we'll try and fetch the user's gravatar if the Firebase auth object did not cointain any profile photo (commonly if the user signed up with email/password). <h2>The code <pre><code>import * as functions from "firebase-functions"; import * as firebase from "firebase-admin"; import {MD5} from "crypto-js"; export const createUserDoc = functions.auth.user().onCreate(event => { const firebaseUser = event.data; // Use gravatar as default if photoUrl isn't specified in user data let fileEnding = "jpg"; let photoURL = `https://www.gravatar.com/avatar/${MD5(firebaseUser.email).toString().toLowerCase()}.jpg?s=1024&d=robohash`; if (firebaseUser.photoURL) { fileEnding = firebaseUser.photoURL.substr(firebaseUser.photoURL.lastIndexOf(".") + 1); photoURL = firebaseUser.photoURL; } const fileName = `users/${firebaseUser.uid}/profile.${fileEnding}`; const profilePhotoStorageOpts = { destination: fileName, metadata: { contentType: `image/${fileEnding}` } }; const user = { name: firebaseUser.displayName || "No Name", email: firebaseUser.email, photoUrl: `gs://${firebase.storage().bucket().name}/${fileName}` }; return Promise.all([ firebase.storage().bucket().upload(photoURL, profilePhotoStorageOpts), firebase.firestore().collection("users").doc(firebaseUser.uid).set(user) ]); }); <h2>Breakdown <p dir="auto">I have those from time to time. But we can talk about that another time. Let's break down the code in the example above. <p dir="auto">First we're getting a <a href="https://firebase.google.com/docs/reference/functions/functions.auth.UserRecord" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link"><code>UserRecord object passed in the <code>event parameter. The property values of that object will depend on the authentication type that was used (email/password, Google, Twitter, etc). Most relevant for this example is that the email/password authentication will not provide any data in the <code>photoURL attribute. <p dir="auto">Since we might not get a <code>photoURL from the user object, we're preparing the default values for user's profile photo with a <a href="https://en.gravatar.com/site/implement/images/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">gravatar URL that even provides us with a fallback image, in case the user doesn't have a gravatar profile either. So no matter what, we'll end up with a user profile pic in the end. <p dir="auto">After that, we're allowing for the Firebase <code>UserRecord to overwrite the gravatar profile image, if there is a <code>photoURL present (i.e. if the user logged in with a with <a href="https://firebase.google.com/docs/auth/" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">any of the federated identity providers. <p dir="auto">We prepare a path for the user profile image to be stored at. It's good practice to use the user's UID in the path so that you can create good <a href="https://firebase.google.com/docs/storage/security/start" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">Storage security rules. <p dir="auto">Storing the content type together with the image helps when you're retrieving the image later. So that the file type can be determined in a HTTP GET request, not just interpreted by its file ending. <p dir="auto">Create the user object with a link to your bucket and file, this will give you an internal link directly to the cloud storage, that will be easy to use with the Firebase SDK for referring to the image later. <p dir="auto">Finally, upload the image. And you might have noticed that here's that wonderful Firebase SDK magic at its best: you can upload the photo just by providing the URL. Let Firebase do the work of fetching it. <h2>Result <p dir="auto">For each created account you will now find a corresponding user document in Firestore and a profile image in the cloud storage. <h3>Profile photo in cloud storage <p dir="auto"><img src="https://images.hive.blog/768x0/https://steemitimages.com/DQmWDk15qLRxgFARpALALn2JN9JQvLc5HrvoUcJwi4fY6wx/image.png" alt="Profile photo in cloud storage" srcset="https://images.hive.blog/768x0/https://steemitimages.com/DQmWDk15qLRxgFARpALALn2JN9JQvLc5HrvoUcJwi4fY6wx/image.png 1x, https://images.hive.blog/1536x0/https://steemitimages.com/DQmWDk15qLRxgFARpALALn2JN9JQvLc5HrvoUcJwi4fY6wx/image.png 2x" /> <h3>User doc in Firestore <p dir="auto"><img src="https://images.hive.blog/768x0/https://steemitimages.com/DQmPNQQvDnjErQV5RGjhbJLDnAoH5LzJEU7oxhFaShwaDbU/image.png" alt="Firestore user doc" srcset="https://images.hive.blog/768x0/https://steemitimages.com/DQmPNQQvDnjErQV5RGjhbJLDnAoH5LzJEU7oxhFaShwaDbU/image.png 1x, https://images.hive.blog/1536x0/https://steemitimages.com/DQmPNQQvDnjErQV5RGjhbJLDnAoH5LzJEU7oxhFaShwaDbU/image.png 2x" /> <h3>User account in Firebase auth <p dir="auto"><img src="https://images.hive.blog/768x0/https://steemitimages.com/DQmUGjZqfHA76aZbAKeJPUAmcvzYMCaSVdtKYg9PG3Rhy8q/image.png" alt="Firebase auth" srcset="https://images.hive.blog/768x0/https://steemitimages.com/DQmUGjZqfHA76aZbAKeJPUAmcvzYMCaSVdtKYg9PG3Rhy8q/image.png 1x, https://images.hive.blog/1536x0/https://steemitimages.com/DQmUGjZqfHA76aZbAKeJPUAmcvzYMCaSVdtKYg9PG3Rhy8q/image.png 2x" /> <h2>Homework <p dir="auto">To complete the snippet above you might want to add in some error checking and graceful fallback if anything should go wrong with file upload for example (e.g. bad response from gravatar.com). <h1>Subscribe if you liked it <p dir="auto">Please like the article if you enjoyed reading it and don't forget to subscribe to more articles like this on Medium and Steemit <ul> <li><a href="https://steemit.com/@dennisalund" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">steemit.com/@dennisalund <li><a href="https://steemit.com/@oddbit" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">steemit.com/@oddbit <li><a href="https://medium.com/evenbit" target="_blank" rel="noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">medium.com/evenbit <p dir="auto">Let me know in the comment section below if you have any questions or feedback. I'd love to hear from you.
This wonderful post has received a @dennisalund 27.99% upvote from @hellowhale. Discord Channel: https://discord.gg/XG4y3mg You can vote in the name of the odl. https://steemit.com/~witnesses
Steem Bot Tracker websitevote for @yabapmatt for witness!You got a 1.02% upvote from @postpromoter courtesy of @dennisalund! Want to promote your posts too? Check out the for more info. If you would like to support development of @postpromoter and the bot tracker please
Your Post Has Been Featured on @Resteemable!
Feature any Steemit post using resteemit.com!
How It Works:
1. Take Any Steemit URL
2. Erase
https://
3. Type
re
Get Featured Instantly – Featured Posts are voted every 2.4hrs
Join the Curation Team Here
Hi Mr.Dennis, I'm iqbal @iqbalhood, last month we met at Clapham Startupfest Medan, welcome to join steemit, I hope there will be many posts about firebase here :)