Devise Электронное письмо с подтверждением отправляется на почту. Как запретить пользователю входить в систему, если он не подтверждает почту?

Я использую devise. Раньше я не мог войти в систему без подтверждения электронной почты. Затем мне пришлось настроить подтверждение по электронной почте для моего приложения. Поэтому я добавил подтверждение в user.rb и внес изменения в миграцию пользователей. Также я внес изменения в файл devise.rb. Также я сделал настройку почтовой программы как smtp в файле config/environment/development.rb.

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

application_controller.rb

# frozen_string_literal: true

# Router entry point
require 'json_web_token'
class ApplicationController < ActionController::Base
    before_action :configure_permitted_parameters, if: :devise_controller?
    before_action :make_action_mailer_use_request_host_and_protocol
    # before_action :authenticate_user!, :set_mailer_host
    protect_from_forgery with: :exception

    respond_to :html, :json

    def index
        render template: 'application'
    end

    def not_found
        render json: { error: 'not_found' }
    end

    def authorize_request
        header = request.headers['Authorization']
        header = header.split(' ').last if header
        begin
        @decoded = JsonWebToken.decode(header)
        @current_user = User.find(@decoded[:user_id])
        rescue ActiveRecord::RecordNotFound => e
        render json: { errors: e.message }, status: :unauthorized
        rescue JWT::DecodeError => e
        render json: { errors: e.message }, status: :unauthorized
        end
    end

    protected

    def current_user
        @current_user ||= User.find_by(id: session[:user_id])
    end

    def signed_in?
        !!current_user
    end
    helper_method :current_user, :signed_in?

    def current_user=(user)
        session[:user_id] = user&.id
        @current_user = user
    end

    def configure_permitted_parameters
        update_attrs = [:password, :password_confirmation, :current_password]
        devise_parameter_sanitizer.permit :account_update, keys: update_attrs
        devise_parameter_sanitizer.permit(:login, keys: [ :email, :password ])
    end

    private

    def make_action_mailer_use_request_host_and_protocol
        ActionMailer::Base.default_url_options[:protocol] = request.protocol
        ActionMailer::Base.default_url_options[:host] = request.host_with_port
    end 
end

авторизация_controller.rb

module Api
    module V1
        class AuthenticationController < ApplicationController
            skip_before_action :verify_authenticity_token
            before_action :authorize_request, except: :login

            # POST /auth/login
            def login
                @user = User.find_by_email(params[:email])
                if @user&.valid_password?(params[:password])
                token = JsonWebToken.encode(user_id: @user.id)
                time = Time.now + 24.hours.to_i
                render json: { token: token, exp: time.strftime("%m-%d-%Y %H:%M"),
                                username: @user.username, user_id: @user.id }, status: :ok
                else
                render json: { error: 'unauthorized' }, status: :unauthorized
                end
            end

            private

            def login_params
                params.permit(:email, :password)
            end
        end
    end
end

users_controller.rb

module Api
    module V1
        class UsersController < ApplicationController
            skip_before_action :verify_authenticity_token

            before_action :authorize_request, except: :create

            # GET /users
            def index
                @users = User.all
                render json: @users, status: :ok
            end

            def create
                # render plain: params.inspect
                @user = User.new(user_params)
                # render plain: user_params.insp
                if @user.save
                    render json: @user, status: :created
                else
                    render json: { errors: @user.errors.full_messages },
                        status: :unprocessable_entity
                end
            end

            def update
                user = User.find(params[:id])
                if user.update(user_params)
                render json: user, status: :created
                else
                render json: { errors: user.errors.full_messages },
                        status: :unprocessable_entity
                end
            end

            def show
                user = User.find(params[:id])
                if !user.nil?
                    render json: user, status: :ok
                else
                    render json: {errors: user.errors.full_messages}, status: :unprocessable_entity
                end
            end

            def destroy
                user = User.find(params[:id])
                if user.destroy
                    render json: {success: "deleted successfully"}, status: :ok
                else
                    render json: {errors: user.errors.full_messages}, status: :not_acceptable
                end
            end

            private

            def find_user
                @user = User.find_by_username!(params[:_username])
                rescue ActiveRecord::RecordNotFound
                render json: { errors: 'User not found' }, status: :not_found
            end

            def user_params
                params.permit(
                    :first_name, :last_name, :username, :email, :password, :password_confirmation
                )
            end
        end
    end
end

Registrations_controller.rb

class RegistrationsController < Devise::RegistrationsController
    skip_before_action :require_no_authentication
    def update_resource(resource, params)
        if resource.encrypted_password.blank?
            resource.email = params[:email] if params[:email]
            if !params[:password].blank? && params[:password] == params[:password_confirmation]
                resource.password = params[:password]
                resource.save
            end
            if resource.valid?
            resource.update_without_password(params)
            end
        else
            resource.update_with_password(params)
        end
    end
end

пользователь.rb

class User < ApplicationRecord
    # has_secure_password
    # Include default devise modules. Others available are:
    # :confirmable, :lockable, :timeoutable and :omniauthable
    devise :database_authenticatable, :registerable,
        :recoverable, :rememberable, :trackable, :validatable,
        :confirmable, :omniauthable, password_length: 8..36
    has_many :identities
    has_one :testimonials
    has_many :questions
    has_many :answers


    def facebook
        identities.where(provider: 'facebook').first
    end

    def facebook_client
        @facebook_client ||= Facebook.client(access_token: facebook.accesstoken)
    end

    def twitter
        identities.where(provider: 'twitter').first
    end

    def twitter_client
        @twitter_client ||= Twitter.client(access_token: twitter.accesstoken)
    end

    def google_oauth2
        identities.where(provider: 'google_oauth2').first
    end

    def google_oauth2_client
        unless @google_oauth2_client
        @google_oauth2_client = Google::APIClient.new(application_name: '',
                                                        application_version: '')
        @google_oauth2_client.authorization.update_token!(access_token: google_oauth2.accesstoken,
                                                            refresh_token: google_oauth2.refreshtoken)
        end
        @google_oauth2_client
    end

    #validation for users
    validates :username, presence: true, uniqueness: {case_sensitive: false}

    # validates_format_of :username, with: /^[a-zA-Z0-9_\.]*$/, :multiline => true
    validates :email, presence: true, uniqueness: {case_senstive: false}
    PASSWORD_FORMAT = /\A
        (?=.{8,})          # Must contain 8 or more characters
        (?=.*\d)           # Must contain a digit
        (?=.*[a-z])        # Must contain a lower case character
        (?=.*[A-Z])        # Must contain an upper case character
        (?=.*[[:^alnum:]]) # Must contain a symbol
        /x

    validates :password,
        presence: true,
        # length: { in: Devise.password_length },
        format: { with: PASSWORD_FORMAT, message: 'must contain 8 Characters with at least One Lowercase, One Uppercase, One Number and One Special Character' },
        confirmation: true,
        on: :create

        validates :password_confirmation,
        presence: true

    validates :password,
        # allow_nil: true,
        # length: { in: Devise.password_length },
        format: { with: PASSWORD_FORMAT, message: 'must contain 8 Characters with at least one Uppercase, One Number and One Special Character' },
        confirmation: true,
        on: :update

end

Дикое предположение, но есть ли логическое значение (чтобы сказать, что пользователь активирован), которое по умолчанию равно true?

Kris 30.05.2019 16:29

Привет, Крис, имеет ли значение передняя часть ??

susie 31.05.2019 04:06

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

Kris 31.05.2019 13:03
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
601
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Взгляните на инициализатор вашего устройства, вам нужно установить allow_unconfirmed_access_for на 0 (на самом деле, по умолчанию он должен быть равен нулю). Согласно разработать документацию:

#   * +allow_unconfirmed_access_for+: the time you want to allow the user to access their account
#     before confirming it. After this period, the user access is denied. You can
#     use this to let your user access some features of your application without
#     confirming the account, but blocking it after a certain period (ie 7 days).
#     By default allow_unconfirmed_access_for is zero, it means users always have to confirm to sign in.

Devise использует этот метод для проверки неподтвержденного доступа.

Не могли бы вы также опубликовать результаты этих методов:

  • User.find(id_of_user_that_was_just_created).confirmation_required?
  • User.find(id_of_user_that_was_just_created).confirmed?
  • User.find(id_of_user_that_was_just_created).confirmation_period_valid?

спасибо за попытку помочь. Но это тоже не работает.

susie 31.05.2019 04:03

Смотрите обновления в моем ответе, пожалуйста, опубликуйте результат вызовов вышеуказанных методов.

Peter Balaban 31.05.2019 08:40

Кроме того, как я вижу, вы используете собственный контроллер для авторизации authorization_controller. Когда вы сказали But even without clicking that mail link User is able to login., вы имели в виду вход через контроллер сеансов разработки или через authorization_controller?

Peter Balaban 31.05.2019 08:51
Ответ принят как подходящий

В приведенном выше коде не было никаких ошибок с логикой. У меня была ошибка в представлениях, какие маршруты генерируют ссылку.

ПРАВИЛЬНЫЙ адрес:

<p>
   <%= link_to 'Confirm my account', confirmation_url(@resource,
   confirmation_token: @token) %>
</p>

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