TL; DR ¿Por qué mi formulario de inicio de sesión de usuario no crea una nueva sesión / por qué falla sin errores?

Soy bastante nuevo en rieles y tengo cierta confusión sobre los formularios de inicio de sesión de los usuarios que crean nuevas sesiones. Básicamente, puedo iniciar sesión con el usuario sin crear una sesión, o iniciar sesión no funciona y tampoco crea la sesión, pero no obtengo ningún error.

He intentado:

  1. Usando cualquier versión de form_with que pueda encontrar, así como form_for y form_tag.
  2. Cambiando rutas a cualquier cosa y todo lo que pueda encontrar en google.
  3. Configuración SameSite="Lax".

New.html.erb

<h1>This is the new viewer page!</h1>

<%= form_with model: @user do |f| %>
    <%= f.label :name %>
    <%= f.text_field :name %><br>

    <%= f.label :username %>
    <%= f.text_field :username %>

    <%= f.label :email %>
    <%= f.text_field :email %>

    <%= f.label :password %>
    <%= f.text_field :password %>

    <%= f.submit %>
<% end %>

<%= form_for :session, url: login_path do |f| %>
    <%= f.label :id %>
    <%= f.text_field :id %>
    <%= f.submit "Sign in" %>
<% end %>

Session_controller.rb

class SessionsController < ApplicationController
    def new
    end

    def create
        @user = User.find_by_id(params[:id])
        if @user && @user.authenticate(params[:id][:password_digest])
            session[:id] = @user.id
            redirect_to user_path(@user), notice: "User logged in"
        else
            redirect_to root_path, alert: "Something is wrong"
        end
    end

    def destroy
        session[:user_id] = nil
        redirect_to root_path
    end
end

Routes.rb

Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  resources :users
  resources :sessions

  get "/login", to: "sessions#new"
  post "/login", to: "sessions#create", via: :"post"
  delete "/logout", to: "sessions#destroy"

  root "users#new"
end

Soy consciente de que mi mensaje flash es inútil para la depuración, tampoco pude encontrar nada sencillo para obtener una salida de depuración más clara. lo único que puedo encontrar es una advertencia en la consola del navegador que habla de samesite = none, por lo que las cookies serán rechazadas (estoy usando firefox)

EDITAR

El registro cuando intento enviar el formulario

Started POST "/login" for 127.0.0.1 at 2021-01-22 01:01:56 -0500
Processing by SessionsController#create as HTML
  Parameters: {"authenticity_token"=>"uUeDMYJKaxduZGqKJvaDiSO1bCFYDSIz6dcmp6CEeUNTYwBycJUb5l10K5KXcPZG2kOgdiK6pvPAKoDexwqSmA==", "session"=>{"id"=>"12"}, "commit"=>"Sign in"}
  [1m[36mUser Load (0.4ms)[0m  [1m[34mSELECT "users".* FROM "users" WHERE "users"."id" IS NULL LIMIT ?[0m  [["LIMIT", 1]]
  ↳ app/controllers/sessions_controller.rb:6:in `create'
Redirected to http://localhost:3000/
Completed 302 Found in 14ms (ActiveRecord: 0.4ms | Allocations: 1013)


Started GET "/" for 127.0.0.1 at 2021-01-22 01:01:56 -0500
Processing by UsersController#new as HTML
  Rendering users/new.html.erb within layouts/application
  Rendered users/new.html.erb within layouts/application (Duration: 2.3ms | Allocations: 1302)
[Webpacker] Everything's up-to-date. Nothing to do
Completed 200 OK in 9ms (Views: 8.7ms | ActiveRecord: 0.0ms | Allocations: 4667)

EDITAR 2

Log después de realizar algunos cambios:

Started POST "/users" for 127.0.0.1 at 2021-01-23 03:22:03 -0500
Processing by UsersController#create as JS
  Parameters: {"authenticity_token"=>"TIbECQO9vWQfDfmT89rGHKtdlamLXOUG3MYVgiB1bqZJJgp8C0h9LmFdyrLOS4HTmi/IHBp5bz0flz7BRU5wYA==", "user"=>{"id"=>"12"}, "commit"=>"Sign in"}
Redirected to http://localhost:3000/users/12
Completed 200 OK in 9ms (ActiveRecord: 0.0ms | Allocations: 2142)


Started GET "/users/12" for 127.0.0.1 at 2021-01-23 03:22:03 -0500
Processing by UsersController#show as HTML
  Parameters: {"id"=>"12"}
  [1m[36mUser Load (0.3ms)[0m  [1m[34mSELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?[0m  [["id", 12], ["LIMIT", 1]]
  ↳ app/controllers/users_controller.rb:3:in `show'
  Rendering users/show.html.erb within layouts/application
  Rendered users/show.html.erb within layouts/application (Duration: 1.3ms | Allocations: 96)
[Webpacker] Everything's up-to-date. Nothing to do
Completed 200 OK in 12ms (Views: 8.1ms | ActiveRecord: 0.3ms | Allocations: 4300)
0
schnondle 22 ene. 2021 a las 09:27

1 respuesta

La mejor respuesta

La razón por la que no sucede nada es que el código está completamente roto.

Mire los parámetros en el registro:

Processing by UsersController#create as JS
  Parameters: {"authenticity_token"=>"TIbECQO9vWQfDfmT89rGHKtdlamLXOUG3MYVgiB1bqZJJgp8C0h9LmFdyrLOS4HTmi/IHBp5bz0flz7BRU5wYA==", "user"=>{"id"=>"12"}, "commit"=>"Sign in"}

Ahora mira tu método de creación:

def create
    @user = User.find_by_id(params[:id])
    if @user && @user.authenticate(params[:id][:password_digest])
        session[:id] = @user.id
        redirect_to user_path(@user), notice: "User logged in"
    else
        redirect_to root_path, alert: "Something is wrong"
    end
end

No hay params[:id] ni contraseña pasada en ningún lugar de los parámetros. params[:id][:password_digest] también siempre será nulo. Entonces, si @user && @user.authenticate(params[:id][:password_digest]) NUNCA va a ser verdad.

params[:id][:password_digest] se vuelve loco cuando genera resúmenes de contraseñas con un algoritmo de cifrado como bcrypt a partir de una contraseña de texto sin formato y los guarda en la base de datos. En realidad, nunca tomaría un resumen de contraseña de un usuario.

En cambio, al iniciar sesión con un usuario, toma una contraseña de texto sin formato y la pasa a bcrypt, que le indica si el resumen de la contraseña coincide con alguno de los hash generados para esa cadena. Si es así, .authenticate devuelve verdadero.

También es extraño que el usuario proporcione una identificación en lugar de algo como un correo electrónico o un nombre de usuario.

Lo que realmente quieres es algo como:

class User < ApplicationRecord
  has_secure_password
end
class SessionsController < ApplicationController
  # GET /login
  def new; end

  # POST /login
  def create
    @user = User.find_by_email(params[:email])
    if @user&.autenticate(params[:password])
      session[:user_id] = @user.id
    else
      flash.now[:error] = 'Invalid email or password'
      render :new
    end
  end

  # DELETE /logout
  def destroy
    session.delete(:user_id)
    redirect_to root_path
  end
end
# app/views/sessions/_form.html.erb
# this creates a form with "unnested" inputs
<%= form_with url: login_path, local: true do |form| %>
  <div class="field">
    <%= f.label :email %>
    <%= f.email_field :email %>
  </div>
  <div class="field">
    <%= f.label :password %>
    <%= f.password_field :email %>
  </div>
  <%= f.submit "Sign in" %>
<% end %>
# app/views/sessions/new.html.erb
<h1>Sign in</h1>

<%= render partial: 'form' %>
1
max 24 ene. 2021 a las 02:46