настройка методов аутентификации и current_user Devise для работы с программным удалением / действует как параноик

Я использую Devise в качестве аутентификации для приложения rails 3.2. Моя пользовательская модель называется User, и я пытался реализовать обратимое удаление. Я пытаюсь сделать это с помощью act_as_paranoid, который автоматически делает всю работу за вас. Все работает так, как ожидалось (другие больше не могут видеть «удаленного» пользователя), за исключением того, что я хочу, чтобы деактивированный пользователь по-прежнему мог войти в систему и видеть «деактивированный» экран и дать им возможность повторно активировать свою учетную запись.

Проблема в том, что Devise (Warden?) больше не может найти удаленного пользователя. Acts_as_paranoid позволяет вам получить доступ к обратимо удаленным записям, если вы используете область «with_deleted». Итак, я могу пройти часть пути с помощью:

def self.find_first_by_auth_conditions(warden_conditions)
  conditions = warden_conditions.dup
  where(conditions).with_deleted.first
end

Я поместил это в свою пользовательскую модель, и поэтому теперь, когда я ввожу информацию для входа в систему, я получаю флэш-сообщение о том, что я успешно вошел в систему, и оно касается столбца «updated_at» в пользовательской модели и увеличивает значение sign_in_count и т. д. Однако на самом деле он не аутентифицируется в том смысле, что аутентифицированный метод возвращает false, а вспомогательный метод current_user возвращает nil. Итак, какова моя лучшая стратегия, чтобы заставить их работать? Могу ли я каким-то образом переопределить метод current_user, чтобы он запрашивал модель User с областью действия with_deleted? Нужно ли мне что-то делать с надзирателем, например добавлять условия, как я сделал с методом find_first_by_auth_conditions? Я не могу понять, как это сделать. Любая помощь приветствуется!

Кроме того, после того, как я заработаю, я хотел бы автоматически отправлять всех мягко удаленных пользователей на «деактивированную» страницу, где их единственными вариантами являются окончательное удаление или повторная активация. Есть ли способ сделать это с помощью маршрутизации через «аутентифицированный: user do {} конец», или мне нужно поместить before_filter в application_controller и проверять пользователей при каждом запросе?


person kindofgreat    schedule 07.04.2013    source источник


Ответы (2)


Я могу ответить на ваш последний вопрос о переходе на «деактивированную страницу». Вы можете использовать лямбду для изоляции разных типов пользователей, например:

authenticated :user, lambda {|u| u.deactivated? } do
  root :to => 'application#deactivated'
end
authenticated :user, lambda {|u| u.active? } do
  root :to => 'application#active'
end
person Teddy    schedule 16.04.2013
comment
Спасибо за ответ по этой части. Проблема в том, что это (насколько я знаю; не пробовал, потому что я все еще работаю над тем, чтобы аутентификация работала с удаленными пользователями) направляет только корневой путь к «application#deactivated» или «application#activate». '. Это не отправляет деактивированного пользователя на эту же страницу независимо от пути. То есть, если деактивированный пользователь зайдет на root.com/any, я все равно хочу, чтобы он увидел деактивированную страницу, но такая настройка маршрутов этого не сделает. Я думаю, что, поскольку я пытаюсь защитить кучу маршрутов, нет никакого способа обойти предварительный фильтр. - person kindofgreat; 17.04.2013

Благодаря подсказке от группы Devise оказалось, что мне нужно было переопределить метод serialize_from_session, который находится внутри аутентифицируемого модуля и выглядит так:

def serialize_from_session(key, salt)
  record = to_adapter.get(key)
  record if record && record.authenticatable_salt == salt
end

Я безуспешно пытался переопределить модули с помощью инициализаторов (я пытался переопределить существующие стратегии, а также попробовать написать новую для надзирателя); но я продолжал получать странные ошибки имени. Я до сих пор этого не понял. Однако, воспользовавшись подсказкой, я пошел дальше и переопределил метод внутри своей модели пользователя. Поскольку я не предполагаю использовать какой-либо другой ресурс, я не возражал просто отредактировать его вот так. Код был просто:

def self.serialize_from_session(key, salt)
  record = with_deleted.find(key).first
  record if record && record.authenticatable_salt == salt
end

Это полностью пропускает метод to_adapter.get (который, для всех, кто интересуется, находится в orm_adapter, а не в devise; мне потребовалось некоторое время, чтобы найти, поскольку я думал, что мне нужно переопределить это). Это, вероятно, не самый чистый способ сделать это, но он работает достаточно хорошо для меня. И даже если у меня есть другой ресурс, это должно переопределять только ресурс пользователя, поэтому я думаю, что в противном случае все будет работать нормально.

Если возникнут проблемы, я добавлю их сюда. Если нет, надеюсь, это кому-то поможет. Конечно, мне понадобилось достаточно времени, чтобы добраться до сути!

person kindofgreat    schedule 18.04.2013