Rails 4 and Devise - User registration via JSON API - devise

I'm attempting to register a devise user via JSON but keep getting an ActiveModel::ForbiddenAttributesError
class Api::V1::RegistrationsController < ApplicationController
skip_before_filter :verify_authenticity_token
respond_to :json
def create
user = User.new(params[:user])
if user.save
render :json => user.as_json(:auth_token=>user.authentication_token, :email=>user.email), :status=>201
return
else
warden.custom_failure!
render :json => user.errors, :status=>422
end
end
def user_params
params.require(:user).permit(:email, :password)
end
end
Here's my JSON request:
Processing by Api::V1::RegistrationsController#create as JSON
Parameters: {"user"=>{"email"=>"jayson#jayson.com", "password"=>"[FILTERED]"}, "registration"=>{"user"=>{"email"=>"jayson#jayson.com", "password"=>"[FILTERED]"}}}
I realize this has something to do with Strong Parameters but haven't been able to crack it yet.

I would change:
user = User.new(params[:user])
with:
user = User.new(user_params)
From docs:
# This will raise an ActiveModel::ForbiddenAttributes exception because it's using mass assignment
# without an explicit permit step.
def create
Person.create(params[:person])
end

Related

Access session in Helper file ? Rails 3

how to get session in helper file?
UserHelper.rb
module UsersHelper
def self.auth login, password
user = Users.where("firstname = :firstname AND password = :password", {:firstname => login, :password => password})
if user != []
return true
else
return false
end
end
def self.is_auth? level
puts #session
user = Users.where("firstname = :firstname AND password = :password", {:firstname => #session[:firstname], :password => #session[:password]})
if user != []
return true
else
return false
end
end
end
Admin_controller.rb
class AdminController < ApplicationController
include Rails.application.routes.url_helpers
def initialization
#session = session
end
def index
#session = session
if UsersHelper.is_auth?(2)
render :text => "ssssss"
end
end
def auth
if params[:send] != nil
if UsersHelper.auth params[:firstname], params[:password]
session[:firstname] = params[:firstname]
session[:password] = params[:password]
redirect_to :action => "index"
else
#error = 1
end
end
end
def exit
session.delete(:firstname)
session.delete(:password)
render :json => session
end
end
Error
undefined method `[]' for nil:NilClass
app/helpers/users_helper.rb:13:in `is_auth?'
app/controllers/admin_controller.rb:8:in `index'
Only Controller can access session.
So, in a nutshell, if you are going to use this method in Controllers only like what is you case, you can define it as ApplicationController's method. Or define it a module and include it in AppplicationController.
class ApplicationController < ActionController::Base
def auth
end
def is_auth?
end
end
If you want to use the method in both controller and view, just declare them as helper_method
class ApplicationController < ActionController::Base
helper_method :auth, :is_auth?
def auth
end
def is_auth?
end
end
Ref: http://apidock.com/rails/ActionController/Helpers/ClassMethods/helper_method
Another note: In my opinion it's really not worth the time to build auth system from scratch by yourself. The functionalities are not easy but quite general. There are well baked gems such as Devise, Authlogic. Better to use them.

rails controller model view advice for ContacUs page

I have a simple static website written in rails 3.
The site has one controller called pages and each static page is served as view. Such as pages/home, pages/about, pages/prices, etc. This all works great.
I've now run into a problem where I need to add a simple contactus feature but I'm struggling to get my head round the model/controller/views for this.
I already have a pages controller with a contactus view, that view has details addresses etc. Now I somehow need to get a message model into the contactus view so I can populate the model attirbutes and send the email.
Can I / Should I just create a new message model from within the Pages Controller as in ,
class PagesController < ApplicationController
def contact
def new
#message = Message.new
end
def create
#message = Message.new(params[:message])
if #message.valid?
# TO DO send message here using OS mail program.
redirect_to root_url, notice: "Message sent! Thank you for contacting us."
else
render "new"
end
end
end
def about
end
def products
end
def portfolio
end
def services
end
end
Or should I take out the contactus view from the pages controller and make new controller called messages ?
Thanks.
I would have a separate controller called contact for example with new and create actions
def new
#message = Message.new
end
def create
#message = Message.new(params[:message])
if #message.valid?
NotificationsMailer.new_message(#message).deliver
redirect_to(root_path, :notice => "Message was successfully sent.")
else
flash.now.alert = "Please fill all fields."
render :new
end
end
end
Then a separate model to handle your messages
class Message
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name, :email, :subject, :body, :file
validates :name, :email, :subject, :body, :presence => true
validates :email, :format => { :with => %r{.+#.+\..+} }, :allow_blank => true
end
your attributes can be anything you like, obviously this is just an example of what you can do

How do I emulate logging in for controller tests?

I have a SearchesController that requires a user to be logged in before it will do its thing.
I'd like to write an rspec helper function login to emulate logging in for controller tests. (NB: I will handle integration / requests specs separately.) My attempts so haven't worked: the logged_in? method in ApplicationController returns false.
The question: how do I write the 'login' helper?
Here's the RSpec controller test:
# file: spec/controllers/searches_controller_spec.rb
require 'spec_helper'
require 'controllers_helper'
describe SearchesController do
include ControllersHelper
describe "GET index" do
it 'without login renders login page' do
get :index
response.should redirect_to(login_path)
end
it 'with login finds searches belonging to user' do
me = FactoryGirl.create(:user)
my_searches = FactoryGirl.create_list(:search, 2, :user => me)
not_me = FactoryGirl.create(:user)
not_my_searches = FactoryGirl.create_list(:search, 2, :user => not_me)
login(me) # want to define this in spec/controllers_helper.rb
get :index
assigns(:searches).should =~ my_searches
end
end
end
Here's the Controller:
# file: app/controllers/searches_controller.rb
class SearchesController < ApplicationController
def index
unless logged_in?
redirect_to login_path, :alert => "You must be logged in to access this page."
else
#searches = Search.where(:user_id => current_user.id)
respond_to do |format|
format.html
format.json { render json: #searches }
end
end
end
end
And here's the ApplicationController code. Note that current_user = x has the effect of logging x in, and it's rather simple: it sets #current_user and session[:user_id].
# file: app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
force_ssl
protected
def current_user
#current_user ||= User.find_by_id(session[:user_id])
end
def current_user=(user)
#current_user = user
session[:user_id] = user && user.id
end
def logged_in?
!!#current_user
end
def require_login
unless logged_in?
redirect_to login_path, :alert => "You must be logged in to access this page."
end
end
helper_method :current_user, :logged_in?, :require_login
end
I may have said this before, but if Stack Overflow gave badges answering one's own questions, I'd have a LOT of badges! :)
Okay, to answer this question you need to look at the documentation for ActionController::TestCase. When you do so, you'll find that it sets up bindings for:
#controller
#request
#response
So for the specific controller given in the OP, writing the login method is trivial:
# file: spec/controllers_helper.rb
module ControllersHelper
def login(user)
#controller.send(:current_user=, user)
end
end
(Did I hear someone say RTFM again? I thought so...)

How to create current user method without using any gem or plugin?

i know it's a silly one but i want to know how can we create a current_user method to get access throughout the app without using any gem or plugin ? To test it i created an app that make a user able to share files and folders.How to create such method that a user can only access his folder and files?Here is my code sample:
Login controller:
class LoginController < ApplicationController
layout 'signup'
#to skip checking the authentication and authorization.
skip_before_filter :check_authentication, :check_authorization
def index
end
def authenticate
if request.post?
user = User.authenticate(params[:username],params[:password])
if user
session[:current_user_id]=user.id
session[:name]= user.first_name
puts "session name #{session[:name]}"
redirect_to(:subdomain => user.company.subdomain, :controller => :dashboard)
else
flash.now[:notice] = "Invalid user/password combination"
end
end
end
def destroy
session[:current_user_id] = nil
reset_session
flash[:notice] = "You have been successfully logged out."
redirect_to root_url
end
end
User model:
require 'digest/sha1'
class User < ActiveRecord::Base
#sharering method start
after_create :check_and_assign_shared_ids_to_shared_folders
#this is to make sure the new user ,of which the email addresses already used to share folders by others, to have access to those folders
def check_and_assign_shared_ids_to_shared_folders
#First checking if the new user's email exists in any of ShareFolder records
shared_folders_with_same_email = SharedFolder.find_all_by_shared_email(self.email)
if shared_folders_with_same_email
#loop and update the shared user id with this new user id
shared_folders_with_same_email.each do |shared_folder|
shared_folder.shared_user_id = self.id
shared_folder.save
end
end
end
#to check if a user has acess to this specific folder
def has_share_access?(folder)
#has share access if the folder is one of one of his own
return true if self.folders.include?(folder)
#has share access if the folder is one of the shared_folders_by_others
return true if self.shared_folders_by_others.include?(folder)
#for checking sub folders under one of the being_shared_folders
return_value = false
folder.ancestors.each do |ancestor_folder|
return_value = self.being_shared_folders.include?(ancestor_folder)
if return_value #if it's true
return true
end
end
return false
end
#sharing method end
def self.authenticate(name, password)
user = self.find_by_username(name)
if user
expected_password = encrypt_password(password, user.salt)
if user.hashed_password != expected_password
user = nil
end
end
user
end
#'password' is a virtual attribute
def password
#password
end
def password= (pwd)
#password =pwd
return if pwd.blank?
create_new_salt
self.hashed_password = User.encrypt_password( self.password, self.salt)
end
def self.users_in_company(user_id)
User.find(user_id).company.users
end
private
def password_non_blank
errors.add(:password, "Missing password, please enter your password") if hashed_password.blank?
end
def create_new_salt
self.salt = self.object_id.to_s + rand.to_s
end
def self.encrypt_password(password, salt)
string_to_hash = password +"prftnxt" + salt
Digest::SHA1.hexdigest(string_to_hash)
end
end
i want to access all files as "current_user.files" is it possible without any gem?
Application helper:
module ApplicationHelper
#for current user to use through out the app
def current_user
#current_user ||= session[:current_user_id] && User.find_by_id(session[:current_user_id]) # Use find_by_id to get nil instead of an error if user doesn't exist
end
end
Application controller:
class ApplicationController < ActionController::Base
include UrlHelper
#include ApplicationHelper
helper_method :current_user #make this method available in views
protect_from_forgery
# def current_user
# #current_user ||= session[:current_user_id] && User.find_by_id(session[:current_user_id]) # Use find_by_id to get nil instead of an error if user doesn't exist
# end
end
and in task controller:
class TasksController < ApplicationController
# GET /tasks
# GET /tasks.xml
def index
#menu = "Timesheet"
#page_name = "Manage Task"
company_id = Company.find_by_subdomain(request.subdomain)
#users = User.find_all_by_company_id(company_id)
#tasks = current_user.tasks.all#Task.all
#task = Task.new
respond_to do |format|
format.html # index.html.erb
format.html # new.html.erb
format.xml { render :xml => #tasks }
end
end
end
and my error message i got:
NameError in TasksController#index
undefined local variable or method `current_user' for #<TasksController:0xfa7e638>
that's not so hard ;) just define the method you need:
class ApplicationController < ...
def current_user
#current_user ||= session[:current_user_id] && User.find_by_id(session[:current_user_id]) # Use find_by_id to get nil instead of an error if user doesn't exist
end
helper_method :current_user #make this method available in views
end
Hi friends i have found the way to create current_user method without using any gem or plugin:
In my application_helper.rb i did this :
module ApplicationHelper
def current_user
User.find(session[:current_user_id])
end
end
and at the end in my application controller.rb i called this, because from here i can access it through the application:
class ApplicationController < ActionController::Base
include UrlHelper
include ApplicationHelper
helper_method :current_user
end
and now i can access any data related to current user:
like :
#tasks = current_user.tasks
Thanks to all my friends for their valuable answers.

How to initiate new profile object (has_one) after successful registration with Rails3 & devise

So I have devise setup to perform registration. After registration the user is redirected to profiles#new however I can't attach profile to current_user id
Actually it doesn't work at all. Here is what I have in my profiles_controller.rb
# POST /profiles
def create
#profile = current_user.Profile.new(params[:profile])
respond_to do |format|
if #profile.save
format.html { redirect_to(#profile, :notice => 'Profile was successfully created.') }
else
format.html { render :action => "new" }
end
end
end
leading to undefined method `Profile' for #
So the User model has_one :profile ?
If so, you likely want:
#profile = current_user.profile.build(params[:profile])
Note that case ('profile' vs 'Profile') is important here.
I think that you should use
#profile = current_user.build_profile(params[:profile])
Check rails api here