diff --git a/pkg/ui/workspaces/db-console/src/redux/cachedDataReducer.ts b/pkg/ui/workspaces/db-console/src/redux/cachedDataReducer.ts index 63ae0611081d..eef85fce30e9 100644 --- a/pkg/ui/workspaces/db-console/src/redux/cachedDataReducer.ts +++ b/pkg/ui/workspaces/db-console/src/redux/cachedDataReducer.ts @@ -24,6 +24,8 @@ import { ThunkAction, ThunkDispatch } from "redux-thunk"; import { createHashHistory } from "history"; import { getLoginPage } from "src/redux/login"; import { APIRequestFn } from "src/util/api"; +import { util as clusterUiUtil } from "@cockroachlabs/cluster-ui"; +const { isForbiddenRequestError } = clusterUiUtil; import { PayloadAction, WithRequest } from "src/interfaces/action"; import { maybeClearTenantCookie } from "./cookies"; @@ -45,6 +47,7 @@ export class CachedDataReducerState { requestedAt?: moment.Moment; // Timestamp when data was last requested. setAt?: moment.Moment; // Timestamp when this data was last updated. lastError?: Error; // populated with the most recent error, if the last request failed + unauthorized = false; // If lastError was a 403 error, we avoid refreshing. } // KeyedCachedDataReducerState is used to track the state of the cached data @@ -63,6 +66,7 @@ export class PaginatedCachedDataReducerState { requestedAt?: moment.Moment; // Timestamp when data was last requested. setAt?: moment.Moment; // Timestamp when this data was last updated. lastError?: Error; // populated with the most recent error, if the last request failed + unauthorized = false; // If lastError was a 403 error, we avoid refreshing. constructor() { this.data = {}; @@ -170,6 +174,9 @@ export class CachedDataReducer< state.inFlight = false; state.lastError = error.data; state.valid = false; + if (isForbiddenRequestError(error.data)) { + state.unauthorized = true; + } return state; } case this.INVALIDATE: @@ -260,7 +267,9 @@ export class CachedDataReducer< if ( state && - (state.inFlight || (this.invalidationPeriod && state.valid)) + (state.inFlight || + (this.invalidationPeriod && state.valid) || + state.unauthorized) ) { return; } @@ -524,6 +533,9 @@ export class PaginatedCachedDataReducer< state.inFlight = false; state.lastError = error.data; state.valid = false; + if (isForbiddenRequestError(error.data)) { + state.unauthorized = true; + } return state; } case this.cachedDataReducer.INVALIDATE: @@ -556,7 +568,9 @@ export class PaginatedCachedDataReducer< stateAccessor(getState(), req); if ( state && - (state.inFlight || (this.invalidationPeriod && state.valid)) + (state.inFlight || + (this.invalidationPeriod && state.valid) || + state.unauthorized) ) { return; } diff --git a/pkg/ui/workspaces/db-console/src/redux/localities.spec.ts b/pkg/ui/workspaces/db-console/src/redux/localities.spec.ts index 2e5bde1aa33b..c80583f5d451 100644 --- a/pkg/ui/workspaces/db-console/src/redux/localities.spec.ts +++ b/pkg/ui/workspaces/db-console/src/redux/localities.spec.ts @@ -30,6 +30,7 @@ function makeStateWithLocalities(localities: LocalityTier[][]) { data: nodes, inFlight: false, valid: true, + unauthorized: false, }, liveness: {}, }, diff --git a/pkg/ui/workspaces/db-console/src/redux/locations.spec.ts b/pkg/ui/workspaces/db-console/src/redux/locations.spec.ts index 687d7c41b2db..c34022f909f1 100644 --- a/pkg/ui/workspaces/db-console/src/redux/locations.spec.ts +++ b/pkg/ui/workspaces/db-console/src/redux/locations.spec.ts @@ -52,6 +52,7 @@ function makeStateWithLocations(locationData: ILocation[]) { }), inFlight: false, valid: true, + unauthorized: false, }, }, }; @@ -64,6 +65,7 @@ describe("selectLocations", function () { locations: { inFlight: false, valid: false, + unauthorized: false, }, }, }; diff --git a/pkg/ui/workspaces/db-console/src/redux/nodes.spec.ts b/pkg/ui/workspaces/db-console/src/redux/nodes.spec.ts index 7500e8cd35de..cb5c2afc93d8 100644 --- a/pkg/ui/workspaces/db-console/src/redux/nodes.spec.ts +++ b/pkg/ui/workspaces/db-console/src/redux/nodes.spec.ts @@ -237,6 +237,7 @@ describe("selectCommissionedNodeStatuses", function () { data: nodeStatuses, inFlight: false, valid: true, + unauthorized: false, }, liveness: { data: { @@ -244,6 +245,7 @@ describe("selectCommissionedNodeStatuses", function () { }, inFlight: false, valid: true, + unauthorized: false, }, }, }; diff --git a/pkg/ui/workspaces/db-console/src/views/statements/statements.spec.tsx b/pkg/ui/workspaces/db-console/src/views/statements/statements.spec.tsx index f07f03147706..e236038bf94c 100644 --- a/pkg/ui/workspaces/db-console/src/views/statements/statements.spec.tsx +++ b/pkg/ui/workspaces/db-console/src/views/statements/statements.spec.tsx @@ -645,6 +645,7 @@ function makeStateWithStatementsAndLastReset( ), inFlight: false, valid: true, + unauthorized: false, }; } }