AVO Internal tool. Authentication, Invitations, Roles, Tests | SupeRails #217

03/12/2024
avo
  • Create new Rails 8 app
  • Install Avo
  • Rails 8 authentication generator
  • Only logged in users can access Avo
  • Generate Avo CRUD resources (User, Session)
  • User Invitations
  • Only Admin Users can access Avo
  • Handle signed in non-admin users
  • Add tests
  • Summary

If you want to build an Internal tool, or Admin dashboard in Ruby on Rails, there is no better tool than Avo.

If you are building an internal tool, you don't need User registrations. You will want new users to join only via Invitation.

0:00 Create new Rails 8 app
1:31 Install Avo
2:45 Rails 8 authentication generator
3:55 Only logged in users can access Avo
7:42 Generate Avo CRUD resources (User, Session)
12:22 User Invitations
15:55 Only Admin Users can access Avo
20:43 Handle signed in non-admin users
25:00 Add tests
27:57 Summary

✅ Install Avo
✅ Rails 8 authentication
✅ Only logged in users can access Avo
✅ Generate Avo CRUD resources (User, Session)
✅ User Invitations
✅ Only Admin Users can access Avo
✅ Test coverage

Usually I try to make my videos shorter, but I really wanted to go through each problem you might have with Avo or Rails 8 authentication.

Episode source code

Avo resources:

Transcript
Hello friends, they all love rubber burn rails 'cause it makes building web applications much faster. And AVO is a layer on top of rubber burn rails to make building applications even faster. So AVO is especially popular for building, uh, uh, admin dashboards and for building internal tools. And in this episode, they're going to start getting acquainted with vo. They're going to, uh, install VO on a user application. They're going to make it so that only internal users can access VO and users can be created only via invitation. So an admin will be able to invite users to join their application and access their vo uh, uh, dashboard. Let's start by creating a new Ribbon Rails application. Let's check our Ruby version, Ruby version 3.2 rails, version eight. Wonderful. We're going to use the latest version of Ruby Rails. So, um, let's start with Rails. New avo, CRM. We don't need to select the, uh, CSS framework like Tailwind or Bootstrap. They're just going to use what is included in avo. Okay, cd, avo, CRM. Let's open the application. I will say rails. The B grade, the B my to create a database. And let's save our changes. Get add all, get com, uh, message create app. Okay, wonderful. Now let's install VO in our application. So I'm just going to run this command and it's going to add GEM to the GEM file. It is going to add the other roots and it is going to add an other in initializer. Let's start the application and, uh, have a look. So, uh, going to our roots, we now have, uh, mount other engine at VO configuration root path. And if you go to avo, rb, the initializer that was just created, we have this, uh, VO configuration root path that is slash vo. So if you go to our new created application and go to slash vo, here we have access to the basic VO dashboard. But at the moment the dashboard is well empty. Okay? We have done the basic installation of, uh, vo, we can exit at slash vo. So let's, uh, save our changes, get add all, get com message, uh, install vo. Okay, now let's make it so that only authenticated users can access Apple. So they're going to start with adding the authentication and they're going to use the Rails eight authentication generator. I will say Rails generate authentication. It'll give us a bunch of files. Uh, by default I will say rails, the B migrate. And, uh, let me just restart the server just in case. So now we have our route. If we go to slash uh, avo, we still have access to avo. And if we go to slash session new, we have the, uh, registration or authentication. We don't have registrations by default in the rails authentication generator. So we can send into an existing account or we can reset our password just to authentication features by default. Okay, let's, uh, save our changes, get status, get at all, get commit message rails, generate authentication. So going like by small steps. Okay, now let's make it so that only log in users can access vo. So if you go to a guide, an official guide from VO have this, uh, way of making VO work with the rails authentication generator. So we can go to our vo uh, IB file. And here we have this authentication part here. I'm going to say config current user method is current user. And I'm going to set the sign out path that is going to be session path. Okay, let me restart the app and uh, navigate to av. You see, I still have access to ava, though I'm not, uh, logged in. I have also the sign out button, but it'll really do nothing. It'll just redirect me to the sign in page. So I still have access to ava though I'm not, uh, sent in. Going further inside this, uh, uh, documentation, we have, uh, the option of creating this AVO application controller. So I'm going to generate the file. We have created the controllers slash avo slash application controller, and inside this file we need to add, include authentication. Authentication is this authentication file that was generated with the, the rails authentication generator and require authentication to access Ava, all the AVA controllers. Okay, let's, uh, refresh. And you see we have this undefined local variable new session path in the request authentication. Let's find it. Um, dev request authentication. So redirect to new session path. I will need to say main app, new session path. That means demonstrate. So here, new session path doesn't fe but if you make it, uh, main app, new session path, it works. So inside VO controllers, everything is named spaced within VO by default. And we need to say main app dot, uh, root name. Let's, uh, refresh one scan. Okay, so now when we go to slash vo, we get related to the sign in page. Now let's actually sign in. Uh, at the moment we don't have any users and we'll need to create a user programmatically. So I will say user dot create email address. It's not email, it is email address. If you go to the schema visit that we have users with email address. So it is the default name of the user email field. It's going to be like ya@superrails.com and password is going to be now 1, 2, 3, 1, 2, 3. Okay, we created the user. Let's try signing in, sign in and wonderful. I am, uh, logged into vo. So as a send end user, I can access uh, VO as a not send end user, I cannot, uh, access vo. It seems to be broken. Let's, uh, save our changes. Let's just see get status. Uh, Okay, uh, let's, uh, say get add all, get com message, uh, require authentication for Apple. Okay, let's go, uh, further. So, uh, at the moment when we are logged in, let's look in again, we just have this, uh, default dashboard. We cannot do anything. They're going to generate the, the views and uh, uh, the possibility to like edit or delete or create users and sessions. These are the two models that we have in our application. Let's go to, uh, our models. So in Apple models, we have, uh, user and session two database back to models. And we are going to generate the other resources for them. Now, if we run rails, generate help, we have all these, uh, commands and, uh, if we have VO installed, we'll also have the VO prompt commands here. So we are going to generate all the resources for vo, we'll just say vo all resources rails generate other all resources. It'll create a resource for session and for user. Let's have a look at our, uh, our folder. Now we have the current file. It is empty. It is not database backed. We don't need it. We have session. So session has, uh, basically all the fields that we have here. Uh, and user has id email address, uh, and sessions. You see, a user has many sessions. It's set as has many. And, uh, session belongs to a user. Let's, uh, open our application. Let's actually restart the application and see how it looks. So you see we have two, uh, tabs now in our sessions and users, if we go to users, we have the list of users at the moment, just one we can view, edit, or destroy the user. Let's view the user. You see, the user has, uh, one session at the moment. Let's open the session. You see it has user ID and it belongs to user. This is not clickable, but this one is, let's go to our session and, uh, remove this field. Okay, yeah. So session belongs to user. We can click and file, navigate within our application, create sessions, create users. Let's actually try, uh, deleting, uh, session. So, uh, I will open the session Destroy. And now, uh, I have destroyed the only session, the current session of this user. So if I refresh the page, it sends me out. So deleted a session, can sign out anybody remotely, and it's a wonderful, uh, feature of, uh, session based authentication that ships with Rails eight. Okay, let's sign back in. And yes, we have generated our sessions, uh, okay. And find local variable method root, URL. Uh, we don't have a root URL in our application, so let's go to our roots and, uh, set it to be, uh, sessions new. Okay, so let's, uh, try again. I will try signing in. I have signed in, but uh, I, uh, don't see that I have signed in and I wasn't directed to slash Ava. So let's, uh, say that, uh, if a user is sent in, he is going to be directed to vo. I will go to our sessions controller, and here in new action I will say redirect two. Uh, we're going to redirect to the VO root path. I think we have it here, VO configuration, route path, uh, if authenticated. So now if I go to Session U as a logged end user, it drives me back to avo. Uh, okay, let's, uh, uh, try signing out. I, uh, just go to session u, sign in again. Okay. And the assigned end user is directed to Ava. So it works well. We have generated the resources and the assigned end user is automatically redirected to Ava. And we have set the default, uh, uh, route to the new session or to the kind of login page. Okay? Uh, as a next step, let's make it so that we can invite users to the application. So, uh, we have users and we want to invite the user by typing in the email. And the user should receive, uh, an email so that he can set his, uh, password and access that application. So let's say like, uh, fu@bar.com, let's, uh, click save, invite the user. And you see password cannot be blank. And, uh, well, the user is not created, was not invited. So let's go to our user model. And um, here we are going to, uh, set a random password for the user while we are creating his, uh, entity. So let's say, uh, before validation, uh, set password on grade. So when we are kind of creating the user account and user accounts can create only via invitation in our application, we are going to set a random password. Let's say private, uh, set password, uh, sell of password equals secure random hex. Okay, let's try creating this user again. Okay, so you see the user has been, uh, created, but, uh, well, he has been set a random password and he doesn't know that he has been invited and he doesn't, uh, have the possibility to log in. So we are going to actually send the user, uh, reset password. The email, remember, uh, we have the reset, the forgot password feature automatically included the when the create the rails a authentication. So we are just going to invite, uh, him to set a password. Let's, uh, try it. So here, uh, how does this reset password work? If we go to our mailers, we have this password mailer. It sends a reset password email. Let's see how it is invoked password mailer, reset, user deliver later. Let's go with this. And they're going to use it in our user model. So, uh, I will say, uh, after create commit, do password mailer reset, the user is self deliver later. So whenever a user is invited to the application, he will get a password reset email, and he'll be able to click on the link and, uh, lo set a password and log into the system. Let's, uh, check if it works. I will, uh, go and create a third user. Click on create. And in the logs we should see an email. Yes, we have the email. So you can reset your password within the next 15 minutes. Let's, uh, go with this reset password link. I will, uh, click on it. I will set a password. Save. Okay, I have set a password. Let's try logging in as this, uh, user. Okay, so I have logged in as this third user. So I have, uh, basically added an invitation, uh, system to our application within AVO in, uh, just a few lines of code. It is, uh, I think quite amazing. Now, let's go, uh, step deeper. Let's say there are users that can be logged in but cannot access avo. So only a user that is, uh, an admin can access, uh, all the AVO features like, uh, using invitations and so on. Uh, how can we do it? First of all, let's, uh, uh, create a new field on the user model, uh, admin that is either true or false. So a balloon and, uh, make it so that only users that have the admin set through can access. Uh, a, let's start with the saying rails. Generate the migration, add admin to users, admin, bullying. Okay, let's open the migration. Add admin to users. I will, uh, say, uh, default, false and null. False rails migrate. Okay? Now, uh, let's, uh, see how can we make it so that only uses the admins that the admins can access. A let's, uh, also display like for the uses an admin or not in the other dashboard. So, uh, I will go to AVO resources user, and here I will have another field, uh, admin as bull. I will refresh. And you see I have just, uh, added this small line here. And obviously whether the user is an admin in the index view in the show view, we can edit the user admin to be true or false. Let's set ourselves, so this third user to admin. Okay? So this user should be able to access, uh, AVO and this other user that is, uh, not an admin should not be able to access. So there are a couple of ways we can do it. The first way would be in our roots, we can add a constraint, I would say constraints, uh, Lambda, um, request, uh, and current user, uh, admin. So if, uh, there is a current user and if he is an admin, then he should be able to access, uh, other rules. I will refresh here. You see, the route is not found because this user is not an admin. And here, uh, okay, this user should be able to access. Um, uh, let's try not. Okay? So this works. Okay, maybe constraints isn't the best way, but, uh, a good way definitely will be in this, uh, VO controller that we have previously generated. So let's go to avo, uh, application controller. And here in this a application controller, we are going to say that only admin users can access avo. So I will say before action, ensure admin or authorized admin drive it, dev authorized admin, and uh, yes, direct to uh, uh, yes, let's say route path or main app path, let's say root path, unless, uh, uh, current user is an admin. Okay, I will refresh. Uh, okay, both users cannot, uh, access at the moment. Let's see why. Yeah, so both users cannot access at the moment because I didn't, uh, remove this, uh, constraint from the rules. So, uh, let's try again. Okay, so here I have too many redirects and here the admin user can access, uh, avo. And this other user, uh, is getting too many redirects because he can access avo. He gets redirected to the, uh, what path to the root path. The root path is uh, uh, our sessions, new path. And from sessions controller, uh, we direct to our, so it's, uh, an endless redirect. So we don't want this endless direct. We would want, uh, some kind of, uh, fallback, uh, location for users that are sent in, but they're not admin, so they cannot access. Uh, so let's create a new controller for this. I will say rails generate controller, a static, and it'll have an action index. Okay? And, uh, let's say that, uh, they're going to set the route URL of our application to be not, uh, uh, sessions new but static index. Okay? And, uh, next step, uh, we will, uh, do what we will redirect in our AVO application controller, uh, to main app, the root path. Okay, let's see if this works. Okay, so now, uh, here I have access to avo, and here I redirect it to the root path. Now, let's also add some buttons to see if the user is, uh, logged in. I will, uh, go to something I've done before authentication, and I'm going to go with some, uh, uh, lines from here. So going to application do, uh, html, EER B here, I will just add all these, uh, uh, links. Let's see if, uh, it works. So undefined method, dashboard path, it'll be not dashboard path, but it'll be our, uh, AVO configuration route path. Okay? So let's see. Now I see that I'm logged in. I have, uh, a link to the homepage. I can sign out, I can click on dashboard, and, uh, well, nothing happens because I have no access to dashboard. Let's also run the flash messages. I will say files notice and equals alert. Okay, so I click on dashboard, uh, maybe I need to restart, uh, the server. Okay, so homepage, dashboard. Yeah, actually I need to add a flash message. Uh, alert, not authorized. Okay? So go into dashboard. And you see I get this not authorized alert. And here if, uh, I go to, uh, the root path, you see I have this, uh, authenticated page and I can click on dashboard and I'm directed to. Okay? So I think everything kind of works. Uh, uh, now let's try signing out just in case. And, uh, I get this, uh, undefined new registration path. Uh, let's see. Yeah, because we don't have registrations, I don't need that. Okay, so now I'm not logged in. I can click home dashboard, sign in. I am always on the sign in, uh, page. Can I go to the static, uh, index page? No, I cannot. Let's make it accessible for any user. So I will go to static controller, and here I will, uh, allow unauthenticated access. In the our authentication. We have the thin for allow unauthenticated access. I will just edit for the whole controller. Now, I, uh, refresh. Okay? And now like all users can see this, uh, screen, uh, but only, uh, sending users can go to the dashboard. Let's try sending in. Okay, I'm sent in, but I'm not authorized to exit the dashboard and let's make that user actually an admin. Okay, now I go to dashboard and voila, finally, I have access to the dashboard. Now we have identified some, uh, authentication logic into our application. Let's write some tests. Static controller test. And it's going to be actually quite, uh, easy. Let's, uh, first of all, test that, uh, just getting the root URL or the application works get root URL as such response success rails test. Okay? And now an user that is not authenticated should not be able to access, uh, vo and the VO route is AVA configuration Route path. So get the VO configuration, route path and assert redirected tool, uh, slash sessions slash new. It's actually slash session. Let's test again. Okay? And now let's, uh, uh, authenticate a user. I will say user equals users one, it'll access the user fixture and this one. And, uh, I will log in with this user. So I will say post slash session, Ram's email address. And the password is, uh, just password. We see it here. And now we'll try to, uh, access other and, uh, uh, let's see what happens. Yeah. So, uh, we didn't do an insertion. Lets assert that the user is logged in, but he's not an admin. He cannot access ava. So, so success, it'll not work. It should be a redirect. So, uh, the expert success, but it was redirected the root path. So actually it should be a certain redirected to, uh, root path. Let's follow the direct and a such response success. So a final destination of the older redirects. Okay? And, uh, let's make the same user an admin and ensure that he can access VO user, uh, update admin. True. Let's again, get, uh, VO and set the response to be success. And you said it is not, uh, success, but because it tries to direct to the first, uh, of the roots inside vo. So if we try to get a route inside VO like, uh, slash vo slash resources slash users, if it try to get, for example, this resource, it should be successful rails test, okay? And it's successful. So just with a couple of, uh, lines of tests, we have, uh, tested the whole, uh, other integration in our application. And basically now we have a small application where, um, users that are not signed in can see the homepage and they see the sign in page, they can, uh, log in and the users that are logged in and that have their admin rights are automatically logged into their admin view. Here, a user is also an admin. Let's make, uh, one of the users not an admin. So I will, uh, revoke adding privileges. I will refer to this user's page. And you see he was, uh, redirected to the homepage and he gets that not authorized. So he cannot access the ever dashboard. And that's basically it. This is, uh, how I would be building the, uh, authentication into avo, uh, that you can use for any internal tools that you would like to build. So thank you for watching and see you in the next one.
0
Join the conversation
Sign in to access PRO lessons, access private repos, leave comments, create watch lists.
We collect your email address, name and username to create your account. We do not share your email address with anyone else.