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 'chewy', '~> 5.0'
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'
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
remote: https://github.com/rtomayko/posix-spawn
revision: 58465d2e213991f8afb13b984854a49fcdcc980c
@ -183,12 +195,6 @@ GEM
rake (> 10, < 14)
ruby-statistics (>= 2.1)
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)
activesupport (< 6.1)
attr_encrypted (>= 1.3, < 4, != 2)
@ -696,7 +702,7 @@ DEPENDENCIES
climate_control (~> 0.2)
concurrent-ruby
derailed_benchmarks
devise (~> 4.6)
devise!
devise-two-factor (~> 3.0)
devise_pam_authenticatable2 (~> 9.2)
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 fetchList = (id) => (dispatch, getState) => {
if (!me) return
@ -82,7 +82,7 @@ const fetchListFail = (id, error) => ({
})
/**
*
*
*/
export const fetchLists = () => (dispatch, getState) => {
return new Promise((resolve, reject) => {
@ -109,12 +109,12 @@ const fetchListsSuccess = (lists) => ({
const fetchListsFail = (error) => ({
type: LISTS_FETCH_FAIL,
showToast: true,
showToast: false,
error,
})
/**
*
*
*/
export const submitListEditor = (shouldReset) => (dispatch, getState) => {
const listId = getState().getIn(['listEditor', 'listId'])
@ -128,7 +128,7 @@ export const submitListEditor = (shouldReset) => (dispatch, getState) => {
}
/**
*
*
*/
export const setupListEditor = (listId) => (dispatch, getState) => {
dispatch({
@ -140,7 +140,7 @@ export const setupListEditor = (listId) => (dispatch, getState) => {
}
/**
*
*
*/
export const changeListEditorTitle = (value) => ({
type: LIST_EDITOR_TITLE_CHANGE,
@ -148,7 +148,7 @@ export const changeListEditorTitle = (value) => ({
})
/**
*
*
*/
export const createList = (title, shouldReset) => (dispatch, getState) => {
if (!me) return
@ -181,7 +181,7 @@ export const createListFail = (error) => ({
})
/**
*
*
*/
export const updateList = (id, title, shouldReset) => (dispatch, getState) => {
if (!me) return
@ -220,7 +220,7 @@ export const resetListEditor = () => ({
})
/**
*
*
*/
export const deleteList = (id) => (dispatch, getState) => {
if (!me) return
@ -251,7 +251,7 @@ export const deleteListFail = (id, error) => ({
})
/**
*
*
*/
export const fetchListAccounts = (listId) => (dispatch, getState) => {
if (!me) return
@ -284,7 +284,7 @@ export const fetchListAccountsFail = (id, error) => ({
})
/**
*
*
*/
export const fetchListSuggestions = (q) => (dispatch, getState) => {
if (!me) return
@ -303,7 +303,7 @@ export const fetchListSuggestions = (q) => (dispatch, getState) => {
}
/**
*
*
*/
const fetchListSuggestionsReady = (query, accounts) => ({
type: LIST_EDITOR_SUGGESTIONS_READY,
@ -312,14 +312,14 @@ const fetchListSuggestionsReady = (query, accounts) => ({
})
/**
*
*
*/
export const clearListSuggestions = () => ({
type: LIST_EDITOR_SUGGESTIONS_CLEAR,
})
/**
*
*
*/
export const changeListSuggestions = (value) => ({
type: LIST_EDITOR_SUGGESTIONS_CHANGE,
@ -327,14 +327,14 @@ export const changeListSuggestions = (value) => ({
})
/**
*
*
*/
export const addToListEditor = accountId => (dispatch, getState) => {
dispatch(addToList(getState().getIn(['listEditor', 'listId']), accountId))
}
/**
*
*
*/
export const addToList = (listId, accountId) => (dispatch, getState) => {
if (!me) return
@ -368,14 +368,14 @@ const addToListFail = (listId, accountId, error) => ({
})
/**
*
*
*/
export const removeFromListEditor = accountId => (dispatch, getState) => {
dispatch(removeFromList(getState().getIn(['listEditor', 'listId']), accountId))
}
/**
*
*
*/
export const removeFromList = (listId, accountId) => (dispatch, getState) => {
if (!me) return
@ -409,14 +409,14 @@ const removeFromListFail = (listId, accountId, error) => ({
})
/**
*
*
*/
export const resetListAdder = () => ({
type: LIST_ADDER_RESET,
})
/**
*
*
*/
export const setupListAdder = accountId => (dispatch, getState) => {
dispatch({
@ -428,7 +428,7 @@ export const setupListAdder = accountId => (dispatch, getState) => {
}
/**
*
*
*/
export const fetchAccountLists = (accountId) => (dispatch, getState) => {
if (!me) return
@ -459,14 +459,14 @@ const fetchAccountListsFail = (id, error) => ({
})
/**
*
*
*/
export const addToListAdder = (listId) => (dispatch, getState) => {
dispatch(addToList(listId, getState().getIn(['listAdder', 'accountId'])))
}
/**
*
*
*/
export const removeFromListAdder = (listId) => (dispatch, getState) => {
dispatch(removeFromList(listId, getState().getIn(['listAdder', 'accountId'])))

View File

@ -25,16 +25,20 @@ function setCSRFHeader() {
ready(setCSRFHeader);
export default getState => axios.create({
headers: Object.assign(csrfHeader, getState ? {
'Authorization': `Bearer ${getState().getIn(['meta', 'access_token'], '')}`,
} : {}),
export default getState => {
const authToken = getState ? getState().getIn(['meta', 'access_token'], '') : null;
transformResponse: [function (data) {
try {
return JSON.parse(data);
} catch (Exception) {
return data;
}
}],
});
return axios.create({
headers: Object.assign(csrfHeader, authToken ? {
'Authorization': `Bearer ${authToken}}`,
} : {}),
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 :target_account, class_name: 'Account'
connects_to database: {
writing: :master,
reading: :master
}
scope :latest, -> { reorder('created_at DESC') }
validates :content, presence: true, length: { maximum: 500 }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -76,6 +76,14 @@ module Devise
end
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|
manager.default_strategies(scope: :user).unshift :ldap_authenticatable if Devise.ldap_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[: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
if ENV['CAS_ENABLED'] == 'true'
cas_options = options