2017-05-10 49 views
0

我構建了一個正在工作的小型Sinatra應用程序,但我在註冊表單中添加了confirm_password,並在user_controller中做了更改並破壞了某些內容。現在,即使輸入了有效的用戶名和密碼,也不會讓用戶登錄。它再次使他們登錄/註冊頁面。如何辨別Sinatra在註冊或登錄後允許用戶連接

我試着用binding.pry進行調試,所以我知道它將session[:user_id]分配到user.id,但我不確定它爲什麼一直要求用戶憑證。

這是我的用戶遷移:

class CreateUsers < ActiveRecord::Migration[5.1] 
    def change 
    create_table :users do |t| 
     t.string :username 
     t.string :password_digest 
     t.string :email 
     t.timestamps 
    end 
    end 
end 

這是我的用戶模型:

class User < ActiveRecord::Base 

    has_secure_password 

    has_many :tips 
    has_many :languages, through: :tips 

    validates_presence_of :username, :email, :password_digest 
    validates_uniqueness_of :username, presence: {message: "That username is already taken, please use another username."} 
    validates_uniqueness_of :email, presence: {message: "That email is already associated to another account. Please use another email."} 

    include Slugifiable::InstanceMethods 
    extend Slugifiable::ClassMethods 

end 

這是我user_Controller:

class UserController < ApplicationController 

    get '/signup' do 
    if !logged_in? 
     erb :'users/signup' 
    else 
     redirect to '/tips' 
    end 
    end 

    post '/signup' do 
    # binding.pry 
    if params[:username] == "" || params[:password] == "" || params[:email] == "" || params[:confirm_password] == "" 
     redirect to '/signup' 
     # binding.pry 
    elsif params[:password] != params[:confirm_password] 
     erb :'users/password_error' 
    else 
     user = User.create(username: params[:username], password: params[:password], email: params[:email]) 
     session[:user_id] = user.id 
     redirect to '/tips' 
    end 
    end 

    get '/login' do 
    if !logged_in? 
     erb :'users/login' 
    else 
     redirect to '/tips' 
    end 
    end 

    post '/login' do 
    # binding.pry 
    user = User.find_by(username: params[:username]) 
    if user && user.authenticate(params[:password]) 
     session[:user_id] = user.id 
     redirect to "#{user.username}/tips" 
    else 
     redirect to '/signup' 
    end 
    end 

    get '/logout' do 
    if logged_in? 
     session.clear 
     # binding.pry 
     redirect to '/login' 
    else 
     redirect to '/' 
    end 
    end 

    get '/users/:slug' do 
    if logged_in? && current_user.slug == params[:slug] 
     @user = User.find_by_slug(params[:slug]) 
     erb :'/users/show' 
    else 
     redirect to '/tips' 
    end 
    end 

end 

我不認爲我的註冊表單正在創建任何問題,但出於調試目的,這裏是我的signup.erb表單:

<h2 style="color: #66FFFF">Sign Up for the Coding Tips </h2></br> </br> 
<form action="/signup" method="POST"> 
    <p> Username:   <input type="text" name="username" ></p> 
    <p> Email:    <input type="email" name="email"></p> 
    <p> Password:   <input type="password" name="password"></p> 
    <p> Confirm password: <input type="password" name="confirm_password"></p></br></br> 
    <input type="submit" value="Sign Up"> 
</form> 

我確定我正在使用有效的用戶名和密碼。我試圖創建一些新的用戶名,它也將它們保存到數據庫,但它不允許任何人登錄。

這些都是我的輔助方法:

def logged_in? 
     !!current_user 
    end 

    def current_user 
     @current_user ||= User.find(session[:id]) if session[:id] 
    end 

這裏是我的tip_comtroller

class TipController < ApplicationController 

    use Rack::Flash 

    get '/:slug/tips' do 
     @user = User.find_with_slug(params[:slug]) 
     if logged_in? && session[:user_id] == @user.id 
      erb :'/users/tips' 
     else 
      redirect to "/login" 
     end 
    end 

    get '/tips' do 
     erb :'/tips/tips' 
    end 

    get '/tips/new' do 
     if logged_in? 
      erb :'/tips/new' 
     else 
      redirect "/login" 
     end 
    end 

    post '/tips' do 
     @tip = current_user.tips.create(content: params[:content]) 
     if @tip 
      if params[:language][:name].nil? || params[:language][:name].empty? 
      @tip.language_id = params[:tip][:language_id] 
      else 
      new_language = Language.create(name: params[:language][:name]) 
      @tip.language_id = new_language.id 
      end 
      @tip.save 
      @user = @tip.user 
      redirect to "/tips/#{@tip.id}" 
     else 
      redirect "/tips/new" 
     end 
    end 

    get '/tips/:id' do 
     @id = params[:id] 
     if logged_in? 
     @tip = Tip.find_by_id(params[:id]) 
     if [email protected]? 
      erb :'/tips/show' 
     else 
      erb :'/tips/show_error' 
     end 
     else 
      redirect "/login" 
     end 
    end 

    get '/tips/:id/edit' do 
     if logged_in? 
      @tip = Tip.find_by_id(params[:id]) 
      if @tip.user.username == current_user.username 
       erb :'/tips/edit' 
      else 
       erb :'/tips/edit_error' 
      end 
     else 
      redirect "/login" 
     end 
    end 

    patch '/tips/:id' do 
     @tip = current_user.tips.find_by(params[:id]) 
     if @tip 
      @tip.update(:content => params[:content]) 
      if params[:language][:name].nil? || params[:language][:name].empty? 
      @tip.language_id = params[:tip][:language_id] 
      else 
      new_language = Language.create(name: params[:language][:name]) 
      @tip.language_id = new_language.id 
      end 
      @user = @tip.user 
      @tip.save 
      # binding.pry 
      redirect "/tips/#{@tip.id}" 
     else 
      redirect "/tips/#{@tip.id}/edit" 
     end 
    end 

    get '/tips/:id/delete' do 
     @tip = Tip.find_by_id(params[:id]) 
     if logged_in? 
      if current_user == @tip.user 
       @tip.destroy 
       redirect '/tips' 
      else 
       erb :'tips/delete_error' 
      end 
     else 
      redirect "/login" 
     end 
    end 

    get '/tips/:id/cancel' do 
     redirect "/tips/#{@tip.id}" 
    end 
end 

回答

1

logged_in功能是使用:id代替:user_id

def logged_in? 
    !!current_user 
end 

def current_user 
    @current_user ||= User.find(session[:id]) if session[:id] 
end 

嘗試將其更改爲:

def logged_in? 
    !!current_user 
end 

def current_user 
    @current_user ||= User.find(session[:user_id]) if session[:user_id] 
end 
+1

你是那麼對。我查了那麼多次,但沒有意識到它。現在它工作得很好。非常感謝。 –

0

當使用has_secure_password,密碼確認由ActiveRecord的處理。你只需要確認同時通過密碼到用戶,當您創建它:

user = User.create(username: params[:username], password: params[:password], password_confirmation: params[:confirm_password], email: params[:email]) 

如果密碼不,ActiveRecord的將返回尚未保存到數據庫無效的用戶。這使我想到下一點 - User.create不會引發任何錯誤。如果您想要拋出錯誤,請使用User.create!。否則,你應該重定向之前驗證您的用戶:

user = User.create(username: params[:username], password: params[:password], password_confirmation: params[:confirm_password], email: params[:email]) 
return erb 'users/password_error' unless user.valid? 
session[:user_id] = user.id 
redirect to '/tips' 

您還可以查看具體的錯誤,像這樣:

unless user.valid? 
    return erb 'users/password_error' if user.errors[:password].any? 
    return erb 'users/username_error' if user.errors[:username].any? 
end 
+0

非常感謝您的建議,但是,我不需要數據庫中的另一個密碼列嗎?如果是,那麼遷移文件中該列的名稱應該是什麼?因爲has_secured_pa​​ssword要求將密碼列命名爲pssword_digest和rake db:遷移不會讓我有兩個具有相同名稱的列。 –

+0

@HimaChhag nope,你不需要更多的專欄!ActiveRecord會檢查':password_confirmation'對':password'來查看它們是否匹配,但它實際上並不實際保存':password_confirmation'。 – eiko

+0

非常感謝您的建議。這比以前更好。檢查密碼並給出相應的錯誤,但仍然給出相同的問題。它在註冊時創建一個新用戶,將會話[:user_id]分配給user.id,但不允許任何人登錄!請提供其他建議嗎? –

相關問題