Implementation of survey using surveyor gem in rails - ruby-on-rails

I am trying to implement a survey using the surveyor gem in rails. I want to make use of the user id to keep track of which user creates the survey and which user gave what response on which survey.
The problem is that I did not use the Devise gem for my user signin and signup. I built it manually. The surveyor gem uses a helper method current_user of Devise which returns details about the current user.
Since, I did not use devise, I am not sure where to add the helper method current_user.
I am not really sure as to what code to post, so please comment the required details. I will edit my post as needed.
Thanks!
application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_filter :authorize
helper_method :current_user
protected
def authorize
return true if ((self.class == SessionsController)|| (self.class == UsersController && (self.action_name == "new" || self.action_name == "create")))
unless (User.find_by_id(session[:user_id]))
redirect_to url_for(:controller => :sessions , :action => :new), alert: "You need to be logged in."
end
end
def current_user
#current_user = User.find(session[:user_id])
end
end
Here is the link of the surveyor gem controller which uses the current_user method: https://github.com/kjayma/surveyor_gui/blob/master/app/controllers/surveyor_gui/survey_controller.rb

Here is one possible solution to implement a current_user method.
helper_method would make the current_user method available in every controller, which inherits from ApplicationController.
class ApplicationController
helper_method :current_user
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end

Related

undefined local variable or method `current_user' cancancan

I'm working on a login/logout system. Instead of using devise, I created an active records User model and use sessions to remember if a user is logged in. Everything was working fine until I added these lines in the application_controller.rb to have a layout before login and one after.
layout :set_layout
def set_layout
if session[:current_user_id]
'afterlogin'
else
'application'
end
end
Now, after I log in and cancancan is being used somewhere in a html page I get undefined local variable or method 'current_user'. I think that I have to add a current_user method but I'm not exactly where and how to define it.
Edit: I already had something similar in another class that is being used by login:
class Admin::ApplicationController < ApplicationController
before_action :authorize
def authorize
begin
#current_user ||= User.find(session[:current_user_id]) if session[:current_user_id]
rescue ActiveRecord::RecordNotFound
session.destroy
redirect_to '/login',alert: 'Please login'
end
end
end
Should I modify this after I add that method ?
CanCanCan expects a current_user method to exist in the controller.
First, set up some authentication (such as Authlogic or Devise).
See Changing Defaults if you need different behavior.
I would suggest you to install Devise so that it comes with a complimentary current_user method.
FYI: https://github.com/plataformatec/devise
UPDATE
when a user logins successfully, you can store the user's id in session.
session[:current_user_id]=user.id
so that, in your applicationcontroller, you can do
def current_user
#current_user ||= session[:current_user_id] && User.find_by_id(session[:current_user_id])
end
helper_method :current_user

Require a user to be logged in (Rails)

How do I guarantee that users only access the routes on my web app if they are logged in? I already have Users and Session models and users are able to create accounts. But how do I make sure that if they are not logged in they are always redirected to the login/sign up page, but if they are they have access to all the routes?
EDIT: So this is what my Application Controller looks like right now:
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
helper_method :current_user
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end
So if there isn't a current user, I want to allow access only to the my Pages controller and its actions (which are basically home, signup, login, etc.). If there is a user, on the other hand, I want that user to be able to access all the routes in my route file.
class SomeController < ApplicationController
def show
if current_user.nil?
redirect_to '/path/to/login'
end
end
end
could probably give a more detailed answer if you paste in some code otherwise we all are just guess what your methods are called.
If you are using devise it comes with the built in helper method authenticate_user! which should be placed in your application controller.
If you are not using devise you can define you own method (for this example I will copy devise) authenticate_user! in application controller and call the before action
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
hide_action :current_user
private
def authenticate_user!
redirect_to :root if current_user.nil?
end
end

Helper methods are not being seen (Rails 4 engine)

I have defined a helper method as such (for my rails engine):
module Xaaron
class ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found
helper_method :current_user
helper_method :authenticate_user!
def current_user
#current_user ||= Xaaron::User.find_by_auth_token(cookies[:auth_token]) if cookies[:auth_token]
end
def authenticate_user!
if current_user
true
else
redirect_to xaaron.login_path
false
end
end
protected
def record_not_found
flash[:error] = 'Could not find specified role'
redirect_to xaaron.record_not_found_path
true
end
end
end
As far as I know everything above is correct in terms of creating helper methods. So now I need to use this helper method:
module Xaaron
class ApiKeysController < ActionController::Base
before_action :authenticate_user!
def index
#api_key = Xaaron::ApiKey.where(:user_id => current_user.id)
end
def create
#api_key = Xaaron::ApiKey.new(:user_id => current_user.id, :api_key => SecureRandom.hex(16))
create_api_key(#api_key)
end
def destroy
Xaaron::ApiKey.find(params[:id]).destroy
flash[:notice] = 'Api Key has been deleted.'
redirect_to xarron.api_keys_path
end
end
end
As you can see, before every action the user must be authenticated. So the authenticat_user!
method is then called.
Lets write a test for this
it "should not create an api key for those not logged in" do
post :create
expect(response).to redirect_to xaaron.login_path
end
This, we expect, to send us back to the login path because we are not signed in, and as you will recall we are using authenticate before every action in the API Controller. What do we get instead:
1) Xaaron::ApiKeysController#create should not create an api key for those not logged in
Failure/Error: post :create
NoMethodError:
undefined method `authenticate_user!' for #<Xaaron::ApiKeysController:0x007f898e908a98>
# ./spec/controllers/api_keys_controller_spec.rb:9:in `block (3 levels) in <top (required)>'
Last I checked the way I defined a helper method is how rails casts has done it, how other stack questions have done it and how rails docs states to do it - unless I missed some majour step - why isn't this working?
Maybe I haven't seen a helper method set up like this before (I'm new to rails) but the helper methods I've seen are defined without controllers.
Usually I see a file like this in the helpers folder
module SessionsHelper
def sign_in(user)
remember_token = User.new_remember_token
cookies.permanent[:remember_token] = remember_token
user.update_attribute(:remember_token, User.encrypt(remember_token))
self.current_user = user
end
def current_user=(user)
#current_user = user
end
...
and then
include SessionsHelper
In the application controller.
To me it looks like you're calling the controller a helper method, I'm not sure what the benefits of that would be - but I suppose I wouldn't.
Sorry if this wasn't helpful

How to create `authenticate_user' method without devise in ror

I am new in Ruby on Rails and i am using Ruby version 1.9.3 and Rails version 4.0.2.
My Query is:-
How to create `authenticate_user' method without devise in Ruby on Rails.
Below my routes
get "admin/users/sign_in" => "admin/users#sign_in"
Below My Application Controller:-
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
rescue_from CanCan::AccessDenied do |exception|
flash[:alert] = "Access denied. You are not authorized to access the requested page."
redirect_to root_path and return
end
helper_method :current_user
before_filter :authenticate_user, :current_user
def current_user
# Note: we want to use "find_by_id" because it's OK to return a nil.
# If we were to use User.find, it would throw an exception if the user can't be found.
#current_user ||= User.find_by_id(session[:user_id]) if session[:user_id]
#current_user ||= User.find_by_authentication_token(cookies[:auth_token]) if cookies[:auth_token] && #current_user.nil?
#current_user
end
def authenticate_user
if #current_user.nil?
flash[:error] = 'You must be signed in to view that page.'
redirect_to :admin_users_sign_in
end
end
protected
#derive the model name from the controller. egs UsersController will return User
def self.permission
return name = self.name.gsub('Controller','').singularize.split('::').last.constantize.name rescue nil
end
def current_ability
#current_ability ||= Ability.new(current_user)
end
#load the permissions for the current user so that UI can be manipulated
def load_permissions
#current_permissions = current_user.role.permissions.collect{|i| [i.subject_class, i.action]}
end
end
Below code using my controller
before_filter :authenticate_user!
My authenticate_user method not redirect properly
redirect_to :admin_users_sign_in
admin_users_sign_in path define in routes see on top
Above the code every time say on browser "The page isn't redirecting properly"
Please help
I suspect the problem is due to this line:
redirect_to :admin_users_sign_in
You need to pass either an action & controller or a friendly name of the path to redirect_to.
Change your routes to be something like
get "admin/users/sign_in" => "admin/users#sign_in", :as => :admin_user_signin
Then you can do something like
redirect_to admin_user_signin_path
This looks an infinite loop.
You defined authenticate_user at ApplicationController level. So, when a visitor visited page 'foo', he is denied by this method because current_user is nil. Then he got redirected to admin sign in page, but that page has this before_filter as well, so he got redirected again, to the same page and never end.
To fix, move such filter to specific controllers which need protection. And do not set it in sign in/sign up page.
Side notes:
You've already used CanCan which has authorization on "read" as well. There is no point to use authenticate_user again for same functionality.

Rails 3 authorization with default auth

I working on an app with user authorization. It has a List and User classes. The authentication was built with Ryan Bates http://railscasts.com/episodes/270-authentication-in-rails-3-1
I'm not sure about authorization process. I read about cancan gem. But i could not understand.
I want to achieve this:
User only able to view/edit/delete his own list.
User only able to view/edit/delete his own profile(user class).
I don't implement user level right now. No guess or admin.
How to use before_filter method in list and User controller with current_user instance?
Since you are defining current_user in the application controller, this is easy. You can use before_filter like this in the Users controller:
class ItemsController < ApplicationController
before_filter :check_if_owner, :only => [:edit, :update, :show, :destroy]
def check_if_owner
unless current_user.admin? # check whether the user is admin, preferably by a method in the model
unless # check whether the current user is the owner of the item (or whether it is his account) like 'current_user.id == params[:id].to_i'
flash[:notice] = "You dont have permission to modify this item"
redirect_to # some path
return
end
end
end
###
end
You should add a similar method to UsersController to check if it is his profile, he is editing.
Also, have a look at Devise which is the recommended plugin for authentication purposes.
For this I'd not use devise. It's way to much for this simple use.
I'd make a seperate controller for the public views and always refere to current_user
Remember to make routes for the actions in the PublicController
class PublicController < ApplicationController
before_filter :login_required?
def list
#list = current_user.list
end
def user
#user = current_user
end
def user_delete
#user = current_user
# do your magic
end
def user_update
#user = current_user
# do your magic
end
# and so on...
end

Resources