Before writing this I have checked out the official guides and similar questions but somehow I keep getting problems and they don't help.
The thing is that I need the users to have the ability to change their passwords. To do that, I use Devise, and its views. I can use Devise perfectly in all other areas, but when I try this, even with account just created for that, It gives 2 errores: current password is not valid, and password confirmation is not valid.
I have tried sanitizers in two ways:
users/registration_controller.rb
# frozen_string_literal: true
class Users::RegistrationsController < Devise::RegistrationsController
# before_action :configure_sign_up_params, only: [:create]
skip_before_action :require_no_authentication
before_action :authenticate_user!
before_action :authorize_admin!, only: :create
# before_action :configure_account_update_params, only: [:update]
# GET /resource/sign_up
# def new
# super
# end
# POST /resource
def create
build_resource(sign_up_params)
resource.save
yield resource if block_given?
if resource.persisted?
if resource.active_for_authentication?
set_flash_message! :notice, :signed_up
respond_with resource, location: after_sign_up_path_for(resource)
else
set_flash_message! :notice, :"signed_up_but_#{resource.inactive_message}"
expire_data_after_sign_in!
respond_with resource, location: after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
set_minimum_password_length
respond_with resource
end
end
# GET /resource/edit
# def edit
# super
# end
# PUT /resource
# def update
# super
# end
# DELETE /resource
# def destroy
# super
# end
# GET /resource/cancel
# Forces the session data which is usually expired after sign
# in to be expired now. This is useful if the user wants to
# cancel oauth signing in/up in the middle of the process,
# removing all OAuth session data.
# def cancel
# super
# 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: [:first_name, :last_name, :email, :password, :password_confirmation, :creditos, :role, :birthday, :dni, :address, :phone, :gender])
end
# If you have extra params to permit, append them to the sanitizer.
def configure_account_update_params
devise_parameter_sanitizer.permit(:account_update, keys: [:first_name, :last_name, :email, :password, :password_confirmation, :current_password, :creditos, :role, :birthday, :dni, :address, :phone, :gender])
end
# The path used after sign up.
def after_sign_up_path_for(resource) #Resource is the user just created
empresa = Empresa.create(user_id: resource.id)
resource.empresa_id = empresa.id
if resource.save(validate: false)
edit_empresa_path(resource.empresa)
else
flash[:alert] = "Ha habido un problema"
redirect_to (root_path)
end
end
# The path used after sign up for inactive accounts.
# def after_inactive_sign_up_path_for(resource)
# super(resource)
# end
private
def authorize_admin!
unless user_signed_in? && current_user.admin?
redirect_to root_path, alert: "TĂș no eres administrador."
end
end
end
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
private
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up) do |user|
user.permit(:email, :password, :password_confirmation, :role, :creditos )
end
devise_parameter_sanitizer.permit(:account_update) do |user|
user.permit(:email, :password, :password_confirmation, :current_password, :role, :creditos )
end
end
end
Note: I have verified several times with different accounts that the current password is ok. The methods above were used one at a time. Not simultaneously.
Related
I want to grant all permission to admin, and only read permission to normal user.
so, after hitting /posts/1/edit for admin its working fine, but for normal user its giving
ArgumentError in PostsController#edit
wrong number of arguments (given 2, expected 0..1)
Application_Controller.rb
class ApplicationController < ActionController::Base
before_action :configure_permitted_parameters, if: :devise_controller?
protect_from_forgery with: :exception
rescue_from CanCan::AccessDenied do
flash[:error] = 'Access denied!'
redirect_to root_url
end
protected
def configure_permitted_parameters
added_attrs = [:first_name, :last_name, :phone, :gender, :username, :email, :password, :password_confirmation, :remember_me]
devise_parameter_sanitizer.permit :sign_up, keys: added_attrs
devise_parameter_sanitizer.permit :sign_in, keys: [:login, :password]
devise_parameter_sanitizer.permit :account_update, keys: added_attrs
end
end
Post_controller.rb
class PostsController < ApplicationController
before_action :authenticate_user!
before_action :fetch_all_posts_and_users
#some code
def edit
#post = Post.find(params[:id])
authorize! :update, #post
end
def update
#post = Post.find(params[:id])
if #post.update(post_params)
redirect_to(post_path(#post))
else
render('edit')
end
end
def destroy
#post = Post.find(params[:id])
#post.destroy
end
private
def post_params
params.require(:post).permit(:title, :image, :total_likes)
end
def fetch_all_posts_and_users
#posts = Post.all
#users = User.all
end
end
I had also add load_and_authorize_resource
but its not working for both admin and normal user
Ability.rb
class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
if user.admin?
can :manage, :all
else
can :read, :all
end
end
end
I am using Rails API and Active model serializers to render custom JSON responses on a user when they sign up / sign in and don't know how to add generated JWT tokens to this so I can retrieve it for further requests using Postman. When I send user sign up information I need to see this token in the response with everything else.
Configuration
Rails API only
Devise for user auth
jwt gem for tokens
Postman for API requests
Here is my code:
User serializer
class UserSerializer < ActiveModel::Serializer
attributes :id, :first_name, :last_name, :email, :username, :bio, :avatar, :created_at, :updated_at
end
user model
class User < ActiveRecord::Base
include ActiveModel::Validations
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable,
:trackable
has_one_attached :avatar
def full_name
"#{first_name} #{last_name}"
end
def generate_jwt
JWT.encode({ id: id,
exp: 60.days.from_now.to_i },
Rails.application.credentials.secret_key_base)
end
end
application_controller.rb
class ApplicationController < ActionController::API
respond_to :json
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :authenticate_user
private
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:account_update, keys: [:first_name, :last_name, :username, :bio, :avatar])
devise_parameter_sanitizer.permit(:sign_up, keys: [:first_name, :last_name])
end
def authenticate_user
if request.headers['Authorization'].present?
authenticate_or_request_with_http_token do |token|
begin
jwt_payload = JWT.decode(token, Rails.application.secrets.secret_key_base).first
#current_user_id = jwt_payload['id']
rescue JWT::ExpiredSignature, JWT::VerificationError, JWT::DecodeError
head :unauthorized
end
end
end
end
def authenticate_user!(options = {})
head :unauthorized unless signed_in?
end
def current_user
#current_user ||= super || User.find(#current_user_id)
end
def signed_in?
#current_user_id.present?
end
end
routes.rb
Rails.application.routes.draw do
scope :api, defaults: { format: :json } do
devise_for :users, controllers: { sessions: :sessions },
path_names: { sign_in: :login }
resource :user, only: [:show, :update]
end
end
Assuming that you have user information stored in #user instance and the token stored in #token instance variable.
Since you have not mentioned the routes, I'll assume that you want to create a user
def create
#user = User.create(user_params)
if #user.save
render json: { user: UserSerializer.new(#user), token: #token }, status: :created
else
render json: #user.errors.full_messages, status: :bad_request
end
end
private
def user_params
# stuff
end
i am currently trying to sign up/create an account for application using devise on ruby on rails(5.2.2) and ruby version 2.3.7 but i am getting the unpermitted parameter message and tried with Strong parms but it didn't work.
tried this two posts below but didn't work
Rails 4 and Devise: Devise not saving new information (First Name, Last Name, Profile Name)
Rails 4 and Devise: Devise not saving new information (First Name, Last Name, Profile Name)
class Api::V3::ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
before_action :configure_permitted_parameters, if: :devise_controller?
# before_filter :authenticate_user!
private
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:firstname,:lastname,:username,:password])
# devise_parameter_sanitizer.for(:sign_up) << :provider
# devise_parameter_sanitizer.for(:sign_up) << :uid
end
end
Processing by Devise::RegistrationsController#create as JSON
Parameters: {"user"=>{"email"=>"testuser#gmail.com",
"password"=>"[FILTERED]", "firstname"=>devise", "lastname"=>"test"}}
Unpermitted parameters: :firstname, :lastname
it looks like devise is not accepting parameters and which is resulting in first and last name not stored in local database.
You can override the registration controller and add fields you want.
class RegistrationsController < Devise::RegistrationsController
def create
build_resource(sign_up_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
# you will get the full registration controller in devise github repo
private
def sign_up_params
params.require(:user).permit(:email, :first_name, :last_name, :password, :password_confirmation)
end
end
and add the new routes too
devise_for :users, :controllers => { :registrations => 'registrations' }
devise github repo here
I'm using devise and activeadmin.
When I log in to my app as an Admin (http://localhost:3000/users/admin) the app redirects me to to the http://localhost:3000/users/sign_in page.
So basically I have to login at some user to be able to log in as Admin. Which is really inconvenient.
this is my application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery prepend: true, with: :exception
before_action :authenticate_user!, except: [:index]
def after_sign_in_path_for(resource)
user_path(resource)
end
def after_sign_up_path_for(resource)
user_path(resource)
end
before_action :configure_permitted_parameters, if: :devise_controller?
protected
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up, keys: [:username, :email, :password, :password_confirmation])
devise_parameter_sanitizer.permit(:sign_in, keys: [:login, :password, :password_confirmation])
devise_parameter_sanitizer.permit(:account_update, keys: [:username, :email, :password, :password_confirmation, :current_password])
end
end
I have added this chunk of code to the controller with out any luck.
before_action :whois, if: :devise_controller?
def whois
if user.admin?
def after_sign_in_path_for(resource)
admin_dashboard_path
end
else
def after_sign_in_path_for(resource)
user_path(resource)
end
def after_sign_up_path_for(resource)
user_path(resource)
end
end
end
Here my routes
devise_for :users
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
resources :overviews
resources :users
root 'overviews#index'
Can anyone help me with this, please?
In the initializer active_admin.rb - try this
config.authentication_method = false
I'm using Devise and Pundit gems in a Ruby on Rails application.
I'm trying to implement RailsAdmin in order to set up a simple admin interface for my non-tech team members, on the URL 'myapp.com/admin', but going to this URL raises the following error :
Pundit::AuthorizationNotPerformedError at /
RailsAdmin::MainController
This error is raised by the file lib/pundit.rb in the following method:
def verify_authorized
raise AuthorizationNotPerformedError, self.class unless pundit_policy_authorized?
end
I understand this is linked to Pundit's policies but cannot find my way through the changes to perform.
Here is what I've tried until now :
In my Gemfile, I have installed :
gem "rails_admin"
and
gem "rails_admin_pundit", :github => "sudosu/rails_admin_pundit"
Then, in my terminal, I ran
'bundle'
In my initializers, I have :
RailsAdmin.config do |config|
## == Devise ==
config.authenticate_with do
warden.authenticate! scope: :user
end
config.current_user_method(&:current_user)
## == Pundit ==
config.authorize_with :pundit
end
In my controllers/application_controller.rb, I have the following code :
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
before_action :configure_permitted_parameters, if: :devise_controller?
before_action :authenticate_user!
include Pundit
after_action :verify_authorized, except: :index, unless: :devise_controller?
after_action :verify_policy_scoped, only: :index, unless: :devise_controller?
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
def user_not_authorized
flash[:alert] = "You are not authorized to perform this action."
redirect_to(root_path)
end
def default_url_options
{ host: ENV['HOST'] || 'localhost:3000' }
end
private
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << [:first_name, :last_name, :bio, :email, :password, :password_confirmation, :photo, :photo_cache]
devise_parameter_sanitizer.for(:account_update) << [:first_name, :last_name, :bio, :email, :password, :password_confirmation, :photo, :photo_cache]
end
end
Last, in my policies/application_policy.rb (see at the end the 'def rails_admin?' method), I have :
class ApplicationPolicy
attr_reader :user, :record
def initialize(user, record)
#user = user
#record = record
end
def index?
false
end
def show?
scope.where(:id => record.id).exists?
end
def create?
false
end
def new?
create?
end
def update?
false
end
def edit?
update?
end
def destroy?
false
end
def scope
Pundit.policy_scope!(user, record.class)
end
class Scope
attr_reader :user, :scope
def initialize(user, scope)
#user = user
#scope = scope
end
def resolve
scope
end
end
def rails_admin?(action)
case action
when :dashboard
user.admin?
when :index
user.admin?
when :show
user.admin?
when :new
user.admin?
when :edit
user.admin?
when :destroy
user.admin?
when :export
user.admin?
when :history
user.admin?
when :show_in_app
user.admin?
else
raise ::Pundit::NotDefinedError, "unable to find policy #{action} for #{record}."
end
end
end
Would you have any idea about what I am missing?
Thanks guys.
I've resolved my problem.
Seems like there is a little bug in rails_admin_pundit gem.
The following change, found in a commit made on the rails_admin_pundit gem's GitHub repository but ignored until now made the job!
In my Gemfile, instead of calling :
gem "rails_admin_pundit", :github => "sudosu/rails_admin_pundit"
I called :
gem "rails_admin_pundit", :github => "Samy-Amar/rails_admin_pundit"
Basically, the commit added one extra line in
lib/rails_admin/extensions/pundit/authorization_adapter.rb
You can see the details of this tiny change on this page: https://github.com/Samy-Amar/rails_admin_pundit/commit/4017395e5e715e2f1fd95918bc4bb9b76d272b25
Hope this will help!