mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-09 15:05:44 +01:00
Fix missing redirect after login (#1592)
Each unauthorized error was caught by the token expired handler, which has reset the whole query state and this leads sometimes to a missing redirect after login.
This commit is contained in:
2
gradle/changelog/flappy_login.yaml
Normal file
2
gradle/changelog/flappy_login.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
- type: fixed
|
||||||
|
description: Sometimes no redirect after login ([#1592](https://github.com/scm-manager/scm-manager/pull/1592))
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
"gitdiff-parser": "^0.1.2",
|
"gitdiff-parser": "^0.1.2",
|
||||||
"query-string": "5",
|
"query-string": "5",
|
||||||
"react": "^17.0.1",
|
"react": "^17.0.1",
|
||||||
"react-query": "^3.5.16"
|
"react-query": "^3.12.2"
|
||||||
},
|
},
|
||||||
"babel": {
|
"babel": {
|
||||||
"presets": [
|
"presets": [
|
||||||
|
|||||||
@@ -23,7 +23,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { contextPath } from "./urls";
|
import { contextPath } from "./urls";
|
||||||
import { BackendErrorContent, createBackendError, ForbiddenError, isBackendError, UnauthorizedError } from "./errors";
|
import {
|
||||||
|
BackendErrorContent,
|
||||||
|
createBackendError,
|
||||||
|
ForbiddenError,
|
||||||
|
isBackendError,
|
||||||
|
TOKEN_EXPIRED_ERROR_CODE,
|
||||||
|
TokenExpiredError,
|
||||||
|
UnauthorizedError
|
||||||
|
} from "./errors";
|
||||||
|
|
||||||
type SubscriptionEvent = {
|
type SubscriptionEvent = {
|
||||||
type: string;
|
type: string;
|
||||||
@@ -119,6 +127,15 @@ const applyFetchOptions: (p: RequestInit) => RequestInit = o => {
|
|||||||
function handleFailure(response: Response) {
|
function handleFailure(response: Response) {
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
if (response.status === 401) {
|
if (response.status === 401) {
|
||||||
|
if (isBackendError(response)) {
|
||||||
|
return response.json().then((content: BackendErrorContent) => {
|
||||||
|
if (content.errorCode === TOKEN_EXPIRED_ERROR_CODE) {
|
||||||
|
throw new TokenExpiredError("Token expired", 401);
|
||||||
|
} else {
|
||||||
|
throw new UnauthorizedError("Unauthorized", 401);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
throw new UnauthorizedError("Unauthorized", 401);
|
throw new UnauthorizedError("Unauthorized", 401);
|
||||||
} else if (response.status === 403) {
|
} else if (response.status === 403) {
|
||||||
throw new ForbiddenError("Forbidden", 403);
|
throw new ForbiddenError("Forbidden", 403);
|
||||||
|
|||||||
@@ -72,14 +72,18 @@ export class BackendError extends Error {
|
|||||||
|
|
||||||
export class UnauthorizedError extends Error {
|
export class UnauthorizedError extends Error {
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
|
|
||||||
constructor(message: string, statusCode: number) {
|
constructor(message: string, statusCode: number) {
|
||||||
super(message);
|
super(message);
|
||||||
this.statusCode = statusCode;
|
this.statusCode = statusCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class TokenExpiredError extends UnauthorizedError {}
|
||||||
|
|
||||||
export class ForbiddenError extends Error {
|
export class ForbiddenError extends Error {
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
|
|
||||||
constructor(message: string, statusCode: number) {
|
constructor(message: string, statusCode: number) {
|
||||||
super(message);
|
super(message);
|
||||||
this.statusCode = statusCode;
|
this.statusCode = statusCode;
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Me } from "@scm-manager/ui-types";
|
import { Me } from "@scm-manager/ui-types";
|
||||||
import { useEffect } from "react";
|
|
||||||
import { useMutation, useQuery } from "react-query";
|
import { useMutation, useQuery } from "react-query";
|
||||||
import { apiClient } from "./apiclient";
|
import { apiClient } from "./apiclient";
|
||||||
import { ApiResult, useIndexLink } from "./base";
|
import { ApiResult, useIndexLink } from "./base";
|
||||||
@@ -111,7 +110,7 @@ export const useLogout = () => {
|
|||||||
if (response?.logoutRedirect) {
|
if (response?.logoutRedirect) {
|
||||||
window.location.assign(response.logoutRedirect);
|
window.location.assign(response.logoutRedirect);
|
||||||
}
|
}
|
||||||
reset();
|
return reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -44,11 +44,18 @@ export const from = (queryString?: string, stateParams?: FromObject | null): str
|
|||||||
return queryParams?.from || stateParams?.from || "/";
|
return queryParams?.from || stateParams?.from || "/";
|
||||||
};
|
};
|
||||||
|
|
||||||
const Login: FC = ({}) => {
|
const Login: FC = () => {
|
||||||
const location = useLocation<FromObject>();
|
const location = useLocation<FromObject>();
|
||||||
const { login, isLoading, error } = useLogin();
|
const { login, isLoading, error } = useLogin();
|
||||||
const loginInfoLink = useIndexLink("loginInfo");
|
const loginInfoLink = useIndexLink("loginInfo");
|
||||||
|
|
||||||
|
// sometimes after logout the url is still /logout
|
||||||
|
// but it does not make sense to redirect to /logout
|
||||||
|
// directly after login
|
||||||
|
if (location.pathname === "/logout") {
|
||||||
|
return <Redirect to="/" />;
|
||||||
|
}
|
||||||
|
|
||||||
if (!login) {
|
if (!login) {
|
||||||
const to = from(window.location.search, location.state);
|
const to = from(window.location.search, location.state);
|
||||||
return <Redirect to={to} />;
|
return <Redirect to={to} />;
|
||||||
|
|||||||
@@ -23,17 +23,16 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { apiClient, clearCache, UnauthorizedError } from "@scm-manager/ui-api";
|
import { apiClient, clearCache, TokenExpiredError } from "@scm-manager/ui-api";
|
||||||
|
|
||||||
let tokenExpired = false;
|
let tokenExpired = false;
|
||||||
|
|
||||||
// We assume that an UnauthorizedError means that the access token is expired.
|
|
||||||
// If the token is expired we want to show an error with the login link.
|
// If the token is expired we want to show an error with the login link.
|
||||||
// This error should be displayed with the state (e.g. navigation) of the previous logged in user.
|
// This error should be displayed with the state (e.g. navigation) of the previous logged in user.
|
||||||
// But if the user navigates away, we want to reset the state to an anonymous one.
|
// But if the user navigates away, we want to reset the state to an anonymous one.
|
||||||
|
|
||||||
apiClient.onError(error => {
|
apiClient.onError(error => {
|
||||||
if (error instanceof UnauthorizedError) {
|
if (error instanceof TokenExpiredError) {
|
||||||
tokenExpired = true;
|
tokenExpired = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
73
yarn.lock
73
yarn.lock
@@ -2636,6 +2636,13 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
regenerator-runtime "^0.13.4"
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
|
"@babel/runtime@^7.6.2":
|
||||||
|
version "7.13.10"
|
||||||
|
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d"
|
||||||
|
integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==
|
||||||
|
dependencies:
|
||||||
|
regenerator-runtime "^0.13.4"
|
||||||
|
|
||||||
"@babel/template@^7.10.4", "@babel/template@^7.3.3", "@babel/template@^7.4.0":
|
"@babel/template@^7.10.4", "@babel/template@^7.3.3", "@babel/template@^7.4.0":
|
||||||
version "7.10.4"
|
version "7.10.4"
|
||||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278"
|
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.10.4.tgz#3251996c4200ebc71d1a8fc405fba940f36ba278"
|
||||||
@@ -7202,6 +7209,11 @@ better-opn@^2.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
open "^7.0.3"
|
open "^7.0.3"
|
||||||
|
|
||||||
|
big-integer@^1.6.16:
|
||||||
|
version "1.6.48"
|
||||||
|
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e"
|
||||||
|
integrity sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==
|
||||||
|
|
||||||
big.js@^5.2.2:
|
big.js@^5.2.2:
|
||||||
version "5.2.2"
|
version "5.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
|
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
|
||||||
@@ -7327,6 +7339,19 @@ braces@^3.0.1, braces@~3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fill-range "^7.0.1"
|
fill-range "^7.0.1"
|
||||||
|
|
||||||
|
broadcast-channel@^3.4.1:
|
||||||
|
version "3.5.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/broadcast-channel/-/broadcast-channel-3.5.3.tgz#c75c39d923ae8af6284a893bfdc8bd3996d2dd2d"
|
||||||
|
integrity sha512-OLOXfwReZa2AAAh9yOUyiALB3YxBe0QpThwwuyRHLgpl8bSznSDmV6Mz7LeBJg1VZsMcDcNMy7B53w12qHrIhQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.7.2"
|
||||||
|
detect-node "^2.0.4"
|
||||||
|
js-sha3 "0.8.0"
|
||||||
|
microseconds "0.2.0"
|
||||||
|
nano-time "1.0.0"
|
||||||
|
rimraf "3.0.2"
|
||||||
|
unload "2.2.0"
|
||||||
|
|
||||||
brorand@^1.0.1:
|
brorand@^1.0.1:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
|
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
|
||||||
@@ -14225,6 +14250,11 @@ js-levenshtein@^1.1.3:
|
|||||||
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
|
resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d"
|
||||||
integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==
|
integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==
|
||||||
|
|
||||||
|
js-sha3@0.8.0:
|
||||||
|
version "0.8.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840"
|
||||||
|
integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==
|
||||||
|
|
||||||
js-string-escape@^1.0.1:
|
js-string-escape@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef"
|
resolved "https://registry.yarnpkg.com/js-string-escape/-/js-string-escape-1.0.1.tgz#e2625badbc0d67c7533e9edc1068c587ae4137ef"
|
||||||
@@ -15515,6 +15545,11 @@ micromatch@^4.0.2:
|
|||||||
braces "^3.0.1"
|
braces "^3.0.1"
|
||||||
picomatch "^2.0.5"
|
picomatch "^2.0.5"
|
||||||
|
|
||||||
|
microseconds@0.2.0:
|
||||||
|
version "0.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/microseconds/-/microseconds-0.2.0.tgz#233b25f50c62a65d861f978a4a4f8ec18797dc39"
|
||||||
|
integrity sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==
|
||||||
|
|
||||||
miller-rabin@^4.0.0:
|
miller-rabin@^4.0.0:
|
||||||
version "4.0.1"
|
version "4.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
|
resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
|
||||||
@@ -15860,6 +15895,13 @@ nan@^2.12.1:
|
|||||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
|
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01"
|
||||||
integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
|
integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==
|
||||||
|
|
||||||
|
nano-time@1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/nano-time/-/nano-time-1.0.0.tgz#b0554f69ad89e22d0907f7a12b0993a5d96137ef"
|
||||||
|
integrity sha1-sFVPaa2J4i0JB/ehKwmTpdlhN+8=
|
||||||
|
dependencies:
|
||||||
|
big-integer "^1.6.16"
|
||||||
|
|
||||||
nanoid@^3.1.3:
|
nanoid@^3.1.3:
|
||||||
version "3.1.20"
|
version "3.1.20"
|
||||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
|
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788"
|
||||||
@@ -18131,12 +18173,13 @@ react-popper@^2.2.4:
|
|||||||
react-fast-compare "^3.0.1"
|
react-fast-compare "^3.0.1"
|
||||||
warning "^4.0.2"
|
warning "^4.0.2"
|
||||||
|
|
||||||
react-query@^3.5.16:
|
react-query@^3.12.2:
|
||||||
version "3.5.16"
|
version "3.12.2"
|
||||||
resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.5.16.tgz#172771a8cdb83b85c353ac32f1e30bfca27893d7"
|
resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.12.2.tgz#57ae8056ba0cb63c9755cd00dc4cda45b29f9bb6"
|
||||||
integrity sha512-zOJimWPC0o2h8fta0uMc+pmFIBgfVkfCvEAeUbrlsbA6m42CFPgyRBJt6kiYjsZ/WRuJl+WIaAh/P27oUXETNw==
|
integrity sha512-Qq/Vy+sz4QscLPfcZMrMHfuZKbKr47tsttHgcqkOiZGhLjsnYkLGcsSnMdOSLBzhzziYhs1i3plLmF0VMZw2Ng==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.5.5"
|
"@babel/runtime" "^7.5.5"
|
||||||
|
broadcast-channel "^3.4.1"
|
||||||
match-sorter "^6.0.2"
|
match-sorter "^6.0.2"
|
||||||
|
|
||||||
react-redux@^5.0.7:
|
react-redux@^5.0.7:
|
||||||
@@ -18918,6 +18961,13 @@ rimraf@2.6.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.1.3"
|
glob "^7.1.3"
|
||||||
|
|
||||||
|
rimraf@3.0.2, rimraf@^3.0.0, rimraf@^3.0.2:
|
||||||
|
version "3.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
||||||
|
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
||||||
|
dependencies:
|
||||||
|
glob "^7.1.3"
|
||||||
|
|
||||||
rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3:
|
rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3:
|
||||||
version "2.7.1"
|
version "2.7.1"
|
||||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
|
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
|
||||||
@@ -18925,13 +18975,6 @@ rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3:
|
|||||||
dependencies:
|
dependencies:
|
||||||
glob "^7.1.3"
|
glob "^7.1.3"
|
||||||
|
|
||||||
rimraf@^3.0.0, rimraf@^3.0.2:
|
|
||||||
version "3.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
|
||||||
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
|
||||||
dependencies:
|
|
||||||
glob "^7.1.3"
|
|
||||||
|
|
||||||
ripemd160@^2.0.0, ripemd160@^2.0.1:
|
ripemd160@^2.0.0, ripemd160@^2.0.1:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
|
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
|
||||||
@@ -20997,6 +21040,14 @@ universalify@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
|
resolved "https://registry.yarnpkg.com/universalify/-/universalify-1.0.0.tgz#b61a1da173e8435b2fe3c67d29b9adf8594bd16d"
|
||||||
integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
|
integrity sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==
|
||||||
|
|
||||||
|
unload@2.2.0:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/unload/-/unload-2.2.0.tgz#ccc88fdcad345faa06a92039ec0f80b488880ef7"
|
||||||
|
integrity sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.6.2"
|
||||||
|
detect-node "^2.0.4"
|
||||||
|
|
||||||
unpipe@1.0.0, unpipe@~1.0.0:
|
unpipe@1.0.0, unpipe@~1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||||
|
|||||||
Reference in New Issue
Block a user