Is there a way to load and set a specific session from the database in ruby on rails? - ruby-on-rails

My Scenario:
Sessions are being stored in the database using ActiveRecord::SessionStore
User is on site at 'http://domain.com '
they go to secure checkout at 'https://domain.secure.com' (our app has lots of domains, but want to send everyone through secure checkout on the same domain to save SSL headaches).
We append session_id and a hash to authenticate and identify the user at 'https://domain.secure.com'
Load that users session data by doing ActiveRecord::SessionStore::Session.find_by_session_id(session_id)
The above all works fine. BUT how can I actually set the same session_id to the user once they are on 'https://domain.secure.com'? I can loop through the data and assign it to the user's session, but Rails automatically gives the user a new session_id on 'https://domain.secure.com'. I want the users session to be stored in the same database row regardless of whether they are on 'http://domain.com' or 'https://domain.secure.com'
Why do I want to do this? For ease of expiring sessions. I can just remove that row from the sessions table.
Otherwise I'm thinking I'll have to add a user_id column to the sessions table and then when i want to expire the session, I delete all rows for that user. But this sounds more complicated to me. I'd rather just have one row in the sessions table.
Any suggestions?

A couple ways to approach this.
One, you could look at a higher level of abstraction for authentication that lets you manage cross server. For example, Devise http://github.com/plataformatec/devise
Second, you can override the whole session controller and write your own session manager. A bit more work, but not that complicated if you ultimately need a bunch of custom functionality. I remember correctly, start with this in your environment:
CGI::Session::ActiveRecordStore.session_class = MySessionClass
and go from there..

Related

Storing anonymous users' favorites on Redis

I am new to Redis and started playing with it.
I have a rails app where unauthenticated users can put newspaper articles as favorites, so they could read them later. What I have been doing until now is storing the favorites in cookies.
But I would like to achieve the same with Redis.
There is the command lset. What I don't understand is if this list will be unique to each visitor or common to everyone.
Redis is a key-value database, if you use same key for every user - then list will be common for everyone. Uniqueness can be achieved by adding some user id into the key.
If you want to add an article id to users' list - RPUSH is more suitable, because you do not know which list index the article will be at.
Other problem is data expiration, because anonymous users' data is useless once the user clears their cookies/change browser etc. In this respect cookie storage is more preferred. If you worry about cookies size - you may look into using localStorage on clientside. Also you can use rails' redis session storage - this way cookies only contain session id and all data goes to redis (where rails will care for it's structure, users are unlikely to face race conditions in your task)

Storing User Data in Session - Standard Practice

I've seen some information on SO and Google regarding storing user data for sessions, but most have been for PHP and not Rails.
Additionally, I've watched Dangers of Model in Session on RailsCasts.
Let's say I have a user that logs in, and I want to access some basic preferences from the user like: zip code, height, weight, and perhaps, 10 other things that I would like to access later.
Should I?
Store those 10 things in a hashed session variable?
e.g., session[:user_prefs] = User.find(:first)
Just store the user's ID as a sesion variable, and then run queries later to access the zip code, height, weight, etc?
e.g., session[:user_id] = User.find(:first).id
Or, is there something entirely different that I should be doing?
I'm not sure what the standard coding practice or best practice would be for this scenario.
Any help would be great.
Option 2 is the way to go.
Option 1 is "No" because your session data will be out of sync with the database as soon as the user information gets updated. Say for example you store those ten fields in the session upon user login, and later in the application the user updates one of those ten fields, now the session data is out of sync with the database. You could define a function that updates the session data when one of the attributes changes but I think this adds unnecessary extra complexity to the application.
Option 3, I cannot think of anything that replaces the session for this requirement. There are other ways you could implement the session logic but they would just be your version of already provided(by Rails) implementation of session.

How to automatically maintain a table of users that have been authenticated by IIS 7.0 using Windows Authentication

I want to build and maintain a table of users. All users that access the ASP.NET MVC site are authenticated via Windows Authentication so they're bound to have a unique username. I'm grabbing the user name from:
System.Web.HttpContext.Current.User.Identity.Name
I feel like I could go two ways with this.
Anytime the user table or any tables that references the user table are accessed, I could add the user if it doesn't exist. I'm worried this might be very error prone if user's existance isn't checked.
Anytime the user visits any page on the site, check if that user exists in the db and if they don't exist, add the user. This may have a lot of overhead as it'll be checked every page change.
I'd like to hear which of these is the better solution and also how to implement them.
I think a better way would be something similar to the option two.
Anytime a user visits a page, check a session variable to see if that user was checked against the DB. If the session variable is not there, check if that user exists in the DB, add the user to your table if necessary, then set the session variable.
That way you don't have to hit the DB on every request.

rails: how to detect other clients browsing the same url

What want to be accomplished is:
I want to "synchronize web browsers". my site has a "wait URL" where when browser gets there it will be kept waiting till another browser also go there and then both will be presented with a quiz-like game.
Right now the wait url will call each second to Rails to check if other player came to the game. How can in the Rails framework detect a different client connecting to the same URL?
As the controller is recreated per request looks like is not the place, not the view for sure and storing this in the model looks really clumsy.
Also, after the pairing I need to check and compare every answer of the paired users so somehow that information must be retained
What you're trying to do is share information between users. So the database or memcached are the most sensible.
Simplest: I'd create an ActiveRecord object, perhaps called Quiz, instances of which people join by virtue of going to a URL, e.g using default routes:
http://yoursite.com/quizes/join/3434
You'd need an ajax poller poller to notify the others; use periodically_call_remote for this -- you could use render :nothing => true by default and render something else if there was an error to keep it efficient. You can also use the frequency method as a basis to determine whether people leave the quiz as well (e.g. if frequency is 1s, then assume someone has left if they didn't ping after 5-10s).
Assuming these users are not registered with the site so don't have some kind of user id you could store I would suggest using the session. It is a per user data store. By default the session is stored in an encrypted cookie on the users machine. However you can use ActiveRecord as the session store and could maybe query that table directly?
Store the URL in the session and do a search for it at a later time. You can normally only access the current users session using the Rails 'session' hash but maybe (untested) if you created a model called Session (or maybe something more specific like 'WaitingGamers') which used the sessions table you could lookup the information you need.
I would guess when using ActiveRecord as the session store the session data is stored as a serialised hash. Use Marshall to turn it back in to a regular hash and find the data you stored in there.
I'm not a rails expert, but since all the state resides in your database that would be the place to keep this information.
You could keep a "waiting users" table, and in the "wait URL" view check if the user is already in the table. If not, add him to the table. Then, check if there is another user waiting (maybe there's more than one?) and if so, match them up and delete them from the table.
Another improvement would be to keep a timestamp for each user in the "waiting users" table, which gets updated in the view - this would serve as a keep-alive that will enable you to detect users that left the "wait URL" page or closed the browser.

Rails w/ ActiveRecord Sessions and Restful-authentication: when does the sessions table get written to?

Warning: some of this may be very wrong-headed, so please let me know if my assumptions are incorrect.
Here's what I'm trying to accomplish:
I'm using restful-authentication for login. However, as I am using flex/ruby_amf for my UI, I have to separately authenticate each connection from flex.
The way I decided to do that was by having the log-in screen redirect to the embedded flash page, inserting the session-id as a flashvar. The flash app sends the session-id with every request, and a before filter on all of the relevant controllers checks to see if the user associated with the session identified by the session-id is logged on.
The way I associate a user with session is by adding a 'user_id' column to the sessions table, and doing an sql "update sessions set user_id...'" type query called from the login function.
However, the user_id only gets updated the 2nd time the user logs in. A little investigating showed that the record in the sessions table does not yet exist during execution of the login function.
So, if everything up to this point makes sense, and conforms to best-practices, etc., then my question is:
At what point in time is the record in the sessions table created? Is there a way to update the session object in the login function and have rails write the user_id to the database for me?
The behavior of sessions in rails is a real mystery to me. I'd appreciate any help.
Thank you.
In Rails 2.3, the session is saved after the Rack application has finished its processing. In traditional Rails applications, this will be after the request is fully processed: before filters, controller action, view rendering, and after filters. Look in actionpack/lib/action_dispatch/vendor/rack-1.1.pre/rack/session/abstract/id.rb.
If you think about it, this makes perfect sense. Writing the session to its store every time you place something in the session would incur a lot of extra overhead.
It's Rails, so if you want to mess with it enough, sure, you can monkeypatch yourself a way to write the session to store anytime you wish. I don't recommend it. You'll end up having to rework the code constantly as Rails evolves.
You are right that for ActiveRecord::SessionStore, one row does map to one session. The data column is an encoded form of every object you put in the session. Each time a request comes in, Rails has to reconstitute the session as it existed by creating new instances of all the objects you previously stored in it.

Resources