Skip to content

Commit

Permalink
Fix and improve error management
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexisSouquiere committed Nov 30, 2023
1 parent 56a042f commit 403c33a
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 30 deletions.
19 changes: 1 addition & 18 deletions client/src/App.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,15 @@
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import { basePath, uriLogin } from './utils/endpoints';
import { basePath } from './utils/endpoints';
import Routes from './utils/Routes';
import { MuiPickersUtilsProvider } from '@material-ui/pickers';
import MomentUtils from '@date-io/moment';
import { ToastContainer } from 'react-toastify';
import { loadProgressBar } from 'axios-progress-bar';
import axios from 'axios';

class App extends React.Component {
componentDidMount() {
loadProgressBar();

axios.interceptors.response.use(null, error => {
try {
// Used for token expiration by redirecting on login page
if (error.response.status === 401) {
window.location = uriLogin();
}

return Promise.reject(error);
} catch (e) {
// Propagate cancel
if (axios.isCancel(error)) {
throw new axios.Cancel('Operation canceled by the user.');
}
}
});
}

render() {
Expand Down
1 change: 0 additions & 1 deletion client/src/components/Root/Root.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ class Root extends Component {
buildConfig() {
let config = new Map();
config.cancelToken = this.cancel.token;
config.validateStatus = () => true;

if (localStorage.getItem('jwtToken')) {
config.headers = {};
Expand Down
5 changes: 5 additions & 0 deletions client/src/containers/Login/Login.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ class Login extends Form {
pathname: '/ui'
});
}

if (localStorage.getItem('toastMessage')) {
toast.warn(localStorage.getItem('toastMessage'));
localStorage.removeItem('toastMessage');
}
}

_renderForm() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ class TopicIncreasePartition extends Form {
partition: formData.partition
};

this.postApi(uriTopicIncreasePartition(selectedCluster, selectedTopic), partitionData)
.then(() => {
this.postApi(uriTopicIncreasePartition(selectedCluster, selectedTopic), partitionData).then(
() => {
this.props.history.push({
pathname: `/ui/${selectedCluster}/topic`
});
toast.success('Topic partition updated');
})
.catch(error => toast.error(error.data.message));
}
);
}
render() {
return (
Expand Down
12 changes: 6 additions & 6 deletions client/src/utils/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ const handleError = err => {
};

if (err.response && err.response.status < 500) {
toast.warn(error.message);
if (err.status === 401) {
history.replace('/ui/login');
if (err.response.status === 401 || err.response.status === 403) {
localStorage.setItem('toastMessage', error.message);
history.push('/ui/login');
history.go(0);
} else {
toast.warn(error.message);
}

return error;
Expand Down Expand Up @@ -79,9 +82,6 @@ export const post = (url, body, config) =>
axios
.post(url, body, { ...configs, ...config })
.then(res => {
if (res.status >= 400) {
reject(res);
}
resolve(res);
})
.catch(err => {
Expand Down
19 changes: 18 additions & 1 deletion src/main/java/org/akhq/controllers/ErrorController.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import io.confluent.kafka.schemaregistry.client.rest.exceptions.RestClientException;
import io.micrometer.core.instrument.util.StringUtils;
import io.micronaut.core.annotation.AnnotationValue;
import io.micronaut.http.HttpAttributes;
import io.micronaut.http.HttpRequest;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.HttpStatus;
Expand All @@ -12,8 +14,10 @@
import io.micronaut.security.annotation.Secured;
import io.micronaut.security.authentication.AuthorizationException;
import io.micronaut.security.rules.SecurityRule;
import io.micronaut.web.router.UriRouteMatch;
import lombok.extern.slf4j.Slf4j;
import org.akhq.modules.InvalidClusterException;
import org.akhq.security.annotation.AKHQSecured;
import org.apache.kafka.common.errors.ApiException;
import org.sourcelab.kafka.connect.apiclient.rest.exceptions.ConcurrentConfigModificationException;
import org.sourcelab.kafka.connect.apiclient.rest.exceptions.InvalidRequestException;
Expand Down Expand Up @@ -79,7 +83,20 @@ private HttpResponse<?> renderExecption(HttpRequest<?> request, Exception e) {
@Error(global = true)
public HttpResponse<?> error(HttpRequest<?> request, AuthorizationException e) throws URISyntaxException {
if (request.getUri().toString().startsWith("/api")) {
return HttpResponse.unauthorized().body(new JsonError("Unauthorized"));
if (e.isForbidden()) {
if (request.getAttribute(HttpAttributes.ROUTE_INFO).isPresent() &&
((UriRouteMatch<?, ?>) request.getAttribute(HttpAttributes.ROUTE_INFO).get()).hasAnnotation(AKHQSecured.class)) {
AnnotationValue<AKHQSecured> annotation =
((UriRouteMatch<?, ?>) request.getAttribute(HttpAttributes.ROUTE_INFO).get()).getAnnotation(AKHQSecured.class);

return HttpResponse.status(HttpStatus.FORBIDDEN)
.body(new JsonError(String.format("Unauthorized: missing permission on resource %s and action %s",
annotation.getValues().get("resource"),
annotation.getValues().get("action"))));
}
} else {
return HttpResponse.unauthorized().body(new JsonError("User not authenticated or token expired"));
}
}

return HttpResponse.temporaryRedirect(this.uri("/ui/login"));
Expand Down

0 comments on commit 403c33a

Please sign in to comment.