Active Admin and the Apartment Gem - ruby-on-rails

I am new to Active Admin but from what I have seen so far I think this is quite easy to implement.
I have an app with the apartment gem to add multi-tenancy.
I am adding active admin to my app. Apartment uses PostgreSQL schemas to segregate data. So for example by default your models in Apartment have a 'public' tenant unless you call something like Apartment::Tenant.switch!('abc').
In my app my User and Company model are in the public tenant and everything else is in tenants. So out of the box Active Admin works fine except that the tenant models show no records - as they should.
I did some tinkering and manually added Apartment::Tenant.switch!('abc') one of my AA model files and that worked perfect. Here is an ideal solution:
when the AdminUser logs in the tenant gets set to a default (say the first tenant)
On each tenanted model there could be a select menu that submits a param (?tenant=abc) and then the tenant is changed
The active tenant is persisted in perhaps the AdminUser session store so you can work in the same tenant data until you need to switch.
I think I can do this myself quite easily but I wanted to see if there was any Active Admin specific issues I would need to address like:
Does AA have an equivalent of a application controller? It would be nice to keep the tenant switching logic in there vs the main one.
The alternate AA Devise AdminUser has a separate session variable store available right?
Any suggestions would be appreciated - I will post my final solution / code back to this post once I sort it out.

Does AA have an equivalent of a application controller? It would be nice to keep the tenant switching logic in there vs the main one.
Indeed, there is an ActiveAdmin::BaseController, but the gem authors don't talk about using it for customization, not sure why. Seems like a fine place for the logic you're talking about.
I've never needed to modify it before, but here's a blog article from someone who did.
The alternate AA Devise AdminUser has a separate session variable store available right?
Hmmm. Devise uses Warden for session management, which supports multiple user 'scopes' logged in simultaneously as well as separate session data, and if memory serves from when I've dug around in the code Warden puts the separate session data in a different key in the same cookie. Not sure if this is what you meant, but I verified that it definitely does not use a different cookie for users vs admins in my current ActiveAdmin-using Rails project.
Not a definitive answer, but moving the ball!

Related

Rails: How to implement login and authentication where i have five different user models in rails?

I'm fairly new to rails. I'm having problem on designing the model classes. So this app will be used by 5 different users(Students, Teachers, Head and Coordinator). They each are different users to login into the website and have different functionality (example: Head makes an event. Students register for an event. Coordinator sets who can be head etc). I have created all four models with USERNAME and PASSWORD on each models.I don't have user model right now because the users in this app are these 4 models. Now, while making login page, i'm having hard time on implementing the best way to authenticate the users. For example, If a Head puts its login credentials, the app should identify that user that logged in is Head. What approach will be best to encounter this?
Also, after not figuring out the way to approach this. I was thinking of using devise and CanCanCan gem. But the same promblem comes in even if i use this gems.(i maybe wrong)
Do not create multiple models for different kinds of users. This is almost always not what you want. Instead add a column called role of the type enum which contains all of the kinds of roles you want to add like Sergio pointed out. Your comment about having too many attributes on one model is a non issue compared to the one you are planning to create with 5 user models.
It sounds like you are possible putting too much data on the user model if that is your concern
and have different functionality (example: Head makes an event. Students register for an event.
For this you want a permissions system such as cancancan where you can specify which features of the website each role has access to.

Ruby on Rails -- How to create table of ALL logins/sessions

I have a working application for using Devise for user models and authentication. I want to create a table that effectively stores ALL the logins a user ever has, and the length of these sessions. I do not need to store session data with the entries. Am using the "timeoutable" option in Devise which I think will ensure I always have a logout time (?) even if a user just closes the browser window.
What I want is effectively the opposite (in some sense) of how the sessions table operates in only recording the latest user session when using active_record_store option in config/initializers/session_store.rb
So what's needed is a logins table with user_id and login_id/index (plus login time and logout time) that is edited automatically any time a user logs in or out, and DOESN'T delete or overwrite the older sessions. Does this require a model, controller, etc. like other user-edited objects?
Answer is probably something simple, but I spent a lot of time looking and didn't see too many folks who actively want to store MORE user data like this. Thanks for any advice! [I'm a Prof. doing this for a basic web-course app so I can make student time on the site part a factor in their grade ;)]
Using rails 3.2.13, devise, sqlite3 for development db
If you don't want to reinvent the wheel, you can have a look at those 2 gems. They offer model data change tracking:
https://github.com/airblade/paper_trail
https://github.com/collectiveidea/audited

Preventing Certain Users from Deleting Records in Rails Admin

I have Rails Admin installed which is working great. However I have a problem. Only admins can sign into Rails Admin and there are two types of admins. The first type of admin can have access to everything, delete anything they want, etc. The second type should only have access to certain tables.
I don't see any configuration with Rails Admin to get what I want so I was thinking of using a callback in my models. But then I would have to somehow pass through the user's credentials to verify what type of admin they are, and even then there would have to be a lot of hacking. My question is, can this be done, and if so, whats the best way to do this?
I have used CanCan in the past to accomplish exactly what you're looking for. It worked well with Rails Admin.
https://github.com/sferik/rails_admin/wiki/CanCan
As an aside: I would recommend using a single role per user as that seems to make things easier.

Authentication with Ruby on Rails & Devise

I am about to build a new site in ruby on rails for residents at my college.
The site will allow residents to change their passwords for the college-firewalls (which means there are certain requirements).
On the site, each resident will have an account with a number of data assigned to it, and for this I need some authentication.
I've been studying Devise for almost the entire day now, but im starting to wonder if I have a too complicated task, to complete it with Devise.
Problem is, I need the passwords to be stored with DES-encryption, something Im not sure if Devise can handle.
Another thing is, users can't make their own profile. Admins will do that (to ensure correct data), which means that user-creation is not the default one. Since there are no controllers for this, is it even possible to do it that way?
I'm not sure if I should keep on going with Devise, or bite the bullet and write it all from scratch instead. Some opinions would be appreciated.
This page on the Devise wiki ( https://github.com/plataformatec/devise/wiki/How-To:-Create-a-custom-encryptor ) tells you how to set up a custom encryptor.
To make it so that admins create a user, remove the :registerable module from the User model. Then add a user resource to your app, example:
scope 'admin' do
resources :users
end
Set up the new/edit pages with your profile fields, etc., normal rails programming.
For an example using CanCan to control access to the users resource, have a look at this post: http://zyphmartin.com/blog/manage-users-with-devise-and-cancan.
If devise does not exactly do what you need, maybe this recent webcast from Ryan Bates will help you.

Ruby on Rails: how to use sessions to implement remote sign-out?

My goal is to allow users of a Rails web app to see all their open sessions on other computers and close/sign out of them remotely. Similar to gmail's "Account activity" page (link found at the bottom of the gmail inbox page).
I can technically achieve this by using the sessions in the database
account_sessions = CGI::Session::ActiveRecordStore::Session.find(:all)
and iterating over them to find sessions corresponding to the current user (the user ID is stored in the session data), and allowing the user to destroy these sessions.
However, this doesn't offer the usual convenience of working with Rails models. I can't easily express a has_many relationship with the user and make use of
current_user.sessions
nor can I easily put an index on user_id since it's in the data part of the session (instead of being its own column).
This approach also may become impractical if the number of sessions grows, since in the above the table is read into memory.
As a solution, I'm thinking of creating my own model which "mirrors" the relevant portions of the session and is created/updated/destroyed to maintain that correspondence.
This isn't a great way to go about it due to data replication and added complexity of code, but I didn't find another way to do it.
So the question is: is this a good way to go about it, or am I missing something?
Thanks in advance!
Fraser
Edit: I should have mentioned that I'm currently using restful-authentication, and would prefer not to switch.
Since authlogic offers a user session model and is easily extendable, you should be able to achieve exactly what you want, if you don't mind to switch to another authentication mechanism.
Edit: This Railscast should give you a pretty good overview.

Resources