Umpermitted parameter in rails devise, even though params .permit(ted) - ruby-on-rails

I have rails (6.0.2.2) project with devise (4.7.1), with two types of accounts: the teachers and the students. The student can to sign up successfully, but there is problem with the teacher for some reason. When I try to make a test account, I get
Unpermitted parameter: :email
error message and my info is not saved in the database.
Migration:
class DeviseCreateTeachers < ActiveRecord::Migration[6.0]
def change
create_table :teachers 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
t.string :username
t.string :name
t.string :neighborhood
t.integer :pet_skin
t.integer :pet_eyes
t.integer :pet_face
t.integer :pet_accessories
## 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
## Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
t.string :unlock_token # Only if unlock strategy is :email or :both
t.datetime :locked_at
t.timestamps null: false
end
add_index :teachers, :email, unique: true
add_index :teachers, :reset_password_token, unique: true
# add_index :teachers, :confirmation_token, unique: true
# add_index :teachers, :unlock_token, unique: true
end
end
my teacher_controller.rb:
class TeacherController < ApplicationController
private
def sign_up_params
params.require(:teacher).permit(:email, :username, :name, :password, :password_confirmation, :neighborhood, :pet_skin, :pet_eyes, :pet_face)
end
def account_update_params
params.require(:teacher).permit(:username, :password, :password_confirmation, :current_password)
end
end
I'm using the default generated teachers/registration/new.html.erb so I think its no problem here.
I DID add a line to config/initializers/devise.rb:
config.authentication_keys = [:username]
to change default log in from email to username, but I don't think this is issue because again students can create the account.
Thanks for your help!

#Tijana I don't know if you have already checked this.
link. If not, it might help
https://github.com/heartcombo/devise#strong-parameters

Related

Rails & Devise: devise specific columns not showing up in rails console

I am trying to use Devise on my User model but when I go into rails console and try User.new I only get:
irb(main):002:0> User.new
=> #<User id: nil, first_name: nil, last_name: nil, email: nil, created_at: nil, updated_at: nil>
Why are the devise columns not showing up?
CreateUsers migration:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :first_name
t.string :last_name
t.string :email
t.timestamps null: false
end
end
end
AddDeviseToUsers migration:
class AddDeviseToUsers < ActiveRecord::Migration
def self.up
change_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
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
# Uncomment below if timestamps were not included in your original model.
# t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
def self.down
# By default, we don't want to make any assumption about how to roll back a migration when your
# model already existed. Please edit below which fields you would like to remove in this migration.
raise ActiveRecord::IrreversibleMigration
end
end
Schema shows the columns are there:
create_table "users", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
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"
end
add_index "users", ["email"], name: "index_users_on_email", unique: true
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
Any ideas?
It's a security feature that Devise has in order to restrict its attributes and the critical information it contains to be exposed to API calls.
You can however override this, you need to override serializable_hash method.
# app/models/user.rb
class User < ActiveRecord::Base
devise :database_authenticatable, :recoverable, :confirmable, :rememberable, :validatable
...
protected
def serializable_hash(options = nil)
super(options).merge(encrypted_password: encrypted_password, reset_password_token: reset_password_token) # you can keep adding attributes here that you wish to expose
end
end
You can check http://www.rubydoc.info/github/plataformatec/devise/Devise/Models/Authenticatable where a constant is declared to blacklist attributes
BLACKLIST_FOR_SERIALIZATION =[:encrypted_password, :reset_password_token, :reset_password_sent_at, :remember_created_at, :sign_in_count, :current_sign_in_at, :last_sign_in_at, :current_sign_in_ip, :last_sign_in_ip, :password_salt, :confirmation_token, :confirmed_at, :confirmation_sent_at, :remember_token, :unconfirmed_email, :failed_attempts, :unlock_token, :locked_at]
Hope this answers your question!
If all you want to do it list all the attributes in the Rails console, it is easier to use User.first.serializable_hash(force_except: true)
See http://www.rubydoc.info/github/plataformatec/devise/Devise%2FModels%2FAuthenticatable:serializable_hash
Devise overrides the inspect method to not expose internal attibutes. You can try:
User.new.attributes
or
User.new.encrypted_password
(or whatever attribute you want)
You can check inspect method here

How to fix the Internal 500 Error in a rails application

I keep getting this error when I try to run my application. It states that there is an undefined method error in the application, but doesn't state where. The closest error I could find as tangible was this:
NameError (undefined local variable or method `confirmed_at' for #<User:0x6049800>):
I'm not sure which part this is directing to. Could someone please tell me what this error means?
This is the code for the devise_users file
class DeviseCreateUsers < ActiveRecord::Migration
def change
create_table(:users) do |t|
## Database authenticatable
t.string :name, null: false, default: ""
t.string :email, null: false, default: ""
t.string :encrypted_password, null: false, default: ""
t.string :about
t.string :avatar
t.string :cover
## 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.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.timestamps null: false
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
add_index :users, :confirmation_token, unique: true
# add_index :users, :confirmation_token, unique: true
add_index :users, :unlock_token, unique: true
end
end
There are not any other places within the application where the method is called, therefore the error states that the method is being called somewhere when it isn't. How can I fix this error?
Your migration file DeviseCreateUsers created a table users in the database, and one of the columns in that table is confirmed_at.
In your app/models/user.rb file you probably declared your devise configuration like:
class User < ActiveRecord::Base
devise :registerable, :confirmable
...
end
ActiveRecord::Base, the class User is inheriting from, automatically creates "getter" and "setter" methods for database columns (i.e. confirmed_at), so the method #confirmed_at should already be defined.
So if the method is "missing", you may not have run the database migrations (e.g. rake db:migrate)
Search your code for confirmed_at -- it seems you used it somewhere without defining it first.
It would be nice if the error message gave you a file name and a line number, but (depending on which text editor or IDE you're using) you might be able to run a search on the entire Rails app at once.
My guess is you called the confirmed_at method on a user object (user_1.confirmed_at, for example) and the method wasn't defined in class User.

How to fix SQLite Devise Error

I'm following a tutorial on adding the Devise gem to Rails. One feature of the gem is generating a "user" using Devise, for further user authentication (Facebook, Twitter, etc.). I'm running into the following error:
== 20150906025001 AddDeviseToUsers: migrating =================================
-- change_table(:users)
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:
SQLite3::SQLException: duplicate column name: email: ALTER TABLE "users" ADD "email" varchar DEFAULT '' NOT
NULL/Users/jaker/.rvm/gems/ruby-2.0.0-p643/gems/sqlite3-1.3.10/lib/sqlite3/database.rb:91:in `initialize'
I already have a User model in my app, that has an email, so this makes sense. However, when I try to run a migration and delete my "User" table, I'm still getting the same error.
[timestamp]_add_devise_to_users.rb:
class AddDeviseToUsers < ActiveRecord::Migration
def self.up
change_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
## Confirmable
t.string :confirmation_token
t.datetime :confirmed_at
t.datetime :confirmation_sent_at
t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
# t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
# t.string :unlock_token # Only if unlock strategy is :email or :both
# t.datetime :locked_at
# Uncomment below if timestamps were not included in your original model.
# t.timestamps null: false
end
add_index :users, :email, unique: true
add_index :users, :reset_password_token, unique: true
# add_index :users, :confirmation_token, unique: true
# add_index :users, :unlock_token, unique: true
end
def self.down
# By default, we don't want to make any assumption about how to roll back a migration when your
# model already existed. Please edit below which fields you would like to remove in this migration.
raise ActiveRecord::IrreversibleMigration
end
end
Does anyone know how to fix this? I'm really confused, and no documentations have seemed to help. Thanks so much.
This error is happening because you already have a column called email in your User model
You could comment (or remove) the line:
t.string :email, null: false, default: ""
and the script will continue.

Migration could not be done undefined method `apply_schema=` for devise

I am getting this error while running rake db:migrate
rake db:migrate
rake aborted!
undefined method `apply_schema=' for Devise:Module
/home/dexter/Desktop/Triton/config/initializers/devise.rb:14:in `block in <top (required)>'
I have checked devise.rb
# Automatically apply schema changes in tableless databases
config.apply_schema = false
devise users model
class DeviseCreateUsers < ActiveRecord::Migration
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
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Encryptable
# t.string :password_salt
## Confirmable
# t.string :confirmation_token
# t.datetime :confirmed_at
# t.datetime :confirmation_sent_at
# t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
t.string :unlock_token # Only if unlock strategy is :email or :both
t.datetime :locked_at
## Token authenticatable
# t.string :authentication_token
t.string :user_name
t.string :first_name
t.string :last_name
t.string :user_type
t.string :about
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
# add_index :users, :confirmation_token, :unique => true
add_index :users, :unlock_token, :unique => true
# add_index :users, :authentication_token, :unique => true
end
end

Gem devise set multiple user model system

In my app i need to do two way-login system:
1) User - only for user part of website, contain's information about user's, it's login data, etc...
2) Admin - another model for admin part of website.
But how to do this?
Now i have only first part, and my migration:
class DeviseCreateUsers < ActiveRecord::Migration
def self.up
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
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.string :current_sign_in_ip
t.string :last_sign_in_ip
## Encryptable
# t.string :password_salt
## Confirmable
#t.string :confirmation_token
#t.datetime :confirmed_at
#t.datetime :confirmation_sent_at
#t.string :unconfirmed_email # Only if using reconfirmable
## Lockable
#t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts
#t.string :unlock_token # Only if unlock strategy is :email or :both
#t.datetime :locked_at
## Token authenticatable
t.string :authentication_token
t.timestamps
end
add_index :users, :email, :unique => true
add_index :users, :reset_password_token, :unique => true
#add_index :users, :confirmation_token, :unique => true
#add_index :users, :unlock_token, :unique => true
add_index :users, :authentication_token, :unique => true
end
def self.down
drop_table :users
end
end
And route:
devise_for :users
But how to add second admin-login part?
You have 3 options:
Add string field type to your table and derive from User model (the admin and user will have the same login route).
Add boolean field admin and use i.e. CanCan gem.
Run rails g devise admin and have separate admin model.
The way you choose depends on your app struct.

Resources