Trouble assigning user access levels - ruby-on-rails

I'm following this tutorial, as I wanted to learn how to create user authorization with singular roles (each user has one role) from scratch rather than using a gem like rolify that does it all for me, but I'm hung up on assigning the users access levels.
When I type erin = User.find(9) in the console it finds my test#test.com user. I try to issue the erin.admin! command but it throws an error about the password? (ActiveRecord::RecordInvalid: Validation failed: Password can't be blank).
I've also tried erin.access_level = "admin" which returns "admin" while I'm still in the console but no longer exists when I exit the console, fire up the rails server and try to test out my test#test.com user in my app.
Is there any other way to assign access levels? Am I just doing it wrong?

The User record cannot be saved because a validation exists that requires a password. I don't know if there are special rules for the format of the password, but you can easily set a password so that you can save the user:
user = User.find(9)
user.password = 'Test1234'
user.password_confirmation = 'Test1234' # you might need this as well
user.access_level = 'admin'
user.save #=> true
If user.save returns false, check user.errors for any other validation errors that would cause the record not to save.

For the second part of my question, where my database didn't seem to deploy to Heroku, it's because I was working in the dev db, not the production db.
To do that, I ran "heroku run rails console" and then followed the above steps to give a user admin access levels. More here: https://devcenter.heroku.com/articles/getting-started-with-rails4#console

Related

Cannot reach the password of the user after assigning it - RSpec

I am trying to write system tests. I want to run a classic login page test.
I have a field for email, password, and submit button.
It is working in production env and alive without any problem.
my test file is like this:
it "can login" do
user = User.create(email: 'mail#mail.com', password: 'password', role:1, name: 'test user')
user.save!
visit '/'
fill_in(:user_email, with: user.email)
fill_in(:user_password, with: 'password')
find(:button, 'Sign in').click
expect(page).to have_content('Signed in.')
end
Whenever I tried to create a user and try to use it in the system testing, it is not working. It is visiting the page, filling the places and clicking the button as it should but it cannot log in, giving error that email or password is not correct.
I believe there is a problem with password encryption or somehow I cannot match the passwords properly.
I have printed out the user after creation in the test case, I have a valid user but somehow I cannot reach its password. I checked the model, there is not a 'password' field. ( I am working on a company project, that is why I am having difficulty to find the problem )
I can assign a password with using user.password = ... but I cannot call it back it seems. (I tried this in rails console, assigning worked, calling back did not and I could use the user and the password for logging in manually)
EDIT:
I found out that the problem is database matching. I could create the user but the test is not using that user...
I found the problem. It was because of data transaction. I changed it truncation for system testing and it worked! It was basically flushing all the data before using it. That was why I was getting error.

Creating users (with no registration) using Devise

I want to be able to create users and save them to the database but Devise doesn't pass the request to the database, and doesn't return any error.
alice = User.new
alice.name = "Alice"
alice.save!
alice gets saved successfully, just not in the database.
I can do User.find(alice.id) and it returns data as long as I'm in the same session.
If someone have this problem, I found that Devise enforces email even when setting
email_required?
false
end
so even hitting save! will not raise an error.
Therefore the only way i found is to create a fake email, using something like this
"guest_#{Time.now.to_i}#{rand(99)}#anyemail.com"
then assign a self.role = guest, so the account would be easily identified.
I hope this helps

Ruby on Rails - ApplicationController

Am working on some guest account feature in my game application.If u register as a game user then devise gem loads the current account id to the session automatically. But when a user is a guest, am creating a account and a user type object with hard coded values and saving that to the database successfully. But when I try to store the object into the session its not working properly.
My code is like this,
def play_as_guest
account = Account.new(email: "guest_#{Time.now.to_i}#{rand(99)}#eossys.com", password: "password", is_guest: true)
account.save
game_user = GameUser.new(account: account, game_profile_attributes: {first_name: "Guest", last_name: "guest", nick_name: "guest"})
game_user.save
session[:current_account] = game_user
redirect_to "/game_profiles/#{account.id}/summary"
end
If i store the account obj
session[:current_account] = game_user
this is throwing an error of "ActionDispatch::Cookies::CookieOverflow in HomeController#play_as_guest"
if I try
session[:current_account_account] = account
its not working, because after redirecting its again asking for the login. since I am using the 'authenticate_account!' filter in every class.
What I want basically is to load the account object I have created into the session, like as if its a registered user.
Thanks for the help in advance.
Rails cookies have a maximum limit of 4k ( http://guides.rubyonrails.org/security.html#session-storage ). When you do something like obj session[:current_account] = game_user, you are attempting to stuff the whole game_user object in there, which causes you to run out of room with the ActionDispatch::Cookies::CookieOverflow error you mentioned. The preferred way to do this is to save only the id, like this obj session[:current_account_id] = game_user.id,and look it up when you need it. This is much more efficient, even if your whole object did fit into memory somehow.
I think we need the code of your authenticate_account! filter to answer it properly but for your error, this is because you try to put an entire object in your session, it is better to only put the id of the object in it :
session[:current_account] = game_user.id
UPDATE
With devise you should use the sign_in method to set the session for this user instead of manually setting the session variable, depending of how your are using devise it could be:
sign_in account or sign_in game_user

How do I reset a user password from the console in Hobo/Rails

The rails framework Hobo is brilliant and automatically creates the first user as the admin user (unless you ask it not to). The problem I have is that running rails in development I can't remember what the password was. This should be trivial because I just run rails console, find the user admin = User.find :first and reset the password (trying)
admin.password = 'Anything1234'
admin.password_confirmation = admin.password
admin.save
>false
admin.errors
>{:current_password=>["is not correct"]}
I.e. the implication is that the variable current_password needs to be set correctly before I can change the existing password.
I'm afraid the Hobo documentation doesn't help in this case. Does anyone know the how to drive the Hobo user model to reset the password?
4 possible solutions:
1: run your app, and click on the forgot password link. The message will appear in your logs, so you don't need a mailer set up.
2: Just save without doing any validations:
admin.save(false)
EDIT: in Rails 3 this is
admin.save(:validate => false)
3: Another option is just to delete all users so you get your initial user entry screen back.
4: If you really want to run the validations, you can trigger the request_password_reset lifecycle:
admin.lifecycle.request_password_reset!(Guest.new)
then look in development log for the reset password key
u.lifecycle.reset_password!(Guest.new, :key => 'a0a2db1035065fa7ad5d46d35669d206aee73668', :password=>"test123", :password_confirmation=>"test123")
Yes, you need to set the current_password before you set the password and password_confirmation fields. This is to stop the user from changing the password without originally knowing the password.
Therefore, you would need to do something like this:
admin.current_password = 'password'
admin.password = 'Anything1234'
admin.password_confirmation = admin.password
admin.save

Migrating existing user model to Devise

I'm trying to migrate a legacy app to Rails 3 and change the authentication to use Devise. I've created the model and migrations and imported all the user data.
I don't plan to migrate the passwords over as the existing scheme is not one we'd like to use going forward, but I want to be able to present users with a simple experience.
Ideally I'd like to catch a login error and then check the password with the legacy field and then update the Devise password with it if it matches.
I can see that Warden gives me a callback that can trap errors so I expect I can trap a login error.
However because all the passwords (in Devise) are blank I get errors relating to the hash as the encrypted_password fields are empty.
Is there a way I can update all the user accounts with a random password?
I've seen in Devise::Models::DatabaseAuthenticatable that there is a method 'password=' but if I call that, e.g. in rails console for the app:
User.find(1).password=('new')
=> "new"
I just get the same plain text string back ('new') and saving the user record post this doesn't populate the encrypted_password field.
I've searched around but can't seem to be able to find it. Any suggestions much appreciated!
Ok just in case anyone else is as cloth headed as I have been the last 24 hours, here's how you set the password:
user = User.find(id)
user.password = 'new-password'
user.save
Simple really :)

Resources