Master Role-Based Access Control (RBAC) in Go: Complete Guide to Hierarchical Permission Mgmt. 2.0

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] [Music] so before we go we go ahead and start testing I would like to also show you how the regular user um the regular user role and or Scopes management can actually be implemented I'm just going to copy all of this here go to the regular user and dump it in and again I need to change this to call this regular um not admin not going to be an admin going to be regular user like this and change this again to new regular user and we that's so we're going to return return here and yes here here here yep so the the the difference more or less would be that for a super admin there's not going to be any restrictions more or less and so for a super admin the Scopes doesn't make sense I mean in in in essence because it's not going to be tied to them then organiz ation admin will be limited to their organization alone and what it means is that our or admins will have just one scope and that scope would be that for their organization that's it now but for a regular user that would be totally different so what it means is that there's going to be an array of Scopes and of course detailing what they have permissions and what they don't have permissions to access and so one we so what it means is that of course we can reuse most of this logic but what needs to change would be more or less what happens in here and to do that what simply means that we need to modify this query to accommodate the Scopes that will be in here and that's really all that needs to change and if you're wondering what this means in essence what this actually means is that we will need to write queries that look like this can say select everything from our DB I think I call the DB do example and now this is where the logic comes in we say some like where because again remember every single thing every single entity in application will have a scope must have a scope so whether be it users be it accounts be it whatever items they will all have Scopes so this will tell us where they belong more or less so we can now leverage this and say where scope um like and then this is where we pass our argument so in this case it's going to be of course we use this percent sign again and then we pass our first scope scope one like this and what it means is that we can now do an or and then we repeat this and we can repeat this as many times as we want so this is going to help us so if if this regular user example has four Scopes attached to them in the end our query over here is just going to look like this so each time they try to fetch users um we will always have this in the query so this this is really what the thought process actually is [Music] here to do this there are actually a number of ways we can go about it we can actually maybe come up over here and create a function um that helps us pass Scopes I don't know so maybe takes an array of strings and return a string in the end and so that way we can actually pass the Scopes and then it's just just going to return orinary tomor a really long um string that we can put over here or what we can also do maybe down here is to maybe look through our scopes so we look to the range of our user Scopes like this and then we simply do something like this I'm just going to copy this here and put this over here and then instead of this we replace this with our scope like this so that in the end we simply just return DB like this and we can again just copy this bring that over here and that's more or less it so what it means now if we can actually go ahead and get rid of this and I'm not going to go this route but I'll leave that for you to to try it out so but what it means is now if this user has five Scopes or whatever attached to them we can already do um something like this and modify this query before we actually interact with our database so this I think is a lot cleaner and um reduces the overhead of having to make a query first with the different to a different service and um get a response validates the response then check if the Reser actually has permissions before we actually perform the quer we want to perform I just feel this is an Overkill and that's why I'm taking this route so what I would want to do next is to actually go ahead we will create three users one will be a global admin an organization admin and a regular user and then we'll make queries when we assume these different roles for these different users and we make queries with their permissions and then we'll see what happens in the end so I think that should be the fun part so let's really jump into that right away so now that we have all of this set up we just need to go ahead and um use it more or less so if you remember if you go for example to our method for let's say let's go to um um maybe let's go to create user so if you you pay attention you see that after we validate the token that a user has and of course the request on everything we just simply get this client which is our DB client you can see over here another special just establish a connecting to our database and then we make our request this is really what we are doing and so but what we need to now now do is more or less to have all these rows that we Define wrap around the client so that it modifies the client depending on the permissions that a given user has so that way we don't have to go ahead and just use directly but we have our row WRA around it so this is this would be just one straightforward way of using the implementation we have so far and we're going to just do what we're going to do right now is just go ahead and set it up and use it and see how it works at the end and what this of course again means in essence for us is that most of these methods we have here defined on the user we will not be using them anymore because it doesn't allow us to again manage our app per permissions based on the Scopes that we've attached to a user and of course all the resources on our application um so yep the first thing I would want to do is I create a folder here and I can call this data manager and in here I have to create one for all our entities so we have one the only entity we have right now is our user so I can create one called user. go and package data manager and what this is going to do for for us is actually pretty straightforward so it's just going to establish or so what I've done now is to open our old implementation on the on the right and the new file that I created this is going to access our manager like it's going to wrap all the queries would ever need to make our use through our user entity and I have this on the left so we try to more less replicate what we have on the right on the L so the first thing I would want to do is I'll create a struct um that's just going to have us to more or less wrap the important objects or information or data will fi will be necessary for our query I can call this user manager I call be user query manager like this is going to be a struct of course and it's going to have a number of things it's going to have a table which is going to be a string it's going to have a user Ru model which is going to be from of type this it's going to have a DB which is going to be of course point that to DB um um it's going to have what else do we want so it's going to have um um user Ro which is going to be a string and it's also going to have user Scopes is going to be an array of string like [Music] this um so this is what it's going to look like um so now I will just create a function that's going to export this for us so I can call this fun new you user query manager is simply just going to return two things one will be our user query manager or an error I like this and so here of course I would like to provide maybe I Collapse this so we have some [Music] room and I like to of course provide our um DB and then I like to provide the user scope which is going to be an array of strings and then user row which is going to be a string and pretty straightforward we return our user query manager like this and of course um new so but before we do that I would like to do some validations so I can say if DB is equal to n or just to make sure of these are provided our user role if this is equal to nil or maybe if again if our user Scopes let's try to make this [Music] plural um if this is equal to maybe an empty array if that's ever the case then I want to return new sorry user query manager I would like to return this and an error and um so if it's an empty string like this um what is the arrow here yeah so if if this is equal to new this should be fine so we return this user so we return this and an error and here we can say something like the incomplete vales provided and I let you to get more creative with this anyways so now I can Define my role so this will be from user rules um this should be from user row. roll and now I can Define my row this way because I'm trying to ru. roll and then I want to pass the user r that was provided and from this I create my [Music] model and the possible error and this is going to come from row. row model so we call this function and then we pass our Scopes um like this um actually we need to pass let's see sorry so this should be user Scopes and now we can do some Arrow handling name so we say if this error is not equal to na then here again we return the user query manager like this and the error but of course if everything goes well until this point so now we can return back to the user so here I would like to provide the table I'm just going to hard code this for now so our table is called the boo. example and user Ro mod I'll pass the model and user Ru of course I have this here pass the user R and user Scopes I'll pass the user Scopes and DB of course pass the DB pretty straightforward so this one way we can have a wrapper over our um like what we have here on the right and now we can I can basically just copy a couple of this so I can maybe take this first one which one can I take um um so let's go to our users let go n two um is it this one no this API definition not sure not sure close out this ones close out this and so here we we actually making use of this get um method which is this one over here and so we can I can actually just copy this actually bring it over here and um dump it here um the only difference now would be this will not be pointing to our user but now it will be tied to this query manager more or less and of course I can just change it to table like this but the only thing now that needs to change more or less would be after the table after we provided the table now I would now like to make use of um all everything we've done until now so I I use the Scopes function and within the Scopes function I can come my user do um user r model and I call the pass user Scopes and inside of this um [Music] yes that's what it should be inside of this passing user Scopes I would like to pass my um let's see what the AR now I can actually close this one let's see what arguments look like so it requires a DB so now I provide my user. DB and I need to provide now my Bas base Scopes and and now I can and after the DB now I can actually pass um let's say my user. r model let's pass user permission read because I know if you get to this get end point you'll be trying to read um what we have so this is what the rapper would have over our initial query the one we read wrote initially so instead of just going ahead and make a query we would add all of this on top of it and I think this is pretty much elegant in my opinion if you ask me and so for now I'm just going to leave this for the get method only and then we'll try to of course come over here and at this point instead of just using this directly to make our query I would now like to create a new manager here and this would be our new user what did we call it um um we call it new user query manager so here I can have data data manager do [Music] new new user query manager and I pass the DB and so now I am assuming that we would get the Scopes and the rule of course either from the session or or from from the header of the request we have or maybe as the cookie or whatever the case may be and but just to maybe show a demo probably what I will do is I come over here I will Define some Scopes and this would be an array of strings and again I'll pass roll this would be a string and now I can quickly pass this here so my Scopes will be Scopes and my roll would be this R and I think this of course returns to T so we still do our error validation so maybe I can now get rid of this [Music] actually and nope that's not what I want but I can quickly copy this one over here and I simply just check my error like this so if this eror is not equal to n and then return but once everything goes well instead of this part I can actually now replace this part with my manager so let say. get and um one second yes I will s this this um find but I'm going to get rid of this and replace it with the manager so it's going to be manager. getet and I pass the DB and now now I do a find so this is more or less what it should look like and we're going to go ahead and test this out and see how it behaves and this request right now is not being used and I don't think I'll ever use it again because I don't really need this in my GS I don't care about any payload anyways so this is what it's going to look like so we just going to go ahead and test it and see if it behaves as we expected and I think before we do that we need to go ahead and create two three users with three different permissions and so I can bring up our terminal one more time so we can run our server and I can go to our HTTP one more time and then come over to create and now here I can create those three permissions so I have here I'm just first going to go ahead and delete what we have in the database so that we would have start with the Clean Slate so I can go ahead and start the server go run men men. go and when it starts I'm just going to go ahead and try to fet other users we have just so you can see that it's completely empty right [Music] now so our server is up and then we try to get all no I think we first need to do a login um we have some error yeah of course we don't have any user anymore so but I'll try to go ahead and create this user and now we get our users let's let's um let's look at the credentials so um here should be admin so this will be our first user actually so admin and the password is still password so we try to log in now and now we have our token and just going to copy it from here this is our token and I'm going to replace this one with the new token we have I'll replace this one so this will be our new token and now what we want to do more or less is to go ahead and create the other users that we need um actually I think we made a mistake because our Global admin is not supposed to have any Scopes so I'm going to delete that one again and then create a new one [Music] or I can actually just modify it in the database and remove the Scopes that's totally fine that's probably what I'm going to do yeah and yeah so I'm now just going to go ahead and create the other user so this admin will be my Global admin and actually I don't have any Global admin anymore so I'll get rid of this so I have a super admin so I need to reflect it in the name I call this um super the last name will be admin and the email will be super admin at um gmail.com password for all of them would be password so Scopes would be actually empty because we really don't need it for Global admin it doesn't matter so we create our super admin and is a success as you can see over here and now we need to create for our o admin um I think it was called H admin it just fine so here I just change this part to H admin again here will be OG admin and the email again is reflect that so OG admin and for this guy again we said it's just going to have one one um one scope which will of course be the organization of course we in this case it's just going to be assumed that we already created have a list of organizations because the groups need to if you remember the hierarchy we created the groups needs to be part of organization every single group so let's assume we already have a group called OG OG one more or less so that would be the only scope that this um OG admin would have so we can save this and now for our regular user call this regular um user um so the email again needs to reflect that regular user and gmail.com and this would be regular [Music] user and this regular is going to be a ties organization one so it's going to be in so I'm just going to copy what I had initially and then modify the results that's really I don't have to type everything out so I can just put this here and it's already there for us so just to confirm it's called regular user so close this up again so regular user and now we save we create this user again and is a success so we've created all the three users that we need so what we have to do now is to we try to log in as each of these individual users and then we try to make a query and see what we get and of course I'm going to use the um um insomnia so we can see the tokens and everything that has been persisted so let's go ahead and do that right away so before we start testing I just realized um we've made this we've omitted something actually in our setup and if you can already guess is that if we go to our user model you would see that even though we have rows defined and we have Scopes the user Scopes you define like the permissions the user can have that user that user itself has no scope with which it can be identified and I think this is also what I realize also in our queries of course this should work work with any other setup we have where that user has a scope but right now it doesn't and let's fix that and then we can start our testing so to fix that we can quickly just go to our models go to user and then basically add a new column for our user and I'm just going to copy this one and put it maybe above it and I can call it it will always be called scope for all entities and of course over here it will be scope it will be a string and the the colume name will also be called scope in the database so I'm just going to add this right away in the database and then we can of course continue with our testing that shouldn't be a problem but before we do that I would also like to modify the way we have defined our Scopes and rows we try to retrieve this from the user so what I would really want to do is actually just pist this information at login and this this will really add us in our test so I can quickly go to this pist cookie method we have over here and I add a new argument this is going to be of type models [Music] do user this one and my IDE is quite slow today for no justifiable reason uh okay so now I can copy this actually because I would like to p a couple more things two things actually so one would be user Rule and the next would be user Scopes and maybe also the scope of the user doesn't hurt nobody so I'll put here scope and this we can of course get from um our user do scope um the user row we can get from user do user Ro and user Scopes we can get from user do users Scopes and we want to stringify it of course and that should be more or less it then here we only need to just pass this user that we have up there so that's when you again will persist um this of course that's not a problem um and the next thing I would of course would want to do is to go to our guess method and then modify how we are retrieving these attributes so if you remember we actually had something like this um predefined initially but now I would want to make this U look like look more like what it should look like in the end so maybe I start with rose so I'm going to set this Echo to C that cookie [Music] and it should be called user rule um if we go back to our login and go to this speci it's actually called user Ro so we want to get it again it's called user Ro and of course it's also going to return an error I'm just going to forget about the error for now because I don't want this to take longer than it should be and for but again if you remember here um for the Scopes it was an array more or less but we had to persist it as a string but what I would want to do now more or less is to mure this again into our Scopes which should be a string which should be of an array of strings and because of that I change this to a this way and now I can over here I can say scope string I also throw this Arrow away please don't do this handle every error graciously so user Scopes and we have the string and what I would want to do now more or less is to J jason. Marshall again I'll first um turn this to bite so this would be my scope string and of course I'll now measure this into our Scopes like this this what I would want to do and so that should be it more or less so again we are getting this from from the cookies and now using this to instantiate our manager so now just want to again go ahead add this scope colum to our table and then we can just test this and wrap this all up I've gone ahead to make a couple of um modifications or queries so um because for for this for login I'm still I'm not actually making so much changes for now I'm just going to focus on our get which is like when we get new users so that's where we will test our our our back implementation but what I've done is I've added this new method here called get by email and it's doing not so much basically just query by email that's it and so and of course in login I've gone ahead to actually use that function over here and then we pass the email that we get from the query like this is pretty straightforward and so so that's the whole point is like I don't want us to focus on the log in so we can seamlessly log in provide an email we verify the password and then you're logged in that's totally fine um but the the focus of course for us will be when you try to fetch users and then this can of course be extended to any other resource you have fetched accounts fetch items whatever it is you would want to fetch in the end so but I think this is okay for now we'll just move over and test our three users again I've going to ahe to create a scope in the database and um um I'm just also going to show you all the users I'm just going to fetch all of them and show you what they look like um before we start working with them so let's go ahead and test and then we can see what happens what we can actually see how that works out for us at the end so we are right here in insomnia I have provided the credentials of the super admin so remember the super admin is supposed to have like golik permissions so you should be able to see everything so this would be the permission say the developers should have at the time of development and other than that you can actually just scrap those accounts so but we go ahead and log in as a super admin and then if we look at the cookies that gets per persisted for us you see um our scope more or less this is just um just some slash um because it has to see everything and then of course the RO is user super admin and again that's what we have over here as a token um these ones we had initially so again we have the token over here and then if we try to if this user tries to fetch all users if we send a request um the same URL you would see that he's able to see all the users so this would be the admin this will be the organization admin if you see for this um admin this is the path I can actually make this unique because I want all of the Scopes to start and end with a forward slash and I can quickly change that in the database right now and then we can just make a query again and see it's reflect the CH so like I make the query again and user Scopes one second should be here this is here so I just add this here I want all of them to start and end with um back slashes just for uniformity to avoid confusions so now if I make the query again we should say this here so this organization admin is able to see everything that is scoped to the root of this organization called aan and then we have over here this a regular user this regular user is only allowed to say things that are scoped to um to Europe um Germany Brin and then this group like within this account as well and of course we have a super admin here who can see everything so if you see over here the scope is just slash and then the user scope is that you can see can see everything so that's also what you see over here in the in the Scopes if we go to manage cookies that's also what you see over here so what I can now do is to go to the login and then try to log in again as a another user so now instead of the super admin I would like to log in as the or admin and I log in and now you see the credentials of course changes now it's H admin over here and no longer super admin and of course it's the same end point but because it's a different user with permissions that we've defined we get something different and then if we go to get users the same endpoint and we make the request now you see he doesn't even see everything he just sees um himself who happens to be the ug admin and of course the regular admin he's able to see the regular admin again because they belong to the same organization and he can see everything in this organization and of course lastly if we test for the regular user called regular user and login and now we see the same end point again just only that his his his permissions is just different if we log in login should be fine and then if we try to get users we should not actually see anything because from the permissions that this user have there's no user currently below this level so what it means is he's definitely not going to be able to manage any user because there are currently no users that he has more permission than more or less so he can edit delete whatever any any uses at all and that's really the goal and so like I said in the beginning I am actually have been more or less working on on a a an a library more or less that can be used um to of course manage um um permissions in an application so it's basically something you could instantiate and then have it of course um work be able to work with this more or less in your project but again I'm going to keep you post it when this is done and then publish it so that I can of course also get feedbacks from people and maybe also see how people are able to uh accept it and maybe use it in their own projects and anyways that will be all for this tutorial I don't want it to it's already getting too long but I really hope you got something um because for me the whole idea has Will has and will always be um more or less to try to improve it doesn't really matter if something works doesn't mean it can be improved um that's really the idea and for me again like I said in the beginning I want to I always like to squeeze out every form of speed I could for my application as much as possible and anyways that will be all for now and please if you if anything is not clear or you have questions of course feel free to leave them I will get back to you as soon as possible and of course if you're new to our Channel just go ahead and subscribe and of course turn the notification Bell and you will I can always guarantee you that I will always bring you like practical tutorials that you can use in your application doesn't matter the scale like they are real um practical Solutions which of I of course um in I of course use in my projects and anyways that will be all for now thank you so much for being part of this journey and continous them have a lovely evening and bye-bye [Music] [Music] n
Info
Channel: Easy Dev For All
Views: 156
Rating: undefined out of 5
Keywords:
Id: kiknmgH_WcM
Channel Id: undefined
Length: 37min 50sec (2270 seconds)
Published: Mon May 27 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.