Reputation: 647
I want to create an 'image' object on the rails server by JSON POST. This worked perfectly, but now I added user authentication and it doesn't work anymore. I use the gem 'devise' for authentication. Register, login and logout work perfectly with json.
user.rb:
class User < ActiveRecord::Base
has_many :images
attr_accessible :name, :email, :password, :password_confirmation, :remember_me, :encrypted_password
has_secure_password
validates :email, format: /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, uniqueness: true
end
images_controller:
class ImagesController < ApplicationController
before_filter :require_login #checks if user is logged in before user accesses images
respond_to :json
def index
@images = current_user.images
respond_to do |format|
format.html { }
format.json { render :json => {:success => true,
:info => "images",
:data => @images } }
end
end
def edit
@image = current_user.images.find(params[:id])
end
def new
@image = current_user.images.build
end
def create
@image = current_user.images.build(params[:image])
respond_to do |format|
if @image.save
format.html { redirect_to images_path }
format.json { render :json => @image }
else
format.html { render "new" }
format.json { render json: @image.errors, status: :unprocessable_entity }
end
end #respond_to
end
private
def require_login
unless user_signed_in? #in application_controller
redirect_to login_path,
alert: "Login first."
end
end
end
sessions_controller:
class SessionsController < ApplicationController
respond_to :json
def new
#empty because no underlying model
end
def create
#user = User.find_by_email(params[:user][:email]) #when JSON: { "user" : { "email":"[email protected]", "password":"asdf" }}
user = User.find_by_email(params[:email]) #when JSON: { "email":"[email protected]", "password":"asdf" }
respond_to do |format|
if user && user.authenticate(params[:password]) #because user has_secure_password
session[:user_id] = user.id
format.html { redirect_to images_path, notice: "Login successful!" }
format.json { render :json => {:success => true,
:info => "Logged in",
:data => { } } }
else
format.html { flash.now.alert = "Wrong email or password"
render "new" }
format.json { render :json => {:success => false, :info => "Wrong email or password" } }
end
end
end
def destroy
session[:user_id] = nil
respond_to do |format|
format.html { redirect_to root_path, notice: "Logout successful!" }
format.json { render :json => {:success => true,
:info => "Logged out",
:data => { } } }
end
end
end
rake routes:
root / pages#home
new_image GET /images/new(.:format) images#new
images GET /images(.:format) images#index
image GET /images/:id(.:format) images#show
POST /images(.:format) images#create
edit_image GET /images/:id/edit(.:format) images#edit
PUT /images/:id(.:format) images#update
image DELETE /images/:id(.:format) images#destroy
users POST /users(.:format) users#create
new_user GET /users/new(.:format) users#new
login GET /login(.:format) sessions#new
sessions POST /sessions(.:format) sessions#create
logout DELETE /logout(.:format) sessions#destroy
application_controller:
class ApplicationController < ActionController::Base
protect_from_forgery
def current_user
if session[:user_id]
@current_user ||= User.find(session[:user_id])
end
end
def user_signed_in?
current_user.present?
end
helper_method :user_signed_in?
end
After logging in, which works (showing images also works with GET method and url http://localhost:3000/images
), I cannot create a new image with JSON. This is my request from client (I use Chrome's Simple REST Client):
url: http://localhost:3000/images
method: POST
Content-Type: application/json
Accept: application/json
Data: {"image":{ "title":"someTitle","url": "someUrl" }}
Response:
500 Internal Server Error
<h1>Template is missing</h1>
<p>Missing template sessions/new, application/new with {:locale=>[:en], :formats=>[:json], :handlers=>[:erb, :builder, :coffee]}. Searched in:
* "c:/Users/XXX/workspaceRubyOnRails/my_server/app/views"
* "c:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/devise-2.2.4/app/views"
</p>
Upvotes: 2
Views: 748
Reputation: 36944
Seems like your JSON request is not authenticated. Because of that, Devise sends you to the sign in page. But you don't have JSON version of your sign in page and therefore you get the Missing template sessions/new
error.
You can send your cookies together with the request or even better, use token authentication from Devise so you can do your request with a token for authentication like this:
curl -v -H "Accept: application/json" -H "Content-type: application/json" http://localhost:3000/images?auth_token=<token>
You can find some code examples here: https://github.com/plataformatec/devise/wiki/How-To:-Simple-Token-Authentication-Example
Upvotes: 1
Reputation: 933
I think that you need to authenticate via the Chrome Simple REST client - your rails app appears to be differentiating between Chrome itself and the rest client.
I will expand this answer once you have gotten past that hurdle.
Upvotes: 0