Bugfix/link not found (#1296)

Redirect to login page if anonymous tries to access a page without permission

Co-authored-by: Eduard Heimbuch <eduard.heimbuch@cloudogu.com>
Co-authored-by: Sebastian Sdorra <sebastian.sdorra@cloudogu.com>
This commit is contained in:
Konstantin Schaper
2020-08-27 13:20:43 +02:00
committed by GitHub
parent bd81d973ec
commit b4c5f49858
17 changed files with 216 additions and 77 deletions

View File

@@ -21,14 +21,24 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
import React, { ReactNode } from "react";
import React, { ComponentType, ReactNode } from "react";
import ErrorNotification from "./ErrorNotification";
import { MissingLinkError } from "./errors";
import { withContextPath } from "./urls";
import { withRouter, RouteComponentProps } from "react-router-dom";
import ErrorPage from "./ErrorPage";
import { WithTranslation, withTranslation } from "react-i18next";
import { compose } from "redux";
import { connect } from "react-redux";
type Props = {
type ExportedProps = {
fallback?: React.ComponentType<any>;
children: ReactNode;
loginLink?: string;
};
type Props = WithTranslation & RouteComponentProps & ExportedProps;
type ErrorInfo = {
componentStack: string;
};
@@ -44,16 +54,44 @@ class ErrorBoundary extends React.Component<Props, State> {
this.state = {};
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
// Catch errors in any components below and re-render with error message
this.setState({
error,
errorInfo
});
componentDidUpdate(prevProps: Readonly<Props>) {
// we must reset the error if the url has changed
if (this.state.error && prevProps.location !== this.props.location) {
this.setState({ error: undefined, errorInfo: undefined });
}
}
componentDidCatch(error: Error, errorInfo: ErrorInfo) {
this.setState(
{
error,
errorInfo
},
() => this.redirectToLogin(error)
);
}
redirectToLogin = (error: Error) => {
const { loginLink } = this.props;
if (error instanceof MissingLinkError) {
if (loginLink) {
window.location.assign(withContextPath("/login"));
}
}
};
renderError = () => {
const { t } = this.props;
const { error } = this.state;
let FallbackComponent = this.props.fallback;
if (error instanceof MissingLinkError) {
return (
<ErrorPage error={error} title={t("errorNotification.prefix")} subtitle={t("errorNotification.forbidden")} />
);
}
if (!FallbackComponent) {
FallbackComponent = ErrorNotification;
}
@@ -69,4 +107,17 @@ class ErrorBoundary extends React.Component<Props, State> {
return this.props.children;
}
}
export default ErrorBoundary;
const mapStateToProps = (state: any) => {
const loginLink = state.indexResources?.links?.login?.href;
return {
loginLink
};
};
export default compose<ComponentType<ExportedProps>>(
withRouter,
withTranslation("commons"),
connect(mapStateToProps)
)(ErrorBoundary);

View File

@@ -22,7 +22,7 @@
* SOFTWARE.
*/
import React, { Component } from "react";
import { Route, Redirect, withRouter, RouteComponentProps, RouteProps } from "react-router-dom";
import { Redirect, Route, RouteComponentProps, RouteProps, withRouter } from "react-router-dom";
type Props = RouteComponentProps &
RouteProps & {
@@ -30,7 +30,16 @@ type Props = RouteComponentProps &
};
class ProtectedRoute extends Component<Props> {
renderRoute = (Component: any, authenticated?: boolean) => {
constructor(props: Props) {
super(props);
this.state = {
error: undefined
};
}
renderRoute = (Component: any) => {
const { authenticated } = this.props;
return (routeProps: any) => {
if (authenticated) {
return <Component {...routeProps} />;
@@ -50,8 +59,8 @@ class ProtectedRoute extends Component<Props> {
};
render() {
const { component, authenticated, ...routeProps } = this.props;
return <Route {...routeProps} render={this.renderRoute(component, authenticated)} />;
const { component, ...routeProps } = this.props;
return <Route {...routeProps} render={this.renderRoute(component)} />;
}
}

View File

@@ -89,6 +89,10 @@ export class ConflictError extends BackendError {
}
}
export class MissingLinkError extends Error {
name = "MissingLinkError";
}
export function createBackendError(content: BackendErrorContent, statusCode: number) {
switch (statusCode) {
case 404: