Adding custom parameters to devise registration - unpermitted parameters - ruby-on-rails

I've been trying to customize the devise register method to register with more parameters and also update more(no luck so far), but I always get Unpermitted parameters: error. I tried using this Adding extra registration fields with Devise and https://github.com/plataformatec/devise#strong-parameters, but I cant get over that.
I've also thought about creating a new table to hold a foreign key the user id and put in there stuff like user_id, display_name, profile_picture, but I would have the same problem when trying to submit everything from the same page(mess with the devise controller).
Do you have any suggestions on how I can solve this? What else do I have to post?
routes.rb
devise_for :users, controllers: { registrations: 'users/registrations' }
users/regC
def create
build_resource(registration_params)
if resource.save
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_navigational_format?
sign_up(resource_name, resource)
respond_with resource, :location => after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
respond_with resource, :location => after_sign_up_path_for(resource)
end
else
clean_up_passwords
respond_with resource
end
end
private
def registration_paramss
params.require(:user).permit(:email, :display_name, :terms_of_services, :profile, :password, :password_confirmation)
end

Looks like you just need to tell devise which parameters should be permitted. By default, devise permits the email (or username depending on configuration), password and password_confirmation params. You just need to add more.
The devise documentation suggests a "lazy way" of setting this up.
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:display_name])
end
end
The documentation then says that
If you have nested attributes (say you're using accepts_nested_attributes_for), then you will need to tell devise about those nestings and types.
Only if you need to override the registrations#create action you should provide your custom route for devise. In that case, make sure you override the sign_up_params method too.
class Users::RegistrationsController < Devise::RegistrationsController
def create
# Your custom code here. Make sure you copy devise's functionality
end
private
# Notice the name of the method
def sign_up_params
params.require(:user).permit(:display_name, :email, :password, :password_confirmation)
end
end
In essence, you'd have to look into how your sign up form is posting the parameters to figure out how to configure strong parameters in the controller. Make sure you read on strong parameters syntax as well.
Hope it helps!

For Devise 4.2.0 you can whitelist additional parameters for your users table by adding those values to keys. By default devise gives you the comment to go off of now. Below I added :avatar
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:attribute, :avatar])
end

The accepted answer says the config should go in your applicationController but it can simply go in your user registration controller and you can specify that you only want to run it for create method and nothing else:
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
protected
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:enter_param_name_here])
end
end

In my case this worked:
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:account_update) { |u| u.permit(:name, :last_name, :image,:email, :password, :password_confirmation, :current_password) }
end
end

Related

Rails 7 Unpermitted parameters:

am gonna add the error and also my controller where i think its the source of the error
I have tried different solutions, but none of them worked, the weird thing, my code was working this morning, and this error only occurs after I added new tables to the database
this is my controller
class UsersController < ApplicationController
before_action :configure_permitted_parameters, if: :devise_controller?
def create
#user = User.new(user_params)
if #user.save
redirect_to root_path, notice: 'Sign up successful.'
else
render :new
end
end
def index
#users = User.all
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:full_name, :password,
:password_confirmation])
end
end
and this is the error
Unpermitted parameters: :full_name, :password_confirmation. Context: { controller: Devise::SessionsController, action: new, request: #ActionDispatch::Request:0x00007fc5b5ca5a58, params: {"authenticity_token"=>"[FILTERED]", "user"=>{"full_name"=>"shaker abu drais", "email"=>"shaker_abady#yahoo.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Sign up", "controller"=>"devise/sessions", "action"=>"create"} }
I have tried different solutions, but none of them worked, the weird thing, my code was working this morning, and this error only occurs after I added new tables to the database
What is it that you're actually trying to acheive here? If you're trying to just add additional attributes to the user registration then this code is just completely misguided.
You can whitelist additional attributes either through your ApplicationController which is the superclass for Devise's controllers:
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
private
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:full_name, :password,
:password_confirmation])
end
end
Or by creating a subclass of Devise::RegistrationsController and configuring the routes if you need to customize the workflow further:
devise_for :user, controllers: { registrations: 'my_registrations' }
class MyRegistrationsController < ::Devise::RegistrationsController
before_action :configure_permitted_parameters, if: :devise_controller?
# Don't clobber the entire `#create` method. Especially not without actually
# replicating its functionality
def create
super do |user|
# do something with the newly registered user
end
end
private
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:full_name, :password,
:password_confirmation])
end
end
Note that I wouldn't call this controller UsersController. There is a reason why Devise choose the name Registrations - its because it differentiates between signing up and for example if users are created by an admin.

Rails 5: devise invitable add custom fields

I'm trying to add devise invitable to my new application. I found a lot of information on the internet but there doesn't seem to be a go to solution.
So the problems I'm facing are the following:
When a user invites someone the account gets created, while the standard email template generated by devise says 'Your account won't be created...'
When a user clicks the activation link he gets redirect to the edit page, but when they submit their information my columns :fullname, :terms_of_service are not saved.
Probably I'm missing something.
This is my invitations_controller
class InvitationsController < Devise::InvitationsController
def new
super
end
def create
User.invite!(invite_params, current_user)
redirect_to dashboard_path
end
def update
user = User.accept_invitation!(accept_invitation_params)
end
def edit
end
private
def invite_params
params.require(:user).permit(:email, :ivitation_token, :provider, :skip_invitation)
end
def accept_invitation_params
params.permit(:password, :password_confirmation, :invitation_token, :fullname, :terms_of_service)
end
end
My console output:
Processing by InvitationsController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"/PoYvD7be0xpE1yBGI2EsojBU62o8d+Kcx0B8LgZ7DJkrqz2lCGs1YrA8d5ziwOAVH68u+1ij7ZacecVmNfaUQ==", "user"=>{"invitation_token"=>"4a24a37282a3881a4d595f251ea4deca4d0c25cbb966d50d8d622941a55c1a4c", "fullname"=>"Arnas Klasauskas", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "terms_of_service"=>"1"}, "commit"=>"Einladen"}
Unpermitted parameters: :utf8, :_method, :authenticity_token, :user, :commit
No template found for InvitationsController#update, rendering head :no_content
My application_controller
before_action :configure_permitted_parameters, if: :devise_controller?
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:accept_invitation, keys: [:email, :fullname, :terms_of_service])
end
So if you want to add custom parameters, you can simply add this line to your update method
User.accept_invitation!(update_resource_params)
Now you'll need to add the update_resource_params method to your invitations_controller with your custom fields:
def update_resource_params
params.require(:user).permit(:password, :password_confirmation, :invitation_token, :fullname, :terms_of_service)
end
This is called when creating invitation.
def invite_resource
User.invite!(invite_params)
end
This is called when accepting invitation.
def accept_resource
resource = resource_class.accept_invitation!(update_resource_params)
resource
end
This is where you customize your fields
def invite_params
params.require(:user).permit(:email, :invitation_token,...)
end
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:accept_invitation, keys: [:name, :time_zone, :terms_of_service,...])
end

log in user right away after the user signs up

I am using devise token authentication(devise_token_auth) for user login and signup based on token because it is only for developing an api. I need to make the user logged in soon after the user registers his/her account. How can i do it so? I have tried but could not succeed so i am here with the hope of help.
class Users::RegistrationsController < DeviseTokenAuth::RegistrationsController
prepend_before_action :configure_permitted_parameters
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:account_update, keys: [:id, :first_name, :last_name, :phone, :status])
devise_parameter_sanitizer.permit(:sign_up, keys: [:confirm_success_url])
end
private
def user_params
params.permit.all #(:id, :email, :firstname, :lastname, :phone, :status)
end
end
Rails.application.routes.draw do
# devise_for :users, controllers: { confirmations: 'confirmations' }
mount_devise_token_auth_for 'User', at: 'auth', controllers: {
# confirmations: 'confirmations',
registrations: 'users/registrations',
passwords: 'users/passwords'
}
class ApplicationController < ActionController::API
before_action :authenticate_user!
include DeviseTokenAuth::Concerns::SetUserByToken
def authenticate_current_user
head :unauthorized if get_current_user.nil?
end
def get_current_user
return nil unless cookies[:auth_headers]
auth_headers = JSON.parse cookies[:auth_headers]
puts('################################')
puts('auth_headers', auth_headers)
expiration_datetime = DateTime.strptime(auth_headers["expiry"], "%s")
current_user = User.find_by(uid: auth_headers["uid"])
if current_user &&
current_user.tokens.has_key?(auth_headers["client"]) &&
expiration_datetime > DateTime.now
#current_user = current_user
end
#current_user
end
end
I tried this below code
def after_sign_up_path_for(resource)
puts('it should be shown')
puts('################################')
puts('resource', resource)
puts('header', request.headers['client'])
client_id = request.headers['client']
new_auth_header = #resource.create_new_auth_token(client_id)
response.headers.merge!(new_auth_header)
end
in the Users::RegistrationController but it is not executed at all after successfully signing up.
Not too complicated. After creating the user, just call sign_in and pass the resource (user).
https://github.com/plataformatec/devise/wiki/How-To:-Sign-in-from-a-controller
Example:
sign_in #current_user
The Devise::RegistrationController in fact, already does this.
Furthermore, since you're using the DeviseTokenAuth gem and the DeviseTokenAuth::RegistrationsController controller inherits from Devise's own base controller, you (should) have access to all the helpers that Devise controllers do.
One implementation might look like this.
class Users::RegistrationsController < DeviseTokenAuth::RegistrationsController
def create
super do |resource|
sign_in(resource)
end
end
end

"Undefined method `concat'" on "devise_parameter_sanitizer.permit"

I'm writing a custom sign-up devise controller, and I'm having trouble adding permitted params due to this error (this is the output from Rspec, but the same error happens manually):
Failure/Error: devise_parameter_sanitizer.permit(:sign_up, keys: [:nome, :password, :password_confirmation, :cnpj, :razao_social, :nome_fantasia, :email, :tipo_entidade_id])
NoMethodError:
undefined method `concat' for #<Proc:0x0055ca9fb2d850>
Did you mean? concern
The full controller:
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_sign_up_params, only: [:create]
# before_action :configure_account_update_params, only: [:update]
# POST /resource
def create
user_params = sign_up_params[:user_params]
entidade_params = sign_up_params[:entidade_params]
if !(User.exists?(email: user_params[:email]) || Entidade.exists?(cnpj: entidade_params[:cnpj]))
#entidade = Entidade.new(entidade_params)
#entidade.data_validade = 30.days.from_now
if #entidade.save
#user = User.new(user_params)
#user.entidade_id = #entidade.id
if #user.save
flash[:notice] = 'Usuario criado com sucesso.'
redirect_to root_path
end
end
end
end
protected
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up, keys: [:nome, :password, :password_confirmation, :cnpj, :razao_social, :nome_fantasia, :email, :tipo_entidade_id])
end
end
At first glance it seems like a bug in the gem, but no one seems to have this issue - google returns nothing relevant. Is this an error in my code?
I'm not sure if it was the case, but this error can occur if you duplicate the parameters sanitizer, like using it in users controller but also in application controller.
You can see a more detailed explanation here:
GitHub issue closed

How to inherit from Devise Controllers

I have a user model which uses Devise for authentication and also have an administrator model, which also uses Devise.
I want administrators to be able to edit users profile via administrators/users/{user.id}/edit, however I want this process to be done through Devise Controllers, therefore I tried to inherit from the Users::RegistrationsController as shown below:
class Administrators::UsersController < Users::RegistrationsController
before_action :set_user, only: [:show,:edit,:update,:destroy]
def index
#users=User.all
end
def show
end
def new
super
end
def update
#user.update(user_params)
redirect_to [:administrators,:users]
end
but I get the following error:
Could not find devise mapping for path "/administrators/users". This may happen for two reasons: 1) You forgot to wrap your route inside the scope block. For example: devise_scope :user do get "/some/route" => "some_devise_controller" end 2) You are testing a Devise controller bypassing the router. If so, you can explicitly tell Devise which mapping to use: #request.env["devise.mapping"] = Devise.mappings[:user]
I tried to change the routes but I still get the same error.
Could you please help me?
Inheriting from Devise::RegistrationsController may initially seem like a good idea from a code reuse standpoint but it really not a very good idea.
The intent of the controllers is very different - Devise::RegistrationsController partially deals with an un-authenicated user - and the Devise controllers are scary beasts due to the amount of flexibility built in Devise.
Instead you should just setup a plain old CRUD controller as the task at hand is not very complex compared to clobbering over half of Devise::RegistrationsController.
# config/routes.rb
namespace :administrators do
resources :users
end
# app/controllers/administrators/base_controller.rb
module Administrators
class AuthorizationError < StandardError; end
class BaseController
respond_to :html
before_action :authenticate_user!
# Replace with the lib of your choice such as Pundit or CanCanCan
before_action :authorize_user!
rescue_from AuthorizationError, with: :unauthorized
private
def authorize_user!
raise AuthorizationError and return unless current_user.admin?
end
def unauthorized
redirect_to new_session_path, alert: 'You are not authorized.'
end
end
end
class Administrators::UsersController < Administrators::BaseController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def show
end
def index
#users = User.all
end
def new
#user = User.new
end
def create
#user = User.create(user_params)
respond_with(:administrators, #user)
end
def edit
end
def update
#user.update(user_params)
respond_with(:administrators, #user)
end
def destroy
#user.destroy
respond_with(:administrators, #user)
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation)
end
end
Instead you may want to focus on reusing the views through partials for example.
See:
ActionController::Responder
Pundit
CanCanCan

Resources