From 47f72ce0cd186358057f179f5bc2f8fedef4136e Mon Sep 17 00:00:00 2001 From: oleghasjanov Date: Wed, 26 Jun 2024 12:11:23 +0300 Subject: [PATCH] added prepend action to format foreign symbols to punicode --- Dockerfile | 3 ++ Gemfile | 1 + Gemfile.lock | 10 +++++-- app/controllers/application_controller.rb | 34 +++++++++++++++-------- app/controllers/users_controller.rb | 6 +++- config/environments/development.rb | 2 +- config/routes.rb | 1 + test/integration/users_test.rb | 27 ++++++++++++++++++ 8 files changed, 69 insertions(+), 15 deletions(-) diff --git a/Dockerfile b/Dockerfile index 282e11ae0..7da75a3bc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,6 +8,9 @@ RUN yarn install --frozen-lockfile FROM base +ENV LAUNCHY_DRY_RUN=true +ENV BROWSER=/dev/null + RUN useradd rails RUN mkdir -p /home/rails && chown rails:rails /home/rails diff --git a/Gemfile b/Gemfile index 09b7466f1..651b0ef75 100644 --- a/Gemfile +++ b/Gemfile @@ -66,6 +66,7 @@ group :development do gem 'htmlbeautifier' gem 'i18n-debug' gem 'letter_opener', '~> 1.8' + gem 'letter_opener_web', '~> 3.0' gem 'listen', '>= 3.0.5', '< 3.9' gem 'ruby-lsp-rails' gem 'web-console', '>= 3.3.0' diff --git a/Gemfile.lock b/Gemfile.lock index 8122eef9f..dde6b7b68 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -208,8 +208,13 @@ GEM language_server-protocol (3.17.0.3) launchy (2.5.2) addressable (~> 2.8) - letter_opener (1.8.1) - launchy (>= 2.2, < 3) + letter_opener (1.10.0) + launchy (>= 2.2, < 4) + letter_opener_web (3.0.0) + actionmailer (>= 6.1) + letter_opener (~> 1.9) + railties (>= 6.1) + rexml listen (3.8.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) @@ -503,6 +508,7 @@ DEPENDENCIES jsbundling-rails jwt letter_opener (~> 1.8) + letter_opener_web (~> 3.0) listen (>= 3.0.5, < 3.9) lograge mimemagic (~> 0.4.3) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 2a6b07b5f..0d0b6ecfc 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,17 +1,19 @@ class ApplicationController < ActionController::Base include Pagy::Backend + prepend_before_action :convert_punycode_params + helper_method :turbo_frame_request? protect_from_forgery with: :exception before_action :set_locale, :clear_flash - before_action :set_notifications + before_action :notifications_for_header content_security_policy do |policy| policy.style_src :self, 'www.gstatic.com', :unsafe_inline end - rescue_from CanCan::AccessDenied do |exception| + rescue_from CanCan::AccessDenied do |_exception| flash[:alert] = I18n.t('unauthorized.message') if turbo_frame_request? @@ -22,7 +24,9 @@ class ApplicationController < ActionController::Base end def store_location - session[:return_to] = request.referer.split('?').first if request.referer + return unless request.referer + + session[:return_to] = request.referer.split('?').first end # If needed, add updated_by to the params hash. Updated by takes format of "123 - User Surname" @@ -36,30 +40,38 @@ def merge_updated_by(update_params) end end - def after_sign_in_path_for(_resource) - root_path - end + def after_sign_in_path_for(_resource) = root_path - def set_notifications + def notifications_for_header # don't change the name, it's used in the header and can be conflict with notification variable in notifications page - @notifications_for_header = current_user&.notifications&.unread&.order(created_at: :desc)&.limit(5) + @notifications_for_header ||= current_user&.notifications&.unread&.order(created_at: :desc)&.limit(5) end private def set_locale - if params[:localize].present? && I18n.available_locales.include?(params[:localize].to_sym) - cookies[:locale] = params[:localize] - end + set_locale_to_cookies I18n.locale = current_user&.locale || cookies[:locale] || I18n.default_locale @pagy_locale = I18n.locale.to_s end + def set_locale_to_cookies + return unless params[:localize].present? && I18n.available_locales.include?(params[:localize].to_sym) + + cookies[:locale] = params[:localize] + end + def clear_flash flash.clear if turbo_frame_request? end + def convert_punycode_params + return unless email = request.params.dig(:user, :email) + + request.params[:user][:email] = email.split('@').map { |val| SimpleIDN.to_ascii(val) }.join('@') + end + protected def authenticate_user! diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index f88af127d..d44ee03d8 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -42,6 +42,8 @@ def create respond_to do |format| if @user.save + flash[:notice] = t(:created) + format.html do sign_in(User, @user) redirect_to user_path(@user.uuid), notice: t(:created) @@ -52,7 +54,9 @@ def create render :show, status: :created, location: @user end else - format.html { render :new } + flash.now[:alert] = @user.errors.full_messages.join(', ') + + format.html { render :new, status: :unprocessable_entity } format.json { render json: @user.errors, status: :unprocessable_entity } end end diff --git a/config/environments/development.rb b/config/environments/development.rb index bb8880009..fdb594521 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -50,7 +50,7 @@ config.active_record.verbose_query_logs = true config.log_formatter = ::Logger::Formatter.new - config.action_mailer.delivery_method = :letter_opener + config.action_mailer.delivery_method = :letter_opener_web config.action_mailer.default_url_options = { host: 'localhost:3000', protocol: 'http' diff --git a/config/routes.rb b/config/routes.rb index 85e17fb0f..b202d82f0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -144,4 +144,5 @@ resources :autobider, param: :uuid, only: [:create, :update, :edit, :new] mount OkComputer::Engine, at: '/healthcheck', as: :healthcheck + mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development? end diff --git a/test/integration/users_test.rb b/test/integration/users_test.rb index 51262608c..4a6c0f70d 100644 --- a/test/integration/users_test.rb +++ b/test/integration/users_test.rb @@ -22,4 +22,31 @@ def test_user_is_notified_about_password_change password_confirmation: new_password } } end end + + def test_user_create_with_punicode + assert_enqueued_emails 1 do + post users_path, params: { + user: { + email: 'example@ää.eu', + given_names: 'John', + surname: 'Doe', + password: 'password123', + password_confirmation: 'password123', + terms_and_conditions_accepted_at: Time.now.utc, + locale: 'en', + mobile_phone: '+37269900366', + identity_code: '60001017793', + country_code: 'EE', + accepts_terms_and_conditions: true, + roles: ['participant'], + phone_number_confirmed: true, + provider: 'email'} + } + end + + punicode = SimpleIDN.to_ascii('ää.eu') + assert User.find_by(email: "example@#{punicode}") + + assert_redirected_to new_user_session_path + end end