Devise, allowing users to change passwords - ruby-on-rails

I have an application that has a custom registration controller, called users_controller, for devise because only Admin is able to create users. I want to allow users to change their password by entering their old password and entering a new one and I found: https://github.com/plataformatec/devise/wiki/How-To:-Allow-users-to-edit-their-password but it does not give enough detail.
What do I need to put in my routes?
Where and what do I need to put in my views?

If you have a devise model User, you can use this path to route to the change password page.
edit_user_registration_path
Just use this in your view as:
<%= link_to 'Change Password', edit_user_registration_path %>
This should do the trick, it works for me.

I have found the soulution and have fixed this on the Devise wiki

This is not enough, tough. You'll have to add attr_accessor :current_password to the model, like explained in here.

Related

code reusability issue in active admin rails

How to avoid common code used in active admin action item and controller action.
I have seen people used to write the same code in the controller and active admin action item.
Is there any way to avoid it?
Example is like i want to cancel a user and it requires 3-4 steps to do it.
So i have writtent this code in users controller.
Now i have resource user in active admin and i want to delete the user from active admin. I have created an action item and again written the same code of deleting the user in the member action.
Is there any way to avoid above.
If you want to share code between different controllers, you should look to the rails concerns https://api.rubyonrails.org/v5.2.2/classes/ActiveSupport/Concern.html
Assuming this is in the User register block (probably at app/admin/users.rb) this might help you. The action_item only contains a link (actually a form that posts) to the actual member_action. This is just example code:
action_item :cancel_user, :only => :edit do
link_to 'Cancel user', do_cancel_user_admin_user_path(resource), method => :post
end
member_action :do_cancel_user, :method => :post do
flash.notice = "User will be canceled"
resource.cancel # I guess this would the 4 lines of code that you are repeating
redirect_to edit_admin_user_path(resource) and return
end
Let me know if this did/did not confuse you. Good luck!
P.S. A few weeks ago someone asked something similar, this might also be of help: How to reset userĀ“s password by Devise authentication token directly from edit_page in Active Admin?

rails single authentication mixed with edit

I have a question on rails. I'm implementing a resource. The new/create actions are finished. Now I am working on the edit/update actions.
I want the user to have to input the password for the resource and then he can edit the values.
Either on two sites, so first "input password" and afterwards he can update the values, or just on one site where he has to enter the correct password and can update the values.
But I have no idea how to achieve this the best way.
Do you have any tips? I'm still a beginner.
Just have a :password field in params. Then in your controller you can do this.
def update
raise Unauthorized unless user.authenticate(params[:password])
#normal update stuff
end
You will have load the user and define what Unauthorized error is in this situations. You could also just render out and return a flash if you would rather go that route.
In the form you will just add an input field that
<%= f.text_field :password %>

How can an admin add another user or admin accounts in ruby devise without logging them in?

I have an admin account which logs into a separate account page. I want to have the ability to add a new account without logging them in I tried using this
<%= link_to "Add a New Account", new_user_registration_path %>
to redirect to the pre-existing sign up view but I keep running into the following message in the application.
You are already signed in.
What am I missing here?
You will need to use a different route to avoid the checking done by devise, such as adding "resources :users" to routes.rb and link_to( "Add a New Account", new_user_path ) in the views.
However, this will clash with the paths used by devise. Thus leading you to the the link #PrakashMurthy recommended his the comment.
Something like this should work: (of course, you'll need the users_controller code too.)
add this your routes.rb
resources :admin_users, controller: "users"
and change this in your views
<%= link_to "Add a New Account", new_admin_user_path %>

if can? in Ruby on Rails

In a Ruby on Rails application that I inherited from someone, I have code that looks like so
<% if can? :create, :objects %>
<%= link_to 'Add New Object', new_object_path %>
This web application has a login and users have different permissions that are defined in a table called groups_roles (which groups (ex. admin, user) have which roles (ex. add new objects))
I want to add new permissions, so where do I do that at? Where are these things defined? How does Ruby know which table to get the different permissions from, and how does it know what :create and :objects are in the code above?
The app seems to be using the cancan gem by ryan bates. You can specify the permissions in the app/models/ability.rb file.
It simply reads the ability file to determine if a user can perform some action or not. These actions correspond directly to the actions you have defined in the controller class.
Cancan has a great wiki at its github repositiory. Also, the screencast by ryan is an excellent place to start off with.
I do not know how the application is working, but the can? comes from the cancan gem. See the screencast.

Keeping a query-string in devise sign up

I am using rails with devise for signing up. Also I added an invite code, so not everybody can sign up.
The invite code gets transmitted via query-string like "/users/sign_up?invite_code=wajdpapojapsd" and gets added to a hidden field of the sign-up form with "f.hidden_field :invite_code, :value => params[:invite_code]".
This works pretty well. The only problem is that if the sign up doesn't get validated and rejected, devise redirects to "/users" and loses the query string with the invite_code in it.
As the email stays in the sign up form after the failed attempt, I believe that this should also work for the invite code. As a worst case solution redirecting :back after a failed sign up and losing the email, but keeping the invite code, would be better than the way it works now.
EDIT: By now I ve set up a registration controller for devise, but don't have any idea how to get the desired behavior.
Any help on how to keep the query string or just the invite code would be awesome.
I found a working solution by now.
I used jstr's answer to set up the controller for devise and added the "session" line.
class MyRegistrationsController < Devise::RegistrationsController
prepend_view_path "app/views/devise"
def create
super
session[:invite_code] = resource.invite_code
end
def update
super
end
end
Afterwards I added following to the devise/registrations/new.html.erb
<% if params[:invite_code]
#invite_code = params[:invite_code]
else
#invite_code = session[:invite_code]
end %>
And changed the hidden_field to
<%= f.hidden_field :invite_code, :value => #invite_code %>
You might need to make your own subclassed Devise controllers to get this to work.
This answer has a good description of how to to this.
The basics:
Install the Devise views if you haven't already with rails generate devise:views
Create a subclassed Devise::RegistrationsController
Update your Devise routes declaration to get Devise to use your subclassed controller
#James Lever 's solution has one disadvantage. invite_code remains in session. In some solutions it can cause problems. The alternative soultion would be:
def create
# set invite code to session:
session[:invite_code] = resource.invite_code
# here the form is rendered and invite code from session would be used:
super
# delete invite code from session:
session.delete('invite_code')
end
why don't use instance variable such
#invite_code = params[:invite_code]
Then when a sign up didn't pass validation, you can use that variable in the view which will be displayed for failed sign up.
I mean before, it's redirected, you should keep the invite code parameters with instance variable. sorry if i'm mistaken.

Resources