Migrate legacy database users to Devise - ruby-on-rails

We have an old PHP app in MySQL that we're currently rewriting in Rails and PostgreSQL.
I'm looking for a way to migrate users one-by-one when they first sign in to the new system, so that we migrate only active users.
Is there a hook in Devise that I can use to catch a failed login towards the new database and check if the user exists in the old MySQL database and migrate the user if found.
BTW, the Rails app can access both databases and the migration code is already in place that accepts old username as input.
Or should I just simply make a separate _migration_assistant_ page that accepts old logins and initiates the migration?
PS. any user can possibly have thousands of database records to migrate so it can take a bit of time, but we already make use of PosgreSQL's COPY FROM to speed it up (about a few secs per account).
EDIT:
There are currently about 5000 users and we expect roughly 1000 of them to return to the new site.

You could migrate the required data from just your users table. Include the original primary key in a column 'old_id'.
Create a custom encryptor so that users can log in with their existing password.
Redirect users when they log in to a page that triggers the migration process per user making use of the saved 'old_id'.
After your migration period you could look at the Devise trackable columns to determine which users can be cleaned up.

Related

Rails App With No Sign Up But Has Log In

I need some advice on a Rails app where I want to have signing up to be private (or not have one at all with users pre-registered in the seeds.rb file). In other words, I do not want random people off of the internet to be able to sign up. I know that I could easily not making a signup form and tweak my app accordingly, but the problem lies with the seeds.rb file containing sensitive information (i.e., passwords). The passwords need to somehow be encrypted. Any advice would help. Thanks.
You have multiple options:
Disable sign up and do it manually using an admin user (thinking about ActiveAdmin gem).
Register that users at DB (without rails' knowledge). I don't know what DB you're using, but imagine you're using postgreSQL (for instance). Go to your DB and manually insert the users on DB using some kind of user interface (command-line or graphic/visual)
Use environment variables at deployment that contain passwords.
Give them a default password and make them change password once they log in.
... there are more options, but you need to be explicit about what you want to achieve. Do you want to start with X users and don't add more? Do you want to start with X users and be able to expand to more users?

Separate database for every users in application in mvc5

I have application which stores all the user specific information in one database. But, I want to make user specific database. For instance, when user register in application then it should create database for that particular user with the same schema, which i currently have in database. Guide me if there is any solution for it.

Changing database structure and migrating password hashes

I currently have a site (Rails 4.1, ActiveRecord, Postgres) where a visitor can log in to one of multiple models — for example, a visitor can create an account or login as a User, Artist, etc. Each of these models have a password_digest column (using bcrypt and has_secure_password).
Now we want to move to the site to a unified login system — everyone creates and logs in as a User, and a User can belong to an Artist and the other models we have.
I think it makes sense to directly use the password_digest column in the User table, rather than looking across all the existing models. This means we'll have to create new entries in the User table and copy the password_digests into them.
Can this be safely done, and would everyone be able to login with the password they already have? I've tried playing around with password_digests in the Rails console (copying digests to known passwords and assigning them to other entries) and it appears to authenticate correctly … are there any downsides to doing this?
There's no uniqueness constraint on passwords (i assume) and so it doesn't matter if the passwords are the same between different User accounts (in the resulting table, with all the Artist etc records copied in). There's no safety issues with copying the data from one table/column to another: there's nothing magical about the password_digest value, it's just a text string. As long as you carry on using the same encryption method then the crypted password you generate to test on login should still match the saved value.
You may have a problem with usernames though, if they are required to be unique: what happens if you have an existing User and an existing Artist who have the same username? Is one of them going to have to change?

Migrating existing authentication to has_secure_password

In my application, I have two different user accounts. The old account type was using a custom built authentication system. The newer one implements has_secure_password. Now I'm ready to move the old account type to the same system. In the database, that user type has a hashed_password column.
I have it working so that creating new users works, and they can login just fine on the new system. The problem is that I need existing users to be able to migrate their passwords from the hashed_password to password_digest. What is the best way to go about doing this?
It's possible, but you'll have to juggle a bit. Let's say you've used MD5 to hash passwords before you wanted to migrate. Make sure you have made a backup before you migrate :) Add a boolean column migrated_password to the database, default true. In your migration, do something like User.update_all(migrated_password: false) for existing users.
Use the current MD5 hashes as input for the has_secure_password function. Alter your login code to handle two paths, depending on the value of the migrated_password column. If the password is migrated (or the user registered after the migration), you use has_secure_password straight out of the box.
If it isn't, you hash the password with MD5 before feeding it to the authenticate method. If the login is successful, change the password of that user with the input password from the params and update the migrated_password column to false (wrap those two actions in a transaction).
After a certain amount of time you can delete the the migrated_password column and the migration code, and let users use your password reset functionality if they still need access but haven't migrated in time.

Is there a way to load and set a specific session from the database in 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..

Resources