I'm new to Ruby and Rails, so I'm trying to do something that might be easy on other languages but I can't deal with it in Rails:
I have designed a couple tables in the database that match each controller and action name. That way, if I wand to administer special permissions for a user, I just ad the proper action to the proper controller in the database, and with the method check_permissions, I know if the user can execute the action or is redirected to a standard "forbidden" page.
So for example, here's my code for the users CRUD:
First I created a check_permissions method in application controller, which grabs the current action, user and controller, and checks authorization rights against the DB:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
include SessionsHelper
def self.check_permissions
remember_token = User.digest(cookies[:remember_token]) # encripto el token para poder buscarlo en la DB, ya que ahi se guarda encriptado.
@current_user ||= User.find_by(remember_token: remember_token)
redirect_to signin_path if (@current_user == nil) or (User.find_by_sql("select * from view_userpermissions where user_id = #{@current_user.id} and pagecontroller='#{self.controller_name}' and accion='#{self.action}' ").count < 1)
end
...
...
Then in each controller, I use the before_action :check_permissions filter to redirect the user in case is not authorized to access the required content:
class UsersController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
before_action self.comprobar_permisos
def index
@users = User.paginate(page: params[:page])
end
...
...
The code flow seems to work very well, but the problem is rails cookies hash is not recognized when before_action filter is called.
I also tried using session, but happens exactly the same.
The first thing that comes to my mind is that in Rails architecture, neither session or cookies hashes are instanced by the moment the filter is executed, and then when the application controller tries to access them, an error is displayed:
Routing Error
undefined local variable or method `cookies' for UsersController:Class
Rails.root: C:/Users/daniel.tenzi/proyectos/MicroEstudio
Application Trace | Framework Trace | Full Trace
app/controllers/application_controller.rb:11:in `check_permissions'
app/controllers/users_controller.rb:3:in `'
app/controllers/users_controller.rb:1:in `'
Routes
Routes match in priority from top to bottom
Helper
HTTP Verb
Path
Controller#Action
Path / Url
pagecontrollers_path GET /pagecontrollers(.:format) pagecontrollers#index
POST /pagecontrollers(.:format) pagecontrollers#create
new_pagecontroller_path GET /pagecontrollers/new(.:format) pagecontrollers#new
edit_pagecontroller_path GET /pagecontrollers/:id/edit(.:format) pagecontrollers#edit
pagecontroller_path GET /pagecontrollers/:id(.:format) pagecontrollers#show
PATCH /pagecontrollers/:id(.:format) pagecontrollers#update
PUT /pagecontrollers/:id(.:format) pagecontrollers#update
DELETE /pagecontrollers/:id(.:format) pagecontrollers#destroy
permissions_path GET /permissions(.:format) permissions#index
POST /permissions(.:format) permissions#create
new_permission_path GET /permissions/new(.:format) permissions#new
edit_permission_path GET /permissions/:id/edit(.:format) permissions#edit
permission_path GET /permissions/:id(.:format) permissions#show
PATCH /permissions/:id(.:format) permissions#update
PUT /permissions/:id(.:format) permissions#update
DELETE /permissions/:id(.:format) permissions#destroy
groups_path GET /groups(.:format) groups#index
POST /groups(.:format) groups#create
new_group_path GET /groups/new(.:format) groups#new
edit_group_path GET /groups/:id/edit(.:format) groups#edit
group_path GET /groups/:id(.:format) groups#show
PATCH /groups/:id(.:format) groups#update
PUT /groups/:id(.:format) groups#update
DELETE /groups/:id(.:format) groups#destroy
users_path GET /users(.:format) users#index
POST /users(.:format) users#create
new_user_path GET /users/new(.:format) users#new
edit_user_path GET /users/:id/edit(.:format) users#edit
user_path GET /users/:id(.:format) users#show
PATCH /users/:id(.:format) users#update
PUT /users/:id(.:format) users#update
DELETE /users/:id(.:format) users#destroy
empresas_path GET /empresas(.:format) empresas#index
POST /empresas(.:format) empresas#create
new_empresa_path GET /empresas/new(.:format) empresas#new
edit_empresa_path GET /empresas/:id/edit(.:format) empresas#edit
empresa_path GET /empresas/:id(.:format) empresas#show
PATCH /empresas/:id(.:format) empresas#update
PUT /empresas/:id(.:format) empresas#update
DELETE /empresas/:id(.:format) empresas#destroy
sessions_path POST /sessions(.:format) sessions#create
new_session_path GET /sessions/new(.:format) sessions#new
session_path DELETE /sessions/:id(.:format) sessions#destroy
root_path GET / users#index
signup_path GET /signup(.:format) users#new
signin_path GET /signin(.:format) sessions#new
signout_path DELETE /signout(.:format) sessions#destroy
But if my guess is true, why would Rails says routing error?
I've been stuck here at least a week trying to find anything that helps me move forward but no luck yet.
What am I doing wrong? Any help will be highly appreciated!
PS: I've seen auth frameworks like Cancan, but don't want to use any of that, this should be easier and more flexible.
Thank you!
...User.find_by_sql("select * from view_userpermissions where user_id = #{@current_user.id} and pagecontroller='#{self.controller_name}' and accion='#{self.action}' ").count < 1)can be rewritten as... ViewUsercondition.where(user_id: @current_user.id).where(pagecontroller: self.controller_name).where(accion: self.action)This is shorter, cleaner, easier to read and survives changing the database technology should you ever need to do that. - A Fader Darkly