Devise, Omniauth and multiple models with STI - devise

I have an application setup with devise authentication using sti (base user model and two other models - company and individual - inheriting from it). From a devise perspective, everything is working. I can have different routes for signup forms and everything works as expected. Now I wanted to give both users (company and individual) the option to signup/sign in using facebook or linked in. If I set the :omniauthable on both models, and set the devise_for on my routes.rb for each model, I get an error saying that only one model can be omniauthable. If I don't use the devise_for for each model, no routes are generated. If I set the omniauthable on user model only, I get only one route and one callback.
I've read somewhere that the solution would be to use omniauth on its own (separated from devise). However, I can't seem to achieve the intended behavior using omniauth separate from devise (I can get one single authorize/callback route, but the two, as intended).
Anyone out there who can help ?
TIA

Devise's Omniauthable module does support multiple models. See
https://github.com/plataformatec/devise/wiki/OmniAuth-with-multiple-models

Related

Authorization with Devise and multiple levels

I need some help with the authorization. So far I was trying to solve it with the internal rails authorization combined with devise.
I have a user who is posting a request. If this request is private only a group of "reader" can see and answer the request. (This is number one)
Then the user give a rating to the answer of the reader. This should be accesible only for the user which received the answer and the "reader" who gave an answer.
So far I was using the following to limit access to the hidden requests:
before_filter :require_reader!, only: [:open_requests]
But if the request is not hidden, than still only the reader should be able to answer the request (but all can see it). Here I do not know how to manage this. Any Ideas?
To continue... I could not manage to solve the second problem (that the rating is seen only be the one who was placing the request and the reader).
Any ideas here?
Is cancancan maybe an option?
Best
witali
What you're doing does not quite follow the 'admin' pattern that's commonly setup with tools like Railsbricks. The 'admin' permissions pattern is typically a whole set of actions/views that are available only to admins, so often the entire Controller, or family of controllers, have the :require_admin! filter applied before every single action and view. Very simple permissions logic, and it depends only on the user and view.
Instead, what you've got is views with permissions that depend on your object's state as well as the user's status and the view. So you're going to have to write your own filter to use instead of using 'require_reader!'.
For example, you might have a RequestsController, and you could add to it:
before_action :must_be_able_to_view_request, except: [:index, :new, :create]
Then define that filter in the controller:
private
def must_be_able_to_view_request
if !current_user.is_reader? && !#request.ispublic
head :forbidden
end
end
If you need to use the same filter in other Controllers, then you can define it in your ApplicationController.

How do I set encryption settings per Devise Class?

Hi StackOverflow community, I'm trying to solve an issue whereby I am wrapping Devise around a legacy model in a Ruby on Rails 3.2 application.
In this app, I actually have 2 pre-existing devise models: Representative and Admin. These two classes use all standard devise configuration and use default password encryption. I need to wrap Devise around a third model, Dealer, which already has a pre-existing, custom SHA1 password encryption implementation. I'd like to leave this encryption implementation in place while I work on adding Devise to this model and not force me to reset several hundred users passwords. Is it possible to set the password encryptor to SHA1 for just this one model, leaving the other two aforementioned classes alone?
I'm still combing the documentation looking for a way to pass options to the devise-encryptable plugin, but so far have yet to find what I'm looking for. Hopefully the community can help me with my search.
I ended up figuring it out.
1) Added gem 'devise-encryptable' to Gemfile
2) Added :encryptor => :legacy_sha1 options hash to model.
class DeviseModel < ActiveRecord::Base
devise :encryptable, :encryptor => :legacy_sha1
end
3) Added a custom Encryptor class to lib/devise/encryptable/encryptors/legacy_sha1.rb
module Devise
module Encryptable
module Encryptors
class LegacySha1 < Base
def self.digest(password, stretches, salt, pepper)
string = #secret routine!
Digest::SHA1.hexdigest(string)
end
end
end
end
end
Works perfectly.

Accessing Custom Parameters when using Devise and Rails 4

I am learning rails using the teamtreehouse tutorial. The tutorial uses 3.1 but I am trying to learn 4.0, and as a result I have run into a difficulty presumably because rails 4 forces of the use of strong parameters. I have two models, a users model and a statuses model. I have used devise to create authentication for users, and have included new parameters. They are :first_name, :last_name, and :profile_name. I have created a relationship between users and statuses.
Currently the user sign-up with the new parameters is working; i can access them using for instance current_user.last_name. However, I want to show the profile_name of the user that created the post on the statuses index view(each user does not yet have a separate page). I want to do this using
status.user.profile_name
However it just shows up blank. If I do
status.user.email(which is a preconfigured devise parameter), it shows up no problem. I am guessing I have to whitelist these parameters in some controller but I don't know where or how.
Thanks
I think, here you will find your answer: https://github.com/plataformatec/devise/tree/rails4#strong-parameters
Based on above link, I think you should insert something like this in your ApplicationController:
class ApplicationController < ActionController::Base
before_filter :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:user) { |u| u.permit(:profile_name) }
end
end
And I already suggested in a previous question...
Strong parameters with Rails and Devise
...that you can create your own controller which could extend devise own controller. There is a gist for that:
https://gist.github.com/bluemont/e304e65e7e15d77d3cb9
A little bit more details in Devise doc: https://github.com/plataformatec/devise/tree/rails4#configuring-controllers

Rails 3 + Devise with different model name

I'm sharing one database for two web applications. The User model is already being used for one of these apps, so, in order to sign in to the other one, I had to create another model to avoid mixing users info.
I could make Devise work for this new model, called SystemUser. The problem is now I'll have to use every variable with another name. For example: current_system_user, system_user_signed_in?, etc. I'm using these variables, with their original name, across the whole application, and I would like to know if there's a way to avoid overwriting it. For example: by creating a method called current_user that returns current_system_user, and that way with the other variables mentioned before.
I think this should do the trick:
devise_for :users, class_name: 'SystemUser'
have you considered using CanCan for roles?
https://github.com/ryanb/cancan
I could finally solve the issue by generating the Devise views again. I don't know why, but the devise/sessions folder was missing, and it was doing it with another view, and when I started using it, it worked.
Thanks anyway.

How to create user specific content, that is invisible to others?

I am absolutely new to Ruby on Rails, even to programming at all. I got started with Michael Hartl's Rails Tutorial using Rails 3.0.10. Now I alter its aim towards creating an application that allows users to manage their own "projects". These projects are to be exclusively available to the logged-in user, thus, invisible to others.
My problem is: I am unable to create a page with an URL like "~/users/1/projects", I don't know about the routing. All i get done is "~/projects", which is fairly not what i want at all. So, how do I get this problem fixed? Or am I totally off track with that idea?
I generated a Projects model by scaffolding. So, how can I implement it for the signed-in users?
this would be done by creating a nested resource. when you are new to rails and programming you should work yourself a way through a lot of tutorials and guides.
a good place to get an overview are the official rails guides. in this specific case the chapter about routing: http://guides.rubyonrails.org/routing.html#nested-resources
# config/routes.rb
resources :users do
resources :projects
end