Rails 4 - разработка гостевых пользователей приводит к остановке цепочки фильтров

Я только начал работать над приложением Rails 4 (4.2.3), где я использую Devise для аутентификации пользователя. Я хочу, чтобы пользователи могли поиграть с приложением, прежде чем подписывать upp, создав тестовый проект, и войти в него как гость. Когда пользователь регистрируется (или в), я хочу назначить тестовый проект новому текущему пользователю.

Я следовал этому руководству от Platformatec: https://github.com/plataformatec/devise/wiki/How-To:-Create-a-guest-user

Создание гостевого пользователя работает, но при регистрации или в сеансе активного гостевого пользователя я получаю следующую ошибку:

Filter chain halted as :require_no_authentication rendered or redirected

Если я очищаю свою сессию, это работает. Метод, который управляет моим гостевым пользователем, выглядит так:

def current_or_guest_user
  if current_user
    if session[:guest_user_id] && session[:guest_user_id] != current_user.id
      logging_in
      guest_user(with_retry = false).try(:destroy)
      session[:guest_user_id] = nil
    end
    current_user
  else
    guest_user
  end
end

Как уже упоминалось, создание гостевых пользователей, кажется, работает просто отлично. Но такой логики никогда не бывает:

# should delete the guest user and clear the session. 
if current_user
  if session[:guest_user_id] && session[:guest_user_id] != current_user.id
    logging_in
    guest_user(with_retry = false).try(:destroy)
    session[:guest_user_id] = nil
  end
  current_user

Я почти уверен, что мой сеанс гостевого пользователя конфликтует с моим новым пользователем и вызывает эту ошибку Devise (так как гостевой пользователь никогда не удаляется при регистрации):

Filter chain halted as :require_no_authentication rendered or redirected

Остальная часть моей гостевой пользовательской логики выглядит более или менее точно так же, как это связанное руководство: https://github.com/plataformatec/devise/wiki/How-To:-Create-a-guest-user. Я также добавил код из параграфа / примера аутентификации: https://github.com/plataformatec/devise/wiki/How-To:-Create-a-guest-user.

Любые идеи о том, что мне не хватает, и как я могу получить свой current_or_guest_user удалить гостевого пользователя при регистрации и подписи при использовании Devise?

Обновить

Вот так выглядят мои маршруты:

devise_for :users, controllers: { sessions: "users/sessions", registrations:  "users/registrations" }

root :to => 'public#index'

resources :apps

get 'users/show', to: "users#show"
get 'users', to: "users#index"

post 'guests/receive_guest', to: "guests#receive_guest"

Обновление 2

В руководстве есть следующее утверждение:

Когда (и если) пользователь регистрируется или входит в систему, мы удаляем гостя и очищаем переменную сеанса.

Это не объясняет, как и где это сделать. Я думаю, мне нужно позвонить current_or_guest_user где-то снова Но я не уверен, где, так как я не очень знаком с Devise.

Обновление 3

Чтобы было немного понятнее. Это шаги, которые я хочу достичь.

  1. Пользователь создает тестовый проект.
  2. При создании тестового проекта создается гостевой пользователь и сеанс. Гостевой пользователь должен быть удален после окончания сеанса или #3.
  3. Если гостевой пользователь регистрируется, он / она должен войти в систему, и тестовый проект должен быть назначен новому реальному пользователю.
  4. Гостевой пользователь должен быть удален.

3 ответа

Решение

Спасибо за ваши ответы skahlert и SsouLlesS. Пропуск стратегии надзирателя помог, а определение обратных вызовов кажется чистым подходом. Помимо этого у меня были некоторые другие проблемы.

Одним из них было то, что мои пользовательские контроллеры Devise никогда не вызывались. Для этого создан еще один вопрос: Rails 4 - devise_for, не использующий пользовательские контроллеры. Решение состояло в том, что я использовал неправильный URL в моей модальной форме регистрации. Моя форма теперь выглядит так:

= form_for(resource, as: resource_name, url: user_registration_path do |f|

Затем я сделал так, как предложил skahlert, и удалил стратегию надзирателя из моего приложения.

Однажды мой обычай придумать Users::RegistrationsController < Devise::RegistrationsController позвонил контроллер, я решил переопределить действие создания. Он не полностью протестирован, но выглядит так:

# POST /resource
def create
  # Delete guest user and reset session. 
  new_user_from_guest = guest_user
  guest_user(with_retry = false).try(:destroy)
  session[:guest_user_id] = nil

  build_resource(sign_up_params)

  resource.save
  yield resource if block_given?
  if resource.persisted?
    if resource.active_for_authentication?
      set_flash_message :notice, :signed_up if is_flashing_format?
      sign_up(resource_name, resource)

      # Assign the guest users app to the new current user.
      new_user_from_guest.apps.each do |app|
        app.user_id = current_user.id
        app.save!
      end
      respond_with resource, location: after_sign_up_path_for(resource)
    else
      set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
      expire_data_after_sign_in!
      respond_with resource, location:  after_inactive_sign_up_path_for(resource)
    end
  else
    # Reset test user if signup fails, I have not tested this part yet. 
    guest_user
    guest_user.apps << new_user_from_guest.apps
    guest_user.save!

    clean_up_passwords resource
    set_minimum_password_length
    respond_with resource
  end
end

Кажется, все работает сейчас. Можно было бы провести некоторый рефакторинг и, возможно, попробовать метод обратного вызова, который SsouLlesS предложил в своем ответе.

Я думаю, что проблема вызвана стратегией надзирателя guest_user, упомянутой в руководстве. Так как Devise проверяет действительный сеанс надзирателя перед входом в систему, он вызывает перенаправление и флэш-сообщение:

if authenticated && resource = warden.user(resource_name)
  flash[:alert] = I18n.t("devise.failure.already_authenticated")
  redirect_to after_sign_in_path_for(resource)
end

Так что если вам строго не нужно это аутентифицировать! Метод для работы с гостевым пользователем, вы можете просто отключить эту стратегию, и она должна работать.

Приведенный выше ответ не имеет объяснения, loggin_in метод не вызывается, потому что вы не определили свой обратный вызов

В вашем ApplicationController вам нужно определить и затем установить обратный вызов следующим образом:

define_callbacks :logging_in_user
set_callback :logging_in_user, :before, :transfer_guest_user_actions_to_current_user

def transfer_guest_user_actions_to_current_user
  # todo
end

Вы пытались использовать драгоценный камень devise- guest? он реализует из коробки эту функциональность, а не делает это с нуля...

Проверьте этот пример контроллера, который реализует гостевой вход в систему. Надеюсь, поможет.

Другие вопросы по тегам