User authentification and validation for Sinatra project
Tags: sinatra, flatiron, session
Published: 2021-04-05 00:45:23


Here I would like to share the process of building user authentication and validation in my Sinatra project as well as share resources I found helpful on this subject. 

Sinatra project for phase two of Flatiron boot camp among other functionality should be able to keep track of whoever uses our web application, keep track of it,  refuse user without proper username and password, and unable certain parts depending on the current user. 

###Building model for our User 
(in this project it will be Dispatcher)

‘./models/dispatcher.rb’
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ca5a36kafwe3p3kkvxik.png)

 Validations on the model:

Main attributes of class Dispatcher: username, passwords, and email must be passed when we are creating one. Also, they need to be unique and for email, a certain format must be followed. 


###Creating migration 
for our Dispatcher class

'./schema.rb'
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k4seoz5vnic4b8gyzxp9.png)

###Session and cookies
Requests come to our Sinatra app through HTTP which is a stateless protocol, each request is treated as an independent transaction that is unable to use information from any previous requests. This means our app will never be able to keep track of requests and responses. The only thing it will do is to match requests sent from browser with the right route in our *ApplicationController*. And this can be a problem since we don't want to have everything open for every user. This is where sessions come in handy, to keep track of users, through session objects.
The first step to do this is to enable sessions in our *ApplicationController:*
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fvrsa97159caqiaii2e9.png)
Now session object is available to us in every route of our Application through cookies. Sessions and cookies go hand in hand. Sessions as cookies are hash-like objects that store data. Sessions on the server-side and cookies on the user side (in browser). The client-side cookie data will be compared to the server-side session data to help the application what step to take.

###Sign up
Before we use a session our dispatcher needs to sign up or log in to our application. This will come as a request that will be matched with the route in our *ApplicationController*. 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6f6riwgjd7tc4fjvu650.png)
Here you can see the *logged_in* helper method but we will get to them later. Next, we will create an instance of a Dispatcher class based on the params hash our *ApplicationController* received via *post* request. And finally, we will use 'id' of that instance created to store it in session hash to keep track of the current user in our app. 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jhby0ypxb7rr1id5g499.png)
This is what the session would look like and how we can authenticate our current user:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1knxfgc7psiup7cwatmg.png)

###Log in
On the log-in route, we will do something different. Instead of creating a new instance, we would need to find one by username and if one is found we will need to check if the password in params matches one stored in our database. 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uu7as1258h4439b2h11p.png)

###Helper methods
We were using helpers methods to check if anyone logged in and to see who is our current user.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xatvmnqm7iru5hs1l2ac.png)
**logged_in** will give us the boolean value of session[:user_id]. Remember that falsy values in Ruby are 'nil' and 'false' all others are truthy (even empty arrays or strings). Therefore if no one is logged in we wouldn't set session[:user_id].
 
*session[:user_id]=@something.id*
*#=> nil*
*!session[:user_id]=@something.id*
*#=> true*
*!!session[:user_id]=@something.id*
*#=> false*
if someone is logged in:
*!!session[:user_id]=@something.id*
*#=> true*
**current_user** will use *find_by* method to match 'id' any instance of Dispatcher object with *session[:user_id]* 
If *current_user* is true it will return found instance which we can later use to grant or denied access from certain parts of our application.

###Clearing sessions
Log out from our application will be done by clearing sessions or setting *session[:user_id]* to **nil**. 
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/swnfxnb750n8fb8dkt2e.png)
Our application (session) is ready for new users to be logged in.