Improve error response to the client. Added errorType so that client can handle better than depending on the http status codes (#14784)

This commit is contained in:
Sriharsha Chintalapani 2024-01-21 08:07:07 -08:00 committed by GitHub
parent 62d1ef7c7d
commit 15eb094cff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 297 additions and 133 deletions

View File

@ -130,11 +130,11 @@ public class AirflowRESTClient extends PipelineServiceClient {
} }
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException e) {
throw IngestionPipelineDeploymentException.byMessage( throw IngestionPipelineDeploymentException.byMessage(
ingestionPipeline.getName(), e.getMessage()); ingestionPipeline.getName(), DEPLOYEMENT_ERROR, e.getMessage());
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
throw IngestionPipelineDeploymentException.byMessage( throw IngestionPipelineDeploymentException.byMessage(
ingestionPipeline.getName(), e.getMessage()); ingestionPipeline.getName(), DEPLOYEMENT_ERROR, e.getMessage());
} }
throw new PipelineServiceClientException( throw new PipelineServiceClientException(
String.format( String.format(
@ -181,14 +181,17 @@ public class AirflowRESTClient extends PipelineServiceClient {
return getResponse(200, response.body()); return getResponse(200, response.body());
} }
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException e) {
throw IngestionPipelineDeploymentException.byMessage(pipelineName, e.getMessage()); throw IngestionPipelineDeploymentException.byMessage(
pipelineName, TRIGGER_ERROR, e.getMessage());
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
throw IngestionPipelineDeploymentException.byMessage(pipelineName, e.getMessage()); throw IngestionPipelineDeploymentException.byMessage(
pipelineName, TRIGGER_ERROR, e.getMessage());
} }
throw IngestionPipelineDeploymentException.byMessage( throw IngestionPipelineDeploymentException.byMessage(
pipelineName, pipelineName,
TRIGGER_ERROR,
"Failed to trigger IngestionPipeline", "Failed to trigger IngestionPipeline",
Response.Status.fromStatusCode(response.statusCode())); Response.Status.fromStatusCode(response.statusCode()));
} }
@ -318,10 +321,12 @@ public class AirflowRESTClient extends PipelineServiceClient {
return getResponse(200, response.body()); return getResponse(200, response.body());
} }
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException e) {
throw IngestionPipelineDeploymentException.byMessage(workflow.getName(), e.getMessage()); throw IngestionPipelineDeploymentException.byMessage(
workflow.getName(), TRIGGER_ERROR, e.getMessage());
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
throw IngestionPipelineDeploymentException.byMessage(workflow.getName(), e.getMessage()); throw IngestionPipelineDeploymentException.byMessage(
workflow.getName(), TRIGGER_ERROR, e.getMessage());
} }
throw new PipelineServiceClientException( throw new PipelineServiceClientException(
String.format( String.format(
@ -354,10 +359,12 @@ public class AirflowRESTClient extends PipelineServiceClient {
return getResponse(200, response.body()); return getResponse(200, response.body());
} }
} catch (IOException | URISyntaxException e) { } catch (IOException | URISyntaxException e) {
throw IngestionPipelineDeploymentException.byMessage(workflowPayload, e.getMessage()); throw IngestionPipelineDeploymentException.byMessage(
workflowPayload, DEPLOYEMENT_ERROR, e.getMessage());
} catch (InterruptedException e) { } catch (InterruptedException e) {
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
throw IngestionPipelineDeploymentException.byMessage(workflowPayload, e.getMessage()); throw IngestionPipelineDeploymentException.byMessage(
workflowPayload, DEPLOYEMENT_ERROR, e.getMessage());
} }
throw new PipelineServiceClientException( throw new PipelineServiceClientException(
String.format( String.format(

View File

@ -18,9 +18,10 @@ import org.openmetadata.sdk.exception.WebServiceException;
public final class BadRequestException extends WebServiceException { public final class BadRequestException extends WebServiceException {
private static final String DEFAULT_MESSAGE = "Bad request."; private static final String DEFAULT_MESSAGE = "Bad request.";
private static final String ERROR_TYPE = "BAD_REQUEST";
private BadRequestException() { private BadRequestException() {
super(Response.Status.BAD_REQUEST, DEFAULT_MESSAGE); super(Response.Status.BAD_REQUEST, ERROR_TYPE, DEFAULT_MESSAGE);
} }
public static BadRequestException of() { public static BadRequestException of() {

View File

@ -28,14 +28,22 @@ import org.openmetadata.service.resources.feeds.MessageParser.EntityLink;
import org.openmetadata.service.util.JsonUtils; import org.openmetadata.service.util.JsonUtils;
public final class CatalogExceptionMessage { public final class CatalogExceptionMessage {
public static final String FAILED_SEND_EMAIL = "FAILED_SEND_EMAIL";
public static final String EMAIL_SENDING_ISSUE = public static final String EMAIL_SENDING_ISSUE =
"There is some issue in sending the Mail. Please contact your administrator."; "There is some issue in sending the Mail. Please contact your administrator.";
public static final String PASSWORD_INVALID_FORMAT = public static final String PASSWORD_INVALID_FORMAT =
"Password must be of minimum 8 characters, with one special, one Upper, one lower case character, and one Digit."; "Password must be of minimum 8 characters, with one special, one Upper, one lower case character, and one Digit.";
public static final String MAX_FAILED_LOGIN_ATTEMPT = public static final String MAX_FAILED_LOGIN_ATTEMPT =
"Failed Login Attempts Exceeded. Please try after some time."; "Failed Login Attempts Exceeded. Please try after some time.";
public static final String INCORRECT_OLD_PASSWORD = "INCORRECT_OLD_PASSWORD";
public static final String INVALID_USER_OR_PASSWORD = "INVALID_USER_OR_PASSWORD";
public static final String INVALID_USERNAME_PASSWORD = public static final String INVALID_USERNAME_PASSWORD =
"You have entered an invalid username or password."; "You have entered an invalid username or password.";
public static final String PASSWORD_RESET_TOKEN_EXPIRED = "PASSWORD_RESET_TOKEN_EXPIRED";
public static final String ENTITY_ALREADY_EXISTS = "Entity already exists"; public static final String ENTITY_ALREADY_EXISTS = "Entity already exists";
public static final String FERNET_KEY_NULL = "Fernet key is null"; public static final String FERNET_KEY_NULL = "Fernet key is null";
public static final String FIELD_NOT_TOKENIZED = "Field is not tokenized"; public static final String FIELD_NOT_TOKENIZED = "Field is not tokenized";
@ -62,17 +70,26 @@ public final class CatalogExceptionMessage {
"Unexpected error occurred while building the teams hierarchy"; "Unexpected error occurred while building the teams hierarchy";
public static final String LDAP_MISSING_ATTR = public static final String LDAP_MISSING_ATTR =
"Username or Email Attribute is incorrect. Please check Openmetadata Configuration."; "Username or Email Attribute is incorrect. Please check Openmetadata Configuration.";
public static final String MULTIPLE_EMAIL_ENTRIES_ERROR = "MULTIPLE_EMAIL_ENTRIES_ERROR";
public static final String MULTIPLE_EMAIL_ENTRIES = public static final String MULTIPLE_EMAIL_ENTRIES =
"Email corresponds to multiple entries in Directory."; "Email corresponds to multiple entries in Directory.";
public static final String INVALID_EMAIL_PASSWORD = public static final String INVALID_EMAIL_PASSWORD =
"You have entered an invalid email or password."; "You have entered an invalid email or password.";
public static final String EMAIL_EXISTS = "EMAIL_EXISTS";
public static final String SELF_SIGNUP_NOT_ENABLED = "SELF_SIGNUP_NOT_ENABLED";
public static final String SELF_SIGNUP_ERROR = "Signup is not supported."; public static final String SELF_SIGNUP_ERROR = "Signup is not supported.";
public static final String NOT_IMPLEMENTED_METHOD = "Method not implemented."; public static final String NOT_IMPLEMENTED_METHOD = "Method not implemented.";
public static final String AUTHENTICATOR_OPERATION_NOT_SUPPORTED =
"AUTHENTICATOR_OPERATION_NOT_SUPPORTED";
public static final String FORBIDDEN_AUTHENTICATOR_OP = public static final String FORBIDDEN_AUTHENTICATOR_OP =
"Operation is not permitted with the Selected Authenticator."; "Operation is not permitted with the Selected Authenticator.";
public static final String INVALID_TOKEN = "INVALID_TOKEN";
public static final String TOKEN_EXPIRED = "TOKEN_EXPIRED";
public static final String TOKEN_EXPIRY_ERROR = public static final String TOKEN_EXPIRY_ERROR =
"Email Verification Token %s is expired. Please issue a new request for email verification."; "Email Verification Token %s is expired. Please issue a new request for email verification.";
public static final String INVALID_BOT_USER = "Revoke Token can only be applied to Bot Users."; public static final String INVALID_BOT_USER = "Revoke Token can only be applied to Bot Users.";

View File

@ -4,11 +4,11 @@ import javax.ws.rs.core.Response;
import org.openmetadata.sdk.exception.WebServiceException; import org.openmetadata.sdk.exception.WebServiceException;
public class CustomExceptionMessage extends WebServiceException { public class CustomExceptionMessage extends WebServiceException {
public CustomExceptionMessage(Response.Status status, String message) { public CustomExceptionMessage(Response.Status status, String errorType, String message) {
super(status.getStatusCode(), message); super(status.getStatusCode(), errorType, message);
} }
public CustomExceptionMessage(int status, String message) { public CustomExceptionMessage(int status, String errorType, String message) {
super(status, message); super(status, errorType, message);
} }
} }

View File

@ -17,8 +17,9 @@ import javax.ws.rs.core.Response;
import org.openmetadata.sdk.exception.WebServiceException; import org.openmetadata.sdk.exception.WebServiceException;
public class EntityMaskException extends WebServiceException { public class EntityMaskException extends WebServiceException {
private static final String ERROR_TYPE = "ENTITY_MASK_ERROR";
public EntityMaskException(String message) { public EntityMaskException(String message) {
super(Response.Status.INTERNAL_SERVER_ERROR, message); super(Response.Status.INTERNAL_SERVER_ERROR, ERROR_TYPE, message);
} }
} }

View File

@ -25,12 +25,14 @@ public class EntityNotFoundException extends WebServiceException {
private static final String BY_PARSER_SCHEMA_MESSAGE = private static final String BY_PARSER_SCHEMA_MESSAGE =
"Parser schema not found for entity with id [%s]."; "Parser schema not found for entity with id [%s].";
private static final String ERROR_TYPE = "ENTITY_NOT_FOUND";
public EntityNotFoundException(String message) { public EntityNotFoundException(String message) {
super(Response.Status.NOT_FOUND, message); super(Response.Status.NOT_FOUND, ERROR_TYPE, message);
} }
private EntityNotFoundException(String message, Throwable cause) { private EntityNotFoundException(String message, Throwable cause) {
super(Response.Status.NOT_FOUND, message, cause); super(Response.Status.NOT_FOUND, ERROR_TYPE, message, cause);
} }
public static EntityNotFoundException byId(String id) { public static EntityNotFoundException byId(String id) {

View File

@ -5,13 +5,14 @@ import org.openmetadata.schema.tests.type.TestCaseResolutionStatusTypes;
import org.openmetadata.sdk.exception.WebServiceException; import org.openmetadata.sdk.exception.WebServiceException;
public class IncidentManagerException extends WebServiceException { public class IncidentManagerException extends WebServiceException {
private static final String ERROR_TYPE = "INCIDENT_INVALID_STATUS";
protected IncidentManagerException(Response.Status status, String message) { protected IncidentManagerException(Response.Status status, String message) {
super(status.getStatusCode(), message); super(status.getStatusCode(), ERROR_TYPE, message);
} }
public IncidentManagerException(String message) { public IncidentManagerException(String message) {
super(Response.Status.INTERNAL_SERVER_ERROR, message); super(Response.Status.INTERNAL_SERVER_ERROR, ERROR_TYPE, message);
} }
public static IncidentManagerException invalidStatus( public static IncidentManagerException invalidStatus(

View File

@ -19,23 +19,27 @@ import org.openmetadata.sdk.exception.WebServiceException;
public class IngestionPipelineDeploymentException extends WebServiceException { public class IngestionPipelineDeploymentException extends WebServiceException {
private static final String BY_NAME_MESSAGE = "Failed to deploy pipeline [%s] due to [%s]."; private static final String BY_NAME_MESSAGE = "Failed to deploy pipeline [%s] due to [%s].";
private static final String ERROR_TYPE = "DEPLOYMENT_ERROR";
public IngestionPipelineDeploymentException(String message) { public IngestionPipelineDeploymentException(String message) {
super(Response.Status.BAD_REQUEST, message); super(Response.Status.BAD_REQUEST, ERROR_TYPE, message);
} }
private IngestionPipelineDeploymentException(Response.Status status, String message) { private IngestionPipelineDeploymentException(
super(status, message); Response.Status status, String errorType, String message) {
super(status, errorType, message);
} }
public static IngestionPipelineDeploymentException byMessage( public static IngestionPipelineDeploymentException byMessage(
String name, String errorMessage, Response.Status status) { String name, String errorType, String errorMessage, Response.Status status) {
return new IngestionPipelineDeploymentException(status, buildMessageByName(name, errorMessage)); return new IngestionPipelineDeploymentException(
status, errorType, buildMessageByName(name, errorMessage));
} }
public static IngestionPipelineDeploymentException byMessage(String name, String errorMessage) { public static IngestionPipelineDeploymentException byMessage(
String name, String errorType, String errorMessage) {
return new IngestionPipelineDeploymentException( return new IngestionPipelineDeploymentException(
Response.Status.BAD_REQUEST, buildMessageByName(name, errorMessage)); Response.Status.BAD_REQUEST, errorType, buildMessageByName(name, errorMessage));
} }
public static String buildMessageByName(String name, String errorMessage) { public static String buildMessageByName(String name, String errorMessage) {

View File

@ -6,13 +6,14 @@ import org.openmetadata.sdk.exception.WebServiceException;
public class InvalidServiceConnectionException extends WebServiceException { public class InvalidServiceConnectionException extends WebServiceException {
private static final String BY_NAME_MESSAGE = private static final String BY_NAME_MESSAGE =
"InvalidServiceConnectionException for service [%s] due to [%s]."; "InvalidServiceConnectionException for service [%s] due to [%s].";
private static final String ERROR_TYPE = "INVALID_SERVICE_EXCEPTION";
public InvalidServiceConnectionException(String message) { public InvalidServiceConnectionException(String message) {
super(Response.Status.BAD_REQUEST, message); super(Response.Status.BAD_REQUEST, ERROR_TYPE, message);
} }
private InvalidServiceConnectionException(Response.Status status, String message) { private InvalidServiceConnectionException(Response.Status status, String message) {
super(status, message); super(status, ERROR_TYPE, message);
} }
public static InvalidServiceConnectionException byMessage( public static InvalidServiceConnectionException byMessage(

View File

@ -1,32 +0,0 @@
package org.openmetadata.service.exception;
import javax.ws.rs.core.Response;
import org.openmetadata.sdk.exception.WebServiceException;
public class OpenMetadataClientSecurityConfigException extends WebServiceException {
private static final String BY_NAME_MESSAGE = "Airflow Exception [%s] due to [%s].";
public OpenMetadataClientSecurityConfigException(String message) {
super(Response.Status.BAD_REQUEST, message);
}
private OpenMetadataClientSecurityConfigException(Response.Status status, String message) {
super(status, message);
}
public static OpenMetadataClientSecurityConfigException byMessage(
String name, String errorMessage, Response.Status status) {
return new OpenMetadataClientSecurityConfigException(
status, buildMessageByName(name, errorMessage));
}
public static OpenMetadataClientSecurityConfigException byMessage(
String name, String errorMessage) {
return new OpenMetadataClientSecurityConfigException(
Response.Status.BAD_REQUEST, buildMessageByName(name, errorMessage));
}
private static String buildMessageByName(String name, String errorMessage) {
return String.format(BY_NAME_MESSAGE, name, errorMessage);
}
}

View File

@ -18,7 +18,9 @@ import org.openmetadata.sdk.exception.WebServiceException;
public class ReflectionException extends WebServiceException { public class ReflectionException extends WebServiceException {
public static final String REFLECTION_ERROR = "REFLECTION_ERROR";
public ReflectionException(String message) { public ReflectionException(String message) {
super(Response.Status.INTERNAL_SERVER_ERROR, message); super(Response.Status.INTERNAL_SERVER_ERROR, REFLECTION_ERROR, message);
} }
} }

View File

@ -20,12 +20,14 @@ public class SecretsManagerException extends WebServiceException {
private static final String BY_NAME_MESSAGE = private static final String BY_NAME_MESSAGE =
"SecretsManagerException for secret manager [%s] when using the secret name [%s] due to [%s]."; "SecretsManagerException for secret manager [%s] when using the secret name [%s] due to [%s].";
public static final String SECRETS_MANAGER_ERROR = "SECRETS_MANAGER_ERROR";
public SecretsManagerException(String message) { public SecretsManagerException(String message) {
super(Response.Status.INTERNAL_SERVER_ERROR, message); super(Response.Status.INTERNAL_SERVER_ERROR, SECRETS_MANAGER_ERROR, message);
} }
public SecretsManagerException(Response.Status status, String message) { public SecretsManagerException(Response.Status status, String message) {
super(status.getStatusCode(), message); super(status.getStatusCode(), SECRETS_MANAGER_ERROR, message);
} }
public static SecretsManagerException byMessage( public static SecretsManagerException byMessage(

View File

@ -20,11 +20,20 @@ public class UnhandledServerException extends WebServiceException {
private static final String MESSAGE = private static final String MESSAGE =
"An exception with message [%s] was thrown while processing request."; "An exception with message [%s] was thrown while processing request.";
public static final String UNHANDLED_ERROR = "REFLECTION_ERROR";
public UnhandledServerException(String exceptionMessage) { public UnhandledServerException(String exceptionMessage) {
super(Response.Status.INTERNAL_SERVER_ERROR, String.format(MESSAGE, exceptionMessage)); super(
Response.Status.INTERNAL_SERVER_ERROR,
UNHANDLED_ERROR,
String.format(MESSAGE, exceptionMessage));
} }
public UnhandledServerException(String exceptionMessage, Throwable cause) { public UnhandledServerException(String exceptionMessage, Throwable cause) {
super(Response.Status.INTERNAL_SERVER_ERROR, String.format(MESSAGE, exceptionMessage), cause); super(
Response.Status.INTERNAL_SERVER_ERROR,
UNHANDLED_ERROR,
String.format(MESSAGE, exceptionMessage),
cause);
} }
} }

View File

@ -171,7 +171,10 @@ public class SystemRepository {
SettingsCache.invalidateSettings(setting.getConfigType().value()); SettingsCache.invalidateSettings(setting.getConfigType().value());
} catch (Exception ex) { } catch (Exception ex) {
LOG.error("Failing in Updating Setting.", ex); LOG.error("Failing in Updating Setting.", ex);
throw new CustomExceptionMessage(Response.Status.INTERNAL_SERVER_ERROR, ex.getMessage()); throw new CustomExceptionMessage(
Response.Status.INTERNAL_SERVER_ERROR,
"FAILED_TO_UPDATE_SLACK_OR_EMAIL",
ex.getMessage());
} }
} }

View File

@ -1272,7 +1272,8 @@ public class UserResource extends EntityResource<User, UserRepository> {
UserTokenCache.invalidateToken(user.getName()); UserTokenCache.invalidateToken(user.getName());
return Response.status(Response.Status.OK).entity(personalAccessToken).build(); return Response.status(Response.Status.OK).entity(personalAccessToken).build();
} }
throw new CustomExceptionMessage(BAD_REQUEST, "Bots cannot have a Personal Access Token."); throw new CustomExceptionMessage(
BAD_REQUEST, "NO_PERSONAL_TOKEN_FOR_BOTS", "Bots cannot have a Personal Access Token.");
} }
@GET @GET
@ -1371,7 +1372,8 @@ public class UserResource extends EntityResource<User, UserRepository> {
public void validateEmailAlreadyExists(String email) { public void validateEmailAlreadyExists(String email) {
if (repository.checkEmailAlreadyExists(email)) { if (repository.checkEmailAlreadyExists(email)) {
throw new CustomExceptionMessage(BAD_REQUEST, "User with Email Already Exists"); throw new CustomExceptionMessage(
BAD_REQUEST, "EMAIL_EXISTS", "User with Email Already Exists");
} }
} }

View File

@ -54,6 +54,8 @@ public interface SearchClient {
String REMOVE_TEST_SUITE_CHILDREN_SCRIPT = String REMOVE_TEST_SUITE_CHILDREN_SCRIPT =
"for (int i = 0; i < ctx._source.testSuites.length; i++) { if (ctx._source.testSuites[i].id == '%s') { ctx._source.testSuites.remove(i) }}"; "for (int i = 0; i < ctx._source.testSuites.length; i++) { if (ctx._source.testSuites[i].id == '%s') { ctx._source.testSuites.remove(i) }}";
String NOT_IMPLEMENTED_ERROR_TYPE = "NOT_IMPLEMENTED";
boolean isClientAvailable(); boolean isClientAvailable();
ElasticSearchConfiguration.SearchType getSearchType(); ElasticSearchConfiguration.SearchType getSearchType();
@ -128,22 +130,26 @@ public interface SearchClient {
throws IOException, ParseException; throws IOException, ParseException;
default BulkResponse bulk(BulkRequest data, RequestOptions options) throws IOException { default BulkResponse bulk(BulkRequest data, RequestOptions options) throws IOException {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
default es.org.elasticsearch.action.bulk.BulkResponse bulk( default es.org.elasticsearch.action.bulk.BulkResponse bulk(
es.org.elasticsearch.action.bulk.BulkRequest data, es.org.elasticsearch.action.bulk.BulkRequest data,
es.org.elasticsearch.client.RequestOptions options) es.org.elasticsearch.client.RequestOptions options)
throws IOException { throws IOException {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
default int getSuccessFromBulkResponse(BulkResponse response) { default int getSuccessFromBulkResponse(BulkResponse response) {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
default int getSuccessFromBulkResponse(es.org.elasticsearch.action.bulk.BulkResponse response) { default int getSuccessFromBulkResponse(es.org.elasticsearch.action.bulk.BulkResponse response) {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
void close(); void close();

View File

@ -22,6 +22,7 @@ import static org.openmetadata.service.search.EntityBuilderConstant.UNIFIED;
import static org.openmetadata.service.search.UpdateSearchEventsConstant.SENDING_REQUEST_TO_ELASTIC_SEARCH; import static org.openmetadata.service.search.UpdateSearchEventsConstant.SENDING_REQUEST_TO_ELASTIC_SEARCH;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import es.org.elasticsearch.ElasticsearchStatusException;
import es.org.elasticsearch.action.ActionListener; import es.org.elasticsearch.action.ActionListener;
import es.org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest; import es.org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
import es.org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import es.org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
@ -65,6 +66,7 @@ import es.org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import es.org.elasticsearch.index.reindex.BulkByScrollResponse; import es.org.elasticsearch.index.reindex.BulkByScrollResponse;
import es.org.elasticsearch.index.reindex.DeleteByQueryRequest; import es.org.elasticsearch.index.reindex.DeleteByQueryRequest;
import es.org.elasticsearch.index.reindex.UpdateByQueryRequest; import es.org.elasticsearch.index.reindex.UpdateByQueryRequest;
import es.org.elasticsearch.rest.RestStatus;
import es.org.elasticsearch.script.Script; import es.org.elasticsearch.script.Script;
import es.org.elasticsearch.script.ScriptType; import es.org.elasticsearch.script.ScriptType;
import es.org.elasticsearch.search.SearchModule; import es.org.elasticsearch.search.SearchModule;
@ -115,6 +117,8 @@ import org.openmetadata.common.utils.CommonUtil;
import org.openmetadata.schema.DataInsightInterface; import org.openmetadata.schema.DataInsightInterface;
import org.openmetadata.schema.dataInsight.DataInsightChartResult; import org.openmetadata.schema.dataInsight.DataInsightChartResult;
import org.openmetadata.schema.service.configuration.elasticsearch.ElasticSearchConfiguration; import org.openmetadata.schema.service.configuration.elasticsearch.ElasticSearchConfiguration;
import org.openmetadata.sdk.exception.SearchException;
import org.openmetadata.sdk.exception.SearchIndexNotFoundException;
import org.openmetadata.service.Entity; import org.openmetadata.service.Entity;
import org.openmetadata.service.dataInsight.DataInsightAggregatorInterface; import org.openmetadata.service.dataInsight.DataInsightAggregatorInterface;
import org.openmetadata.service.jdbi3.DataInsightChartRepository; import org.openmetadata.service.jdbi3.DataInsightChartRepository;
@ -422,14 +426,23 @@ public class ElasticSearchClient implements SearchClient {
} }
searchSourceBuilder.timeout(new TimeValue(30, TimeUnit.SECONDS)); searchSourceBuilder.timeout(new TimeValue(30, TimeUnit.SECONDS));
String response = try {
client String response =
.search( client
new es.org.elasticsearch.action.search.SearchRequest(request.getIndex()) .search(
.source(searchSourceBuilder), new es.org.elasticsearch.action.search.SearchRequest(request.getIndex())
RequestOptions.DEFAULT) .source(searchSourceBuilder),
.toString(); RequestOptions.DEFAULT)
return Response.status(OK).entity(response).build(); .toString();
return Response.status(OK).entity(response).build();
} catch (ElasticsearchStatusException e) {
if (e.status() == RestStatus.NOT_FOUND) {
throw new SearchIndexNotFoundException(
String.format("Failed to to find index %s", request.getIndex()));
} else {
throw new SearchException(String.format("Search failed due to %s", e.getMessage()));
}
}
} }
@Override @Override

View File

@ -22,6 +22,7 @@ import static org.openmetadata.service.search.EntityBuilderConstant.UNIFIED;
import static org.openmetadata.service.search.UpdateSearchEventsConstant.SENDING_REQUEST_TO_ELASTIC_SEARCH; import static org.openmetadata.service.search.UpdateSearchEventsConstant.SENDING_REQUEST_TO_ELASTIC_SEARCH;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import es.org.elasticsearch.index.IndexNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.text.ParseException; import java.text.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
@ -48,6 +49,7 @@ import org.openmetadata.common.utils.CommonUtil;
import org.openmetadata.schema.DataInsightInterface; import org.openmetadata.schema.DataInsightInterface;
import org.openmetadata.schema.dataInsight.DataInsightChartResult; import org.openmetadata.schema.dataInsight.DataInsightChartResult;
import org.openmetadata.schema.service.configuration.elasticsearch.ElasticSearchConfiguration; import org.openmetadata.schema.service.configuration.elasticsearch.ElasticSearchConfiguration;
import org.openmetadata.sdk.exception.SearchIndexNotFoundException;
import org.openmetadata.service.Entity; import org.openmetadata.service.Entity;
import org.openmetadata.service.dataInsight.DataInsightAggregatorInterface; import org.openmetadata.service.dataInsight.DataInsightAggregatorInterface;
import org.openmetadata.service.jdbi3.DataInsightChartRepository; import org.openmetadata.service.jdbi3.DataInsightChartRepository;
@ -418,14 +420,19 @@ public class OpenSearchClient implements SearchClient {
} }
searchSourceBuilder.timeout(new TimeValue(30, TimeUnit.SECONDS)); searchSourceBuilder.timeout(new TimeValue(30, TimeUnit.SECONDS));
String response = try {
client String response =
.search( client
new os.org.opensearch.action.search.SearchRequest(request.getIndex()) .search(
.source(searchSourceBuilder), new os.org.opensearch.action.search.SearchRequest(request.getIndex())
RequestOptions.DEFAULT) .source(searchSourceBuilder),
.toString(); RequestOptions.DEFAULT)
return Response.status(OK).entity(response).build(); .toString();
return Response.status(OK).entity(response).build();
} catch (IndexNotFoundException e) {
throw new SearchIndexNotFoundException(
String.format("Failed to to find index %s", request.getIndex()));
}
} }
@Override @Override

View File

@ -23,6 +23,8 @@ import org.openmetadata.service.exception.CustomExceptionMessage;
import org.openmetadata.service.security.jwt.JWTTokenGenerator; import org.openmetadata.service.security.jwt.JWTTokenGenerator;
public interface AuthenticatorHandler { public interface AuthenticatorHandler {
String NOT_IMPLEMENTED_ERROR_TYPE = "NOT_IMPLEMENTED";
void init(OpenMetadataApplicationConfig config); void init(OpenMetadataApplicationConfig config);
JwtResponse loginUser(LoginRequest loginRequest) throws IOException, TemplateException; JwtResponse loginUser(LoginRequest loginRequest) throws IOException, TemplateException;
@ -38,42 +40,51 @@ public interface AuthenticatorHandler {
User lookUserInProvider(String userName); User lookUserInProvider(String userName);
default User registerUser(RegistrationRequest registrationRequest) { default User registerUser(RegistrationRequest registrationRequest) {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
default void sendEmailVerification(UriInfo uriInfo, User user) throws IOException { default void sendEmailVerification(UriInfo uriInfo, User user) throws IOException {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
default void confirmEmailRegistration(UriInfo uriInfo, String emailToken) { default void confirmEmailRegistration(UriInfo uriInfo, String emailToken) {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
default void resendRegistrationToken(UriInfo uriInfo, User registeredUser) throws IOException { default void resendRegistrationToken(UriInfo uriInfo, User registeredUser) throws IOException {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
default void sendPasswordResetLink( default void sendPasswordResetLink(
UriInfo uriInfo, User user, String subject, String templateFilePath) throws IOException { UriInfo uriInfo, User user, String subject, String templateFilePath) throws IOException {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
default void resetUserPasswordWithToken(UriInfo uriInfo, PasswordResetRequest req) default void resetUserPasswordWithToken(UriInfo uriInfo, PasswordResetRequest req)
throws IOException { throws IOException {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
default void changeUserPwdWithOldPwd(UriInfo uriInfo, String userName, ChangePasswordRequest req) default void changeUserPwdWithOldPwd(UriInfo uriInfo, String userName, ChangePasswordRequest req)
throws IOException { throws IOException {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
default RefreshToken createRefreshTokenForLogin(UUID currentUserId) { default RefreshToken createRefreshTokenForLogin(UUID currentUserId) {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
default JwtResponse getNewAccessToken(TokenRefreshRequest request) { default JwtResponse getNewAccessToken(TokenRefreshRequest request) {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
default void sendInviteMailToUser( default void sendInviteMailToUser(
@ -83,7 +94,8 @@ public interface AuthenticatorHandler {
CreateUser.CreatePasswordType requestType, CreateUser.CreatePasswordType requestType,
String pwd) String pwd)
throws IOException { throws IOException {
throw new CustomExceptionMessage(Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_METHOD); throw new CustomExceptionMessage(
Response.Status.NOT_IMPLEMENTED, NOT_IMPLEMENTED_ERROR_TYPE, NOT_IMPLEMENTED_METHOD);
} }
default JwtResponse getJwtResponse(User storedUser, long expireInSeconds) { default JwtResponse getJwtResponse(User storedUser, long expireInSeconds) {

View File

@ -22,10 +22,18 @@ import static org.openmetadata.schema.auth.ChangePasswordRequest.RequestType.USE
import static org.openmetadata.schema.auth.TokenType.EMAIL_VERIFICATION; import static org.openmetadata.schema.auth.TokenType.EMAIL_VERIFICATION;
import static org.openmetadata.schema.auth.TokenType.PASSWORD_RESET; import static org.openmetadata.schema.auth.TokenType.PASSWORD_RESET;
import static org.openmetadata.schema.entity.teams.AuthenticationMechanism.AuthType.BASIC; import static org.openmetadata.schema.entity.teams.AuthenticationMechanism.AuthType.BASIC;
import static org.openmetadata.service.exception.CatalogExceptionMessage.EMAIL_EXISTS;
import static org.openmetadata.service.exception.CatalogExceptionMessage.EMAIL_SENDING_ISSUE; import static org.openmetadata.service.exception.CatalogExceptionMessage.EMAIL_SENDING_ISSUE;
import static org.openmetadata.service.exception.CatalogExceptionMessage.FAILED_SEND_EMAIL;
import static org.openmetadata.service.exception.CatalogExceptionMessage.INCORRECT_OLD_PASSWORD;
import static org.openmetadata.service.exception.CatalogExceptionMessage.INVALID_TOKEN;
import static org.openmetadata.service.exception.CatalogExceptionMessage.INVALID_USERNAME_PASSWORD; import static org.openmetadata.service.exception.CatalogExceptionMessage.INVALID_USERNAME_PASSWORD;
import static org.openmetadata.service.exception.CatalogExceptionMessage.INVALID_USER_OR_PASSWORD;
import static org.openmetadata.service.exception.CatalogExceptionMessage.MAX_FAILED_LOGIN_ATTEMPT; import static org.openmetadata.service.exception.CatalogExceptionMessage.MAX_FAILED_LOGIN_ATTEMPT;
import static org.openmetadata.service.exception.CatalogExceptionMessage.PASSWORD_RESET_TOKEN_EXPIRED;
import static org.openmetadata.service.exception.CatalogExceptionMessage.SELF_SIGNUP_ERROR; import static org.openmetadata.service.exception.CatalogExceptionMessage.SELF_SIGNUP_ERROR;
import static org.openmetadata.service.exception.CatalogExceptionMessage.SELF_SIGNUP_NOT_ENABLED;
import static org.openmetadata.service.exception.CatalogExceptionMessage.TOKEN_EXPIRED;
import static org.openmetadata.service.exception.CatalogExceptionMessage.TOKEN_EXPIRY_ERROR; import static org.openmetadata.service.exception.CatalogExceptionMessage.TOKEN_EXPIRY_ERROR;
import static org.openmetadata.service.resources.teams.UserResource.USER_PROTECTED_FIELDS; import static org.openmetadata.service.resources.teams.UserResource.USER_PROTECTED_FIELDS;
import static org.openmetadata.service.util.EmailUtil.getSmtpSettings; import static org.openmetadata.service.util.EmailUtil.getSmtpSettings;
@ -126,7 +134,7 @@ public class BasicAuthenticator implements AuthenticatorHandler {
registeredUser.setAuthenticationMechanism(null); registeredUser.setAuthenticationMechanism(null);
return registeredUser; return registeredUser;
} else { } else {
throw new CustomExceptionMessage(NOT_IMPLEMENTED, SELF_SIGNUP_ERROR); throw new CustomExceptionMessage(NOT_IMPLEMENTED, SELF_SIGNUP_NOT_ENABLED, SELF_SIGNUP_ERROR);
} }
} }
@ -146,6 +154,7 @@ public class BasicAuthenticator implements AuthenticatorHandler {
if (emailVerificationToken.getExpiryDate().compareTo(Instant.now().toEpochMilli()) < 0) { if (emailVerificationToken.getExpiryDate().compareTo(Instant.now().toEpochMilli()) < 0) {
throw new CustomExceptionMessage( throw new CustomExceptionMessage(
INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR,
TOKEN_EXPIRED,
String.format(TOKEN_EXPIRY_ERROR, emailVerificationToken.getToken())); String.format(TOKEN_EXPIRY_ERROR, emailVerificationToken.getToken()));
} }
@ -180,7 +189,7 @@ public class BasicAuthenticator implements AuthenticatorHandler {
EmailUtil.sendEmailVerification(emailVerificationLink, user); EmailUtil.sendEmailVerification(emailVerificationLink, user);
} catch (TemplateException e) { } catch (TemplateException e) {
LOG.error("Error in sending mail to the User : {}", e.getMessage(), e); LOG.error("Error in sending mail to the User : {}", e.getMessage(), e);
throw new CustomExceptionMessage(424, EMAIL_SENDING_ISSUE); throw new CustomExceptionMessage(424, FAILED_SEND_EMAIL, EMAIL_SENDING_ISSUE);
} }
// insert the token // insert the token
tokenRepository.insertToken(emailVerificationToken); tokenRepository.insertToken(emailVerificationToken);
@ -204,7 +213,7 @@ public class BasicAuthenticator implements AuthenticatorHandler {
EmailUtil.sendPasswordResetLink(passwordResetLink, user, subject, templateFilePath); EmailUtil.sendPasswordResetLink(passwordResetLink, user, subject, templateFilePath);
} catch (TemplateException e) { } catch (TemplateException e) {
LOG.error("Error in sending mail to the User : {}", e.getMessage(), e); LOG.error("Error in sending mail to the User : {}", e.getMessage(), e);
throw new CustomExceptionMessage(424, EMAIL_SENDING_ISSUE); throw new CustomExceptionMessage(424, FAILED_SEND_EMAIL, EMAIL_SENDING_ISSUE);
} }
// don't persist tokens delete existing // don't persist tokens delete existing
tokenRepository.deleteTokenByUserAndType(user.getId(), PASSWORD_RESET.toString()); tokenRepository.deleteTokenByUserAndType(user.getId(), PASSWORD_RESET.toString());
@ -226,7 +235,7 @@ public class BasicAuthenticator implements AuthenticatorHandler {
new EntityUtil.Fields(fields, String.join(",", fields))); new EntityUtil.Fields(fields, String.join(",", fields)));
// token validity // token validity
if (!passwordResetToken.getUserId().equals(storedUser.getId())) { if (!passwordResetToken.getUserId().equals(storedUser.getId())) {
throw new CustomExceptionMessage(BAD_REQUEST, "Token does not belong to the user."); throw new CustomExceptionMessage(BAD_REQUEST, INVALID_TOKEN, "Invalid Token.");
} }
verifyPasswordResetTokenExpiry(passwordResetToken); verifyPasswordResetTokenExpiry(passwordResetToken);
// passwords validity // passwords validity
@ -252,7 +261,7 @@ public class BasicAuthenticator implements AuthenticatorHandler {
EmailUtil.sendAccountStatus(storedUser, "Update Password", "Change Successful"); EmailUtil.sendAccountStatus(storedUser, "Update Password", "Change Successful");
} catch (TemplateException ex) { } catch (TemplateException ex) {
LOG.error("Error in sending Password Change Mail to User. Reason : " + ex.getMessage(), ex); LOG.error("Error in sending Password Change Mail to User. Reason : " + ex.getMessage(), ex);
throw new CustomExceptionMessage(424, EMAIL_SENDING_ISSUE); throw new CustomExceptionMessage(424, FAILED_SEND_EMAIL, EMAIL_SENDING_ISSUE);
} }
loginAttemptCache.recordSuccessfulLogin(request.getUsername()); loginAttemptCache.recordSuccessfulLogin(request.getUsername());
} }
@ -291,7 +300,8 @@ public class BasicAuthenticator implements AuthenticatorHandler {
&& !BCrypt.verifyer() && !BCrypt.verifyer()
.verify(request.getOldPassword().toCharArray(), storedHashPassword) .verify(request.getOldPassword().toCharArray(), storedHashPassword)
.verified) { .verified) {
throw new CustomExceptionMessage(BAD_REQUEST, "Old Password is not correct"); throw new CustomExceptionMessage(
BAD_REQUEST, INCORRECT_OLD_PASSWORD, "Old Password is not correct");
} }
storedBasicAuthMechanism.setPassword(newHashedPassword); storedBasicAuthMechanism.setPassword(newHashedPassword);
@ -393,6 +403,7 @@ public class BasicAuthenticator implements AuthenticatorHandler {
if (token.getExpiryDate().compareTo(Instant.now().toEpochMilli()) < 0) { if (token.getExpiryDate().compareTo(Instant.now().toEpochMilli()) < 0) {
throw new CustomExceptionMessage( throw new CustomExceptionMessage(
INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR,
PASSWORD_RESET_TOKEN_EXPIRED,
String.format( String.format(
"Password Reset Token %s Expired token. Please issue a new request", "Password Reset Token %s Expired token. Please issue a new request",
token.getToken())); token.getToken()));
@ -400,6 +411,7 @@ public class BasicAuthenticator implements AuthenticatorHandler {
if (Boolean.FALSE.equals(token.getIsActive())) { if (Boolean.FALSE.equals(token.getIsActive())) {
throw new CustomExceptionMessage( throw new CustomExceptionMessage(
INTERNAL_SERVER_ERROR, INTERNAL_SERVER_ERROR,
PASSWORD_RESET_TOKEN_EXPIRED,
String.format("Password Reset Token %s Token was marked inactive", token.getToken())); String.format("Password Reset Token %s Token was marked inactive", token.getToken()));
} }
} }
@ -412,6 +424,7 @@ public class BasicAuthenticator implements AuthenticatorHandler {
if (storedRefreshToken.getExpiryDate().compareTo(Instant.now().toEpochMilli()) < 0) { if (storedRefreshToken.getExpiryDate().compareTo(Instant.now().toEpochMilli()) < 0) {
throw new CustomExceptionMessage( throw new CustomExceptionMessage(
BAD_REQUEST, BAD_REQUEST,
PASSWORD_RESET_TOKEN_EXPIRED,
"Expired token. Please login again : " + storedRefreshToken.getToken().toString()); "Expired token. Please login again : " + storedRefreshToken.getToken().toString());
} }
// TODO: currently allow single login from a place, later multiple login can be added // TODO: currently allow single login from a place, later multiple login can be added
@ -449,7 +462,7 @@ public class BasicAuthenticator implements AuthenticatorHandler {
public void validateEmailAlreadyExists(String email) { public void validateEmailAlreadyExists(String email) {
if (userRepository.checkEmailAlreadyExists(email)) { if (userRepository.checkEmailAlreadyExists(email)) {
throw new CustomExceptionMessage(BAD_REQUEST, "User with Email Already Exists"); throw new CustomExceptionMessage(BAD_REQUEST, EMAIL_EXISTS, "User with Email Already Exists");
} }
} }
@ -523,10 +536,12 @@ public class BasicAuthenticator implements AuthenticatorHandler {
} }
if (storedUser != null && Boolean.TRUE.equals(storedUser.getIsBot())) { if (storedUser != null && Boolean.TRUE.equals(storedUser.getIsBot())) {
throw new CustomExceptionMessage(BAD_REQUEST, INVALID_USERNAME_PASSWORD); throw new CustomExceptionMessage(
BAD_REQUEST, INVALID_USER_OR_PASSWORD, INVALID_USERNAME_PASSWORD);
} }
} catch (Exception ex) { } catch (Exception ex) {
throw new CustomExceptionMessage(BAD_REQUEST, INVALID_USERNAME_PASSWORD); throw new CustomExceptionMessage(
BAD_REQUEST, INVALID_USER_OR_PASSWORD, INVALID_USERNAME_PASSWORD);
} }
return storedUser; return storedUser;
} }

View File

@ -5,6 +5,7 @@ import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; import static javax.ws.rs.core.Response.Status.UNAUTHORIZED;
import static org.openmetadata.schema.auth.TokenType.REFRESH_TOKEN; import static org.openmetadata.schema.auth.TokenType.REFRESH_TOKEN;
import static org.openmetadata.service.exception.CatalogExceptionMessage.INVALID_EMAIL_PASSWORD; import static org.openmetadata.service.exception.CatalogExceptionMessage.INVALID_EMAIL_PASSWORD;
import static org.openmetadata.service.exception.CatalogExceptionMessage.INVALID_USER_OR_PASSWORD;
import static org.openmetadata.service.exception.CatalogExceptionMessage.LDAP_MISSING_ATTR; import static org.openmetadata.service.exception.CatalogExceptionMessage.LDAP_MISSING_ATTR;
import static org.openmetadata.service.exception.CatalogExceptionMessage.MAX_FAILED_LOGIN_ATTEMPT; import static org.openmetadata.service.exception.CatalogExceptionMessage.MAX_FAILED_LOGIN_ATTEMPT;
import static org.openmetadata.service.exception.CatalogExceptionMessage.MULTIPLE_EMAIL_ENTRIES; import static org.openmetadata.service.exception.CatalogExceptionMessage.MULTIPLE_EMAIL_ENTRIES;
@ -200,14 +201,16 @@ public class LdapAuthenticator implements AuthenticatorHandler {
&& Objects.equals( && Objects.equals(
bindingResult.getResultCode().getName(), ResultCode.INVALID_CREDENTIALS.getName())) { bindingResult.getResultCode().getName(), ResultCode.INVALID_CREDENTIALS.getName())) {
recordFailedLoginAttempt(providedIdentity, storedUser); recordFailedLoginAttempt(providedIdentity, storedUser);
throw new CustomExceptionMessage(UNAUTHORIZED, INVALID_EMAIL_PASSWORD); throw new CustomExceptionMessage(
UNAUTHORIZED, INVALID_USER_OR_PASSWORD, INVALID_EMAIL_PASSWORD);
} }
} }
if (bindingResult != null) { if (bindingResult != null) {
throw new CustomExceptionMessage( throw new CustomExceptionMessage(
INTERNAL_SERVER_ERROR, bindingResult.getResultCode().getName()); INTERNAL_SERVER_ERROR, INVALID_USER_OR_PASSWORD, bindingResult.getResultCode().getName());
} else { } else {
throw new CustomExceptionMessage(INTERNAL_SERVER_ERROR, INVALID_EMAIL_PASSWORD); throw new CustomExceptionMessage(
INTERNAL_SERVER_ERROR, INVALID_USER_OR_PASSWORD, INVALID_EMAIL_PASSWORD);
} }
} }
@ -234,15 +237,17 @@ public class LdapAuthenticator implements AuthenticatorHandler {
if (!CommonUtil.nullOrEmpty(userDN) && emailAttr != null) { if (!CommonUtil.nullOrEmpty(userDN) && emailAttr != null) {
return getUserForLdap(email).withName(userDN); return getUserForLdap(email).withName(userDN);
} else { } else {
throw new CustomExceptionMessage(FORBIDDEN, LDAP_MISSING_ATTR); throw new CustomExceptionMessage(FORBIDDEN, INVALID_USER_OR_PASSWORD, LDAP_MISSING_ATTR);
} }
} else if (result.getSearchEntries().size() > 1) { } else if (result.getSearchEntries().size() > 1) {
throw new CustomExceptionMessage(INTERNAL_SERVER_ERROR, MULTIPLE_EMAIL_ENTRIES); throw new CustomExceptionMessage(
INTERNAL_SERVER_ERROR, MULTIPLE_EMAIL_ENTRIES, MULTIPLE_EMAIL_ENTRIES);
} else { } else {
throw new CustomExceptionMessage(INTERNAL_SERVER_ERROR, INVALID_EMAIL_PASSWORD); throw new CustomExceptionMessage(
INTERNAL_SERVER_ERROR, MULTIPLE_EMAIL_ENTRIES, INVALID_EMAIL_PASSWORD);
} }
} catch (LDAPException ex) { } catch (LDAPException ex) {
throw new CustomExceptionMessage(INTERNAL_SERVER_ERROR, ex.getMessage()); throw new CustomExceptionMessage(INTERNAL_SERVER_ERROR, "LDAP_ERROR", ex.getMessage());
} }
} }

View File

@ -1,5 +1,6 @@
package org.openmetadata.service.security.auth; package org.openmetadata.service.security.auth;
import static org.openmetadata.service.exception.CatalogExceptionMessage.AUTHENTICATOR_OPERATION_NOT_SUPPORTED;
import static org.openmetadata.service.exception.CatalogExceptionMessage.FORBIDDEN_AUTHENTICATOR_OP; import static org.openmetadata.service.exception.CatalogExceptionMessage.FORBIDDEN_AUTHENTICATOR_OP;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
@ -17,26 +18,41 @@ public class NoopAuthenticator implements AuthenticatorHandler {
@Override @Override
public JwtResponse loginUser(LoginRequest loginRequest) { public JwtResponse loginUser(LoginRequest loginRequest) {
throw new CustomExceptionMessage(Response.Status.FORBIDDEN, FORBIDDEN_AUTHENTICATOR_OP); throw new CustomExceptionMessage(
Response.Status.FORBIDDEN,
AUTHENTICATOR_OPERATION_NOT_SUPPORTED,
FORBIDDEN_AUTHENTICATOR_OP);
} }
@Override @Override
public void checkIfLoginBlocked(String userName) { public void checkIfLoginBlocked(String userName) {
throw new CustomExceptionMessage(Response.Status.FORBIDDEN, FORBIDDEN_AUTHENTICATOR_OP); throw new CustomExceptionMessage(
Response.Status.FORBIDDEN,
AUTHENTICATOR_OPERATION_NOT_SUPPORTED,
FORBIDDEN_AUTHENTICATOR_OP);
} }
@Override @Override
public void recordFailedLoginAttempt(String providedIdentity, User user) { public void recordFailedLoginAttempt(String providedIdentity, User user) {
throw new CustomExceptionMessage(Response.Status.FORBIDDEN, FORBIDDEN_AUTHENTICATOR_OP); throw new CustomExceptionMessage(
Response.Status.FORBIDDEN,
AUTHENTICATOR_OPERATION_NOT_SUPPORTED,
FORBIDDEN_AUTHENTICATOR_OP);
} }
@Override @Override
public void validatePassword(String providedIdentity, User storedUser, String reqPassword) { public void validatePassword(String providedIdentity, User storedUser, String reqPassword) {
throw new CustomExceptionMessage(Response.Status.FORBIDDEN, FORBIDDEN_AUTHENTICATOR_OP); throw new CustomExceptionMessage(
Response.Status.FORBIDDEN,
AUTHENTICATOR_OPERATION_NOT_SUPPORTED,
FORBIDDEN_AUTHENTICATOR_OP);
} }
@Override @Override
public User lookUserInProvider(String userName) { public User lookUserInProvider(String userName) {
throw new CustomExceptionMessage(Response.Status.FORBIDDEN, FORBIDDEN_AUTHENTICATOR_OP); throw new CustomExceptionMessage(
Response.Status.FORBIDDEN,
AUTHENTICATOR_OPERATION_NOT_SUPPORTED,
FORBIDDEN_AUTHENTICATOR_OP);
} }
} }

View File

@ -77,6 +77,9 @@ public abstract class PipelineServiceClient {
public static final String STATUS_KEY = "status"; public static final String STATUS_KEY = "status";
public static final String APP_TRIGGER = "run_application"; public static final String APP_TRIGGER = "run_application";
public static final String APP_VALIDATE = "validate_registration"; public static final String APP_VALIDATE = "validate_registration";
public static final String DEPLOYEMENT_ERROR = "DEPLOYMENT_ERROR";
public static final String TRIGGER_ERROR = "TRIGGER_ERROR";
public static final Map<String, String> TYPE_TO_TASK = public static final Map<String, String> TYPE_TO_TASK =
Map.of( Map.of(
PipelineType.METADATA.toString(), PipelineType.METADATA.toString(),

View File

@ -17,13 +17,14 @@ import javax.ws.rs.core.Response;
public class PipelineServiceClientException extends WebServiceException { public class PipelineServiceClientException extends WebServiceException {
private static final String BY_NAME_MESSAGE = "Airflow Exception [%s] due to [%s]."; private static final String BY_NAME_MESSAGE = "Airflow Exception [%s] due to [%s].";
private static final String ERROR_TYPE = "PIPELINE_SERVICE_ERROR";
public PipelineServiceClientException(String message) { public PipelineServiceClientException(String message) {
super(Response.Status.BAD_REQUEST, message); super(Response.Status.BAD_REQUEST, ERROR_TYPE, message);
} }
private PipelineServiceClientException(Response.Status status, String message) { private PipelineServiceClientException(Response.Status status, String message) {
super(status, message); super(status, ERROR_TYPE, message);
} }
public static PipelineServiceClientException byMessage( public static PipelineServiceClientException byMessage(

View File

@ -19,13 +19,14 @@ public class PipelineServiceVersionException extends WebServiceException {
private static final String BY_NAME_MESSAGE = private static final String BY_NAME_MESSAGE =
"Pipeline Service [%s] Version mismatch due to [%s]."; "Pipeline Service [%s] Version mismatch due to [%s].";
private static final String ERROR_TYPE = "PIPELINE_SERVICE_VERSION_MISMATCH";
public PipelineServiceVersionException(String message) { public PipelineServiceVersionException(String message) {
super(Response.Status.INTERNAL_SERVER_ERROR, message); super(Response.Status.INTERNAL_SERVER_ERROR, ERROR_TYPE, message);
} }
private PipelineServiceVersionException(Response.Status status, String message) { private PipelineServiceVersionException(Response.Status status, String message) {
super(status, message); super(status, ERROR_TYPE, message);
} }
public static PipelineServiceVersionException byMessage( public static PipelineServiceVersionException byMessage(

View File

@ -0,0 +1,30 @@
package org.openmetadata.sdk.exception;
import javax.ws.rs.core.Response;
public class SearchException extends WebServiceException {
private static final String BY_NAME_MESSAGE =
"Search Index Not Found Exception [%s] due to [%s].";
private static final String ERROR_TYPE = "SEARCH_ERROR";
public SearchException(String message) {
super(Response.Status.INTERNAL_SERVER_ERROR, ERROR_TYPE, message);
}
private SearchException(Response.Status status, String message) {
super(status, ERROR_TYPE, message);
}
public static SearchException byMessage(
String name, String errorMessage, Response.Status status) {
return new SearchException(status, buildMessageByName(name, errorMessage));
}
public static SearchException byMessage(String name, String errorMessage) {
return new SearchException(Response.Status.BAD_REQUEST, buildMessageByName(name, errorMessage));
}
private static String buildMessageByName(String name, String errorMessage) {
return String.format(BY_NAME_MESSAGE, name, errorMessage);
}
}

View File

@ -0,0 +1,31 @@
package org.openmetadata.sdk.exception;
import javax.ws.rs.core.Response;
public class SearchIndexNotFoundException extends WebServiceException {
private static final String BY_NAME_MESSAGE =
"Search Index Not Found Exception [%s] due to [%s].";
private static final String ERROR_TYPE = "SEARCH_INDEX_NOT_FOUND";
public SearchIndexNotFoundException(String message) {
super(Response.Status.INTERNAL_SERVER_ERROR, ERROR_TYPE, message);
}
private SearchIndexNotFoundException(Response.Status status, String message) {
super(status, ERROR_TYPE, message);
}
public static SearchIndexNotFoundException byMessage(
String name, String errorMessage, Response.Status status) {
return new SearchIndexNotFoundException(status, buildMessageByName(name, errorMessage));
}
public static SearchIndexNotFoundException byMessage(String name, String errorMessage) {
return new SearchIndexNotFoundException(
Response.Status.BAD_REQUEST, buildMessageByName(name, errorMessage));
}
private static String buildMessageByName(String name, String errorMessage) {
return String.format(BY_NAME_MESSAGE, name, errorMessage);
}
}

View File

@ -13,51 +13,55 @@
package org.openmetadata.sdk.exception; package org.openmetadata.sdk.exception;
import io.dropwizard.jersey.errors.ErrorMessage;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import lombok.Getter; import lombok.Getter;
@Getter
public abstract class WebServiceException extends RuntimeException { public abstract class WebServiceException extends RuntimeException {
@Getter private final transient Response response; private final transient Response response;
protected WebServiceException(Response.Status status, String msg) { protected WebServiceException(Response.Status status, String errorType, String msg) {
super(msg); super(msg);
response = response =
Response.status(status) Response.status(status)
.entity(convertToErrorResponseMessage(msg)) .entity(convertToErrorResponseMessage(errorType, msg))
.type(MediaType.APPLICATION_JSON_TYPE) .type(MediaType.APPLICATION_JSON_TYPE)
.build(); .build();
} }
protected WebServiceException(int status, String msg) { protected WebServiceException(int status, String errorType, String msg) {
super(msg); super(msg);
response = response =
Response.status(status) Response.status(status)
.entity(new ErrorMessage(status, msg)) .entity(convertToErrorResponseMessage(errorType, msg))
.type(MediaType.APPLICATION_JSON_TYPE) .type(MediaType.APPLICATION_JSON_TYPE)
.build(); .build();
} }
protected WebServiceException(Response.Status status, String msg, Throwable cause) { protected WebServiceException(
Response.Status status, String errorType, String msg, Throwable cause) {
super(msg, cause); super(msg, cause);
response = response =
Response.status(status) Response.status(status)
.entity(convertToErrorResponseMessage(msg)) .entity(convertToErrorResponseMessage(errorType, msg))
.type(MediaType.APPLICATION_JSON_TYPE) .type(MediaType.APPLICATION_JSON_TYPE)
.build(); .build();
} }
private static ErrorResponse convertToErrorResponseMessage(String msg) { private static ErrorResponse convertToErrorResponseMessage(String errorType, String msg) {
return new ErrorResponse(msg); return new ErrorResponse(errorType, msg);
} }
private static class ErrorResponse { private static class ErrorResponse {
/** Response message. */ /** Response message. */
@Getter private final String responseMessage; @Getter private final String responseMessage;
ErrorResponse(String responseMessage) { @Getter private final String errorType;
ErrorResponse(String errorType, String responseMessage) {
this.responseMessage = responseMessage; this.responseMessage = responseMessage;
this.errorType = errorType;
} }
} }
} }