kurenn / market_place_api

The API on Rails tutorial application
142 stars 70 forks source link

email and password not coming through params when signing in user. #61

Open JoeyBodnar opened 8 years ago

JoeyBodnar commented 8 years ago

I am trying to access this from my iPhone app. I am trying to sign someone in via a post request, by sending in the email and password. currently I am just hard coding the email and password. Here is my code:

  def create
    user_password = params[:password]
    user_email = params[:email]
    user = user_email.present? && User.find_by(email: user_email)

    if user and valid_password? user_password
        puts "ok"
        sign_in user, store: false
        user.generate_authentication_token!
        user.save
        render json: user, status: 200, location: [:api, user]
    else
        puts "not ok"
        render json: { errors: "Invalid Email or password", status: 422 }
    end
end

You're first reaction is probably "it should be params[:session][:password] and params[:session][:email]." However, I already tried that, and when I do it that way, I get a server error 500. Actually, when I run the request as params[:session][:password], in my terminal (as I am tracking each request), I get the following error:

 Started POST "/api/sessions" for ::1 at 2016-01-28 02:54:20 -0500
 Processing by Api::V1::SessionsController#create as JSON
 Parameters: {"{\"email\":\"hey@hello.com\",\"password\":\"password\"}"=>"[FILTERED]"}
 Completed 500 Internal Server Error in 1ms (ActiveRecord: 0.0ms)

 NoMethodError (undefined method `[]' for nil:NilClass):
 app/controllers/api/v1/sessions_controller.rb:4:in `create'

So it says that there is an error in line 4 (which is of course where the params[:session][:password] line is). When I run just params[:password] there is no error, and it connects to the server, but the email and password come through as empty strings. I know this because I put this:

    user_password = params[:session][:password]
    user_email = params[:email]
user = user_email.present? && User.find_by(email: user_email)
    puts user
    puts user_email 
    puts user_password

and puts user evaluated to false, and user_email and user_password were just blank.

How can I get these values to come through from my iPhone app? And here is my code from Xcode:

 func postrequest() {
    let string = "http://localhost:3000/api/sessions"
    let url = NSURL(string: string)
    let session = NSURLSession.sharedSession()
    let request = NSMutableURLRequest(URL: url!)
    let params = ["email": "hey@hello.com", "password": "password"]
    request.HTTPMethod = "POST"
    do {
         request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions())

    }
    catch {

    }
    let tache = session.dataTaskWithRequest(request) { (data, response, error) -> Void in
        //
        if let antwort = response as? NSHTTPURLResponse {
            let code = antwort.statusCode
            print(code)
            do {
                let json = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
                print(json)
            }
            catch {

            }
        }
    }
    tache.resume()
}

thanks

JoeyBodnar commented 8 years ago

I should add, when I print the parameters coming through the hash, it says they are this:

{"{\"email\":\"hey@hello.com\",\"password\":\"password\"}"=>nil, "format"=>:json,       
"controller"=>"api/v1/sessions", "action"=>"create"}
JoeyBodnar commented 8 years ago

I understand that the reason they are coming back as empty strings is because the params[:password] and params[:email] looks for the key "password' and 'email' in the params hash, but there are no actual keys called that. How can I format my request from the iOS side so that instead my params hash looks like:

 {"email"=>"hey@hello.com", "password"=>"my_password", "format"=>:json,       
 "controller"=>"api/v1/sessions", "action"=>"create"}
ghost commented 8 years ago

It may be because you're not setting the content type to "application/json" in the header

kurenn commented 8 years ago

Your hash looks good, have you tried @SirUncleCid suggestion about the header?

Something I notice is the valid_password? method, shouldn't be user.valid_password? ?

buncis commented 8 years ago

I have same issue I have follow this workaround #68 and have add content type header still its return nil

I send my email and password via basic-authenticate header

I have solves this problem the problem is you cannot sent the email and password via authorization header you should sent it via data form curl -v -H "Content-Type:application/json" -X POST -d '{"session":{"password":"password","email":"user@user.com"}}' http://api.marketplaceapi.dev:3000/sessions/

@kurenn is there a solution so that we can use authorization header instead sent it via post parameter?

I think we can use the authorization header by parsing it by ourself and assign it to the desired variables

my code for sessions_controller.rb so that we can take email and passwords from authorization header

  def create
    authenticate_with_http_basic do |email, password|
      user_email = email
      user_password = password
      user = user_email.present? && User.find_by(email: user_email)
      if user and user.valid_password? user_password
        sign_in user, store: false
        user.generate_authentication_token!
        user.save
        render json: user, status: 200, location: [:api, user]
      else
        render json: { errors: "Invalid email or password" }, status: 422
      end
    end
  end

@kurenn hey bro i think you have a lot things to do for your next(rails5) books keep the good works I hope your book will be stable as michael hartl's

kurenn commented 8 years ago

@buncismamen Yeah on the new version I'm working on, I'll make a better effort on making the book more stable and less painful in some parts, and thanks for the kind words!