1 Вопрос: PG :: SyntaxError в / bookmarks - я не могу понять, почему SQL-запрос неправильный

вопрос создан в Wed, May 8, 2019 12:00 AM

При запуске приложения с помощью sinatra появляется сообщение об ошибке PG::SyntaxError at /bookmarks ERROR: syntax error at or near "{" LINE 1: SELECT * FROM users WHERE id = {:id=>"5"} ^ Это происходит, когда я нажимаю кнопку отправки на маршруте /users/new, после чего следует перейти к индексу маршрута /.

Обратный след предоставляет следующую информацию

/Users/BartJudge/Desktop/Makers_2018/bookmark-manager-2019/lib/database_connection.rb in async_exec @connection.exec(sql) р>

/Users/BartJudge/Desktop/Makers_2018/bookmark-manager-2019/lib/database_connection.rb in query @connection.exec(sql) р>

/Users/BartJudge/Desktop/Makers_2018/bookmark-manager-2019/lib/user.rb in find result = DatabaseConnection.query("SELECT * FROM users WHERE id = #{id}") app.rb in block in <class:BookmarkManager> @user = User.find(id: session[:user_id]) р>

Это файл базы данных_соединения

require 'pg'

class DatabaseConnection
  def self.setup(dbname)
    @connection = PG.connect(dbname: dbname)
  end

  def self.connection
    @connection
  end

  def self.query(sql)
    @connection.exec(sql)
  end
end

Это модель пользователя

require_relative './database_connection'
require 'bcrypt'

class User
  def self.create(email:, password:)
    encypted_password = BCrypt::Password.create(password
    )
    result = DatabaseConnection.query("INSERT INTO users (email, password) VALUES('#{email}', '#{encypted_password}') RETURNING id, email;")

    User.new(id: result[0]['id'], email: result[0]['email'])
  end

  attr_reader :id, :email

  def initialize(id:, email:)
    @id = id
    @email = email
  end

  def self.find(id)
    return nil unless id
    result = DatabaseConnection.query("SELECT * FROM users WHERE id = #{id}")
    User.new(
      id: result[0]['id'],
      email: result[0]['email'])
  end
end

Это контроллер

require 'sinatra/base'
require './lib/bookmark'
require './lib/user'
require './database_connection_setup.rb'
require 'uri'
require 'sinatra/flash'
require_relative './lib/tag'
require_relative './lib/bookmark_tag'

class BookmarkManager < Sinatra::Base
  enable :sessions, :method_override
  register Sinatra::Flash

  get '/' do
    "Bookmark Manager"
  end
  get '/bookmarks' do
    @user = User.find(id: session[:user_id])
    @bookmarks = Bookmark.all
    erb :'bookmarks/index'
  end

  post '/bookmarks' do
    flash[:notice] = "You must submit a valid URL" unless     Bookmark.create(url: params[:url], title: params[:title])

    redirect '/bookmarks'
  end

  get '/bookmarks/new' do
    erb :'bookmarks/new'
  end

  delete '/bookmarks/:id' do
    Bookmark.delete(id: params[:id])
    redirect '/bookmarks'
  end

  patch '/bookmarks/:id' do
    Bookmark.update(id: params[:id], title: params[:title], url: params[:url])
    redirect('/bookmarks')
  end

  get '/bookmarks/:id/edit' do
    @bookmark = Bookmark.find(id: params[:id])
    erb :'bookmarks/edit'
  end

  get '/bookmarks/:id/comments/new' do
    @bookmark_id = params[:id]
    erb :'comments/new'
  end

  post '/bookmarks/:id/comments' do
    Comment.create(text: params[:comment], bookmark_id: params[:id])
    redirect '/bookmarks'
  end

  get '/bookmarks/:id/tags/new' do
    @bookmark_id = params[:id]
    erb :'/tags/new'
  end

  post '/bookmarks:id/tags' do
    tag = Tag.create(content: params[:tag])
    BookmarkTag.create(bookmark_id: params[:id], tag_id: tag.id)
    redirect '/bookmarks'
  end

  get '/users/new' do
    erb :'users/new'
  end

  post '/users' do
    user = User.create(email: params[:email], password: params[:password])
    session[:user_id] = user.id
    redirect '/bookmarks'
  end

  run! if app_file == $0
end

self.find (id) в пользовательской модели - это место, где находится потенциально опасный SQL-запрос.

Я пробовал; "ВЫБЕРИТЕ * ОТ ПОЛЬЗОВАТЕЛЕЙ, ГДЕ id = # {id}"

и "SELECT * FROM пользователей WHERE id = '# {id}'"

Кроме того, я в тупике. Запрос выглядит хорошо, но у sinatra его нет.

Надеюсь, кто-нибудь поможет мне решить эту проблему. Заранее спасибо.

    
0
1 ответ                              1                         

Вы звоните по номеру find с аргументом хеширования:

User.find(id: session[:user_id])

но он ожидает только id:

class User
  ...
  def self.find(id)
    ...
  end
  ...
end

Затем вы в конечном итоге интерполируете хеш в строку SQL, что приводит к неверному HTML.

Вы должны сказать:

@user = User.find(session[:user_id])

передать только id, который ожидает User.find.

Вы также оставляете себя открытым для проблем с внедрением SQL, потому что для своих запросов вы используете незащищенную интерполяцию строк, а не заполнители.

Ваш метод query должен использовать exec_params вместо exec и должен принимать некоторые дополнительные параметры для значений заполнителя:

class DatabaseConnection
  def self.query(sql, *values)
    @connection.exec_params(sql, values)
  end
end

Тогда вещи, которые вызывают query, должны использовать заполнители в SQL и передавать значения отдельно:

result = DatabaseConnection.query(%q(
  INSERT INTO users (email, password)
  VALUES($1, $2) RETURNING id, email
), email, encypted_password)

result = DatabaseConnection.query('SELECT * FROM users WHERE id = $1', id)

...
    
1
2019-05-08 20: 59: 31Z
  1. Спасибо, это разобрало ошибки Синатры. У меня также была ошибка Rspec из-за той же проблемы, которую я сейчас также отсортировал благодаря вашей помощи.
    2019-05-08 22: 31: 02Z
источник размещен Вот