has_permission_on with Declarative Authorization, non attribute condition - ruby-on-rails

I want to give authorization to a specific action if a session variable is set in my app. I can't figure out how to do this. Something like:
has_permission_on :admin, :to => :action do
true if session[:key]
end
I don't understand how to accomplish this basic task. Any help appreciated.

You want to use a before_filter on the function e.g.
before_filter :authorize, :only => :action
private
def authorize
unless session[:key]
flash[:notice] = "Cannot do this"
redirect_to(:controller => "controller", :action => "otheraction")
end

Related

Rails: half-restful routes

I've got these three bottom routes below which are very error-prone because of other routes declared normally:
# normal routes
resources :documents, :except => [:show, :edit, :update]
resources :photos, :except => [:show, :index]
...
# error-prone routes
get ":client_code" => "share#index", :as => :shares, :format => false
get ":client_code/:id" => "share#show", :as => :share, :format => false
get ":client_code/:document_id/more/:component_id" => "share#more", :as => :more, :format => false
I've got a few methods in the ShareController to deal with the requests like so:
def show
get_user_by_parameter
if get_document_by_user_or_issue and #document.is_showable? and #parameter_user == #document.user
...
end
private
def get_user_by_parameter
#parameter_user = User.where(:client_code => params[:client_code]).first
end
def get_document_by_user_or_issue
if params[:id].match(/\D/)
#document = Document.where(:user_id => #user.id, :issue => params[:id]).first
else
#document = Document.find(params[:id])
end
end
I need the routes to be that minimal, but not only is this ugly and un-RESTful but it's very error prone.
The :client_code will always be the owner of the #document being viewed. It's kinda like a safety check/ownership kinda function. But, because of all the reasons listed above: is there a better way to write this? There's gotta be a better way than that.
Thanks.
Controller Based Check:
before_filter :find_document
def find_document
Document.find(params[:id])
end
def is_owner?(document)
redirect_to root_path if current_user.id != document.owner_id
end
Isn't a check like this much easier? I'm not sure why you have a share controller, so I don't want to be presumptuous here.
Which will allow you to do:
resources :shares, only: [:index, :show]
Also:
User.where(:client_code => params[:client_code]).first
Can be refactored to:
User.find_by(client_code: params[:client_code])
Assuming you are on latest rails version, else:
User.find_by_client_code(params[:client_code])
Let me know what the shares are for, I'm not sure I provided the full solution for you.
Cheers.
EDIT
if you are using shares to provide a different view, i suggest doing this:
Within the controller,
def index
if params[:shares]
render 'shares'
end
end
Unless you really wish to have a different route for it. This allows you to not have a shares controller for essentially what is the document model.

Devise redirect to custom action on sign in

I'm using Devise for user authentication, and want to have the user redirected to a custom action that I have set up for the User class called 'myaccount'. However, I can't get the syntax right - I'm getting varying errors with everything I'm trying.
This code might show you what I'm trying to acheive (it doesn't work though):
def after_sign_in_path_for(resource)
redirect_to :controller => 'users', :action => 'myaccount', :id => current_user.id and return
end
And the routes:
devise_for :users, :controllers => { :registrations => "registrations" }
devise_for :users
resources :users do
member do
get 'myaccount'
end
end
Apologies, it's probably quite a newbie question - but how do I either change my redirect, or add a new route so that e.g. user_sign_in_path would work?
Thanks!
UPDATE:
In case anyone else finds this question, this is what worked for me:
url_for :controller => '/users', :id => current_user.id, :action => 'myaccount'
which is the correct order that I need it in. I had to put a slash infront of the controller name to make it use that instead of the Devise controller.
you don't have to call redirect_to
def after_sign_in_path_for(resource)
{ controller: 'users', action: 'myaccount', id: current_user.id }
end
if that doesn't work, wrap that up in url_for and that should work :)

rails devise using current_user and matching routes :id

I am having issues with devise current_user confusing my model's :id as the users :id.
routes:
match "/causes/:id/:slug" => "causes#show", :as => :cause, :via => 'get'
match "/causes/:id/:slug/edit" => "causes#edit", :as => :edit_cause, :via => 'get'
match "/causes/:id/:slug" => "causes#update", :via => 'put'
resources :causes, :only => [:index, :new, :create]
in my :causes controller:
before_filter :check_privileges, only: [:new, :create, :edit, :new, :update]
def check_privileges
#when I use this code everyone can access edit, etc.
redirect_to root_path unless current_user
end
and in my :causes model
belongs_to :user
For some reason, when I use current_user at all, in this controller, it always thinks that current_user is equal to the id in /causes/:id/:slug/
I have tried putting the check privileges code in the application controller,
I have even tried assigning code like this:
def check_privileges
#when I use this code no one can access edit, etc
#user = User.find_by_id(params[:id])
redirect_to root_path unless #user
end
I need help, anyone have suggestions? All I want it to do is verify the user is the current user so not everyone can edit the cause.
Your post is a bit confusing. IIRC devise stores the current user id in the session and does not ever get it from the url.
Seeing that this is a problem associated with privileges and rolling out your own solution. I would highly recommend an alternative.
https://github.com/ryanb/cancan
This works great with devise and should solve your problems

Thoughtbot's Clearance gem, overriding url_after_destroy

I was able to successfully override url_after_create, but my url_after_destroy is being ignored.
What am I messing up?
routes:
map.resource :session,
:controller => 'sessions',
:only => [:new, :create, :destroy]
my Sessions controller:
class SessionsController < Clearance::SessionsController
private
def url_after_create
puts "************after create****************" #called on sign in
end
def url_after_destroy
puts "************after destroy****************" #never called
end
end
The docs say:
You may also need to add code such as
the following to your routes.rb:
map.sign_out 'sign_out',
:controller => 'sessions',
:action => 'destroy',
:method => :delete
That's what I'm missing. Perhaps 'may' is not the best choice of verb for documentation.

before_filter except override not working

Good afternoon all,
I've got a controller running a before filter with an except override. It works fine for all the methods in the controller, save one. I've copied the code for the method in question from another part of my app, just making the changes I need to get it working for this particular area.
Here is an example of the controller code:
class Admin::DealsController < ApplicationController
before_filter :populate, :except => [:index, :create, :new, :search]
# GET /deals
def index
#deals = Deal.paginate(:page => params[:page], :per_page => PAGESIZE, :order => 'start_time DESC')
#page_subtitle = "Deals"
end
def search
#searchString = params[:search_string]
#deals = Deal.paginate(:page => params[:page], :per_page => PAGESIZE, :conditions => "subject LIKE '%#{#searchString}%'")
#page_subtitle = "Deal Search Results"
render 'index'
end
protected
def populate
#deal = Deal.find(params[:id])
end
end
And here is the route in my routes.rb file for the method in question:
admin.search_deal 'deals/search', :controller => 'deals', :action => 'search', :method => 'get'
Now, when I attempt to visit this URL:
/admin/deals/search?search_string=test&commit=Search
It generates the following error message:
Couldn't find Deal with ID=search
This code works on several other controllers, and I've been beating my head against the wall all day trying to see what I'm doing wrong. I would appreciate any help, thank you.
It would appear that your routes are not in the correct order. If you look more closely at the log file you may be able to verify this, but the action being called is probably "show" and not "search".
Any custom routes should be listed above the default ones, or better, you should remove the defaults entirely.
Look for a line like this in your log/development.log:
Processing Admin::DealsController#show
If you list your routes with rake routes make sure that your custom search_deal route is listed before any generic routes.
You might want to use resourceful routes, too:
map.namespace :admin do |admin|
admin.resources :deals, :collection => { :search => :get }
end

Resources