rails role based access using cancan - ruby

There is no user and roles table. I have a tabless model for users and roles. user information is set in the application controller with the values from the environmental variables, for this one I have hard coded the value. The role information comes from the service.
#Application controller setting the user object
before_filter :set_user
def set_user
#user = User.new(:id => 123)
end
I am using cancan for authorization and ability.rb doesnt see this #user or user and comes in as nil.Does ability load before the application controller? Am I missing anything in the controllers for cancan? I have load_and_authorize_resource in the controllers.
Any suggestion will be greatly helpful.
Thanks
Ramya

Add this method in your ApplicationController if you don't have it:
def current_user
#user
end

Related

Rails 5 Using Devise and acts_as_tenant

I have an application that's using Devise to handle sign in/registration. I'm also using acts_as_tenant. I need to ensure a Tenant is set every time someone goes to register/sign in. For acts as tenant to work, the tenant must be set prior to authentication. Right now I'm using a before_action on my ApplicationController but the issue is that method gets called even if someone has invalid credentials etc, and I'm trying to avoid having to write if statements in the method to figure out if I have a valid user or not.
What is the best way to achieve this? Anyone in a similar situation?
If you need to set your tenant before authenticating with Devise, you need to use acts_as_tenant's manual tenant setting method so that you can control the timing.
# application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
# tell acts_as_tenant you'll manually set the tenant
set_current_tenant_through_filter
# manually set the tenant before Devise auth
prepend_before_action :set_current_tenant_by_subdomain
# Devise auth as usual but after tenant is set
before_action :authenticate_user!
private
def set_current_tenant_by_subdomain
current_organization = Organization.find_by_subdomain(request.subdomain)
set_current_tenant(current_organization)
end
end

Building an OmniAuth strategy with a custom workflow

I want to achieve the following login workflow:
user clicks on login button
user gets redirected to our authentication platform
user submits the login credentials and then gets redirected back to our
website via a pre-set callback URL
the OmniAuth strategy must decode the response (using our SDK) and
save the result in the omniauth.auth hash
Is this process easily achievable using a OmniAuth Strategy? It's not very clear to me from the documentation, and the majority of already built strategies seem to be using the OAuth workflow.
Apparently this is quite easy to do.
The OmniAuth strategy
module OmniAuth
module Strategies
class Service
include OmniAuth::Strategy
def request_phase
redirect AUTHENTICATION_URL
end
uid { #user_details.user_id }
def extra
#user_details # Return a hash with user data
end
def callback_phase
# Configure Service SDK
#user_details = Service.user_data # Make SDK call to get user details
super
end
end
end
end
The App
1) Add a login button with the authentication URL:
<%= link_to 'Login', 'auth/service' %>
2) Add a callback route
get '/auth/service/callback', to: 'sessions#create'
3) Handle the callback response in the controller
class SessionsController < ApplicationController
def create
#user = User.find_or_create_by(service_id: auth_hash.uid)
# Handle #user
end
end

Unable to store session data into cookie and send back to server

Currently, I am working on signup functionality of a web application using Rails 4. Basically, the working flow will be as follow:
User fills in signup form and submit it to server
Signup request then will be handled by create method of UserController
Session data will be then stored in cookie and sent back to server to persist session data among requests.
However, when observing response header after trying to signup, I did not see set-cookie property. And, in fact, current cookies does not store any session data for server to realize session. Below is my code:
users_controller.rb
class UsersController < ApplicationController
...
def create
#user = User.create(user_params)
# set session
log_in #user
render 'index'
end
...
end
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: :null_session
include SessionHelper
end
session_helper.rb
module SessionHelper
# Log in a given user
def log_in(user)
# Send session stored in a temporary cookie to browser
# By default, cookie will be storage mechanism for session
session[:user_id] = user.id
end
I will be thankful if someone can explain the root of problem and give me some workarounds.
Have you tried without the parameter with: :null_session in application_controller?
everyone.
After having done some research, I had found out a workaround by adding skip_before_action :verify_authenticity_token in UserController to bypass authenticity_token as follow:
class UsersController < ApplicationController
# To make the sesson get reset
skip_before_action :verify_authenticity_token
end
Thank you so much for your attention.
Regards.

Ruby on Rails - Session in Model for External API

I have an app without models or any database connectivity.
I have a method defined in the ApplicationController called "api_call" which does all api calls within the app. This method uses the ruby session to store things about the user, such as authentication info, access token info, and user info. In the session I store an Authentication hash for sending to the api for security when the user is logged.
Two things:
I'd like to put all api calls (the api_call method) in models (that don't use db or validation), but the problem is I don't have access session.
If I use a module, the module in the model also doesn't have access to the session.
If I create a model class without using ActiveRecord, should I use class methods rather than object methods?
How about passing the "authentication hash" to the API model's constructor?
class Api
def initialize auth
#auth = auth
end
end
class FooController < ApplicationController
def index
api = Api.new session[:auth]
end
end
Also, if you haven't see Pratik Naik's article about this, it's pretty funny.

Ruby On Rails authentication with Devise and (warden) callbacks

I have a rails app that is using Devise, with a User model, no scope.
I've also added activeadmin gem in to the app, Active Admin is a gem used for adding an admin dashboard in your application. It uses Devise for logging in users and creates a separate admin_user model for the admins.
I am allowing anonymous, non-logged in users to create shopping carts, creating a session[:cart_id]. If a user logs in I want associate the user with the cart, something like
Cart.find(session[:cart_id]).user = current_user
I was planning to use Wardens callbacks wardens callbacks to impliment this, something like so :
Warden::Manager.after_set_user :scope => :user do |user, auth, opts|
Cart.find(session[:cart_id]).user = user
end
However I get an error if I do that:
<% unless user_signed_in? %> throws an error :admin_user user is not logged in
Anyone got any ideas what is going on?
I've looked at related questions, but no help:
How to access session from Warden/Devise after_authentication callback in Rails
Where should warden callbacks be placed in a rails app?
The AdminUser model that Active Admin uses also executes this callback. So, maybe, an if can solve your problem:
Warden::Manager.after_set_user :scope => :user do |user, auth, opts|
Cart.find(session[:cart_id]).user = user if user.class == User
end
Actually it turned out the issue was solved by setting the default scope in warden,in the devise initializer file.
# Configure the default scope given to Warden. By default it's the first
# devise role declared in your routes (usually :user).
# config.default_scope = :user
Since the active admin routes were added above the devise routes for my user, the adminuser became the default user.

Resources