You have a nil object when you didn't expect it - ruby

I’m interested in the topic of Rails security and using Security on Rails. I'm on Implementing RBAC /page 142/ and i cannot get past the error in the subject.
Here is the code:
module RoleBasedControllerAuthorization
def self.included(base)
base.extend(AuthorizationClassMethods)
end
def authorization_filter
user = User.find(:first,
:conditions => ["id = ?", session[:user_id]])
action_name = request.parameters[:action].to_sym
action_roles = self.class.access_list[action_name]
if action_roles.nil?
logger.error "You must provide a roles declaration\
or add skip_before_filter :authorization_filter to\
the beginning of #{self}."
redirect_to :controller => 'root', :action => 'index'
return false
elsif action_roles.include? user.role.name.to_sym
return true
else
logger.info "#{user.user_name} (role: #{user.role.name}) attempted to access\
#{self.class}##{action_name} without the proper permissions."
flash[:notice] = "Not authorized!"
redirect_to :controller => 'root', :action => 'index'
return false
end
end
end
module AuthorizationClassMethods
def self.extended(base)
class << base
#access_list = {}
attr_reader :access_list
end
end
def roles(*roles)
#roles = roles
end
def method_added(method)
logger.debug "#{caller[0].inspect}"
logger.debug "#{method.inspect}"
#access_list[method] = #roles
end
end
And #access_list[method] = #roles line throwing following exception:
ActionController::RoutingError (You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]=):
app/security/role_based_controller_authorization.rb:66:in `method_added'
app/controllers/application_controller.rb:5:in `<class:ApplicationController>'
app/controllers/application_controller.rb:1:in `<top (required)>'
app/controllers/home_controller.rb:1:in `<top (required)>'
I'm using Rails 3.0.3 and Ruby 1.9.2. I'm storing session in database. In finally thank you for every advise.

It seems like you can't access #access_list in method_added. I would try
class << base
attr_accessor :access_list
#access_list = {}
end
Might not solve your particular problem, but otherwise you won't be able to call #access_list[method] = #roles if your access_list attribute is read-only.

I'm not sure if this is the problem, but this looks suspicious:
class << base
#access_list = {}
attr_reader :access_list
end
Shouldn't #access_list be a class variable ##access_list?

Your defining #access_list as a instance variable of the class but your accessing it in as a instance_variable of an instance of the class. The following should probably work:
module AuthorizationClassMethods
def access_list
#access_list ||={}
end
def method_added(method)
logger.debug "#{caller[0].inspect}"
logger.debug "#{method.inspect}"
access_list[method] = #roles
end
end
If you need Auhorization you might want to check out Cancan by Ryan Bates
https://github.com/ryanb/cancan

Related

How to upgrade redmine plugin to rails 5, alias_method_chain is deprecated now

Story mode
Just started learning RoR, but in short period of time I need to add functionality similar to Loading images from LDAP (incompatible version) into our project. Project is abondoned, and I can't find any related info/docs, so I'm asking for help here. Solution, tutorial, anything could work.
Error log
$ ruby bin/rake redmine:plugins RAILS_ENV="production"
rake aborted!
NoMethodError: undefined method `alias_method_chain' for ApplicationHelper:Module
Did you mean? alias_method
...
Monkey patch that needs update
plugins\redmine_gemavatar\lib\application_helper_gemavatar_patch.rb :
require 'application_helper'
module GemAvatarPlugin
module ApplicationAvatarPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
alias_method_chain :avatar, :gemavatar
end
end
module InstanceMethods
def avatar_with_gemavatar(user, options = { })
if Setting.gravatar_enabled? && user.is_a?(User)
options.merge!({:ssl => (defined?(request) && request.ssl?), :default => Setting.gravatar_default})
options[:size] = "64" unless options[:size]
avatar_url = url_for :controller => :pictures, :action => :delete, :user_id => user
return "<img class=\"gravatar\" width=\"#{options[:size]}\" height=\"#{options[:size]}\" src=\"#{avatar_url}\" />".html_safe
else
''
end
end
end
end
end
My attempts / Articles
I've found good article here How To Replace alias_method_chain, but I'm not quite sure how to apply prepend style to redmine plugin's monkey patch. Just can't get it work :/
Is this related to this plugin?
If so, here is how I would do it:
In the init.rb file, change this:
RedmineApp::Application.config.after_initialize do
ApplicationHelper.send(:include, GemAvatarPlugin::ApplicationAvatarPatch)
end
To this:
RedmineApp::Application.config.after_initialize do
ApplicationHelper.prepend(GemAvatarPlugin::ApplicationAvatarPatch)
end
In lib/application_helper_gemavatar_patch.rb, change this:
require 'application_helper'
module GemAvatarPlugin
module ApplicationAvatarPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
alias_method_chain :avatar, :gemavatar
end
end
module InstanceMethods
def avatar_with_gemavatar(user, options = { })
# method content omitted for clarity
end
end
end
end
to this:
module GemAvatarPlugin
module ApplicationAvatarPatch
def avatar(user, options = { })
# method content omitted for clarity
end
end
end
I would remove the require 'application_helper' because I don't see why it's needed
I also tried to update this plugin. I used https://github.com/alexandermeindl/redmine_local_avatars as an example.
In init.rb changed this:
RedmineApp::Application.config.after_initialize do
ApplicationHelper.send(:include, GemAvatarPlugin::ApplicationAvatarPatch)
end
to this:
RedmineApp::Application.config.after_initialize do
ApplicationHelper.include ApplicationAvatarPatch
end
the patched lib/application_helper_gemavatar_patch.rb, looks like this:
module ApplicationAvatarPatch
def self.included(base)
base.send(:include, InstanceMethods)
base.class_eval do
alias_method :avatar_without_gemavatar, :avatar
alias_method :avatar, :avatar_with_gemavatar
end
end
module InstanceMethods
def avatar_with_gemavatar(user, options = { })
if Setting.gravatar_enabled? && user.is_a?(User)
options.merge!({:ssl => (defined?(request) && request.ssl?), :default => Setting.gravatar_default})
options[:size] = "64" unless options[:size]
avatar_url = url_for :controller => :pictures, :action => :delete, :user_id => user
return "<img class=\"gravatar\" width=\"#{options[:size]}\" height=\"#{options[:size]}\" src=\"#{avatar_url}\" alt=\"Gemavatar text\" />".html_safe
else
avatar_without_gemavatar(user, options)
end
end
end
end
I tried it only with Redmine 4.0.3 but it seems to be working. However there are warnings in the webserver log:
127.0.0.1 - - [06/Mar/2020:20:58:23 CET] "GET /gemavatar/164 HTTP/1.1" 200 3545
http://tredmine1:3000/users/164 -> /gemavatar/164
[2020-03-06 20:58:23] WARN Could not determine content-length of response body. Set content-length of the response or set Response#chunked = true
In the redmine_local_avatars plugin there was a different patch for Redmine 4.1.
Update: I set a up a github repository with the changes: https://github.com/pentekl/redmine_gemavatar
You can use alias_method instead of alias_method_chain, but I'm searching for something like prepend solution
alias_method :avatar_without_gemavatar, :avatar
alias_method :avatar, :avatar_with_gemavatar
UPD:
But it throws warnings:
/app/helpers/application_helper.rb:180: warning: already initialized constant ApplicationHelper
::RECORD_LINK
/app/helpers/application_helper.rb:180: warning: previous definition of RECORD_LINK was here
/app/helpers/application_helper.rb:199: warning: already initialized constant ApplicationHelper
::ATTACHMENT_CONTAINER_LINK
/app/helpers/application_helper.rb:199: warning: previous definition of ATTACHMENT_CONTAINER_LI
NK was here
/app/helpers/application_helper.rb:1053: warning: already initialized constant ApplicationHelpe
r::LINKS_RE
/app/helpers/application_helper.rb:1053: warning: previous definition of LINKS_RE was here
Exiting
UPD:
As ste26054 mentioned in his answer and commented here
require 'application_helper' can be deleted to prevent warnings, since it already included in the core.

undefined method for calling methode in class

i try to call my methode check_table_exists for check my table. This methode is on my module, and i dont understand why i get this error .
i know #connexion is a Mysql2::Client instance, which doesn't include the module Sgbd. but i dont see how to include my methode ?
./yamlReadFile.rb:44:in `mysql_connection': undefined method `check_table_exists' for #<Mysql2::Client:0x000000033a7750> (NoMethodError)
$LOAD_PATH << '.'
require 'yaml'
require 'rubygems'
require 'mysql2'
require 'creatDatabase'
#binding.pry
class StreamMysql
include Sgbd
def mysql_connection(conf)
#connexion = Mysql2::Client.new(:host => conf['ost'], :username => conf['user'], :password => conf['password'], :table => conf['table'], :port => conf['port'])
if #connexion
puts check_table_exists
#connexion.check_table_exists
puts "connexion etablie"
else
puts "error connexion"
end
rescue Mysql2::Error => e
puts e.errno
puts e.error
#connexion.close
end
def read_config_file
config = YAML::load_file(File.join(__dir__, 'config.yml'))
conf = config['database']
mysql_connection(conf)
end
end
my module file with the mehode check_table_exists
module Sgbd
# class ModuleCreateDatabase
def create_database
end
def check_table_exists
query=("SHOW TABLES;")
end
end
It’s unclear why would you want to include your module in the foreign class, but it’s doable:
Mysql2::Client.include Sgbd
The line above should be put e. g. before class StreamMysql declaration.

API integration error HTTParty

I'm learning how to work with HTTParty and API and I'm having an issue with my code.
Users/admin/.rbenv/versions/2.0.0-p481/lib/ruby/2.0.0/uri/generic.rb:214:in `initialize': the scheme http does not accept registry part: :80 (or bad hostname?)
I've tried using debug_output STDOUT both as an argument to my method and after including HTTParty to have a clue but with no success. Nothing gets displayed:
require 'httparty'
class LolObserver
include HTTParty
default_timeout(1) #timeout after 1 second
attr_reader :api_key, :playerid
attr_accessor :region
def initialize(region,playerid,apikey)
#region = region_server(region)
#playerid = playerid
#api_key = apikey
end
def region_server(region)
case region
when "euw"
self.class.base_uri "https://euw.api.pvp.net"
self.region = "EUW1"
when "na"
self.class.base_uri "https://na.api.pvp.net"
self.region = "NA1"
end
end
def handle_timeouts
begin
yield
#Timeout::Error, is raised if a chunk of the response cannot be read within the read_timeout.
#Timeout::Error, is raised if a connection cannot be created within the open_timeout.
rescue Net::OpenTimeout, Net::ReadTimeout
#todo
end
end
def base_path
"/observer-mode/rest/consumer/getSpectatorGameInfo"
end
def current_game_info
handle_timeouts do
url = "#{ base_path }/#{region}/#{playerid}?api_key=#{api_key}"
puts '------------------------------'
puts url
HTTParty.get(url,:debug_output => $stdout)
end
end
end
I verified my URL which is fine so I'm lost as to where the problem is coming from.
I tested with a static base_uri and it doesn't change anything.
The odd thing is when I do:
HTTParty.get("https://euw.api.pvp.net/observer-mode/rest/consumer/getSpectatorGameInfo/EUW1/randomid?api_key=myapikey")
Everything is working fine and I'm getting a response.
HTTParty doesn't seem to like the way you set your base_uri.
Unless you need it to be like that just add another attr_reader called domain and it will work.
require 'httparty'
class LolObserver
include HTTParty
default_timeout(1) #timeout after 1 second
attr_reader :api_key, :playerid, :domain
attr_accessor :region
def initialize(region,playerid,apikey)
#region = region_server(region)
#playerid = playerid
#api_key = apikey
end
def region_server(region)
case region
when "euw"
#domain = "https://euw.api.pvp.net"
self.region = "EUW1"
when "na"
#domain = "https://na.api.pvp.net"
self.region = "NA1"
end
end
def handle_timeouts
begin
yield
#Timeout::Error, is raised if a chunk of the response cannot be read within the read_timeout.
#Timeout::Error, is raised if a connection cannot be created within the open_timeout.
rescue Net::OpenTimeout, Net::ReadTimeout
#todo
end
end
def base_path
"/observer-mode/rest/consumer/getSpectatorGameInfo"
end
def current_game_info
handle_timeouts do
url = "#{domain}/#{ base_path }/#{region}/#{playerid}?api_key=#{api_key}"
puts '------------------------------'
puts url
HTTParty.get(url,:debug_output => $stdout)
end
end
end

Rails 4 strong parameters ActiveModel::ForbiddenAttributesError

For some reason in my current controller I am getting ActiveModel::ForbiddenAttributesError even though I believe I am using strong parameters just fine. Albeit I am using permit! for the time being to permit all model attributes. See code below, what am I missing
class HeuristicsController < ApplicationController
def index
#heuristics = Heuristic.order(:name).page params[:page]
#heuristic = Heuristic.new
end
def create
#heuristic = Heuristic.new(params[:heuristic])
if #heuristic.save
redirect_to action: 'index', :flash => {:success => "New heuristic created!" }
else
render 'new'
end
end
def new
#title = "Heuristic"
#heuristic = Heuristic.new
end
private
def heuristic_params
params.require(:heuristic).permit!
end
end
i think you did not fully understand the way that strong-params work...
you have a method
def heuristic_params
params.require(:heuristic).permit!
end
and you are not using it
Heuristic.new(params[:heuristic])

rails 3.1.0 belongs_to ActiveResource no longer working

I am upgrading from rails 3.0.7 to 3.1 and am having trouble getting my tests to pass. The problem occurs when I try to use a stubbed active resource object in a factory.
#employee.rb
class Employee < ActiveResource::Base; end
#task.rb
class Task < ActiveRecord::Base
belongs_to :employee
end
#factories.rb
Factory.define :employee do |e|
e.name "name"
end
Factory.define :task do |t|
t.employee { Factory.stub(:employee) }
end
On the console and in the spec stubbing an employee works. Referencing the stubbed employee object in a new task gives the following error.
Factory.create( :task, :employee => Factory.stub(:employee) )
NoMethodError:
undefined method `[]' for #<Employee:0x007fc06b1c7798>
EDIT
This is not a factory girl issue. I get the same error if I do the following in the console.
Task.new( :employee => Employee.first )
It must be related to how belongs_to maps the id column.
I didn't like the monkey patch so I created a module that I will include at initialization to extend ActiveRecord
module BelongsToActiveResource
def self.included(base)
base.extend(ClassMethods)
end
module ClassMethods
def ar_belongs_to( name, options = {} )
class_eval %(
def #{name}
##{name} ||= #{options[:class_name] || name.to_s.classify }.find( #{options[:foreign_key] || name.to_s + "_id" } )
end
def #{name}=(obj)
##{name} ||= obj
self.#{ options[:foreign_key] || name.to_s + "_id" } = ##{name}.#{ options[:primary_key ] || 'id' }
end
)
end
end
end
ActiveRecord::Base.class_eval { include BelongsToActiveResource }
Then in each ActiveRecord model would look like:
#task.rb
class Task < ActiveRecord::Base
ar_belongs_to :employee
end
Hope this helps someone

Resources