diff --git a/cvat-ui/src/actions/auth-actions.ts b/cvat-ui/src/actions/auth-actions.ts
index 9db70b5a..0ea9a937 100644
--- a/cvat-ui/src/actions/auth-actions.ts
+++ b/cvat-ui/src/actions/auth-actions.ts
@@ -40,7 +40,7 @@ export const authActions = {
authorizeSuccess: (user: any) => createAction(AuthActionTypes.AUTHORIZED_SUCCESS, { user }),
authorizeFailed: (error: any) => createAction(AuthActionTypes.AUTHORIZED_FAILED, { error }),
login: () => createAction(AuthActionTypes.LOGIN),
- loginSuccess: (user: any) => createAction(AuthActionTypes.LOGIN_SUCCESS, { user }),
+ loginSuccess: (user: any, next: string | null) => createAction(AuthActionTypes.LOGIN_SUCCESS, { user, next }),
loginFailed: (error: any) => createAction(AuthActionTypes.LOGIN_FAILED, { error }),
register: () => createAction(AuthActionTypes.REGISTER),
registerSuccess: (user: any) => createAction(AuthActionTypes.REGISTER_SUCCESS, { user }),
@@ -98,14 +98,16 @@ export const registerAsync = (
}
};
-export const loginAsync = (username: string, password: string): ThunkAction => async (dispatch) => {
+export const loginAsync = (username: string, password: string, next: string | null): ThunkAction => async (
+ dispatch,
+) => {
dispatch(authActions.login());
try {
await cvat.server.login(username, password);
const users = await cvat.users.get({ self: true });
- dispatch(authActions.loginSuccess(users[0]));
+ dispatch(authActions.loginSuccess(users[0], next));
} catch (error) {
dispatch(authActions.loginFailed(error));
}
diff --git a/cvat-ui/src/components/cvat-app.tsx b/cvat-ui/src/components/cvat-app.tsx
index b3c742cd..cfefaa7d 100644
--- a/cvat-ui/src/components/cvat-app.tsx
+++ b/cvat-ui/src/components/cvat-app.tsx
@@ -64,6 +64,7 @@ interface CVATAppProps {
authActionsInitialized: boolean;
notifications: NotificationsState;
user: any;
+ next: string | null;
isModelPluginActive: boolean;
}
@@ -231,16 +232,19 @@ class CVATApplication extends React.PureComponent
)}
-
+
{/* eslint-disable-next-line */}
@@ -337,7 +341,9 @@ class CVATApplication extends React.PureComponent
-
+ 1 ? `/auth/login/?next=${location.pathname}` : '/auth/login'}
+ />
);
diff --git a/cvat-ui/src/components/login-page/login-page.tsx b/cvat-ui/src/components/login-page/login-page.tsx
index f252606f..9e00e841 100644
--- a/cvat-ui/src/components/login-page/login-page.tsx
+++ b/cvat-ui/src/components/login-page/login-page.tsx
@@ -15,7 +15,8 @@ import CookieDrawer from './cookie-policy-drawer';
interface LoginPageComponentProps {
fetching: boolean;
renderResetPassword: boolean;
- onLogin: (username: string, password: string) => void;
+ next: string;
+ onLogin: (username: string, password: string, next: string | null) => void;
}
function LoginPageComponent(props: LoginPageComponentProps & RouteComponentProps): JSX.Element {
@@ -27,7 +28,11 @@ function LoginPageComponent(props: LoginPageComponentProps & RouteComponentProps
xl: { span: 4 },
};
- const { fetching, onLogin, renderResetPassword } = props;
+ const {
+ fetching, onLogin, renderResetPassword, location,
+ } = props;
+
+ const search = new URLSearchParams(location.search);
return (
<>
@@ -37,7 +42,7 @@ function LoginPageComponent(props: LoginPageComponentProps & RouteComponentProps
{
- onLogin(loginData.username, loginData.password);
+ onLogin(loginData.username, loginData.password, search.get('next'));
}}
/>
diff --git a/cvat-ui/src/components/login-with-token/login-with-token.tsx b/cvat-ui/src/components/login-with-token/login-with-token.tsx
index cadb0542..b40ca03a 100644
--- a/cvat-ui/src/components/login-with-token/login-with-token.tsx
+++ b/cvat-ui/src/components/login-with-token/login-with-token.tsx
@@ -3,15 +3,17 @@
// SPDX-License-Identifier: MIT
import React, { useEffect } from 'react';
-import { Redirect, useParams } from 'react-router';
+import { Redirect, useParams, useLocation } from 'react-router';
import { useCookies } from 'react-cookie';
export default function LoginWithTokenComponent(): JSX.Element {
- const { sessionId, token } = useParams();
+ const location = useLocation();
+ const { sessionId, token } = useParams<{ sessionId: string; token: string }>();
const [cookies, setCookie] = useCookies(['sessionid', 'csrftoken']);
const expires1y = new Date(new Date().setFullYear(new Date().getFullYear() + 1));
const expires2w = new Date(new Date().setDate(new Date().getDate() + 13));
+ const search = new URLSearchParams(location.search);
setCookie('sessionid', sessionId, { path: '/', expires: expires2w });
setCookie('csrftoken', token, { path: '/', expires: expires1y });
@@ -24,7 +26,7 @@ export default function LoginWithTokenComponent(): JSX.Element {
);
if (cookies.sessionid && cookies.csrftoken) {
- return ;
+ return ;
}
return <>>;
}
diff --git a/cvat-ui/src/index.tsx b/cvat-ui/src/index.tsx
index 31188f77..1d527605 100644
--- a/cvat-ui/src/index.tsx
+++ b/cvat-ui/src/index.tsx
@@ -45,6 +45,7 @@ interface StateToProps {
allowResetPassword: boolean;
notifications: NotificationsState;
user: any;
+ next: string | null;
keyMap: Record;
isModelPluginActive: boolean;
}
@@ -91,6 +92,7 @@ function mapStateToProps(state: CombinedState): StateToProps {
allowResetPassword: auth.allowResetPassword,
notifications: state.notifications,
user: auth.user,
+ next: auth.next,
keyMap: shortcuts.keyMap,
isModelPluginActive: plugins.list.MODELS,
};
diff --git a/cvat-ui/src/reducers/auth-reducer.ts b/cvat-ui/src/reducers/auth-reducer.ts
index eac8449b..2e226c20 100644
--- a/cvat-ui/src/reducers/auth-reducer.ts
+++ b/cvat-ui/src/reducers/auth-reducer.ts
@@ -10,6 +10,7 @@ const defaultState: AuthState = {
initialized: false,
fetching: false,
user: null,
+ next: null,
authActionsFetching: false,
authActionsInitialized: false,
allowChangePassword: false,
@@ -40,6 +41,7 @@ export default function (state = defaultState, action: AuthActions | BoundariesA
...state,
fetching: false,
user: action.payload.user,
+ next: action.payload.next,
};
case AuthActionTypes.LOGIN_FAILED:
return {
@@ -94,9 +96,9 @@ export default function (state = defaultState, action: AuthActions | BoundariesA
return {
...state,
showChangePasswordDialog:
- typeof action.payload.showChangePasswordDialog === 'undefined'
- ? !state.showChangePasswordDialog
- : action.payload.showChangePasswordDialog,
+ typeof action.payload.showChangePasswordDialog === 'undefined' ?
+ !state.showChangePasswordDialog :
+ action.payload.showChangePasswordDialog,
};
case AuthActionTypes.REQUEST_PASSWORD_RESET:
return {
diff --git a/cvat-ui/src/reducers/interfaces.ts b/cvat-ui/src/reducers/interfaces.ts
index 088be88d..8a518d68 100644
--- a/cvat-ui/src/reducers/interfaces.ts
+++ b/cvat-ui/src/reducers/interfaces.ts
@@ -14,6 +14,7 @@ export interface AuthState {
initialized: boolean;
fetching: boolean;
user: any;
+ next: string | null;
authActionsFetching: boolean;
authActionsInitialized: boolean;
showChangePasswordDialog: boolean;