Afolabi Olaoluwa Akinwumi Afolabi Olaoluwa Akinwumi - 2 months ago 5
Ruby Question

How to make my RESTful show action show token instead of ID

I created a website with Ruby on Rails, which I believe is vulnerable and easy to scrape since ids are shown in the URL.

When I click on each lawyer which is managed by my

show-action
in my controller, the RESTful url shows http://localhost:3000/lawyers/1. The 1 in this case is the ID of the lawyer on my lawyers table.


Question:

How do I show token instead of id when a particular entry is viewed
with show action? Such the I have something like http://localhost:3000/lawyers/92a5e084-d660-41a7-98d7-cb8075797591


Note

Every lawyer on the lawyers table has a unique token.

Here are my code:

lawyers_controller.rb

class LawyersController < ApplicationController

before_action :get_lawyer, only: [:show, :edit, :preview, :destroy]


def show
respond_to do |format|
format.html # show.html.erb
format.json {render json: @lawyer }
format.xml {render xml: @lawyer }
end
end


private

def get_lawyer
@lawyer = Lawyer.find(params[:id])
end


def law_params
params.require(:lawyer).permit(:name, :category_id,
:image, :title, :category_id,
:phone_number, :website, :email,
:twitter_link, :linkedin_link,
:professional_details, :published,
:token, :remove_image )
end

end


route.rb

Rails.application.routes.draw do

mount RedactorRails::Engine => '/redactor_rails'
root 'lawyers#index'


resources :lawyers, except: [:index, :new]
get 'lawyers/:id/preview' => 'lawyers#preview', as: :preview_lawyer
get 'new' => 'lawyers#new', as: :new
end


lawyer.rb

class Lawyer < ActiveRecord::Base
belongs_to :category

mount_uploader :image, ImageUploader

validates :image,
:name,
:title,
:category_id,
:website,
:email,
presence: true
validates :professional_details, length: { minimum: 300 }
#validates :website, format: URI::regexp(%w(http https))

validates_formatting_of :email, using: :email

before_create :add_token
before_save :format_lawyer_url



def its_published?
(!(self.published == nil))
end


private

def add_token
self.token = SecureRandom.uuid
end

def format_lawyer_url
unless website =~ URI::regexp(%w(http https))
add_http_prefix
end
end

def add_http_prefix
if website
self.website = "http://#{self.website}"
end
end
end


schema.rb

ActiveRecord::Schema.define(version: 20160909121118) do

create_table "categories", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "parent_id"
end

create_table "lawyers", force: :cascade do |t|
t.string "name"
t.string "image"
t.string "title"
t.string "email", default: "", null: false
t.integer "phone_number"
t.text "professional_details"
t.string "website"
t.string "twitter_link"
t.string "linkedin_link"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "category_id"
t.string "token"
t.boolean "published"
end

add_index "lawyers", ["category_id"], name: "index_lawyers_on_category_id"
add_index "lawyers", ["email"], name: "index_lawyers_on_email"
add_index "lawyers", ["name"], name: "index_lawyers_on_name"
add_index "lawyers", ["phone_number"], name: "index_lawyers_on_phone_number"
add_index "lawyers", ["published"], name: "index_lawyers_on_published"
add_index "lawyers", ["token"], name: "index_lawyers_on_token"
end


Note: As suggested from the comments below, I have tried solutions posted there. i.e. Route Post#TOKEN instead of Post#ID in rails but I will not go with it.

Why?


  1. It makes my code error prone.

  2. My interest is only to show
    token
    on my show action and not
    id
    .

  3. The last answer which suggested I overwrite the to_param method in the model, works using this:

    def to_param
    "#{id}-#{token}"
    end


    but still doesn't make my code not vulnerable to parse by Scrappers.
    Any tech savy guy could easily copy the database table because it still adds the
    id
    .


Answer

This is what I used to solve the problem:

In my model, I overwrite the to_param method such that I append it to token:

  def to_param # overridden
    token
  end

Though still leaves me with a tricky bug of NoMethodError in Lawyers#show when I go to vulnerable URLs such as http://localhost:3000/lawyers/7 which corresponds to showing lawyer with id 7.

I afterall had a better solution using this Railscast Revised Video: https://www.youtube.com/watch?v=963wTp9FCn4

Comments