How to build an eCommerce Website using React Redux, GraphQL, Firebase #10 – Admin User Roles

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome to the 10th video in this tutorial series on building an e-commerce website using react Redux graph QL and firebase in this tutorial we're going to learn how we can restrict access to certain pages so that only users with admin rights can access them we're also going to build this admin toolbar so that whenever an admin is signed in to the application they'll see this toolbar which has a link to their admin before we get started with this tutorial I just want to encourage you guys to check out my official youtube channel before we begin this video tutorial I just want to encourage you guys to check out my official youtube channel which is youtube.com forward slash simple Tut not only to view my other videos and content but we also have an official playlist for this video series I'm adding each video from this series to this playlist so it's just a great place for you to find previous and future videos I also want to remind you guys that there is an official github repository for this project so you can actually come here and look at the code that I'm writing and again there'll be a direct link in the description of this video and finally I just want to let you guys know that you can visit my official website which is simple to calm join our community look at our other tutorials and open source projects and again show your support please like comment and subscribe let's get started we already have the ability to restrict access to pages and content within our application this means that users have to be signed in in order to access those pages in this tutorial we want to extend that logic to allow for additional user levels this means that depending on the user that's signed into the application and the rights associated with their account will be used to determine the content that they will have access to this is my users collection within my firebase database and as you can see I'm looking at this particular users document within the collection and on this document we can see the data that we're currently storing about our users so that includes the date that they signed up to our website their full name and their email address now in this tutorial we're going to have to add a new field and this will be added programmatically but first I want to manually add that to this users document because they are already signed up to our application so this field is going to be called user roles and we're going to use this it's going to be an array but we're going to use this to assign users their roles so any user that signs up to the application will automatically be assigned the user role but we're also going to add this particular user an additional role which is going to be the admin role and we're going to use this user roles array to determine if a user has the correct access rights to view content and pages within our website now before I can actually implement this programmatically within our application the first thing I need to do is make sure and to remind you guys how authentication works within our firebase app I'm going to remind you guys that we have two tabs which are relevant to our authentication within our website here and that is our authentication tab and the database tab itself so again our authentication currently we are we have two types of authentication enabled within our application currently and that includes the email and password provider and our Google provider that means that we allow users to sign up or sign into our application with their email and password or we allow them to sign in or sign up to our application through their existing Google account now what happens whenever a user is authenticated within our firebase app is firebase we'll automatically store their information and generate a unique user ID which is their you you UID here now although we store users information within our users collection regardless of how they signed in or up to our website this is actually completely separate to firebase or authentication and we're actually manually doing this after a user has already been authenticated within our application to actually implement this programmatically as I said I need to come back over to my text editor and I need to go into a file that we created in one of the earlier videos in this series which is in our firebase folder and the utility file that we created here now what this file contains is basically a bunch of helper functions that we're using throughout the website we're also exporting a few things from our firebase library you know so for example earth or fire store but the thing that we need to look at here is this handle user profile utility function now we call this after a user has been authenticated within our website right so whenever this is cold we're passing in a user auth object and this is what we get back from firebase whenever a user signs into our application all right so this user oath object contains the users ID right which is a UUID and what we do is we check our users collection here and we find to determine if the user exists within our database because we're trying to find out here is if the user is just returning and is signing in to the application or if they're a new user and they don't currently exist within our users collection within our firebase database and then what we do is if they do not exist we know we need to store their information and register them in our database so what we do is we we then create a new request to actually add that user and their data to our firebase now currently we are restructuring from the user oath object the display name and email and we're generating dynamically the the current date the current timestamp and then we're sending that information with any additional data that might have been passed through to this function and we're sending that to our to firebase and var fire store and we are actually storing that data in our users collection now this is where I am going to add our user roles array because this is going to be a static array it's never going to change and it should only ever assign a particular the user role to normal users that sign up using this flow so it's pretty safe for us to just create a constitute all user roles which is going to equal an array with a user role assigned to it and then all I'm gonna do is I'm just gonna pass this user roles array into the object that we're sending firebase whenever we sign up a new user to store them in our database right so now what I'm gonna do is I'm gonna head back over to my browser click on register and I'm gonna register a new account so I'm just gonna call this one so this guy is gonna be cold Jack black and let me say Jack Black at gmail.com into a password and we're gonna register and I'm gonna be signed up to the application and signed in at the same time but I'm gonna come now over to firebase and as you can see in real time a new documents being created their information is here as we entered it with a timestamp but we also have this user roles array which has the user role assigned to it okay so before we go any further let's just remind ourselves how we're currently restricting access to pages so to do that let's head over to FJs this is where we define our routes and currently we're aware we are restricting access to this dashboard route and to do that we're using this with auth hi order component and what this does is it just it's a very simple higher order component a higher order components just a component that makes it change and then returns that component so what we're doing in this case is we're we're actually cooling this custom react hook called use auth and we're grabbing inside of this hook we're grabbing the current user that signed in to the application and if they're not signed in this is actually no by default but we're grabbing that from the Redux store and then depending on if it exists or not we're either redirecting the user to login or we're returning the current user which is then used to render the the page component the page that we were restricting access to so what we need to do to restrict access to pages based on admin only access is actually very similar to what we're doing here but we actually need to create a new page that we want to restrict access to for admins only so within my pages folder I'm gonna create another folder called admin and this is just going to contain an index j/s file and a style sheet so we'll say styles dot s CSS and within the index dot J's file I'm just going to import react so I'll say import react from react and we also want to import the style sheet so I'll say import styles got s CSS and then we want to create our component so we'll just say admin equals it's gonna take props and we'll just return for now I just want to return a div and h1 which just says my admin and then we need to export that from the file so we'll say export to full admin ok so we actually need to be able to access this page so we need to create the route we can do that in apps yes the first thing we need to do here is just import the component so we'll say import admin from it will be pages admin and then I'm just going to duplicate one of these routes I'm going to duplicate the recovery route and what I'm gonna do is I'm just going to rename the path to admin and I'm gonna replace the component we want to render with at the admin component we just created and import it in the file above so now that we have that we can head back over to the web browser and because we don't have the link to this page anywhere in the application I'm just going to manually enter that into the browser so forward slash admin and I can obviously see and access the page currently we're not restricting access to this to this page in any way so that's the first thing that we're going to we're going to work on we need to create an additional higher-order component that works very similar to with auth so what we're gonna do is within my hawk folder which stands for higher-order component I'm gonna create another higher-order component called with admin earth jeaious and for now all we're gonna do is create a Const called with admin earth and that's just going to take props it's gonna be a function and for now we're just going to immediately return the children passed to it we're gonna do that but we're gonna have to do a bit more in this file shortly but for now I'm just going to export this by default so with admin auth so now within objects I'm going to be able to import that higher-order component so we're gonna say with admin auth from the higher-order component folder with admin auth and then I can take that and the same way I used with auth I'm gonna wrap my admin route with my higher-order component so notice here that I'm passing in these nested children these nested components to my heart of the component and for now we're immediately rendering them so if I come back over to the browser and I'm on my admin route and I can refresh this a few times everything is working exactly as it did before we're still rendering it but we are now using this higher-order component now currently this this higher-order component is not making any changes to the component we're not doing any kind of checks or anything like that we're just immediately returning the children so what we want to do here is we want to create a custom react hook what we need to do is we need to evaluate the current user we've to get the current user from a Redux tour we need to evaluate both that they're not only signed into the application but we need to also check that they have the admin rights assigned to their account and then based on that we will either redirect them away or we will we will we will allow them to access the page so to do that we need a custom a custom react hook in a similar way that we created our use auth react hook we need to do something very similar here for for our admin auth so I'm gonna create a new hook so I'll just create a new file within my custom cooks folder called use admin or j/s and within this file we need to import a few things from well we just need to import a few things so the first thing I'm going to do is I'm going to import from react and I'm going to import the user fact hook I then need to import something from react redux so we'll say import from react Redux and we to import use selector and to redirect the user we're also going to import from react router down the use history hook and then what we'll do is we'll create the hook itself so we'll say Const use admin auth which is going to take props and what we want to do is first of all we want to call the use effect hook which is going to take a function and we're going to pass it our current user as a dependency so to do that we need to actually get that from our Redux store so what we'll do is we'll say Const map state will create our map state function so what we'll do is we'll it will take the state but both the structure the user state from that and then we want to get the current user which will be on user current user and then to get that from the redox tour will simply say Const use selector and posit our map state function and that will give us the current user and then all we need to do is evaluate that current user object so we'll wrap that in a condition but what I actually want to do here is I want to create a utility function that will take the current user and and determine if the user is an admin so what I'm going to do is within my source folder I'm going to create a new folder called utils and in my Utah's folder I'm going to create index J s what we need to do is create a new function we're going to export it so we'll say export Const check user is admin it's going to take the current user and then we need to add some fullbacks here so the first thing I'll do is I'll check that the current user has been passed and then we need to also check that it is a valid that it the user the current user object has the user roles array so we'll say array dot is array current user dot user roles and if that returns and evaluates to false we are simply going to immediately return false right so that means that the user would then not have the rights to access that page or that content however what we will then do is we're going to grab the the users roles so we're just going to say Const and we'll D structure from the current user the user roles array right and then all we need to do is check to see if the user has been assigned the admin rights so to do that we're simply going to say if the user roles array includes admin and in that case we're gonna return true otherwise we're gonna return false okay so now that we've done that we can come back over to our custom use admin oath hook and what we need to do is import that utility function so we're going to import that from our utility file so I need to come out of that folder into utils and then we're simply gonna import check user is admin and if this evaluates to false right and remember we need to pass the current user here and if that evaluates to false we're going to use our use history hook here so we'll say Const history so we'll say Const history equals use history equals use history and we'll call that as a function and we'll simply call history dot push and we'll push the user to login and we need to make sure that we past the current user we need to make sure that we past the current user as a dependency otherwise we're simply going to return the current user which will then evaluate to true so we'll simply say export default use admin oath now although we can import it directly from this this file what I want what I want to do is within my custom hooks is I have this index at JS file which means I can just import all of my custom hooks from one place so to do that I import all of them here so I'm going to import use admin off from use admin auth and then I simply export it from this file and then what that allows me to do with it my higher-order component is when I go to import that custom hook so I'll import that from custom hooks I can just import it directly so I can say use admin or rather than having to go slash use admin or authorities or I can just import it directly from custom hooks and then all I need to do here is just pass this in so I'll say use admin auth I'm gonna pass props and depending on whether this evaluates to true or false we will either redirect the user or we will render the children okay so now all we need to do is head over to our web browser to test this out so head over to my web browser and let's try to access our admin route and as you can see I'm redirected away to login but there is one last thing that we need to do right so we need a way of actually we need a way of allowing a user to easily access the admin route they shouldn't have to you know manually enter the admin route in in the browser right there should be a link so what I'm gonna do is I'm gonna create a toolbar that has a link to the admin page on it and maybe in the future we can add some additional links there too so that is just gonna go at the very top of the browser and only admins when they're signed in are going to actually see this this toolbar so what we'll do is we need to come back over to our application and what we will do is we'll create a new component so we'll create a folder we'll call it admin toolbar and it's just going to contain index J s and a style sheet so Styles s CSS and all we're going to do here is we're going to import react from react and then we'll create our we need to also import our our style sheet so I'll say import Styles s CSS and then all we need to do is create our component so we'll say Const admin toolbar which will take props and what we're gonna do is we're going to return something for now I'm gonna create a div give it a class name something like admin toolbar and that's going to contain an unordered list with a list item we only need one and then for now we can just export that as well so what's the export default admin toolbar and I need to basically create a link here so I'm gonna import something from react router dumb which is going to be the link component so here I can say link the text is just going to be my admin and we're going to direct the user whenever they click this to the admin route so it's pretty simple at this point let's actually add this to our our page for now so what I'm gonna do is I'm gonna come back over to app J s because I want this to be visible regardless of what route they're on I want it to be separate from the layout or the design of the page it literally has to be just a bar that literally sits at the top of the page so at the very top of this file I'm just gonna have a new section which imports components and I'm going to import the admin toolbar from that component I just created so I'll say it's gonna come from components and admin toolbar and then just above my switch component here I'm going to render out my admin toolbar so now if I come back over to the browser you're gonna see that I have this link okay so there's two things that we need to do here we need to number one we need to style it and number two we need to conditionally render this component this should only appear if the user is signed in and they are they have admin rights so first of all let's just style this so let's come back over to my admin component my admin toolbar component the first thing I'm gonna do is I'm just going to target the admin toolbar class that I created I want it to be display:inline-block we'll set a width of a hundred percent we want the background color to be black we'll set the height to also set the margin to zero also and we want some padding on either side to match the margins and of the website so we'll say a padding:0 there is zero top and bottom and ten pixels on the left and right then we'll just target the unordered list and the list items we'll set the list style type to none but we'll also reset the margin and padding both to zero then we're going to set the unordered list here we're going to float to it right we want to set the list items to be display inline block and we're going to target the individual links we want those to be well display look but we want the font size to be something like 1.6 REM which is 16 pixels we want the line height to be 1 we'll set the color here to white but we'll add padding of 10 pixels all around I'm also going to add a transition here something like 0.4 seconds he's in out but I'm also going to target the hover state because what I want to do is change the color the background color I'm going to say RGB a to a white but we'll set an opacity to something like point 6 and I'll change the color here of the text to black and also I want to take the same transition for the hover State cool so let's head back over to the browser and just look at what that's done so as you can see now we have this admin toolbar here it looks pretty nice having horror effect that the user can click and it would take them to their admin page if they were signed in as an admin so currently I'm not signed in as an admin so I can't access that page so if I'm so if the user is not an admin or they're not signed in to the application they should not be able to access this route and they should also not see this toolbar so to do that what we need to do is head back over to our our text editor come back over to our admin toolbar component and the first thing we need to do is we need to get the current user from our Redux store so we need to create our map state function which is basically just going to take the state from the redux tour wildy structure from that the user state and then what we'll do is we'll return the current user from user Laurent user and what we need to do here is we also need to import something from react Redux which is going to be use selector which is a Redux hook and we're going to use that what we're going to do is we'll say Const and we'll call you selector and posit map state or map state function that will give us back the current user and all we need to do here is just determine if the user is an admin or not so we'll say is admin and all we'll do is we'll just we need to use the utility function here called check user is admin which we created earlier we're going to import this into our admin toolbar so I'll import that here so we'll say import from our utils file and it's cold check user is admin we just want to pull that and pass it the current user object and then we'll just have an if statement here which will say if the user is not an admin return no so what that means is that if the user is not an admin the whole component is not going to render so I'm just gonna reload this a couple of times and as you can see that works just fine okay so let's now sign into so if I actually look at my users collection I have two users right so I have Jack black who is a normal user and I have Joe Bloggs who is an admin so what I'll do is I'll sign in to both of those accounts and I'll see if I can what I see in what I can access so first of all is login to our admin account so that's Joe Bloggs at outlook.com I'll enter the password click on login and I'll be logged into the application I can also now see this admin toolbar which has a link to the admin I can click on that and I can access the admin route so I can also then log out of the application and the toolbar will be will be removed let's now sign into a normal user account so that's Jack black at gmail.com I'll enter the password let's sign in and as you can see on signed into the application but I'm not I'm not able to see the admin toolbar and I'm also not able to access the admin route now before we finish this tutorial I just want to make one small code refactor so currently we have two types of higher-order components one is called with auth and this is used to restrict access to normal pages and another which is called with admin orth we just created this and it's used to restrict access to pages with 42 users who have admin rights now if we look at how we handle are with earth which is a higher-order component we created in a previous tutorial in order to redirect the user within our use OAuth hook here and I can look at that if I go into custom hooks use auth what we did was we used with router from react router dumb to pass the history into this custom hook so that we could push the user to the login route we don't need to use that so what I'm gonna do is a small refactor instead of exporting this with router I'm just going to go ahead and export you with auth we don't need to import react router Dom here either and I'm going to come back over to use auth because we still need to push the user to the login route in this case but to do that I'm going to import something from reacts router dome which is the use history hook I'm then going to be able to create an instance of I'm then gonna be able to access history so I'll say history use history like that and then we can simply remove props as we have access to history directly within our custom react hook and that brings us to the end of this video tutorial this was the tenth video in this series on building an e-commerce website but before I ended I just want to remind you guys that there is an official github repository for this project which you can find in the direct link to in the description of this video and I also want to ask you guys to subscribe like and comment on these videos and of course don't forget there is an official playlist for this series so if you which is just a really easy way for you to find previous videos but also find the next video that I will be posting for this series once again thank you for watching please subscribe and I'll see you in the next one
Info
Channel: SimpleTut
Views: 7,353
Rating: undefined out of 5
Keywords: ecommerce, react, react redux, GraphQL, React Context API, Node, Node JS, redux, online store, stripe, stripe api, shopping card, paypal, firebase, react router, react router dom, routes, routing, Google Sign-In, Google Auth, Google Sign In Authentication, login, signin, react hooks, useEffect, useSelector, useDispatch, redux hooks, useState, redux saga, saga, user roles, admin backend
Id: _tw5lvIp59o
Channel Id: undefined
Length: 35min 9sec (2109 seconds)
Published: Sat Jun 13 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.