From fce49e580d15f2f869116cccb3bdb5317d15081d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Mon, 25 Jun 2018 15:04:33 +0200 Subject: [PATCH 01/17] Start adding support of accept_language header --- lib/locomotive/steam/middlewares/locale.rb | 19 ++++++++++-- spec/unit/middlewares/locale_spec.rb | 35 +++++++++++++++++++--- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/lib/locomotive/steam/middlewares/locale.rb b/lib/locomotive/steam/middlewares/locale.rb index c5b2c20e..3ef008d9 100644 --- a/lib/locomotive/steam/middlewares/locale.rb +++ b/lib/locomotive/steam/middlewares/locale.rb @@ -17,6 +17,7 @@ class Locale < ThreadSafe def _call locale = extract_locale + session['locale'] = locale log "Detecting locale #{locale.upcase}" @@ -28,7 +29,7 @@ def _call protected def extract_locale - _locale = locale_from_params || default_locale + _locale = locale_from_params || locale_from_session || locale_from_header || default_locale _path = request.path_info if _path =~ /^\/(#{site.locales.join('|')})+(\/|$)/ @@ -44,10 +45,24 @@ def extract_locale env['steam.locale'] = services.locale = _locale end + def locale_from_header + request.accept_language.lazy + .sort { |a, b| b[1] <=> a[1] } + .map { |lang, _| lang[0..1].to_sym } + .find { |lang| locales.include?(lang) } + end + + def locale_from_session + session['locale'] && session['locale'].to_sym + end + def locale_from_params - locales.include?(params[:locale]) ? params[:locale] : nil + params[:locale] && locales.include?(params[:locale].to_sym) ? params[:locale].to_sym : nil end + def session + env['rack.session'] + end end end end diff --git a/spec/unit/middlewares/locale_spec.rb b/spec/unit/middlewares/locale_spec.rb index 83c78f2c..3e45dae1 100644 --- a/spec/unit/middlewares/locale_spec.rb +++ b/spec/unit/middlewares/locale_spec.rb @@ -6,20 +6,47 @@ describe Locomotive::Steam::Middlewares::Locale do - let(:site) { instance_double('Site', default_locale: :de, locales: %w(de fr)) } + let(:site) { instance_double('Site', default_locale: :de, locales: [:de, :fr, :en]) } let(:url) { 'http://models.example.com' } let(:app) { ->(env) { [200, env, 'app'] } } let(:services) { instance_double('Services', :locale= => 'en') } let(:middleware) { Locomotive::Steam::Middlewares::Locale.new(app) } + let(:session) { {} } + let(:accept_language) { '' } subject do - env = env_for(url, 'steam.site' => site) + env = env_for( + url, + 'steam.site' => site, + 'rack.session' => session, + 'HTTP_ACCEPT_LANGUAGE' => accept_language) env['steam.request'] = Rack::Request.new(env) env['steam.services'] = services code, env = middleware.call(env) env['steam.locale'] end + describe 'no locale defined in the path' do + + describe 'first connexion' do + + context 'without accept-language header' do + it { is_expected.to eq :de } + end + + context 'with accept-language header' do + let(:accept_language) { 'fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7' } + it { is_expected.to eq :fr } + end + end + + context 'user with session, use it' do + let(:session) { {'locale' => 'en'} } + it { is_expected.to eq :en } + end + + end + describe 'locale asked in the request params' do context 'the locale is blank' do @@ -32,9 +59,9 @@ context 'the locale exists' do - let(:url) { 'http://models.example.com?locale=fr' } + let(:url) { 'http://models.example.com?locale=en' } - it { is_expected.to eq 'fr' } + it { is_expected.to eq :en } end From 7788ef873d2ba59bc33333106e297916abfd5210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Mon, 25 Jun 2018 15:19:38 +0200 Subject: [PATCH 02/17] Improve code, and test if local is set in the session --- lib/locomotive/steam/middlewares/helpers.rb | 4 +++ lib/locomotive/steam/middlewares/locale.rb | 8 ++---- spec/unit/middlewares/locale_spec.rb | 27 +++++++++++++-------- 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/lib/locomotive/steam/middlewares/helpers.rb b/lib/locomotive/steam/middlewares/helpers.rb index 2341c1b8..6278b675 100644 --- a/lib/locomotive/steam/middlewares/helpers.rb +++ b/lib/locomotive/steam/middlewares/helpers.rb @@ -45,6 +45,10 @@ def default_locale site.default_locale end + def session + env['rack.session'] + end + def live_editing? !!env['steam.live_editing'] end diff --git a/lib/locomotive/steam/middlewares/locale.rb b/lib/locomotive/steam/middlewares/locale.rb index 3ef008d9..04b2b081 100644 --- a/lib/locomotive/steam/middlewares/locale.rb +++ b/lib/locomotive/steam/middlewares/locale.rb @@ -16,8 +16,7 @@ class Locale < ThreadSafe include Helpers def _call - locale = extract_locale - session['locale'] = locale + session['locale'] = locale = extract_locale log "Detecting locale #{locale.upcase}" @@ -53,16 +52,13 @@ def locale_from_header end def locale_from_session - session['locale'] && session['locale'].to_sym + session['locale']&.to_sym end def locale_from_params params[:locale] && locales.include?(params[:locale].to_sym) ? params[:locale].to_sym : nil end - def session - env['rack.session'] - end end end end diff --git a/spec/unit/middlewares/locale_spec.rb b/spec/unit/middlewares/locale_spec.rb index 3e45dae1..cc861311 100644 --- a/spec/unit/middlewares/locale_spec.rb +++ b/spec/unit/middlewares/locale_spec.rb @@ -23,7 +23,7 @@ env['steam.request'] = Rack::Request.new(env) env['steam.services'] = services code, env = middleware.call(env) - env['steam.locale'] + [env['steam.locale'], session['locale'].to_sym] end describe 'no locale defined in the path' do @@ -31,18 +31,27 @@ describe 'first connexion' do context 'without accept-language header' do - it { is_expected.to eq :de } - end + + it { is_expected.to eq [:de, :de] } + + end context 'with accept-language header' do + let(:accept_language) { 'fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7' } - it { is_expected.to eq :fr } + + it { is_expected.to eq [:fr, :fr] } + end + end context 'user with session, use it' do + let(:session) { {'locale' => 'en'} } - it { is_expected.to eq :en } + + it { is_expected.to eq [:en, :en] } + end end @@ -53,7 +62,7 @@ let(:url) { 'http://models.example.com?locale=' } - it { is_expected.to eq :de } + it { is_expected.to eq [:de, :de] } end @@ -61,7 +70,7 @@ let(:url) { 'http://models.example.com?locale=en' } - it { is_expected.to eq :en } + it { is_expected.to eq [:en, :en] } end @@ -69,11 +78,9 @@ let(:url) { 'http://models.example.com?locale=onload' } - it { is_expected.to eq :de } + it { is_expected.to eq [:de, :de] } end - end - end From 0da298978835a5153d8486cb455d0ccade7c5e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Mon, 25 Jun 2018 17:05:25 +0200 Subject: [PATCH 03/17] finish to implement lang redirection --- lib/locomotive/steam/middlewares/locale.rb | 16 +++++++++++++--- .../steam/middlewares/locale_redirection.rb | 13 +++++++++---- spec/unit/middlewares/locale_redirection_spec.rb | 11 +++++++++++ spec/unit/middlewares/locale_spec.rb | 8 ++++++++ 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/lib/locomotive/steam/middlewares/locale.rb b/lib/locomotive/steam/middlewares/locale.rb index 04b2b081..e9f4ec48 100644 --- a/lib/locomotive/steam/middlewares/locale.rb +++ b/lib/locomotive/steam/middlewares/locale.rb @@ -28,8 +28,9 @@ def _call protected def extract_locale - _locale = locale_from_params || locale_from_session || locale_from_header || default_locale - _path = request.path_info + _path = request.path_info + + _locale_params = locale_from_params if _path =~ /^\/(#{site.locales.join('|')})+(\/|$)/ _locale = $1 @@ -38,6 +39,12 @@ def extract_locale # let the other middlewares that the locale was # extracted from the path. env['steam.locale_in_path'] = true + elsif _locale_params + _locale = _locale_params + elsif _path.gsub(/^\//, '') == '' + _locale = locale_from_session || locale_from_header || default_locale + else + _locale = default_locale end env['steam.path'] = _path @@ -52,7 +59,10 @@ def locale_from_header end def locale_from_session - session['locale']&.to_sym + if session['locale'] + env['steam.locale_in_session'] = true + session['locale'].to_sym + end end def locale_from_params diff --git a/lib/locomotive/steam/middlewares/locale_redirection.rb b/lib/locomotive/steam/middlewares/locale_redirection.rb index ecab5207..f193e7ca 100644 --- a/lib/locomotive/steam/middlewares/locale_redirection.rb +++ b/lib/locomotive/steam/middlewares/locale_redirection.rb @@ -11,7 +11,9 @@ class LocaleRedirection < ThreadSafe include Helpers def _call - if url = redirect_url + if redirect_to_root_path_with_lang + redirect_to(path_with_locale, 302) + elsif url = redirect_url redirect_to url end end @@ -21,7 +23,7 @@ def _call def redirect_url if apply_redirection? if site.prefix_default_locale - path_with_default_locale if locale_not_mentioned_in_path? + path_with_locale if locale_not_mentioned_in_path? else env['steam.path'] if default_locale? && locale_mentioned_in_path? end @@ -44,12 +46,15 @@ def locale_not_mentioned_in_path? !locale_mentioned_in_path? end - def path_with_default_locale + def path_with_locale modify_path do |segments| - segments.insert(1, site.default_locale) + segments.insert(1, locale) end end + def redirect_to_root_path_with_lang + locale_not_mentioned_in_path? && path.gsub(/^\//, '') == "" && !default_locale? + end end end diff --git a/spec/unit/middlewares/locale_redirection_spec.rb b/spec/unit/middlewares/locale_redirection_spec.rb index 5c99da8c..2fa968a8 100644 --- a/spec/unit/middlewares/locale_redirection_spec.rb +++ b/spec/unit/middlewares/locale_redirection_spec.rb @@ -32,6 +32,17 @@ let(:locale_in_path) { false } it { is_expected.to eq [200, nil] } + context 'the lang elected is not the default lang' do + let(:locale) { 'fr' } + it { is_expected.to eq [302, '/fr'] } + end + + end + + describe 'locale is part of the path' do + let(:url) { 'http://models.example.com/fr' } + let(:locale) { 'fr' } + it { is_expected.to eq [200, nil] } end describe 'for seo purpose redirect to the path without the locale' do diff --git a/spec/unit/middlewares/locale_spec.rb b/spec/unit/middlewares/locale_spec.rb index cc861311..2ffd1ac5 100644 --- a/spec/unit/middlewares/locale_spec.rb +++ b/spec/unit/middlewares/locale_spec.rb @@ -42,6 +42,14 @@ it { is_expected.to eq [:fr, :fr] } + context 'with url path' do + + let(:url) { 'http://models.example.com/werkzeug' } + + it { is_expected.to eq [:de, :de] } + + end + end end From 4c65b6f94612912f0099d984fbf7a103b0b18910 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Fri, 31 Aug 2018 15:20:50 +0200 Subject: [PATCH 04/17] [IMP] add enable_starttls_auto and authentication for smtp and simplify the code. Smtp key are now hardcoded, only stmp namespace is customizable --- lib/locomotive/steam/middlewares/auth.rb | 40 +++++++++++++++++------- spec/integration/server/auth_spec.rb | 4 --- spec/unit/middlewares/auth_spec.rb | 9 +++++- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/lib/locomotive/steam/middlewares/auth.rb b/lib/locomotive/steam/middlewares/auth.rb index a2281672..a0b66694 100644 --- a/lib/locomotive/steam/middlewares/auth.rb +++ b/lib/locomotive/steam/middlewares/auth.rb @@ -169,7 +169,7 @@ def reset_token end def from - params[:auth_email_from] || 'support@locomotivecms.com' + smtp_config['sender'] || 'support@locomotivecms.com' end def subject @@ -188,23 +188,39 @@ def entry params[:auth_entry] end + def smtp_config + @config ||= _read_smtp_config + end + def smtp - name = params[:auth_email_smtp_namespace] || 'smtp' - namespace = site.metafields.try(:[], name) + if smtp_config.blank? + {} + else + { + address: smtp_config['address'], + port: smtp_config['port'], + user_name: smtp_config['user_name'], + password: smtp_config['password'], + authentication: smtp_config['authentication'] || 'plain', + enable_starttls_auto: (smtp_config['enable_starttls_auto'] || "0").to_bool, + } + end + end - if namespace.blank? + private + + def _read_smtp_config + name = params[:auth_email_smtp_namespace] || 'smtp' + config = site.metafields.try(:[], name) + if config.blank? Locomotive::Common::Logger.error "[Auth] Missing SMTP settings in the Site metafields. Namespace: #{name}".light_red - return {} + {} + else + config end - - { - address: namespace[params[:auth_email_smtp_address_alias] || 'address'], - port: namespace[params[:auth_email_smtp_port_alias] || 'port'], - user_name: namespace[params[:auth_email_smtp_user_name_alias] || 'user_name'], - password: namespace[params[:auth_email_smtp_password_alias] || 'password'] - } end + end end diff --git a/spec/integration/server/auth_spec.rb b/spec/integration/server/auth_spec.rb index 3d4403b4..c37f9ada 100644 --- a/spec/integration/server/auth_spec.rb +++ b/spec/integration/server/auth_spec.rb @@ -171,11 +171,7 @@ def sign_in(params, follow_redirect = false) auth_id: email, auth_reset_password_url: 'http://acme.com/account/reset-password', auth_callback: '/account/sign-in', - auth_email_from: 'support@acme.com', auth_email_handle: 'reset_password_instructions', - auth_email_smtp_address: 'smtp.nowhere.net', - auth_email_smtp_user_name: 'jane', - auth_email_smtp_password: 'easyone' } } it 'renders the forgot password page with an error message' do diff --git a/spec/unit/middlewares/auth_spec.rb b/spec/unit/middlewares/auth_spec.rb index 775200f5..17313731 100644 --- a/spec/unit/middlewares/auth_spec.rb +++ b/spec/unit/middlewares/auth_spec.rb @@ -16,7 +16,14 @@ subject { options.smtp } - it { is_expected.to eq('address': '127.0.0.1', 'user_name': 'John', 'password': 'doe', 'port': 25) } + it { is_expected.to eq( + address: '127.0.0.1', + user_name: 'John', + password: 'doe', + port: 25, + authentication: 'plain', + enable_starttls_auto: false, + ) } context 'no smtp metafields' do From d63ec4c3b19e9a368c401bf068483fcca79e6b80 Mon Sep 17 00:00:00 2001 From: Didier Lafforgue Date: Mon, 1 Oct 2018 16:48:26 +0200 Subject: [PATCH 05/17] complete the PR #111 by handling the case when we want to display the index page in the default locale by calling path_to --- .../steam/middlewares/locale_redirection.rb | 2 +- .../steam/services/url_builder_service.rb | 28 ++++++++++++++---- spec/unit/liquid/tags/link_to_spec.rb | 2 +- spec/unit/liquid/tags/locale_switcher_spec.rb | 2 +- spec/unit/liquid/tags/path_to_spec.rb | 29 +++++++++++++++++-- .../unit/services/url_builder_service_spec.rb | 16 ++++++++-- 6 files changed, 65 insertions(+), 14 deletions(-) diff --git a/lib/locomotive/steam/middlewares/locale_redirection.rb b/lib/locomotive/steam/middlewares/locale_redirection.rb index f193e7ca..3c88a9db 100644 --- a/lib/locomotive/steam/middlewares/locale_redirection.rb +++ b/lib/locomotive/steam/middlewares/locale_redirection.rb @@ -53,7 +53,7 @@ def path_with_locale end def redirect_to_root_path_with_lang - locale_not_mentioned_in_path? && path.gsub(/^\//, '') == "" && !default_locale? + locale_not_mentioned_in_path? && path.gsub(/^\//, '') == '' && !default_locale? end end end diff --git a/lib/locomotive/steam/services/url_builder_service.rb b/lib/locomotive/steam/services/url_builder_service.rb index 883622de..642b8e34 100644 --- a/lib/locomotive/steam/services/url_builder_service.rb +++ b/lib/locomotive/steam/services/url_builder_service.rb @@ -11,17 +11,33 @@ def url_for(page, locale = nil) def _url_for(page, locale = nil) [''].tap do |segments| - locale ||= current_locale - same_locale = locale.to_sym == site.default_locale.to_sym + locale = locale&.to_sym + _locale = (locale || current_locale).to_sym + default_locale = site.default_locale.to_sym + same_locale = _locale == default_locale - # if the prefix_default_locale is enabled, we need to - # add the locale no matter if the locale is the same as the default one + fullpath = sanitized_fullpath(page, same_locale) + + # To insert the locale in the path, 2 cases: + # + # 1. if the prefix_default_locale is enabled, we need to + # add the locale no matter if the locale is the same as the default one. + # + # 2. since we also store the locale in session, calling the index page ("/") + # will always return the page in the locale stored in session. + # In order to see the index page in the default locale, we need to allow + # "/" instead of just "/". + # if site.prefix_default_locale || !same_locale + segments << _locale + elsif fullpath.blank? && locale == default_locale && current_locale != locale segments << locale end - # fullpath - segments << sanitized_fullpath(page, same_locale) + # we don't want a trailing slash for the home page if a locale is set + fullpath = nil if segments.size == 2 && fullpath.blank? + + segments << fullpath end.compact.join('/') end diff --git a/spec/unit/liquid/tags/link_to_spec.rb b/spec/unit/liquid/tags/link_to_spec.rb index 6b7a202f..58625e72 100644 --- a/spec/unit/liquid/tags/link_to_spec.rb +++ b/spec/unit/liquid/tags/link_to_spec.rb @@ -71,7 +71,7 @@ context 'prefix_default_locale is true' do let(:prefix_default) { true } - it { is_expected.to eq 'My link: Home!' } + it { is_expected.to eq 'My link: Home!' } end diff --git a/spec/unit/liquid/tags/locale_switcher_spec.rb b/spec/unit/liquid/tags/locale_switcher_spec.rb index 8b13b74d..f92adfe9 100644 --- a/spec/unit/liquid/tags/locale_switcher_spec.rb +++ b/spec/unit/liquid/tags/locale_switcher_spec.rb @@ -30,7 +30,7 @@ context 'prefix_default_locale is true' do let(:prefix_default) { true } - it { is_expected.to eq '
en | fr
' } + it { is_expected.to eq '
en | fr
' } end diff --git a/spec/unit/liquid/tags/path_to_spec.rb b/spec/unit/liquid/tags/path_to_spec.rb index abd38e0c..ee9c9ab6 100644 --- a/spec/unit/liquid/tags/path_to_spec.rb +++ b/spec/unit/liquid/tags/path_to_spec.rb @@ -4,9 +4,11 @@ let(:prefix_default) { false } let(:assigns) { {} } + let(:current_locale) { 'en' } + let(:locales) { ['en'] } let(:services) { Locomotive::Steam::Services.build_instance } - let(:site) { instance_double('Site', locales: ['en'], default_locale: 'en', prefix_default_locale: prefix_default) } - let(:context) { ::Liquid::Context.new(assigns, {}, { services: services, site: site, locale: 'en' }) } + let(:site) { instance_double('Site', locales: locales, default_locale: 'en', prefix_default_locale: prefix_default) } + let(:context) { ::Liquid::Context.new(assigns, {}, { services: services, site: site, locale: current_locale }) } subject { render_template(source, context) } @@ -52,10 +54,31 @@ end + context 'the current locale in session is different from the requested locale' do + + let(:current_locale) { 'fr' } + let(:locales) { ['en', 'fr'] } + let(:source) { "{% path_to index, locale: 'en' %}" } + + before do + services.url_builder.current_locale = current_locale + end + + it { is_expected.to eq '/en' } + + context 'prefix_default_locale is true' do + + let(:prefix_default) { true } + it { is_expected.to eq '/en' } + + end + + end + context 'prefix_default_locale is true' do let(:prefix_default) { true } - it { is_expected.to eq '/en/' } + it { is_expected.to eq '/en' } end diff --git a/spec/unit/services/url_builder_service_spec.rb b/spec/unit/services/url_builder_service_spec.rb index b5d923a0..4f34b13d 100644 --- a/spec/unit/services/url_builder_service_spec.rb +++ b/spec/unit/services/url_builder_service_spec.rb @@ -7,13 +7,15 @@ let(:request) { instance_double('Request', env: { 'steam.mounted_on' => mounted_on }) } let(:site) { instance_double('Site', default_locale: 'en', prefix_default_locale: prefix_default) } let(:locale) { 'en' } - let(:service) { described_class.new(site, locale, request) } + let(:current_locale) { 'en' } + let(:locale) { nil } + let(:service) { described_class.new(site, current_locale, mounted_on) } describe '#url_for' do let(:page) { instance_double('AboutUs', fullpath: 'about-us', templatized?: false) } - subject { service.url_for(page) } + subject { service.url_for(page, locale) } it { is_expected.to eq '/about-us' } @@ -37,6 +39,16 @@ end + describe 'asking for the index page url in the defaut locale when the current locale is different from the default one' do + + let(:current_locale) { 'fr' } + let(:locale) { 'en' } + let(:page) { instance_double('index', fullpath: 'index', templatized?: false) } + + it { is_expected.to eq '/en' } + + end + describe 'no need to put the index slug' do let(:page) { instance_double('Index', fullpath: 'index', templatized?: false) } From 8f0700811fbeb87b827cda1ba9817eaf95765ba4 Mon Sep 17 00:00:00 2001 From: Didier Lafforgue Date: Sat, 13 Oct 2018 23:08:54 +0200 Subject: [PATCH 06/17] don't use a permanent redirection for the index page in case the locale is not set --- lib/locomotive/steam/middlewares/locale_redirection.rb | 9 ++++++++- spec/unit/middlewares/locale_redirection_spec.rb | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/locomotive/steam/middlewares/locale_redirection.rb b/lib/locomotive/steam/middlewares/locale_redirection.rb index 3c88a9db..6c24ba2c 100644 --- a/lib/locomotive/steam/middlewares/locale_redirection.rb +++ b/lib/locomotive/steam/middlewares/locale_redirection.rb @@ -14,7 +14,7 @@ def _call if redirect_to_root_path_with_lang redirect_to(path_with_locale, 302) elsif url = redirect_url - redirect_to url + redirect_to(url, redirect_type) end end @@ -30,6 +30,13 @@ def redirect_url end end + # only applied if redirect_url is not nil + def redirect_type + # We don't want a permanent redirection for the index page in case + # the user wants to change the current locale from the index page. + self.path == '/' && self.locales.size > 1 ? 302 : 301 + end + def apply_redirection? site.locales.size > 1 && request.get? && env['PATH_INFO'] != '/sitemap.xml' end diff --git a/spec/unit/middlewares/locale_redirection_spec.rb b/spec/unit/middlewares/locale_redirection_spec.rb index 2fa968a8..a7a72c18 100644 --- a/spec/unit/middlewares/locale_redirection_spec.rb +++ b/spec/unit/middlewares/locale_redirection_spec.rb @@ -64,7 +64,7 @@ describe 'add default locale to root path' do let(:url) { 'http://models.example.com/' } - it { is_expected.to eq [301, '/de'] } + it { is_expected.to eq [302, '/de'] } end describe 'add default locale to long path' do From b4ac954cee5c8b3e74fdc87372a01986cde3bbb7 Mon Sep 17 00:00:00 2001 From: Didier Lafforgue Date: Sun, 21 Oct 2018 00:04:54 +0200 Subject: [PATCH 07/17] better support for the locale in preview mode (engine) --- lib/locomotive/steam/middlewares/locale.rb | 79 +++++++++++++++------- lib/locomotive/steam/middlewares/path.rb | 2 +- 2 files changed, 54 insertions(+), 27 deletions(-) diff --git a/lib/locomotive/steam/middlewares/locale.rb b/lib/locomotive/steam/middlewares/locale.rb index e9f4ec48..7df3f8c1 100644 --- a/lib/locomotive/steam/middlewares/locale.rb +++ b/lib/locomotive/steam/middlewares/locale.rb @@ -9,16 +9,19 @@ module Middlewares # /fr/ => locale = :fr # /index => locale = :en (default one) # - # The + # /en/index?locale=fr => locale = :fr + # /index => redirection to /en if the locale in session is :en # class Locale < ThreadSafe include Helpers def _call - session['locale'] = locale = extract_locale + env['steam.path'] = request.path_info - log "Detecting locale #{locale.upcase}" + env['steam.locale'] = session[session_key_name] = services.locale = extract_locale + + log "Locale used: #{locale.upcase}" I18n.with_locale(locale) do self.next @@ -28,45 +31,69 @@ def _call protected def extract_locale - _path = request.path_info + # Regarding the index page (basically, "/"), we've to see if we could + # guess the locale from the headers the browser sends to us. + locale = if is_index_page? + locale_from_params || locale_from_session || locale_from_header + else + locale_from_path || locale_from_params + end + + # make sure, the locale is among the ones defined in the site, + # otherwise take the default one. + locale && locales.include?(locale) ? locale : default_locale + end - _locale_params = locale_from_params + def locale_from_params + params[:locale]&.to_sym.tap do |locale| + log 'Locale extracted from the params' unless locale.blank? + end + end - if _path =~ /^\/(#{site.locales.join('|')})+(\/|$)/ - _locale = $1 - _path = _path.gsub($1 + $2, '') + def locale_from_path + path = request.path_info - # let the other middlewares that the locale was - # extracted from the path. + if path =~ /^\/(#{site.locales.join('|')})+(\/|$)/ + locale = $1 + + # no need to keep the locale in the path used to fetch the page + env['steam.path'] = path.gsub($1 + $2, '') env['steam.locale_in_path'] = true - elsif _locale_params - _locale = _locale_params - elsif _path.gsub(/^\//, '') == '' - _locale = locale_from_session || locale_from_header || default_locale - else - _locale = default_locale - end - env['steam.path'] = _path - env['steam.locale'] = services.locale = _locale + log 'Locale extracted from the path' + + locale.to_sym + end end def locale_from_header request.accept_language.lazy - .sort { |a, b| b[1] <=> a[1] } - .map { |lang, _| lang[0..1].to_sym } - .find { |lang| locales.include?(lang) } + .sort { |a, b| b[1] <=> a[1] } + .map { |lang, _| lang[0..1].to_sym } + .find { |lang| locales.include?(lang) }.tap do |locale| + log 'Locale extracted from the header' unless locale.blank? + end end def locale_from_session - if session['locale'] + if locale = session[session_key_name] env['steam.locale_in_session'] = true - session['locale'].to_sym + + log 'Locale extracted from the session' + + locale.to_sym end end - def locale_from_params - params[:locale] && locales.include?(params[:locale].to_sym) ? params[:locale].to_sym : nil + # The preview urls for all the sites share the same domain, so session[:locale] + # would be the same for all the preview urls and this is not good. + # This is why we need to use a different key. + def session_key_name + live_editing? ? "locale-#{site.handle}" : 'locale' + end + + def is_index_page? + ['/', ''].include?(request.path_info) end end diff --git a/lib/locomotive/steam/middlewares/path.rb b/lib/locomotive/steam/middlewares/path.rb index e8ea3fae..d710f48b 100644 --- a/lib/locomotive/steam/middlewares/path.rb +++ b/lib/locomotive/steam/middlewares/path.rb @@ -16,7 +16,7 @@ def call(env) protected def set_path!(env) - path = (env['steam.path'] || request.path_info).dup + path = env['steam.path'].dup path.gsub!(/\.[a-zA-Z][a-zA-Z0-9]{2,}$/, '') path.gsub!(/^\//, '') From adc3b9e7ab0ae57aa1fe470cb5f8d0b13e37a361 Mon Sep 17 00:00:00 2001 From: Didier Lafforgue Date: Sun, 21 Oct 2018 16:51:12 +0200 Subject: [PATCH 08/17] prefix the session key used to store the locale with the string steam in order to avoid conflicts --- lib/locomotive/steam/middlewares/locale.rb | 2 +- spec/unit/middlewares/locale_spec.rb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/locomotive/steam/middlewares/locale.rb b/lib/locomotive/steam/middlewares/locale.rb index 7df3f8c1..598dbaf2 100644 --- a/lib/locomotive/steam/middlewares/locale.rb +++ b/lib/locomotive/steam/middlewares/locale.rb @@ -89,7 +89,7 @@ def locale_from_session # would be the same for all the preview urls and this is not good. # This is why we need to use a different key. def session_key_name - live_editing? ? "locale-#{site.handle}" : 'locale' + live_editing? ? "steam-locale-#{site.handle}" : 'steam-locale' end def is_index_page? diff --git a/spec/unit/middlewares/locale_spec.rb b/spec/unit/middlewares/locale_spec.rb index 2ffd1ac5..034eb90f 100644 --- a/spec/unit/middlewares/locale_spec.rb +++ b/spec/unit/middlewares/locale_spec.rb @@ -23,7 +23,7 @@ env['steam.request'] = Rack::Request.new(env) env['steam.services'] = services code, env = middleware.call(env) - [env['steam.locale'], session['locale'].to_sym] + [env['steam.locale'], session['steam-locale']&.to_sym] end describe 'no locale defined in the path' do @@ -56,7 +56,7 @@ context 'user with session, use it' do - let(:session) { {'locale' => 'en'} } + let(:session) { {'steam-locale' => 'en'} } it { is_expected.to eq [:en, :en] } From e684053baed9acd4c6f518a9d4df7c50ced6e0f1 Mon Sep 17 00:00:00 2001 From: "Luis J. Romero" Date: Wed, 26 Sep 2018 10:42:11 +0200 Subject: [PATCH 09/17] Adding get/setCookiesProp to access cookies from liquid actions --- lib/locomotive/steam/middlewares/renderer.rb | 3 ++- lib/locomotive/steam/services/action_service.rb | 10 ++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/locomotive/steam/middlewares/renderer.rb b/lib/locomotive/steam/middlewares/renderer.rb index bb4d6715..13028fdc 100644 --- a/lib/locomotive/steam/middlewares/renderer.rb +++ b/lib/locomotive/steam/middlewares/renderer.rb @@ -59,7 +59,8 @@ def liquid_registers repositories: services.repositories, logger: Locomotive::Common::Logger, live_editing: !!env['steam.live_editing'], - session: request.session + session: request.session, + cookies: request.cookies } end diff --git a/lib/locomotive/steam/services/action_service.rb b/lib/locomotive/steam/services/action_service.rb index 1cc97bb0..4515bf5e 100644 --- a/lib/locomotive/steam/services/action_service.rb +++ b/lib/locomotive/steam/services/action_service.rb @@ -18,6 +18,8 @@ class ActionService setProp getSessionProp setSessionProp + getCookiesProp + setCookiesProp sendEmail allEntries findEntry @@ -81,6 +83,14 @@ def set_session_prop_lambda(liquid_context) -> (name, value) { liquid_context.registers[:session][name.to_sym] = value } end + def get_cookies_prop_lambda(liquid_context) + -> (name) { liquid_context.registers[:cookies][name.to_s].as_json } + end + + def set_cookies_prop_lambda(liquid_context) + -> (name, value) { liquid_context.registers[:cookies][name.to_s] = value.to_s } + end + def all_entries_lambda(liquid_context) -> (type, conditions) { content_entry_service.all(type, conditions, true) } end From 3c27a2ddf3b6af8bd53dd193d5ff16053551b747 Mon Sep 17 00:00:00 2001 From: "Luis J. Romero" Date: Wed, 26 Sep 2018 10:57:02 +0200 Subject: [PATCH 10/17] Tests --- spec/unit/services/action_service_spec.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/spec/unit/services/action_service_spec.rb b/spec/unit/services/action_service_spec.rb index 75bc1d04..bb4eaeda 100644 --- a/spec/unit/services/action_service_spec.rb +++ b/spec/unit/services/action_service_spec.rb @@ -112,6 +112,23 @@ end + describe 'getCookiesProp' do + + let(:cookie) { { name: 'John' } } + let(:script) { "return getCookiesProp('name');" } + + it { is_expected.to eq 'John' } + + end + + describe 'sendCookiesProp' do + + let(:script) { "return setCookiesProp('done', true);" } + + it { subject; expect(cookies[:done]).to eq true } + + end + describe 'allEntries' do let(:now) { Time.use_zone('America/Chicago') { Time.zone.local(2015, 'mar', 25, 10, 0) } } From 3077d225293a9d22894e906cbae67dbf92fb43e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Mon, 12 Nov 2018 14:01:46 +0100 Subject: [PATCH 11/17] [FIX] fix setting the cookies. Cookies must be added in the response header with all the params --- .../steam/middlewares/default_env.rb | 1 + lib/locomotive/steam/middlewares/helpers.rb | 6 ++- lib/locomotive/steam/services.rb | 6 ++- .../steam/services/action_service.rb | 6 +-- .../steam/services/cookie_service.rb | 25 ++++++++++++ spec/unit/services/action_service_spec.rb | 24 ++++++------ spec/unit/services/cookie_service_spec.rb | 38 +++++++++++++++++++ 7 files changed, 89 insertions(+), 17 deletions(-) create mode 100644 lib/locomotive/steam/services/cookie_service.rb create mode 100644 spec/unit/services/cookie_service_spec.rb diff --git a/lib/locomotive/steam/middlewares/default_env.rb b/lib/locomotive/steam/middlewares/default_env.rb index 62cd75c3..9ffc4a3d 100644 --- a/lib/locomotive/steam/middlewares/default_env.rb +++ b/lib/locomotive/steam/middlewares/default_env.rb @@ -11,6 +11,7 @@ def call(env) env['steam.request'] = request env['steam.services'] = build_services(request) env['steam.liquid_assigns'] = {} + env['steam.cookies'] = {} app.call(env) end diff --git a/lib/locomotive/steam/middlewares/helpers.rb b/lib/locomotive/steam/middlewares/helpers.rb index addd9ef9..9ea1065e 100644 --- a/lib/locomotive/steam/middlewares/helpers.rb +++ b/lib/locomotive/steam/middlewares/helpers.rb @@ -88,7 +88,11 @@ def json? #= Helper methods def render_response(content, code = 200, type = nil) - @next_response = [code, { 'Content-Type' => type || 'text/html' }, [content]] + headers = { 'Content-Type' => type || 'text/html' } + request.env['steam.cookies'].each do |key, vals| + Rack::Utils.set_cookie_header!(headers, key, vals.symbolize_keys!) + end + @next_response = [code, headers, [content]] end def redirect_to(location, type = 301) diff --git a/lib/locomotive/steam/services.rb b/lib/locomotive/steam/services.rb index 235882e5..5df84361 100644 --- a/lib/locomotive/steam/services.rb +++ b/lib/locomotive/steam/services.rb @@ -63,7 +63,7 @@ class Instance end register :action do - Steam::ActionService.new(current_site, email, content_entry: content_entry, api: external_api, redirection: page_redirection) + Steam::ActionService.new(current_site, email, content_entry: content_entry, api: external_api, redirection: page_redirection, cookie: cookie) end register :content_entry do @@ -130,6 +130,10 @@ class Instance Steam::NoCacheService.new end + register :cookie do + Steam::CookieService.new(request) + end + register :configuration do Locomotive::Steam.configuration end diff --git a/lib/locomotive/steam/services/action_service.rb b/lib/locomotive/steam/services/action_service.rb index 4515bf5e..c3a08926 100644 --- a/lib/locomotive/steam/services/action_service.rb +++ b/lib/locomotive/steam/services/action_service.rb @@ -11,7 +11,7 @@ module Steam class ActionService - SERVICES = %w(content_entry api redirection) + SERVICES = %w(content_entry api redirection cookie) BUILT_IN_FUNCTIONS = %w( getProp @@ -84,11 +84,11 @@ def set_session_prop_lambda(liquid_context) end def get_cookies_prop_lambda(liquid_context) - -> (name) { liquid_context.registers[:cookies][name.to_s].as_json } + -> (name) { cookie_service.get(name.to_s) } end def set_cookies_prop_lambda(liquid_context) - -> (name, value) { liquid_context.registers[:cookies][name.to_s] = value.to_s } + -> (name, values) { cookie_service.set(name.to_s, values) } end def all_entries_lambda(liquid_context) diff --git a/lib/locomotive/steam/services/cookie_service.rb b/lib/locomotive/steam/services/cookie_service.rb new file mode 100644 index 00000000..9fe86cb6 --- /dev/null +++ b/lib/locomotive/steam/services/cookie_service.rb @@ -0,0 +1,25 @@ +module Locomotive + module Steam + + class CookieService + + def initialize(request) + @request = request + @cookies = request.env['steam.cookies'] + end + + def set(key, vals) + @cookies[key] = vals + end + + def get(key) + if @cookies.include?(key) + @cookies[key]['value'] + else + @request.cookies[key] + end + end + + end + end +end diff --git a/spec/unit/services/action_service_spec.rb b/spec/unit/services/action_service_spec.rb index bb4eaeda..afbf2e80 100644 --- a/spec/unit/services/action_service_spec.rb +++ b/spec/unit/services/action_service_spec.rb @@ -8,7 +8,8 @@ let(:entry_service) { instance_double('ContentService') } let(:api_service) { instance_double('ExternalAPIService') } let(:redirection_service) { instance_double('PageRedirectionService') } - let(:service) { described_class.new(site, email_service, content_entry: entry_service, api: api_service, redirection: redirection_service) } + let(:cookie_service) { instance_double('CookieService') } + let(:service) { described_class.new(site, email_service, content_entry: entry_service, api: api_service, redirection: redirection_service, cookie: cookie_service) } describe '#run' do @@ -113,20 +114,19 @@ end describe 'getCookiesProp' do - - let(:cookie) { { name: 'John' } } let(:script) { "return getCookiesProp('name');" } - - it { is_expected.to eq 'John' } - + before do + expect(cookie_service).to receive(:get).with('name').and_return('John') + end + it { is_expected.to eq('John') } end - describe 'sendCookiesProp' do - - let(:script) { "return setCookiesProp('done', true);" } - - it { subject; expect(cookies[:done]).to eq true } - + describe 'setCookiesProp' do + let(:script) { "return setCookiesProp('done', {'value': true});" } + before do + expect(cookie_service).to receive(:set).with('done', {'value' => true}) + end + it { is_expected.to eq(nil) } end describe 'allEntries' do diff --git a/spec/unit/services/cookie_service_spec.rb b/spec/unit/services/cookie_service_spec.rb new file mode 100644 index 00000000..bc61c4da --- /dev/null +++ b/spec/unit/services/cookie_service_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Locomotive::Steam::CookieService do + + let(:steam_cookies) { {} } + let(:request_cookies) { {} } + let(:request) { instance_double('Request', env: { 'steam.cookies' => steam_cookies }, cookies: request_cookies) } + let(:cookie) { {'value' => 'bar2'} } + let(:service) { described_class.new(request)} + + describe '#get cookies from request' do + + let(:request_cookies) { {'foo' => 'bar'} } + subject { service.get('foo') } + + context 'from request' do + it { is_expected.to eq 'bar' } + end + + context 'from response' do + let(:steam_cookies) { {'foo' => {'value' => 'bar2'}} } + it { is_expected.to eq 'bar2' } + end + + end + + describe '#set cookies from response' do + + subject { service.set('foo', cookie) } + + it 'set the cookies into steam' do + is_expected.to eq cookie + expect(steam_cookies).to eq({'foo' => cookie}) + end + + end + +end From 8aaac353f0ee6df445be454f192fee89f2df838c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Mon, 12 Nov 2018 16:31:43 +0100 Subject: [PATCH 12/17] [IMP] move the storage of the lang selected in a separated cookie instead of the session, so you can cache it easier with external proxy --- lib/locomotive/steam/middlewares/locale.rb | 23 +++++---- spec/unit/middlewares/locale_spec.rb | 54 ++++++++++++++++------ 2 files changed, 55 insertions(+), 22 deletions(-) diff --git a/lib/locomotive/steam/middlewares/locale.rb b/lib/locomotive/steam/middlewares/locale.rb index 598dbaf2..b9a40dff 100644 --- a/lib/locomotive/steam/middlewares/locale.rb +++ b/lib/locomotive/steam/middlewares/locale.rb @@ -10,7 +10,7 @@ module Middlewares # /index => locale = :en (default one) # # /en/index?locale=fr => locale = :fr - # /index => redirection to /en if the locale in session is :en + # /index => redirection to /en if the locale in cookie is :en # class Locale < ThreadSafe @@ -19,7 +19,9 @@ class Locale < ThreadSafe def _call env['steam.path'] = request.path_info - env['steam.locale'] = session[session_key_name] = services.locale = extract_locale + env['steam.locale'] = services.locale = extract_locale + + set_locale_cookie log "Locale used: #{locale.upcase}" @@ -34,7 +36,7 @@ def extract_locale # Regarding the index page (basically, "/"), we've to see if we could # guess the locale from the headers the browser sends to us. locale = if is_index_page? - locale_from_params || locale_from_session || locale_from_header + locale_from_params || locale_from_cookie || locale_from_header else locale_from_path || locale_from_params end @@ -75,20 +77,23 @@ def locale_from_header end end - def locale_from_session - if locale = session[session_key_name] - env['steam.locale_in_session'] = true + def locale_from_cookie + if locale = services.cookie.get(cookie_key_name) - log 'Locale extracted from the session' + log 'Locale extracted from the cookie' locale.to_sym end end - # The preview urls for all the sites share the same domain, so session[:locale] + def set_locale_cookie + services.cookie.set(cookie_key_name, {'value': locale, 'path': '/', 'max_age': 1.year}) + end + + # The preview urls for all the sites share the same domain, so cookie[:locale] # would be the same for all the preview urls and this is not good. # This is why we need to use a different key. - def session_key_name + def cookie_key_name live_editing? ? "steam-locale-#{site.handle}" : 'steam-locale' end diff --git a/spec/unit/middlewares/locale_spec.rb b/spec/unit/middlewares/locale_spec.rb index 034eb90f..aa69ef2e 100644 --- a/spec/unit/middlewares/locale_spec.rb +++ b/spec/unit/middlewares/locale_spec.rb @@ -9,21 +9,24 @@ let(:site) { instance_double('Site', default_locale: :de, locales: [:de, :fr, :en]) } let(:url) { 'http://models.example.com' } let(:app) { ->(env) { [200, env, 'app'] } } - let(:services) { instance_double('Services', :locale= => 'en') } + let(:cookie_lang) { nil } + let(:cookie_service) { instance_double('Cookie Service', :get => cookie_lang) } + let(:services) { instance_double('Services', :locale= => 'en', :cookie => cookie_service) } let(:middleware) { Locomotive::Steam::Middlewares::Locale.new(app) } - let(:session) { {} } + let(:cookie) { {} } let(:accept_language) { '' } + let(:expected_lang) { :de } + let(:cookie) { { value: expected_lang, path: '/', max_age: 1.year } } subject do env = env_for( url, 'steam.site' => site, - 'rack.session' => session, 'HTTP_ACCEPT_LANGUAGE' => accept_language) env['steam.request'] = Rack::Request.new(env) env['steam.services'] = services code, env = middleware.call(env) - [env['steam.locale'], session['steam-locale']&.to_sym] + env['steam.locale'] end describe 'no locale defined in the path' do @@ -32,21 +35,32 @@ context 'without accept-language header' do - it { is_expected.to eq [:de, :de] } + it 'should use default language' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end end context 'with accept-language header' do let(:accept_language) { 'fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7' } + let(:expected_lang) { :fr } - it { is_expected.to eq [:fr, :fr] } + it 'should use "fr" in header' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end context 'with url path' do let(:url) { 'http://models.example.com/werkzeug' } + let(:expected_lang) { :de } - it { is_expected.to eq [:de, :de] } + it 'should use "de" in path' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end end @@ -54,11 +68,15 @@ end - context 'user with session, use it' do + context 'user with cookie, use it' do - let(:session) { {'steam-locale' => 'en'} } + let(:cookie_lang) { 'en' } + let(:expected_lang) { :en } - it { is_expected.to eq [:en, :en] } + it 'should use "en" in cookie' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end end @@ -70,15 +88,22 @@ let(:url) { 'http://models.example.com?locale=' } - it { is_expected.to eq [:de, :de] } + it 'should use default locale "de"' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end end context 'the locale exists' do let(:url) { 'http://models.example.com?locale=en' } + let(:expected_lang) { :en } - it { is_expected.to eq [:en, :en] } + it 'should use existing locale "en"' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end end @@ -86,7 +111,10 @@ let(:url) { 'http://models.example.com?locale=onload' } - it { is_expected.to eq [:de, :de] } + it 'should use default locale "de"' do + expect(cookie_service).to receive(:set).with('steam-locale', cookie).and_return(nil) + is_expected.to eq expected_lang + end end From 639a24fdff358909f99b24d7e49eddec64e92970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Tue, 13 Nov 2018 15:24:00 +0100 Subject: [PATCH 13/17] [FIX] cookie should also be set in case of redirection --- lib/locomotive/steam/middlewares/helpers.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/locomotive/steam/middlewares/helpers.rb b/lib/locomotive/steam/middlewares/helpers.rb index 9ea1065e..bb173196 100644 --- a/lib/locomotive/steam/middlewares/helpers.rb +++ b/lib/locomotive/steam/middlewares/helpers.rb @@ -89,9 +89,7 @@ def json? def render_response(content, code = 200, type = nil) headers = { 'Content-Type' => type || 'text/html' } - request.env['steam.cookies'].each do |key, vals| - Rack::Utils.set_cookie_header!(headers, key, vals.symbolize_keys!) - end + inject_cookies(headers) @next_response = [code, headers, [content]] end @@ -100,7 +98,16 @@ def redirect_to(location, type = 301) self.log "Redirected to #{_location}".blue - @next_response = [type, { 'Content-Type' => 'text/html', 'Location' => _location }, []] + headers = { 'Content-Type' => 'text/html', 'Location' => _location } + inject_cookies(headers) + + @next_response = [type, headers, []] + end + + def inject_cookies(headers) + request.env['steam.cookies'].each do |key, vals| + Rack::Utils.set_cookie_header!(headers, key, vals.symbolize_keys!) + end end def modify_path(path = nil, &block) From d226a08856073a48636011a43c14ddaba6d5c581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Thu, 15 Nov 2018 03:22:18 +0100 Subject: [PATCH 14/17] [FIX] sign out should do a redirect to avoid tricky case when one of the service registred already have keep in memory the information of the person logged. By doing a redirect we are sure to build a page without information that depend of the current sign out user --- lib/locomotive/steam/middlewares/auth.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/locomotive/steam/middlewares/auth.rb b/lib/locomotive/steam/middlewares/auth.rb index a0b66694..0d560c3c 100644 --- a/lib/locomotive/steam/middlewares/auth.rb +++ b/lib/locomotive/steam/middlewares/auth.rb @@ -62,6 +62,8 @@ def sign_out(options) store_authenticated(nil) + redirect_to options.callback || path + append_message(:signed_out) end From f085cff8b8c88777926116d25b8e6aaf8234ce77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Tue, 18 Dec 2018 17:27:00 +0100 Subject: [PATCH 15/17] empty commit for travis --- .test | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 .test diff --git a/.test b/.test new file mode 100644 index 00000000..e69de29b From ea61ffd7400a28c62f17dc4f7d15ec99b3038853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20BEAU?= Date: Sun, 13 Jan 2019 22:38:31 +0100 Subject: [PATCH 16/17] [FIX] solve issue on robot.txt page, en is not build in the helper, this raise an issue when injecting cookie. As cookies are not needed for robots.txt we do not pass them --- lib/locomotive/steam/middlewares/helpers.rb | 6 ++++-- lib/locomotive/steam/middlewares/robots.rb | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/locomotive/steam/middlewares/helpers.rb b/lib/locomotive/steam/middlewares/helpers.rb index bb173196..d636287f 100644 --- a/lib/locomotive/steam/middlewares/helpers.rb +++ b/lib/locomotive/steam/middlewares/helpers.rb @@ -87,9 +87,11 @@ def json? #= Helper methods - def render_response(content, code = 200, type = nil) + def render_response(content, code = 200, type = nil, no_cookies=false) headers = { 'Content-Type' => type || 'text/html' } - inject_cookies(headers) + unless no_cookies + inject_cookies(headers) + end @next_response = [code, headers, [content]] end diff --git a/lib/locomotive/steam/middlewares/robots.rb b/lib/locomotive/steam/middlewares/robots.rb index cfd7fa4a..110595b1 100644 --- a/lib/locomotive/steam/middlewares/robots.rb +++ b/lib/locomotive/steam/middlewares/robots.rb @@ -10,7 +10,7 @@ class Robots def call(env) if env['PATH_INFO'] == '/robots.txt' site = env['steam.site'] - render_response(site[:robots_txt] || '', 200, 'text/plain') + render_response(site[:robots_txt] || '', 200, 'text/plain', no_cookies=true) else app.call(env) end From 842907c6451958dba67432d9c038d5376475bd39 Mon Sep 17 00:00:00 2001 From: Sylvain Calador Date: Mon, 8 Apr 2019 14:43:25 +0200 Subject: [PATCH 17/17] [WIP] add a new liquid variable country for geoip location of the visitor --- .gitignore | 1 + .../steam/liquid/drops/i18n_base.rb | 4 ++ lib/locomotive/steam/middlewares/locale.rb | 68 +++++++++++++++++++ lib/locomotive/steam/middlewares/renderer.rb | 1 + 4 files changed, 74 insertions(+) diff --git a/.gitignore b/.gitignore index 8cc86459..20b63c58 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.swp *.gem *.rbc .bundle diff --git a/lib/locomotive/steam/liquid/drops/i18n_base.rb b/lib/locomotive/steam/liquid/drops/i18n_base.rb index 1b99353c..91c1653b 100644 --- a/lib/locomotive/steam/liquid/drops/i18n_base.rb +++ b/lib/locomotive/steam/liquid/drops/i18n_base.rb @@ -16,6 +16,10 @@ def context=(context) @_source.__locale__ = locale end + if country = context.registers[:country] + @_source.__country__ = country + end + @_source.__default_locale__ = context.registers[:site].try(:default_locale) super diff --git a/lib/locomotive/steam/middlewares/locale.rb b/lib/locomotive/steam/middlewares/locale.rb index b9a40dff..b694b788 100644 --- a/lib/locomotive/steam/middlewares/locale.rb +++ b/lib/locomotive/steam/middlewares/locale.rb @@ -1,3 +1,5 @@ +require 'maxmind/db' + module Locomotive::Steam module Middlewares @@ -21,9 +23,14 @@ def _call env['steam.locale'] = services.locale = extract_locale + country = extract_country + env['steam.country'] = country + set_locale_cookie + set_country_cookie(country) log "Locale used: #{locale.upcase}" + log "Country used: #{country.upcase}" I18n.with_locale(locale) do self.next @@ -32,6 +39,58 @@ def _call protected + def extract_country + country = country_from_params || country_from_cookie || country_from_geoip(env) || country_from_default + country.to_s.downcase + end + + def country_from_params + params[:country]&.to_sym.tap do |country| + log 'Country extracted from the params' unless country.blank? + end + end + + def country_from_cookie + if country = services.cookie.get(cookie_country_key_name) + log 'Country extracted from the cookie' + country.to_sym + end + end + + def country_from_geoip(remote_ip) + reader = MaxMind::DB.new('/home/akretion/GeoLite2-Country.mmdb', mode: MaxMind::DB::MODE_MEMORY) + remote_ip = env["action_dispatch.remote_ip"].to_s + record = reader.get(remote_ip) + if record.nil? + log "Country not found in database for: #{remote_ip}" + return nil + else + log "Country found in database for: #{remote_ip}" + return record['country']['iso_code'] + end + end + + def country_from_default + return "fr" + end + + def locale_from_path + path = request.path_info + + if path =~ /^\/(#{site.locales.join('|')})+(\/|$)/ + locale = $1 + + # no need to keep the locale in the path used to fetch the page + env['steam.path'] = path.gsub($1 + $2, '') + env['steam.locale_in_path'] = true + + log 'Locale extracted from the path' + + locale.to_sym + end + end + + def extract_locale # Regarding the index page (basically, "/"), we've to see if we could # guess the locale from the headers the browser sends to us. @@ -90,6 +149,11 @@ def set_locale_cookie services.cookie.set(cookie_key_name, {'value': locale, 'path': '/', 'max_age': 1.year}) end + + def set_country_cookie(country) + services.cookie.set(cookie_country_key_name, {'value': country, 'path': '/', 'max_age': 1.year}) + end + # The preview urls for all the sites share the same domain, so cookie[:locale] # would be the same for all the preview urls and this is not good. # This is why we need to use a different key. @@ -97,6 +161,10 @@ def cookie_key_name live_editing? ? "steam-locale-#{site.handle}" : 'steam-locale' end + def cookie_country_key_name + live_editing? ? "steam-country-#{site.handle}" : 'steam-country' + end + def is_index_page? ['/', ''].include?(request.path_info) end diff --git a/lib/locomotive/steam/middlewares/renderer.rb b/lib/locomotive/steam/middlewares/renderer.rb index 13028fdc..08e346bd 100644 --- a/lib/locomotive/steam/middlewares/renderer.rb +++ b/lib/locomotive/steam/middlewares/renderer.rb @@ -98,6 +98,7 @@ def _steam_liquid_assigns def _locale_liquid_assigns { 'locale' => locale.to_s, + 'country' => env['steam.country'], 'default_locale' => site.default_locale.to_s, 'locales' => site.locales.map(&:to_s) }