How do I get Devise 3.4 to permit Parameters Rails 4.2 - ruby

Suggestions on how to improve this question are welcome
I added 3 things to the Devise user after generating it.
t.integer "role"
t.string "firstname"
t.string "lastname"
At User Signup these parameters are permitted and user is created correctly.
When a user tries to edit their account the "firstname" and "lastname" values can be changed fine but when a user tries to change their role on their /users/edit page, no error is given, flash says "account updated successfully" but the role value have not changed.
From /log/development.log showing all 3 parameters as unpermitted, if this really is the case I don't know why the other two can be updated.
Parameters: {"utf8"=>"✓", "authenticity_token"=>"LnVPFFJKV+RtnB21ZUGr4HF1siVcEuT/BRXaLVkch1nWQXiGRFVGhdWchlQSZ9A7mFgKX2njEjCbqR4CHp5hmQ==", "user"=>{"role"=>"worker", "firstname"=>"asdfDe Wet", "lastname"=>"Blomerus", "email"=>"dewet#blomerus.org", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]", "current_password"=>"[FILTERED]"}, "commit"=>"Update"}
[1m[36mUser Load (0.8ms)[0m [1mSELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT 1[0m [["id", 6]]
[1m[35mUser Load (0.4ms)[0m SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 6]]
Unpermitted parameters: role, firstname, lastname
Redirected to http://localhost:3000/
Completed 302 Found in 84ms (ActiveRecord: 1.5ms)
/config/initializers/devise_permitted_parameters.rb
module DevisePermittedParameters
extend ActiveSupport::Concern
included do
before_filter :configure_permitted_parameters
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) << [:firstname, :lastname, :role]
devise_parameter_sanitizer.for(:account_update) << [:firstname, :lastname, :role]
end
end
DeviseController.send :include, DevisePermittedParameters
Relevant parts of /app/controllers/users_controller.rb
def update
#user = User.find(params[:id])
if #user.update_attributes(secure_params)
redirect_to users_path, :notice => "User updated."
else
redirect_to users_path, :alert => "Unable to update user."
end
end
private
def secure_params
params.require(:user).permit(:role, :firstname, :lastname)
end
The update action never runs, I can completely comment it out and nothing changes.

This is what works for me with devise:
I change the users/registrations_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
before_action :configure_permitted_parameters, only: [:create]
before_filter :configure_account_update_params, only: [:update]
def create
super
end
# GET /resource/edit
def edit
super
end
# PUT /resource
def update
super
end
# DELETE /resource
def destroy
super
end
protected
def configure_permitted_parameters
devise_parameter_sanitizer.for(:sign_up) do |u|
u.permit(:first_name, :last_name, :user_name, :email, :password, :password_confirmation, :avatar, :avatar_cache)
end
end
def configure_account_update_params
devise_parameter_sanitizer.for(:account_update)do |u|
u.permit(:first_name, :last_name, :user_name, :email, :password, :password_confirmation, :current_password, :avatar, :avatar_cache)
end
end
I don't define any update action in the users_controller.rb . It is not needed. Also, I don;t use any type of module that you are defining and it works fine.

Related

How do I get rid of undefined method `to_sym' for nil:NilClass error when deleting rows in rails?

My project is at this github: https://github.com/hoolahoop/RoR_Projects.
I have a project which has Users, Events, and a join table between the two tables. An event is owned by a user, with a foreign key on the event table. The join table allows many users to be guests for many events.
I'm trying to let owners of events add and delete multiple guests at a time.
Below is the controller action code that throws the error when deleting rows from the join table. Ctrl + f "error thrown here" to see where the error is thrown.
def create
Rails.logger.event.debug("===New Create===\n")
#user_check = true;
##event = Event.new(event_params)
#event = Event.new(event_user_params)
#users = User.new
#event.users.each do |user|
user.password = SecureRandom.base64
user.password_confirmation = user.password
#test all saves here
if(!user.try(:save))
user_check = false;
end
end
Rails.logger.event.debug("Can we save all users: #{#user_check}. If true, continue.")
if(#user_check)
#add all saves here
#add all associations here
#event.users.each do |user|
#user_in_database = User.find_by email: user.email
Rails.logger.event.debug("User in database check. Id: #{#user_in_database.id}. Email: #{#user_in_database.email}.")
if (#user_in_database.nil?) # if user is not in the database (unique email check)
# create a new user
User.transaction do
user.save
end
Rails.logger.event.debug("User id check: #{#user}")
#event_user = EventUser.new(user_id: user.id, event_id: params[:event_id])
# create a new join table record
EventUser.transaction do
#event_user.save
end
else
#event_user_join = EventUser.find_by user_id: #user_in_database.id, event_id: params[:event_id]
Rails.logger.event.debug("Is there a join on this event for this user?. Join object: #{#event_user_join}. If this is nil, no join exists.")
if (#event_user_join.nil?)
#event_user = EventUser.new(user_id: #user_in_database.id, event_id: params[:event_id])
EventUser.transaction do
#event_user.save
end
else
Rails.logger.event.debug("Join user_id: #{#event_user_join.user_id}. Join event_id: #{#event_user_join.event_id}.")
Rails.logger.event.debug("Try removing join.")
EventUser.transaction do
#event_user_join.delete
end
Rails.logger.event.debug("Removal success.")
end
end
end
Rails.logger.event.debug("===Redirect to Event Guests Page===\n")
redirect_to event_display_path(params[:event_id])
else
render 'new'
Rails.logger.event.debug("===Render New===\n")
end
end
private
def event_user_params
#params.require(:user).permit(:first_name, :last_name, :email)
params.require(:event).permit(users_attributes: [:id, :first_name, :last_name, :email, :_destroy])
end
def random_password
random_pass = SecureRandom.base64
end
Models:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
has_many :event_users
has_many :events, through: :event_users
#validation code...
end
class EventUser < ApplicationRecord
belongs_to :event
belongs_to :user
end
class Event < ApplicationRecord
#belongs_to :user
belongs_to :owner, class_name: "User", foreign_key: :user_id
has_many :event_users
has_many :users, through: :event_users
accepts_nested_attributes_for :users
#validation code...
end
Migrations:
class DeviseCreateUsers < ActiveRecord::Migration[5.1]
def change
create_table :users do |t|
## Database authenticatable
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
## Recoverable
t.string :reset_password_token
t.datetime :reset_password_sent_at
## Rememberable
t.datetime :remember_created_at
## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
end
end
class AddNamesToUsers < ActiveRecord::Migration[5.1]
def change
add_column :users, :first_name, :string, null: false, default: ""
add_column :users, :last_name, :string, null: false, default: ""
end
end
class CreateEvents < ActiveRecord::Migration[5.1]
def change
create_table :events do |t|
t.string :name, null: false, default: ""
t.text :description, null: true
t.integer :option, null: false, default: 1
t.string :street_address, null: true
t.integer :apartment_number, null: true
t.string :city, null: true
t.date :date, null: true
t.time :time, null: true
t.string :password, null: false, default: ""
t.references :user, foreign_key: true
end
end
end
class CreateJoinTableEventUser < ActiveRecord::Migration[5.1]
def change
create_join_table :events, :users do |t|
t.index [:event_id, :user_id]
t.index [:user_id, :event_id]
end
end
end
class RenameTableEventsUsers < ActiveRecord::Migration[5.1]
def change
rename_table :events_users, :event_users
end
end
Full error in command prompt:
app/controllers/users_controller.rb:21:in `create'
Started POST "/events/16/users" for 127.0.0.1 at 2018-03-05 10:06:40 -0500
Processing by UsersController#create as HTML
Parameters: {"utf8"=>"√", "authenticity_token"=>"ph5zsZQ0HhHt2NAsCtGFDUo/+PmlrQmKyeXt6dcQMnnXFVoEgeh4Srp+p0z0C8mtOhF6Uf48suCw+2YO72+bzw==", "event"=
{"users_attributes"=>{"0"=>{"first_name"=>"Test1", "last_name"=>"Test11", "email"=>"test1#test.com", "_destroy"=>"false", "id"=>"8"}, "1"=>{"first_na
me"=>"Test4", "last_name"=>"Test44", "email"=>"test4#test.com", "_destroy"=>"false", "id"=>"11"}, "2"=>{"first_name"=>"Test5", "last_name"=>"Test55",
"email"=>"test5#test.com", "_destroy"=>"false", "id"=>"12"}}}, "commit"=>"Save", "event_id"=>"16"}
Unpermitted parameter: :id
Unpermitted parameter: :id
Unpermitted parameter: :id
(0.0ms) begin transaction
User Exists (0.0ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "test1#test.com"], ["LIMIT", 1]]
(0.0ms) rollback transaction
(0.0ms) begin transaction
User Exists (0.0ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "test4#test.com"], ["LIMIT", 1]]
(0.0ms) rollback transaction
(0.0ms) begin transaction
User Exists (0.0ms) SELECT 1 AS one FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "test5#test.com"], ["LIMIT", 1]]
(0.0ms) rollback transaction
User Load (0.0ms) SELECT "users".* FROM "users" WHERE "users"."email" = ? LIMIT ? [["email", "test1#test.com"], ["LIMIT", 1]]
EventUser Load (0.0ms) SELECT "event_users".* FROM "event_users" WHERE "event_users"."user_id" = ? AND "event_users"."event_id" = ? LIMIT ? [["us
er_id", 8], ["event_id", 16], ["LIMIT", 1]]
(0.0ms) begin transaction
(0.0ms) rollback transaction
Completed 401 Unauthorized in 441ms (ActiveRecord: 2.0ms)
NoMethodError (undefined method `to_sym' for nil:NilClass):
app/controllers/users_controller.rb:56:in block (2 levels) in create'
app/controllers/users_controller.rb:54:inblock in create'
app/controllers/users_controller.rb:34:in `create'
Full error on browser
NoMethodError in UsersController#create
undefined method `to_sym' for nil:NilClass
Extracted source (around line #65):
63
64
65
66
67
68
Rails.logger.event.debug("Try removing join.")
EventUser.transaction do
#event_user_join.delete
end
Rails.logger.event.debug("Removal success.")
end
Rails.root: D:/Development/RoR_Projects/Maestro/blog
Application Trace | Framework Trace | Full Trace
app/controllers/users_controller.rb:65:in block (2 levels) in create'
app/controllers/users_controller.rb:64:inblock in create'
app/controllers/users_controller.rb:39:in `create'
Request
Parameters:
{"utf8"=>"✓","authenticity_token"=>"HfCo+U+X7DtWUrCn/O2KFEkioGtXyut99NEsjUL08DBs+4FMWkuKYAH0x8cCN8a0OQwiwwxbUBeNz6dqeotZhg==",
"event"=>
{"id"=>"16",
"owner"=>"5",
"users_attributes"=>
{"0"=>{"first_name"=>"Test1", "last_name"=>"Test11", "email"=>"test1#test.com", "_destroy"=>"false", "id"=>"8"},
"1"=>{"first_name"=>"Test4", "last_name"=>"Test44", "email"=>"test4#test.com", "_destroy"=>"false", "id"=>"11"},
"2"=>{"first_name"=>"Test5", "last_name"=>"Test55", "email"=>"test5#test.com", "_destroy"=>"false", "id"=>"12"}}},
"commit"=>"Save",
"event_id"=>"16"}
Version information:
OS: Windows 7 Professional Service Pack 1
Ruby -v: ruby 2.4.3p205 (2017-12-14 revision 61247) [x64-mingw32]
Rails -v: Rails 5.1.4
Libraries: please check gemfile.
Related lib's to this problem include gem 'bcrypt', '~> 3.1.11', gem 'devise', and gem 'cocoon'.
Additional Information:
If you need any more information to help debug this problem, I will be happy to edit this post.
I don't know where the to_sys no method error is coming from. I've found a few places inside devise where it is used, but I'm having trouble deciphering why it's happening, and which exact place it's being used.
I'm using cocoon to generate multiple user fields on my form, and then trying to save them all. Perhaps I'm using cocoon incorrectly. The sample projects didn't seem to cover my use case of having a join table.
Devise github: https://github.com/plataformatec/devise
Cocoon github: https://github.com/nathanvda/cocoon

How do i add default data in rails strong params?

Lets say if i want to generate and set default password for user while creating them in admin.
and i want to do something like this,
def user_params
params.require(:user).permit(:first_name, :last_name, :email, :password=> #default_generated_password, :password_confirmation => #default_generated_password)
end
I am using sorcery for User Authentication.
I am having a feeling that this is completely wrong way, But how do i do it?
You want to use reverse_merge (appeared in rails 5.1) or with_defaults (alias appeared in rails 5.2)
def user_params
params
.require(:user)
.permit(:first_name, :last_name, :email, :password, :password_confirmation)
.with_defaults(password: #default_generated_password, password_confirmation: #default_generated_password)
end
Merge them in after
params
.require(:user)
.permit(:first_name, :last_name)
.merge(password: #default_generated_password, password_confirmation: #default_generated_password)
Or if you need it just in one action (create for example)
def create
# password generation code...
# ...
#user = User.new(user_params.merge(password: #default_generated_password, password_confirmation: #default_generated_password))
if #user.save
redirect_to ...
else
flash[:error] = "Did not save"
render :new
end
end
private
def user_params
params.require(:user).permit(:first_name, :last_name)
end

Strong params, unpermitted parameters

I'm having an issue with strong parameters.
My permuted parameters are:
def post_params
params.require(:post).permit(:content, :user_id, :topic_id).merge(:user_id => get_user.id)
end
The parameters being passed are:
{"utf8"=>"✓",
"authenticity_token"=>"5+OEnLgihamJC37BSn4r/spoiRmccJzHhe6eaeC2Fuc=",
"post"=>{"topid_id"=>"10",
"content"=>"awfawfaw"}}
And the create function is:
def create
post = Post.new(post_params)
if post.valid? && post.save
redirect_to :controler => :topic, :action => :show, :topic => post.topic.id
end
end
That is the error in the console. I want to know why it is not permitting topic_id.
You have a typo in your permitted params:
what you have is:
def post_params
params.require(:post).permit(:content, :user_id, :topic_id).merge(:user_id => get_user.id)
end
and It should be:
def post_params
params.require(:post).permit(:content, :user_id, :topid_id).merge(:user_id => get_user.id)
end
But it depends on your model what name of attribute you have in your model. Either you have to change in the form in typo in the form, or either you have to change everywhere else.

Padrino Admi - Omniauth - Can't Access Restricted Space after Successful Login

I primarily come from a PHP and ASP.NET background. Recently I got involved with Ruby and am starting an interesting relationship with Padrino. Not too much like Rails and not too less like Sinatra.
I am making first serious application using Padrino and it didn't take long to get stuck and would appreciate your help.
The issue with what I believe is with Padrino Admin. I am trying make users login to my website using Facebook and Omniauth.
I have been following this tutorial: Padrino and Omniauth Overview.
The application is hosted at Heroku.
Result: On Facebook login, an account is crated ( in the database ). But when I reach the restricted area, I get redirected back to the login page.
Here is what I have.
app.rb
module PDeen
class App < Padrino::Application
register Padrino::Admin::AccessControl
register SassInitializer
register Padrino::Rendering
register Padrino::Mailer
register Padrino::Helpers
enable :sessions
# get '/' do
# "Welcome to me # internet"
# end
use OmniAuth::Builder do
provider :facebook, 'xxxx', 'yyyy'
# provider :facebook, 'app_id', 'app_secret'
end
set :login_page, "/login" # determines the url login occurs
access_control.roles_for :any do |role|
role.protect "/profile"
role.protect "/admin" # here a demo path
end
# now we add a role for users
access_control.roles_for :users do |role|
role.allow "/profile"
end
get :index do
'Hi'
end
get :login do
slim :'index'
end
get :profile do
content_type :text
current_account.to_yaml
end
get :destroy do
set_current_account(nil)
redirect url(:index)
end
get :auth, :map => '/auth/:provider/callback' do
auth = request.env["omniauth.auth"]
# account = Account.find_by_provider_and_uid(auth["provider"], auth["uid"]) ||
# Account.create_with_omniauth(auth)
#
account = User.first( :provider => auth["provider"], :uid => auth["uid"] )
if ! account.nil?
set_current_account(account)
redirect :existing
end
if account.nil?
# Create account
account = User.new
account.uid = auth['uid']
account.name = auth['name']
account.provider = auth['provider']
account.email = auth['user_info']['email'] if auth['user_info']
account.role = 'users'
account.save
end
set_current_account(account)
#redirect "http://" + request.env["HTTP_HOST"] + url(:profile)
redirect :new
end
get :existing do
'existing'
end
get '/session/test' do
session[:test] = 'This is a test'
end
get '/session/print' do
"You saved: #{session[:test]}"
end
end
end
User.rb
class User
include DataMapper::Resource
# property <name>, <type>
property :id, Serial
property :name, String
property :email, String
property :role, String
property :uid, String
property :provider, String
end
What happens >>
List item
I go to [server]/profile ~> redirects to [server]/login
I click on Facebook ~> takes to the page to accept the app ~> redirects back to the app
I go to [server]/profile ~> redirects to [server]/login
I thought that sessions are not working. In the time I was working on my first PHP app, I had similar session based issue. But it turned out to be that it wroks. That is where the [server]/session/test and [server]/session/print came in.
When I login to the Padriono console in Heroku and use User.all I see the entry.
I also see that the user gets authenticated. Some thing has to be with `
I checked the Padrino admin Accounts modal. I think the important parameters would be id and role.
Have I done some thing wrong?
Thanks in advance. Any help is highly appreciated.
After going through the Padrino source code, I noticed that it is expecting the Account class for Padrino Admin authentication.
I was assuming, I could make any class and just use it. But for the moment, I have modified the Account.rb modal and instead of using User ( above ) I used Account.
I write this just as I got it resolved, so the validation section of the modal is commented out.
class Account
include DataMapper::Resource
include DataMapper::Validate
attr_accessor :password, :password_confirmation
# Properties
property :id, Serial
property :name, String
property :surname, String
property :email, String
property :crypted_password, String, :length => 70
property :role, String
property :uid, String
property :display_name, String
property :provider, String
# # Validations
# validates_presence_of :email, :role
# validates_presence_of :password, :if => :password_required
# validates_presence_of :password_confirmation, :if => :password_required
# validates_length_of :password, :min => 4, :max => 40, :if => :password_required
# validates_confirmation_of :password, :if => :password_required
# validates_length_of :email, :min => 3, :max => 100
# validates_uniqueness_of :email, :case_sensitive => false
# validates_format_of :email, :with => :email_address
# validates_format_of :role, :with => /[A-Za-z]/
# Callbacks
before :save, :encrypt_password
##
# This method is for authentication purpose
#
def self.authenticate(email, password)
account = first(:conditions => ["lower(email) = lower(?)", email]) if email.present?
account && account.has_password?(password) ? account : nil
end
##
# This method is used by AuthenticationHelper
#
def self.find_by_id(id)
get(id) rescue nil
end
def has_password?(password)
::BCrypt::Password.new(crypted_password) == password
end
private
def password_required
crypted_password.blank? || password.present?
end
def encrypt_password
self.crypted_password = ::BCrypt::Password.create(password) if password.present?
end
end
Note that just after the role, I added 3 more fields namely uid, display_name and provider.
It seems as though, uid provder and role are what is important for the access control.
The controller / route are the same except for one minor change. That is the Model name.
if account.nil?
# Create account
account = Account.new
Would be interesting to use own modal with Omniauth and Padrino Admin helpers. But for the moment, this is great!

User model test error from inserting into Group table

I'm just starting out with tests. When I run this one:
rake test test/models/user_test.rb
require 'test_helper'
class UserTest < ActiveSupport::TestCase
test "should not save without an email address" do
user = User.new
assert_not user.save
end
end
I get the following error:
1) Error:
UserTest#test_should_not_save_without_an_email_address:
ActiveRecord::StatementInvalid: SQLite3::ConstraintException: NOT NULL constraint failed: groups.name: INSERT INTO "groups" ("created_at", "updated_at", "id") VALUES ('2015-08-11 17:31:07', '2015-08-11 17:31:07', 980190962)
This is user.rb
class User < ActiveRecord::Base
has_many :groups
has_many :user_groups
attr_accessor :password
EMAIL_REGEX = /A[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}\z/i
validates :password, :confirmation => true #password_confirmation attr
validates_length_of :password, :in => 6..20, :on => :create
validates :email, :presence => true, :uniqueness => true, :format => EMAIL_REGEX
before_save :encrypt_password
after_save :clear_password
def encrypt_password
if password.present?
self.salt = Digest::SHA1.hexdigest("# We add {self.email} as unique value and #{Time.now} as random value")
self.encrypted_password = Digest::SHA1.hexdigest("Adding #{self.salt} to {password}")
end
end
def clear_password
self.password = nil
end
end
This is test_helper.rb
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
class ActiveSupport::TestCase
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
fixtures :all
# Add more helper methods to be used by all tests here...
end
As far as I can tell I don't have any callback or otherwise that would attempt to write to the "groups" table. My "groups.yml" is default, but that shouldn't matter if I'm only testing this one model, correct? Any help as to where I could start looking would be much appreciated. Thanks!
test_helper.rb was setting up all my fixtures and they weren't defined. Commenting "fixtures :all" fixed it.

Resources