Sinatra Application Building & Protecting

Posted by Todd Stoneberg on December 19, 2020

Sinatra has allowed me to create an application with a Domain Specific Language(DSL) using Models, Views, and Controllers(MVC). Basically, you can play with the application in the browser.

What my app does

The application is called the Hobby Gear App

It’s an app where users can log in/out, create, read, update and delete hobbies that will associate to the user and items that will belong to a specific hobby. All of these model objects will be stored in a database using Active Record.

My 3 models:

class User < ActiveRecord::Base
    has_secure_password
    validates :name, presence: true
    validates :email, presence: true
    validates :email, uniqueness: true

    has_many :hobbies
    has_many :items, through: :hobbies
end

class Hobby < ActiveRecord::Base
    validates :name, presence: true
    
    belongs_to :user
    has_many :items
end

class Item < ActiveRecord::Base
    validates :name, presence: true
    
    belongs_to :hobby
end

Our User passwords are encrypted with the gem 'bcrypt', which allows us to call the method has_secure_password. In order for this to work the password needs to be saved as a t.string :password_digest in the users table. With this gem no one will be able to view actual passwords that are saved to our database.

No bad data can be persisted into the database because of our Active Record validations written in our models. User must have a name, email, and that email must be unique. A hobby or item must at least have a name validates :name, presence: true. If someone enters bad data it will trigger error messages to display in the view.

My biggest takeaway

Making an application hackerproof

The has_many / belongs_to relationships combined with the helper methods help make the applications Views and Controllers hacker proof.

helpers do

   def logged_in?
      !!session[:user_id]
   end

   def current_user
      @current_user ||= User.find_by(id: session[:user_id])
   end
	 
end

All post, patch and delete requests are protected using

if logged_in? && current_user == hobby.user
     or
if logged_in? && current_user == item.hobby.user

These high level relationships allow us to make sure the User associated with the object and current_user are identical and have the permission to navigate to that View and/or Controller. All post, patch and delete requests must be protected in the views and controllers to make sure we can’t be hacked in the dev tools or through our routes.