Follow up - ca56de3648
- Maintenance: Updated to Rails 6.0.4 and the new Zeitwerk autoloader: Fixed deprecation of autoloading in initializers causing namespace lookup errors.
This commit is contained in:
parent
3d946cf362
commit
887b779b40
17 changed files with 194 additions and 68 deletions
|
@ -2,4 +2,17 @@
|
|||
|
||||
class Session < ActiveRecord::SessionStore::Session
|
||||
include Session::SetsPersistentFlag
|
||||
|
||||
def self.secure_flag?
|
||||
# enable runtime change support in test/develop environments
|
||||
return https? if !Rails.env.production?
|
||||
|
||||
@secure_flag ||= https?
|
||||
rescue ActiveRecord::NoDatabaseError, ActiveRecord::StatementInvalid
|
||||
false
|
||||
end
|
||||
|
||||
def self.https?
|
||||
Setting.get('http_type') == 'https'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
# Rails' constant auto-loading resolves to 'rails/initializable' instead
|
||||
require_dependency 'zammad/application/initializer/db_preflight_check'
|
||||
require 'zammad/application/initializer/db_preflight_check'
|
||||
|
||||
Zammad::Application::Initializer::DbPreflightCheck.perform
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
return if !ActiveRecord::Base.connected?
|
||||
Rails.application.reloader.to_prepare do
|
||||
|
||||
# sync logo to fs / only if settings already exists
|
||||
return if ActiveRecord::Base.connection.tables.exclude?('settings')
|
||||
return if Setting.column_names.exclude?('state_current')
|
||||
next if !ActiveRecord::Base.connected?
|
||||
|
||||
StaticAssets.sync
|
||||
# sync logo to fs / only if settings already exists
|
||||
next if ActiveRecord::Base.connection.tables.exclude?('settings')
|
||||
next if Setting.column_names.exclude?('state_current')
|
||||
|
||||
StaticAssets.sync
|
||||
end
|
||||
|
|
|
@ -2,10 +2,12 @@
|
|||
|
||||
# update settings for searchable models
|
||||
|
||||
begin
|
||||
return if !Setting.exists?(name: 'models_searchable')
|
||||
Rails.application.reloader.to_prepare do
|
||||
begin
|
||||
next if !Setting.exists?(name: 'models_searchable')
|
||||
|
||||
Setting.set('models_searchable', Models.searchable.map(&:to_s))
|
||||
rescue ActiveRecord::StatementInvalid
|
||||
rescue ActiveRecord::StatementInvalid
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
# Rails' constant auto-loading resolves to 'rails/initializable' instead
|
||||
require_dependency 'zammad/application/initializer/session_store'
|
||||
require 'zammad/application/initializer/session_store'
|
||||
|
||||
Zammad::Application::Initializer::SessionStore.perform
|
||||
|
|
17
lib/core_ext/action_dispatch/middleware/cookies.rb
Normal file
17
lib/core_ext/action_dispatch/middleware/cookies.rb
Normal file
|
@ -0,0 +1,17 @@
|
|||
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
require 'action_dispatch/middleware/cookies'
|
||||
|
||||
module ActionDispatch
|
||||
class Cookies
|
||||
class CookieJar
|
||||
|
||||
alias original_write_cookie? write_cookie?
|
||||
|
||||
# https://github.com/rails/rails/blob/v6.0.4/actionpack/lib/action_dispatch/middleware/cookies.rb#L447-L449
|
||||
def write_cookie?(cookie)
|
||||
original_write_cookie?(cookie.merge(secure: ::Session.secure_flag?))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
20
lib/core_ext/rack/session/abstract/id.rb
Normal file
20
lib/core_ext/rack/session/abstract/id.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
require 'rack/session/abstract/id'
|
||||
|
||||
module Rack
|
||||
module Session
|
||||
module Abstract
|
||||
class Persisted
|
||||
|
||||
alias original_security_matches? security_matches?
|
||||
|
||||
# https://github.com/rack/rack/blob/2.2.3/lib/rack/session/abstract/id.rb#L363-L366
|
||||
def security_matches?(request, options)
|
||||
options[:secure] = ::Session.secure_flag?
|
||||
original_security_matches?(request, options)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
22
lib/core_ext/rack/utils.rb
Normal file
22
lib/core_ext/rack/utils.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
require 'rack/utils'
|
||||
|
||||
module Rack
|
||||
module Utils
|
||||
|
||||
module_function
|
||||
|
||||
singleton_class.alias_method :original_add_cookie_to_header, :add_cookie_to_header
|
||||
|
||||
# https://github.com/rack/rack/blob/2.2.3/lib/rack/session/utils.rb#L223-L262
|
||||
def add_cookie_to_header(header, key, value)
|
||||
|
||||
if value.is_a?(Hash)
|
||||
value[:secure] = ::Session.secure_flag?
|
||||
end
|
||||
|
||||
original_add_cookie_to_header(header, key, value)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,7 +7,7 @@ require 'zammad/application/initializer/db_preflight_check/nulldb'
|
|||
|
||||
module Zammad
|
||||
class Application
|
||||
class Initializer
|
||||
module Initializer
|
||||
module DbPreflightCheck
|
||||
def self.perform
|
||||
adapter.perform
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
module Zammad
|
||||
class Application
|
||||
class Initializer
|
||||
module Initializer
|
||||
module DbPreflightCheck
|
||||
module Base
|
||||
def check_version_compatibility
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
module Zammad
|
||||
class Application
|
||||
class Initializer
|
||||
module Initializer
|
||||
module DbPreflightCheck
|
||||
module Mysql2
|
||||
extend Base
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module Zammad
|
||||
class Application
|
||||
class Initializer
|
||||
module Initializer
|
||||
module DbPreflightCheck
|
||||
module Nulldb
|
||||
# no-op
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
module Zammad
|
||||
class Application
|
||||
class Initializer
|
||||
module Initializer
|
||||
module DbPreflightCheck
|
||||
module Postgresql
|
||||
extend Base
|
||||
|
|
|
@ -6,24 +6,28 @@
|
|||
|
||||
module Zammad
|
||||
class Application
|
||||
class Initializer
|
||||
module Initializer
|
||||
module SessionStore
|
||||
STORE_TYPE = :active_record_store # default: :cookie_store
|
||||
SESSION_KEY = "_zammad_session_#{Digest::MD5.hexdigest(Rails.root.to_s)[5..15]}".freeze # default: '_zammad_session'
|
||||
|
||||
def self.perform
|
||||
ActionDispatch::Session::ActiveRecordStore.session_class = Session
|
||||
# it's important to register the session store at initialization time
|
||||
# otherwise the store won't be used
|
||||
# ATTENTION: Rails/Rack Cookie handling was customized to call `Session.secure_flag?`
|
||||
# instead of accessing the `:secure` key (default Rack/Rails behavior).
|
||||
# See: lib/core_ext/action_dispatch/middleware/cookies.rb
|
||||
# See: lib/core_ext/rack/session/abstract/id.rb
|
||||
# See: lib/core_ext/rack/session/utils.rb
|
||||
Rails.application.config.session_store STORE_TYPE,
|
||||
key: SESSION_KEY,
|
||||
secure: secure?
|
||||
end
|
||||
key: SESSION_KEY
|
||||
|
||||
def self.secure?
|
||||
Setting.get('http_type') == 'https'
|
||||
rescue ActiveRecord::StatementInvalid
|
||||
false
|
||||
# once the application is initialized and we can access the models
|
||||
# we need to update the session_class
|
||||
Rails.application.reloader.to_prepare do
|
||||
ActionDispatch::Session::ActiveRecordStore.session_class = Session
|
||||
end
|
||||
end
|
||||
private_class_method :secure?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Zammad::Application::Initializer::SessionStore do
|
||||
describe '.perform' do
|
||||
context 'for HTTP deployment' do
|
||||
before { Setting.set('http_type', 'http') }
|
||||
|
||||
# Why not use the "change" matcher in this example?
|
||||
#
|
||||
# This initializer is already run when the application is loaded for testing.
|
||||
# Since the test env always uses http, the :secure option is already set to false.
|
||||
it 'adds { secure: false } to application session options' do
|
||||
described_class.perform
|
||||
|
||||
expect(Rails.application.config.session_options).to include(secure: false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'for HTTPS deployment' do
|
||||
before { Setting.set('http_type', 'https') }
|
||||
|
||||
it 'adds { secure: true } to application session options' do
|
||||
expect { described_class.perform }
|
||||
.to change(Rails.application.config, :session_options)
|
||||
.to include(secure: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -192,7 +192,7 @@ RSpec.describe 'External Credentials', type: :request do
|
|||
|
||||
shared_examples 'for failure cases' do
|
||||
it 'responds with the appropriate status and error message' do
|
||||
send(*endpoint, as: :json, params: try(:params) || {})
|
||||
send(*endpoint, as: :json, params: try(:params) || {}, headers: headers)
|
||||
|
||||
expect(response).to have_http_status(status)
|
||||
expect(json_response).to include('error' => error_message)
|
||||
|
@ -415,7 +415,14 @@ RSpec.describe 'External Credentials', type: :request do
|
|||
|
||||
let!(:twitter_credential) { create(:twitter_credential) }
|
||||
|
||||
before { get '/api/v1/external_credentials/twitter/link_account', as: :json }
|
||||
# Rails / Rack needs to detect that the request comes via HTTPS as well
|
||||
let(:headers) do
|
||||
{
|
||||
'X-Forwarded-Proto' => 'https'
|
||||
}
|
||||
end
|
||||
|
||||
before { get '/api/v1/external_credentials/twitter/link_account', as: :json, headers: headers }
|
||||
|
||||
include_examples 'for failure cases' do
|
||||
let(:status) { :unprocessable_entity }
|
||||
|
@ -458,7 +465,14 @@ RSpec.describe 'External Credentials', type: :request do
|
|||
let(:oauth_token) { 'DyhnyQAAAAAA9CNXAAABcSxAexs' }
|
||||
let(:oauth_verifier) { '15DOeRkjP4JkOSVqULkTKA1SCuIPP105' }
|
||||
|
||||
before { get '/api/v1/external_credentials/twitter/link_account', as: :json }
|
||||
# Rails / Rack needs to detect that the request comes via HTTPS as well
|
||||
let(:headers) do
|
||||
{
|
||||
'X-Forwarded-Proto' => 'https'
|
||||
}
|
||||
end
|
||||
|
||||
before { get '/api/v1/external_credentials/twitter/link_account', as: :json, headers: headers }
|
||||
|
||||
context 'if Twitter account has already been added' do
|
||||
let!(:channel) { create(:twitter_channel, custom_options: channel_options) }
|
||||
|
@ -472,12 +486,12 @@ RSpec.describe 'External Credentials', type: :request do
|
|||
end
|
||||
|
||||
it 'uses the existing channel' do
|
||||
expect { send(*endpoint, as: :json, params: params) }
|
||||
expect { send(*endpoint, as: :json, params: params, headers: headers) }
|
||||
.not_to change(Channel, :count)
|
||||
end
|
||||
|
||||
it 'updates channel properties' do
|
||||
expect { send(*endpoint, as: :json, params: params) }
|
||||
expect { send(*endpoint, as: :json, params: params, headers: headers) }
|
||||
.to change { channel.reload.options[:user][:name] }
|
||||
.and change { channel.reload.options[:auth][:external_credential_id] }
|
||||
.and change { channel.reload.options[:auth][:oauth_token] }
|
||||
|
@ -485,7 +499,7 @@ RSpec.describe 'External Credentials', type: :request do
|
|||
end
|
||||
|
||||
it 'subscribes to webhooks' do
|
||||
send(*endpoint, as: :json, params: params)
|
||||
send(*endpoint, as: :json, params: params, headers: headers)
|
||||
|
||||
expect(WebMock)
|
||||
.to have_requested(:post, "https://api.twitter.com/1.1/account_activity/all/#{twitter_credential.credentials[:env]}/subscriptions.json")
|
||||
|
@ -496,7 +510,7 @@ RSpec.describe 'External Credentials', type: :request do
|
|||
end
|
||||
|
||||
it 'creates a new channel' do
|
||||
expect { send(*endpoint, as: :json, params: params) }
|
||||
expect { send(*endpoint, as: :json, params: params, headers: headers) }
|
||||
.to change(Channel, :count).by(1)
|
||||
|
||||
expect(Channel.last.options)
|
||||
|
@ -506,19 +520,19 @@ RSpec.describe 'External Credentials', type: :request do
|
|||
end
|
||||
|
||||
it 'redirects to the newly created channel' do
|
||||
send(*endpoint, as: :json, params: params)
|
||||
send(*endpoint, as: :json, params: params, headers: headers)
|
||||
|
||||
expect(response).to redirect_to(%r{/#channels/twitter/#{Channel.last.id}$})
|
||||
end
|
||||
|
||||
it 'clears the :request_token session variable' do
|
||||
send(*endpoint, as: :json, params: params)
|
||||
send(*endpoint, as: :json, params: params, headers: headers)
|
||||
|
||||
expect(session[:request_token]).to be(nil)
|
||||
end
|
||||
|
||||
it 'subscribes to webhooks' do
|
||||
send(*endpoint, as: :json, params: params)
|
||||
send(*endpoint, as: :json, params: params, headers: headers)
|
||||
|
||||
expect(WebMock)
|
||||
.to have_requested(:post, "https://api.twitter.com/1.1/account_activity/all/#{twitter_credential.credentials[:env]}/subscriptions.json")
|
||||
|
|
|
@ -4,6 +4,68 @@ require 'rails_helper'
|
|||
|
||||
RSpec.describe 'Sessions endpoints', type: :request do
|
||||
|
||||
describe 'GET /' do
|
||||
|
||||
let(:headers) { {} }
|
||||
let(:session_key) { Zammad::Application::Initializer::SessionStore::SESSION_KEY }
|
||||
|
||||
before do
|
||||
Setting.set('http_type', http_type)
|
||||
|
||||
get '/', headers: headers
|
||||
end
|
||||
|
||||
context "when Setting 'http_type' is set to 'https'" do
|
||||
|
||||
let(:http_type) { 'https' }
|
||||
|
||||
context "when it's not an HTTPS request" do
|
||||
|
||||
it 'sets no Cookie' do
|
||||
expect(response.header['Set-Cookie']).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context "when it's an HTTPS request" do
|
||||
|
||||
let(:headers) do
|
||||
{
|
||||
'X-Forwarded-Proto' => 'https'
|
||||
}
|
||||
end
|
||||
|
||||
it "sets Cookie with 'secure' flag" do
|
||||
expect(response.header['Set-Cookie']).to include(session_key).and include('; secure;')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when Setting 'http_type' is set to 'http'" do
|
||||
|
||||
let(:http_type) { 'http' }
|
||||
|
||||
context "when it's not an HTTPS request" do
|
||||
|
||||
it 'sets Cookie' do
|
||||
expect(response.header['Set-Cookie']).to include(session_key).and not_include('; secure;')
|
||||
end
|
||||
end
|
||||
|
||||
context "when it's an HTTPS request" do
|
||||
|
||||
let(:headers) do
|
||||
{
|
||||
'X-Forwarded-Proto' => 'https'
|
||||
}
|
||||
end
|
||||
|
||||
it "sets Cookie without 'secure' flag" do
|
||||
expect(response.header['Set-Cookie']).to include(session_key).and not_include('; secure;')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET /signshow' do
|
||||
|
||||
context 'user logged in' do
|
||||
|
|
Loading…
Reference in a new issue