Ilya Cherevkov
Ilya Cherevkov

Reputation: 1803

curl POST create association request via terminal in rails app

I am trying to create CRUD api for my app, which has two models: User and Group, which have many-to-many association through :memberships table.

For authentication I use Devise (with :token_authenticatable option enabled)

I want to test API using curl.

Sign Up works perfectly

curl -v -H 'Content-Type: application/json' -H 'application/vnd.greenapp.v1' -X POST http://localhost:3000/api/registrations -d "{\"user\":{\"email\":\"[email protected]\",\"name\":\"username\",\"password\":\"secret\",\"password_confirmation\":\"secret\"}}"

with response

{"success":true,"info":"Welcome! You have signed up successfully.","data":{"user":{"created_at":"2013-08-04T11:14:35Z","email":"[email protected]","id":2,"name":"username","updated_at":"2013-08-04T11:14:35Z"},"auth_token":"Eqp8jYsr5ExeNWbzrqef"}}* Closing connection #0

but I am struggling to find solution to create groups via API. I tried

curl -v -H 'Content-Type: application/json' -H 'application/vnd.greenapp.v1' -X POST http://localhost:3000/api/groups -d "{\"group\":{\"name\":\"groupname\",\"desc\":\"group description\"}}"

which returns (in server logs)

RuntimeError (Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id): app/controllers/api/v1/groups_controller.rb:49:in `create'

So here is my groups controller:

class Api::V1::GroupsController < ApplicationController
  skip_before_filter :verify_authenticity_token,
                     :if => Proc.new { |c| c.request.format == 'application/json' }

  respond_to :json

  def new
    @group = Group.new

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @group }
    end
  end

  def create
    @group = Group.new(params[:group])
    @group.memberships.build(user_id: current_user.id)
    respond_to do |format|
      if @group.save

        format.html { redirect_to @group, notice: 'Group was successfully created.' }
        format.json { render json: @group, status: :created, location: @group }
      else
        format.html { render action: "new" }
        format.json { render json: @group.errors, status: :unprocessable_entity }
      end
    end
  end

end

Any ideas?

Update

SessionsCotroller

class Api::V1::SessionsController < Devise::SessionsController
  skip_before_filter :verify_authenticity_token,
                 :if => Proc.new { |c| c.request.format == 'application/json' }

  respond_to :json

  def create
    warden.authenticate!(:scope => resource_name, :store => false, :recall => "#  {controller_path}#failure")
    render :status => 200,
       :json => { :success => true,
                  :info => t("devise.sessions.signed_in"),
                  :data => { :auth_token => current_user.authentication_token } }
  end

  def destroy
    warden.authenticate!(:scope => resource_name, :store => false, :recall => "#{controller_path}#failure")
    current_user.reset_authentication_token!
    render :status => 200,
       :json => { :success => true,
                  :info => t("devise.sessions.signed_out"),
                  :data => {} }
  end

  def failure
    render :status => 401,
       :json => { :success => false,
                  :info => "Login Failed",
                  :data => {} }
  end
end

Upvotes: 1

Views: 1278

Answers (1)

jamesc
jamesc

Reputation: 12837

Your current_user instance is nil. As part of your curl command you will need to supply the login credentials and ensure that your code logs in using those credentials as part of your before_filter.

I'm surprised you are not getting an authentication exception. But maybe you haven't implemented your authentication system properly.

To log in with an api you really need to be using HTTP BASIC authentication with a user name and password or to use some form of auth token.

Unable to advise further as you have not supplied any information about your authentication functionality.

p.s. You really should write a test for this.

UPDATE IN RESPONSE TO COMMENTS

Remove the skip_before_filter :verify_authenticity_token from your groups controller and supply a valid auth token along with your curl command. I've never used devise or warden so I'm not entirely sure if you are going to face redirect issues.

I usually find it is far simpler to roll my own authentication and it focuses the mind on making sure that ssl is forced on the right controller actions and gets me thinking about SSL certs for the web server and all those other little security things that tend to get forgotten about when you rely on a gem.

Upvotes: 2

Related Questions