Добавление настраиваемых полей в модель пользователя с использованием функциональности на стороне сервера и использование Devise для первоначальной аутентификации - PullRequest
0 голосов
/ 16 марта 2019

Я использую Devise для аутентификации в веб-приложении Rails 5. Все мои представления регистрации пользователей сгенерированы разработчиками, и я добавил несколько полей в форму, чтобы иметь возможность динамически генерировать ключи PGP на внешнем интерфейсе. Я создал миграцию базы данных для этих дополнительных ключевых полей, и они сохраняются правильно. Теперь я пытаюсь добавить некоторые поля, которые я создаю на стороне сервера, которые не являются полями ввода пользователя.

Вот мой регистрационный контроллер:

class User::RegistrationsController < Devise::RegistrationsController
  before_action :sign_up_params, only: [:create]
  # before_action :configure_account_update_params, only: [:update]

  def show
    @user = User.find(params[:id])

  end

  private
  def sign_up_params
    params.require(:user).permit(
        :handle,
        :pin,
        :email,
        :password,
        :password_confirmation,
        :pgp_privatekey,
        :pgp_publickey
    )
  end
end

Теперь я пытаюсь выяснить, каков «лучший» способ сохранения полей, которые не являются результатом ввода данных пользователем (например, оценка широты / долготы на основе их IP-адреса или что-то в этом роде). как биткойн-адрес, который полностью генерируется на стороне сервера). Я чувствую, что это может быть наиболее подходящим образом сделано в моем контроллере во время первоначального вызова контроллера регистрации, возможно, когда это происходит при первоначальной регистрации. Но так как он не управляется пользователем, я не уверен, где в моем контроллере имеет смысл добавить эту логику.

Я реализовал метод в моей модели User под названием «generate_bitcoin_keypair», и я хочу сохранить сгенерированные поля в правильной записи пользователя в БД, но я пытаюсь понять, должен ли я просто добавить это в свой первоначальный регистрационный код с помощью расширение базовой функциональности Devise с помощью вызова super () и блока ресурсов, или имеет ли смысл поместить это в другое место? Очевидно, что теперь, когда метод определен в моем коде модели User.rb, я могу вызвать его в своем контроллере, но я просто пытаюсь понять, является ли это лучшим, наиболее кратким способом сделать то, что я пытаюсь выполнить.

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

require 'bitcoin'
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  def self.generate_bitcoin_keypair
    key = Bitcoin::Key.generate()
    {:btc_addr => key.addr, :btc_privkey => key.priv}
  end
end

Должен ли я реализовать метод create в моем контроллере регистрации, который в основном вызывает код generate_bitcoin_keypair модели пользователя, а затем сохраняет его для соответствующего пользователя (на основе сеанса [: id])?

Я пытаюсь понять, как лучше всего это сделать, и если мой вопрос вообще неясен, пожалуйста, дайте мне знать.

Я думаю, что-то подобное может сработать:

  def create
    super do
      btcdata = User.generate_bitcoin_keypair()
      resource.btc_address = btcdata.btc_addr
      resource.btc_privatekey = btcdata.btc_privkey
      resource.save
    end
  end

в моем registration_controller.rb, но так как пользовательская запись уже была создана и сохранена в базе данных, я думаю, может быть, она должна быть чем-то вроде метода редактирования, а не метода создания, и я не совсем ясно, где именно должна сидеть логика.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 16 марта 2019

Я бы не положил его в контроллер.Как вы упомянули, это не поведение пользователя.Я думаю, что это поведение, присущее созданию нового пользователя.Поэтому я бы оставил логику для генерации пар ключей биткойнов в модели User и назвал бы ее в ActiveRecord обратном вызове

require 'bitcoin'
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  before_create :generate_bitcoin_keypair

  def generate_bitcoin_keypair
    key = Bitcoin::Key.generate()
    self.btc_address = key.addr
    self.btc_privatekey = key.priv
  end
end

. Это сгенерирует ключ биткойнов.создать пару и назначить атрибуты записи пользователя до ее создания в базе данных.

0 голосов
/ 16 марта 2019

Вы можете подключиться к потоку Devise::RegistrationsController#create перед сохранением записи, переопределив #build_resource:

class User::RegistrationsController < Devise::RegistrationsController
  protected
  def build_resource(hash = {})
    super
    self.resource.ip_address = request.remote_ip
  end
end

В этом методе Devise связывает параметры и сессиюинформация для создаваемого ресурса.

Devise также предоставляет #update_resource, где вы можете использовать метод #update.Я бы посоветовал вам прочитать источник - поначалу это может быть немного утомительно из-за сумасшедшего уровня конфигурируемости, но предоставляет тонны хуков.

Чтобы дополнительные параметры были лучшеИдея добавить средство для дезинфекции Devise Param вместо повторной реализации всего этого, поскольку это будет просто работать , если вы решите добавить больше модулей Devise в будущем.

class User::RegistrationsController < Devise::RegistrationsController
  # ...
  def configure_permitted_parameters
     #
    devise_parameter_sanitizer.permit(:sign_up, keys: [:handle])
  end
end

Обратите внимание, что вы НЕ ДОЛЖНЫ разрешать параметры, которые не должны поступать из параметров запроса, такие как pgp_privatekey и pgp_publickey, поскольку злоумышленник может легко обмануть ваш контроллер с помощью cURL.Это относится к Rails в целом и является единственной причиной, по которой у нас есть строгие параметры.

При этом вы должны разместить как можно больше бизнес-логики в той модели, которой она принадлежит.Например, генерация пары ключей биткойнов может быть выполнена в модели, а также геолокация с IP .Модели гораздо проще тестировать, чем контроллеры.

# Example uses the Geocoder gem
require 'bitcoin'
class User < ApplicationRecord
  # Omit this if you have a database column for ip_address
  attr_accessor :ip_address 
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  before_create :generate_bitcoin_keypair!
  before_create :geocode_from_ip!, if: :can_be_geocoded?

  protected

  def generate_bitcoin_keypair!
    Bitcoin::Key.generate.tap do |key|
      self.btc_address = key.addr
      self.btc_privatekey = key.priv
    end
  end

  def geocode_from_ip!
    results = Geocoder.search(self.ip_address)
    self.coordinates = results.first.coordinates if results.any?
  end

  def can_be_geocoded?
    ip_address.present?
  end
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...