feat: more SIP-40 errors (#15482)

This commit is contained in:
Beto Dealmeida 2021-06-30 16:32:59 -07:00 committed by GitHub
parent ffa51753e3
commit e606477ec1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 98 additions and 14 deletions

View File

@ -311,3 +311,19 @@ The results stored in the backend were stored in a different format, and no long
```
The query results were stored in a format that is no longer supported. Please re-run your query.
## Issue 1035
```
Failed to start remote query on a worker.
```
The query was not started by an asynchronous worker. Please reach out to your administrator for further assistance.
## Issue 1036
```
The database was deleted.
```
The operation failed because the database referenced no longer exists. Please reach out to your administrator for further assistance.

View File

@ -57,6 +57,7 @@ export const ErrorTypeEnum = {
// Other errors
BACKEND_TIMEOUT_ERROR: 'BACKEND_TIMEOUT_ERROR',
DATABASE_NOT_FOUND_ERROR: 'DATABASE_NOT_FOUND_ERROR',
// Sqllab error
MISSING_TEMPLATE_PARAMS_ERROR: 'MISSING_TEMPLATE_PARAMS_ERROR',
@ -67,6 +68,7 @@ export const ErrorTypeEnum = {
INVALID_CVAS_QUERY_ERROR: 'INVALID_CVAS_QUERY_ERROR',
SQLLAB_TIMEOUT_ERROR: 'SQLLAB_TIMEOUT_ERROR',
RESULTS_BACKEND_ERROR: 'RESULTS_BACKEND_ERROR',
ASYNC_WORKERS_ERROR: 'ASYNC_WORKERS_ERROR',
// Generic errors
GENERIC_COMMAND_ERROR: 'GENERIC_COMMAND_ERROR',

View File

@ -35,6 +35,10 @@ export default function setupErrorMessages() {
ErrorTypeEnum.BACKEND_TIMEOUT_ERROR,
TimeoutErrorMessage,
);
errorMessageComponentRegistry.registerValue(
ErrorTypeEnum.DATABASE_NOT_FOUND_ERROR,
DatabaseErrorMessage,
);
errorMessageComponentRegistry.registerValue(
ErrorTypeEnum.GENERIC_DB_ENGINE_ERROR,
DatabaseErrorMessage,
@ -83,6 +87,10 @@ export default function setupErrorMessages() {
ErrorTypeEnum.RESULTS_BACKEND_ERROR,
DatabaseErrorMessage,
);
errorMessageComponentRegistry.registerValue(
ErrorTypeEnum.ASYNC_WORKERS_ERROR,
DatabaseErrorMessage,
);
errorMessageComponentRegistry.registerValue(
ErrorTypeEnum.SQLLAB_TIMEOUT_ERROR,
DatabaseErrorMessage,

View File

@ -66,6 +66,7 @@ class SupersetErrorType(str, Enum):
# Other errors
BACKEND_TIMEOUT_ERROR = "BACKEND_TIMEOUT_ERROR"
DATABASE_NOT_FOUND_ERROR = "DATABASE_NOT_FOUND_ERROR"
# Sql Lab errors
MISSING_TEMPLATE_PARAMS_ERROR = "MISSING_TEMPLATE_PARAMS_ERROR"
@ -76,6 +77,7 @@ class SupersetErrorType(str, Enum):
INVALID_CVAS_QUERY_ERROR = "INVALID_CVAS_QUERY_ERROR"
SQLLAB_TIMEOUT_ERROR = "SQLLAB_TIMEOUT_ERROR"
RESULTS_BACKEND_ERROR = "RESULTS_BACKEND_ERROR"
ASYNC_WORKERS_ERROR = "ASYNC_WORKERS_ERROR"
# Generic errors
GENERIC_COMMAND_ERROR = "GENERIC_COMMAND_ERROR"
@ -131,6 +133,8 @@ ISSUE_CODES = {
"The results stored in the backend were stored in a "
"different format, and no longer can be deserialized."
),
1035: _("Failed to start remote query on a worker."),
1036: _("The database was deleted."),
}
@ -163,6 +167,8 @@ ERROR_TYPES_TO_ISSUE_CODES_MAPPING = {
SupersetErrorType.OBJECT_DOES_NOT_EXIST_ERROR: [1029],
SupersetErrorType.SYNTAX_ERROR: [1030],
SupersetErrorType.RESULTS_BACKEND_ERROR: [1031, 1032, 1033],
SupersetErrorType.ASYNC_WORKERS_ERROR: [1035],
SupersetErrorType.DATABASE_NOT_FOUND_ERROR: [1011, 1036],
}

View File

@ -53,7 +53,7 @@ class SupersetErrorException(SupersetException):
class SupersetGenericErrorException(SupersetErrorException):
"""Exceptions that are too generic to have their own type"""
def __init__(self, message: str) -> None:
def __init__(self, message: str, status: Optional[int] = None) -> None:
super().__init__(
SupersetError(
message=message,
@ -61,6 +61,8 @@ class SupersetGenericErrorException(SupersetErrorException):
level=ErrorLevel.ERROR,
)
)
if status is not None:
self.status = status
class SupersetErrorFromParamsException(SupersetErrorException):

View File

@ -15,6 +15,7 @@
# specific language governing permissions and limitations
# under the License.
# pylint: disable=comparison-with-callable, line-too-long, too-many-branches
import dataclasses
import logging
import re
from contextlib import closing
@ -2035,10 +2036,21 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods
table_name = data["datasourceName"]
database_id = data["dbId"]
except KeyError:
return json_error_response("Missing required fields", status=400)
raise SupersetGenericErrorException(
"One or more required fields are missing in the request. Please try "
"again, and if the problem persists conctact your administrator.",
status=400,
)
database = db.session.query(Database).get(database_id)
if not database:
return json_error_response("Database not found", status=400)
raise SupersetErrorException(
SupersetError(
message="The database was not found.",
error_type=SupersetErrorType.DATABASE_NOT_FOUND_ERROR,
level=ErrorLevel.ERROR,
),
status=404,
)
table = (
db.session.query(SqlaTable)
.filter_by(database_id=database_id, table_name=table_name)
@ -2101,7 +2113,14 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods
stats_logger.incr(
f"deprecated.{self.__class__.__name__}.select_star.database_not_found"
)
return json_error_response("Not found", 404)
raise SupersetErrorException(
SupersetError(
message="The database was not found.",
error_type=SupersetErrorType.DATABASE_NOT_FOUND_ERROR,
level=ErrorLevel.ERROR,
),
status=404,
)
schema = utils.parse_js_uri_path_item(schema, eval_undefined=True)
table_name = utils.parse_js_uri_path_item(table_name) # type: ignore
if not self.appbuilder.sm.can_access_table(database, Table(table_name, schema)):
@ -2114,7 +2133,18 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods
table_name,
schema,
)
return json_error_response("Not found", 404)
raise SupersetErrorException(
SupersetError(
message=__(
"You are not authorized to fetch samples from this table. If "
"you think this is an error, please reach out to your "
"administrator."
),
error_type=SupersetErrorType.QUERY_SECURITY_ACCESS_ERROR,
level=ErrorLevel.ERROR,
),
status=403,
)
stats_logger.incr(f"deprecated.{self.__class__.__name__}.select_star.success")
return json_success(
database.select_star(
@ -2425,15 +2455,21 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods
)
except Exception as ex: # pylint: disable=broad-except
logger.exception("Query %i: %s", query.id, str(ex))
msg = _(
"Failed to start remote query on a worker. "
"Tell your administrator to verify the availability of "
"the message queue."
message = _("Failed to start remote query on a worker.")
error = SupersetError(
message=message,
error_type=SupersetErrorType.ASYNC_WORKERS_ERROR,
level=ErrorLevel.ERROR,
)
error_payload = dataclasses.asdict(error)
query.set_extra_json_key("errors", [error_payload])
query.status = QueryStatus.FAILED
query.error_message = msg
query.error_message = message
session.commit()
return json_error_response("{}".format(msg))
raise SupersetErrorException(error)
# Update saved query with execution info from the query execution
QueryDAO.update_saved_query_exec_info(query_id)
@ -2638,9 +2674,23 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods
try:
query.raise_for_access()
except SupersetSecurityException as ex:
message = _(
"You are not authorized to see this query. If you think this "
"is an error, please reach out to your administrator."
)
error = SupersetError(
message=message,
error_type=SupersetErrorType.QUERY_SECURITY_ACCESS_ERROR,
level=ErrorLevel.ERROR,
)
error_payload = dataclasses.asdict(error)
query.set_extra_json_key("errors", [error_payload])
query.status = QueryStatus.FAILED
query.error_message = message
session.commit()
return json_errors_response([ex.error], status=403)
raise SupersetErrorException(error, status=403) from ex
try:
template_processor = get_template_processor(
@ -2657,7 +2707,7 @@ class Superset(BaseSupersetView): # pylint: disable=too-many-public-methods
'The query contains one or more malformed template parameters. Please check your query and confirm that all template parameters are surround by double braces, for example, "{{ ds }}". Then, try running your query again.'
),
error=SupersetErrorType.INVALID_TEMPLATE_PARAMS_ERROR,
)
) from ex
if is_feature_enabled("ENABLE_TEMPLATE_PROCESSING"):
# pylint: disable=protected-access

View File

@ -1197,7 +1197,7 @@ class TestCore(SupersetTestCase):
self.login(username="gamma")
example_db = utils.get_example_database()
resp = self.client.get(f"/superset/select_star/{example_db.id}/birth_names")
self.assertEqual(resp.status_code, 404)
self.assertEqual(resp.status_code, 403)
@mock.patch("superset.views.core.results_backend_use_msgpack", False)
@mock.patch("superset.views.core.results_backend")