Avoid redundant OAuth queries when not signed in

If you aren't signed in, you don't have an auth token.
When you don't have an auth token, React was sending the headers

"Authorization: Bearer null"

This caused 5 Doorkeeper token lookups using
WHERE "oauth_access_tokens"."token" = 'null'
on the Explore page (the root of the app when not signed in).
This commit is contained in:
Free Speech Forever 2021-02-15 23:26:00 +00:00
parent 7bfe6c7709
commit 92c9092abd
13 changed files with 82 additions and 77 deletions

View File

@ -30,7 +30,9 @@ gem 'charlock_holmes', '~> 0.7.6'
gem 'iso-639' gem 'iso-639'
gem 'chewy', '~> 5.0' gem 'chewy', '~> 5.0'
gem 'cld3', '~> 3.2.4' gem 'cld3', '~> 3.2.4'
gem 'devise', '~> 4.6' git 'https://github.com/freespeech4ever/devise.git', branch: 'gab2' do
gem 'devise'
end
gem 'devise-two-factor', '~> 3.0' gem 'devise-two-factor', '~> 3.0'
group :pam_authentication, optional: true do group :pam_authentication, optional: true do

View File

@ -1,3 +1,15 @@
GIT
remote: https://github.com/freespeech4ever/devise.git
revision: 4009905531f28ebd7ecab22f898b5d6180eefb4a
branch: gab2
specs:
devise (4.7.3)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
GIT GIT
remote: https://github.com/rtomayko/posix-spawn remote: https://github.com/rtomayko/posix-spawn
revision: 58465d2e213991f8afb13b984854a49fcdcc980c revision: 58465d2e213991f8afb13b984854a49fcdcc980c
@ -183,12 +195,6 @@ GEM
rake (> 10, < 14) rake (> 10, < 14)
ruby-statistics (>= 2.1) ruby-statistics (>= 2.1)
thor (>= 0.19, < 2) thor (>= 0.19, < 2)
devise (4.7.3)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
responders
warden (~> 1.2.3)
devise-two-factor (3.1.0) devise-two-factor (3.1.0)
activesupport (< 6.1) activesupport (< 6.1)
attr_encrypted (>= 1.3, < 4, != 2) attr_encrypted (>= 1.3, < 4, != 2)
@ -696,7 +702,7 @@ DEPENDENCIES
climate_control (~> 0.2) climate_control (~> 0.2)
concurrent-ruby concurrent-ruby
derailed_benchmarks derailed_benchmarks
devise (~> 4.6) devise!
devise-two-factor (~> 3.0) devise-two-factor (~> 3.0)
devise_pam_authenticatable2 (~> 9.2) devise_pam_authenticatable2 (~> 9.2)
doorkeeper (~> 5.1) doorkeeper (~> 5.1)

View File

@ -51,7 +51,7 @@ export const LIST_ADDER_LISTS_FETCH_SUCCESS = 'LIST_ADDER_LISTS_FETCH_SUCCESS'
export const LIST_ADDER_LISTS_FETCH_FAIL = 'LIST_ADDER_LISTS_FETCH_FAIL' export const LIST_ADDER_LISTS_FETCH_FAIL = 'LIST_ADDER_LISTS_FETCH_FAIL'
/** /**
* *
*/ */
export const fetchList = (id) => (dispatch, getState) => { export const fetchList = (id) => (dispatch, getState) => {
if (!me) return if (!me) return
@ -82,7 +82,7 @@ const fetchListFail = (id, error) => ({
}) })
/** /**
* *
*/ */
export const fetchLists = () => (dispatch, getState) => { export const fetchLists = () => (dispatch, getState) => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -109,12 +109,12 @@ const fetchListsSuccess = (lists) => ({
const fetchListsFail = (error) => ({ const fetchListsFail = (error) => ({
type: LISTS_FETCH_FAIL, type: LISTS_FETCH_FAIL,
showToast: true, showToast: false,
error, error,
}) })
/** /**
* *
*/ */
export const submitListEditor = (shouldReset) => (dispatch, getState) => { export const submitListEditor = (shouldReset) => (dispatch, getState) => {
const listId = getState().getIn(['listEditor', 'listId']) const listId = getState().getIn(['listEditor', 'listId'])
@ -128,7 +128,7 @@ export const submitListEditor = (shouldReset) => (dispatch, getState) => {
} }
/** /**
* *
*/ */
export const setupListEditor = (listId) => (dispatch, getState) => { export const setupListEditor = (listId) => (dispatch, getState) => {
dispatch({ dispatch({
@ -140,7 +140,7 @@ export const setupListEditor = (listId) => (dispatch, getState) => {
} }
/** /**
* *
*/ */
export const changeListEditorTitle = (value) => ({ export const changeListEditorTitle = (value) => ({
type: LIST_EDITOR_TITLE_CHANGE, type: LIST_EDITOR_TITLE_CHANGE,
@ -148,7 +148,7 @@ export const changeListEditorTitle = (value) => ({
}) })
/** /**
* *
*/ */
export const createList = (title, shouldReset) => (dispatch, getState) => { export const createList = (title, shouldReset) => (dispatch, getState) => {
if (!me) return if (!me) return
@ -181,7 +181,7 @@ export const createListFail = (error) => ({
}) })
/** /**
* *
*/ */
export const updateList = (id, title, shouldReset) => (dispatch, getState) => { export const updateList = (id, title, shouldReset) => (dispatch, getState) => {
if (!me) return if (!me) return
@ -220,7 +220,7 @@ export const resetListEditor = () => ({
}) })
/** /**
* *
*/ */
export const deleteList = (id) => (dispatch, getState) => { export const deleteList = (id) => (dispatch, getState) => {
if (!me) return if (!me) return
@ -251,7 +251,7 @@ export const deleteListFail = (id, error) => ({
}) })
/** /**
* *
*/ */
export const fetchListAccounts = (listId) => (dispatch, getState) => { export const fetchListAccounts = (listId) => (dispatch, getState) => {
if (!me) return if (!me) return
@ -284,7 +284,7 @@ export const fetchListAccountsFail = (id, error) => ({
}) })
/** /**
* *
*/ */
export const fetchListSuggestions = (q) => (dispatch, getState) => { export const fetchListSuggestions = (q) => (dispatch, getState) => {
if (!me) return if (!me) return
@ -303,7 +303,7 @@ export const fetchListSuggestions = (q) => (dispatch, getState) => {
} }
/** /**
* *
*/ */
const fetchListSuggestionsReady = (query, accounts) => ({ const fetchListSuggestionsReady = (query, accounts) => ({
type: LIST_EDITOR_SUGGESTIONS_READY, type: LIST_EDITOR_SUGGESTIONS_READY,
@ -312,14 +312,14 @@ const fetchListSuggestionsReady = (query, accounts) => ({
}) })
/** /**
* *
*/ */
export const clearListSuggestions = () => ({ export const clearListSuggestions = () => ({
type: LIST_EDITOR_SUGGESTIONS_CLEAR, type: LIST_EDITOR_SUGGESTIONS_CLEAR,
}) })
/** /**
* *
*/ */
export const changeListSuggestions = (value) => ({ export const changeListSuggestions = (value) => ({
type: LIST_EDITOR_SUGGESTIONS_CHANGE, type: LIST_EDITOR_SUGGESTIONS_CHANGE,
@ -327,14 +327,14 @@ export const changeListSuggestions = (value) => ({
}) })
/** /**
* *
*/ */
export const addToListEditor = accountId => (dispatch, getState) => { export const addToListEditor = accountId => (dispatch, getState) => {
dispatch(addToList(getState().getIn(['listEditor', 'listId']), accountId)) dispatch(addToList(getState().getIn(['listEditor', 'listId']), accountId))
} }
/** /**
* *
*/ */
export const addToList = (listId, accountId) => (dispatch, getState) => { export const addToList = (listId, accountId) => (dispatch, getState) => {
if (!me) return if (!me) return
@ -368,14 +368,14 @@ const addToListFail = (listId, accountId, error) => ({
}) })
/** /**
* *
*/ */
export const removeFromListEditor = accountId => (dispatch, getState) => { export const removeFromListEditor = accountId => (dispatch, getState) => {
dispatch(removeFromList(getState().getIn(['listEditor', 'listId']), accountId)) dispatch(removeFromList(getState().getIn(['listEditor', 'listId']), accountId))
} }
/** /**
* *
*/ */
export const removeFromList = (listId, accountId) => (dispatch, getState) => { export const removeFromList = (listId, accountId) => (dispatch, getState) => {
if (!me) return if (!me) return
@ -409,14 +409,14 @@ const removeFromListFail = (listId, accountId, error) => ({
}) })
/** /**
* *
*/ */
export const resetListAdder = () => ({ export const resetListAdder = () => ({
type: LIST_ADDER_RESET, type: LIST_ADDER_RESET,
}) })
/** /**
* *
*/ */
export const setupListAdder = accountId => (dispatch, getState) => { export const setupListAdder = accountId => (dispatch, getState) => {
dispatch({ dispatch({
@ -428,7 +428,7 @@ export const setupListAdder = accountId => (dispatch, getState) => {
} }
/** /**
* *
*/ */
export const fetchAccountLists = (accountId) => (dispatch, getState) => { export const fetchAccountLists = (accountId) => (dispatch, getState) => {
if (!me) return if (!me) return
@ -459,14 +459,14 @@ const fetchAccountListsFail = (id, error) => ({
}) })
/** /**
* *
*/ */
export const addToListAdder = (listId) => (dispatch, getState) => { export const addToListAdder = (listId) => (dispatch, getState) => {
dispatch(addToList(listId, getState().getIn(['listAdder', 'accountId']))) dispatch(addToList(listId, getState().getIn(['listAdder', 'accountId'])))
} }
/** /**
* *
*/ */
export const removeFromListAdder = (listId) => (dispatch, getState) => { export const removeFromListAdder = (listId) => (dispatch, getState) => {
dispatch(removeFromList(listId, getState().getIn(['listAdder', 'accountId']))) dispatch(removeFromList(listId, getState().getIn(['listAdder', 'accountId'])))

View File

@ -25,16 +25,20 @@ function setCSRFHeader() {
ready(setCSRFHeader); ready(setCSRFHeader);
export default getState => axios.create({ export default getState => {
headers: Object.assign(csrfHeader, getState ? { const authToken = getState ? getState().getIn(['meta', 'access_token'], '') : null;
'Authorization': `Bearer ${getState().getIn(['meta', 'access_token'], '')}`,
} : {}),
transformResponse: [function (data) { return axios.create({
try { headers: Object.assign(csrfHeader, authToken ? {
return JSON.parse(data); 'Authorization': `Bearer ${authToken}}`,
} catch (Exception) { } : {}),
return data;
} transformResponse: [function (data) {
}], try {
}); return JSON.parse(data);
} catch (Exception) {
return data;
}
}],
});
};

View File

@ -15,11 +15,6 @@ class AccountModerationNote < ApplicationRecord
belongs_to :account belongs_to :account
belongs_to :target_account, class_name: 'Account' belongs_to :target_account, class_name: 'Account'
connects_to database: {
writing: :master,
reading: :master
}
scope :latest, -> { reorder('created_at DESC') } scope :latest, -> { reorder('created_at DESC') }
validates :content, presence: true, length: { maximum: 500 } validates :content, presence: true, length: { maximum: 500 }

View File

@ -15,8 +15,8 @@
class AccountVerificationRequest < ApplicationRecord class AccountVerificationRequest < ApplicationRecord
connects_to database: { connects_to database: {
writing: :master, writing: :primary,
reading: :master reading: :primary
} }
LIMIT = 4.megabytes LIMIT = 4.megabytes

View File

@ -2,7 +2,7 @@
class ApplicationRecord < ActiveRecord::Base class ApplicationRecord < ActiveRecord::Base
connects_to database: { connects_to database: {
writing: :master, writing: :primary,
reading: :slave1 reading: :slave1
} }
self.abstract_class = true self.abstract_class = true

View File

@ -29,11 +29,6 @@ class Report < ApplicationRecord
validates :comment, length: { maximum: 1000 } validates :comment, length: { maximum: 1000 }
connects_to database: {
writing: :master,
reading: :master
}
def local? def local?
false # Force uri_for to use uri attribute false # Force uri_for to use uri attribute
end end

View File

@ -19,9 +19,4 @@ class ReportNote < ApplicationRecord
validates :content, presence: true, length: { maximum: 500 } validates :content, presence: true, length: { maximum: 500 }
connects_to database: {
writing: :master,
reading: :master
}
end end

View File

@ -23,11 +23,6 @@ class SessionActivation < ApplicationRecord
to: :access_token, to: :access_token,
allow_nil: true allow_nil: true
connects_to database: {
writing: :master,
reading: :master
}
def detection def detection
@detection ||= Browser.new(user_agent) @detection ||= Browser.new(user_agent)
end end
@ -45,7 +40,9 @@ class SessionActivation < ApplicationRecord
class << self class << self
def active?(id) def active?(id)
id && where(session_id: id).exists? ActiveRecord::Base.connected_to(role: :writing) do
id && where(session_id: id).exists?
end
end end
def activate(**options) def activate(**options)
@ -61,19 +58,16 @@ class SessionActivation < ApplicationRecord
def deactivate(id) def deactivate(id)
return unless id return unless id
ActiveRecord::Base.connected_to(role: :writing) do where(session_id: id).destroy_all
conn = ActiveRecord::Base.connection
conn.exec_query "delete from session_activations where session_id = '#{id}'"
end
end end
def purge_old def purge_old
order('created_at desc').offset(Rails.configuration.x.max_session_activations).destroy_all order('created_at desc').offset(Rails.configuration.x.max_session_activations).destroy_all
end end
def exclusive(id) #def exclusive(id)
where('session_id != ?', id).destroy_all # where('session_id != ?', id).destroy_all
end #end
end end
private private
@ -93,6 +87,5 @@ class SessionActivation < ApplicationRecord
expires_in: Doorkeeper.configuration.access_token_expires_in, expires_in: Doorkeeper.configuration.access_token_expires_in,
use_refresh_token: Doorkeeper.configuration.refresh_token_enabled?) use_refresh_token: Doorkeeper.configuration.refresh_token_enabled?)
end end
self.access_token
end end
end end

View File

@ -7,7 +7,7 @@ default: &default
prepared_statements: <%= ENV['PREPARED_STATEMENTS'] || 'false' %> prepared_statements: <%= ENV['PREPARED_STATEMENTS'] || 'false' %>
development: development:
master: primary:
<<: *default <<: *default
url: <%= ENV['DB_MASTER_URL'] %> url: <%= ENV['DB_MASTER_URL'] %>
slave1: slave1:
@ -39,7 +39,7 @@ test:
# port: <%= ENV['DB_PORT'] || 5432 %> # port: <%= ENV['DB_PORT'] || 5432 %>
# prepared_statements: <%= ENV['PREPARED_STATEMENTS'] || 'true' %> # prepared_statements: <%= ENV['PREPARED_STATEMENTS'] || 'true' %>
production: production:
master: primary:
<<: *default <<: *default
url: <%= ENV['DB_MASTER_URL'] %> url: <%= ENV['DB_MASTER_URL'] %>
slave1: slave1:

View File

@ -76,6 +76,14 @@ module Devise
end end
Devise.setup do |config| Devise.setup do |config|
config.warden_hook_save_wrapper = Proc.new do |hook|
# ensure the writable connection is used to avoid read-only write errors
ApplicationRecord.connected_to(role: :writing) do
hook.call
end
end
config.warden do |manager| config.warden do |manager|
manager.default_strategies(scope: :user).unshift :ldap_authenticatable if Devise.ldap_authentication manager.default_strategies(scope: :user).unshift :ldap_authenticatable if Devise.ldap_authentication
manager.default_strategies(scope: :user).unshift :pam_authenticatable if Devise.pam_authentication manager.default_strategies(scope: :user).unshift :pam_authenticatable if Devise.pam_authentication

View File

@ -7,6 +7,13 @@ Devise.setup do |config|
options = {} options = {}
options[:redirect_at_sign_in] = ENV['OAUTH_REDIRECT_AT_SIGN_IN'] == 'true' options[:redirect_at_sign_in] = ENV['OAUTH_REDIRECT_AT_SIGN_IN'] == 'true'
config.warden_hook_save_wrapper = Proc.new do |hook|
# ensure the writable connection is used to avoid read-only write errors
ApplicationRecord.connected_to(role: :writing) do
hook.call
end
end
# CAS strategy # CAS strategy
if ENV['CAS_ENABLED'] == 'true' if ENV['CAS_ENABLED'] == 'true'
cas_options = options cas_options = options