Skip to content

Commit

Permalink
Support new types of errors in charts and selectors (#1516)
Browse files Browse the repository at this point in the history
Co-authored-by: WeblateGravity <[email protected]>
Co-authored-by: Weblate <[email protected]>
Co-authored-by: Darya Tikhonova <[email protected]>
Co-authored-by: Matthew Casserly <[email protected]>
  • Loading branch information
5 people authored Oct 2, 2024
1 parent 6225edb commit 57af1c6
Show file tree
Hide file tree
Showing 31 changed files with 312 additions and 153 deletions.
7 changes: 7 additions & 0 deletions src/i18n-keysets/common.errors/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"label_error-access-message": "This token cannot be used with the specified parameters",
"label_error-invalid-format-token-message": "Invalid token format",
"label_error-invalid-token-message": "This token is not suitable for this embed",
"label_error-outdated-message": "Embed settings expired",
"label_error-token-not-found-message": "The embed has no token"
}
7 changes: 7 additions & 0 deletions src/i18n-keysets/common.errors/ru.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"label_error-access-message": "Невозможно использовать токен с заданными параметрами",
"label_error-invalid-format-token-message": "Неверный формат токена",
"label_error-invalid-token-message": "Токен не подходит для данного встраивания",
"label_error-outdated-message": "Настройки встраивания устарели",
"label_error-token-not-found-message": "Во встраивании отсутствует токен"
}
3 changes: 1 addition & 2 deletions src/i18n-keysets/dash.error.view/en.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{
"label_error-404-message": "Object not found",
"label_error-access-message": "No view rights"
"label_error-404-message": "Object not found"
}
3 changes: 1 addition & 2 deletions src/i18n-keysets/dash.error.view/ru.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{
"label_error-404-message": "Объект не найден",
"label_error-access-message": "Нет прав на просмотр"
"label_error-404-message": "Объект не найден"
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
US_PUBLIC_API_TOKEN_HEADER,
WORKBOOK_ID_HEADER,
} from '../../../../../../shared';
import {TIMEOUT_10_SEC} from '../../../../../../shared/constants';
import {ErrorCode, TIMEOUT_10_SEC} from '../../../../../../shared/constants';
import {createErrorHandler} from '../../error-handler';
import {getDuration} from '../../utils';
import type {ChartEntryData, DashEntryData, EmbeddingInfo} from '../types';
Expand All @@ -42,7 +42,6 @@ axiosRetry(axios, {
});

const ENTRY_NOT_FOUND = 'ENTRY_NOT_FOUND';
const ENTRY_FORBIDDEN = 'ENTRY_FORBIDDEN';
const PASSED_PROPERTIES: (keyof Entry)[] = [
'entryId',
'data',
Expand Down Expand Up @@ -308,7 +307,7 @@ export class USProvider {
throw error;
} else if (error.response && error.response.status === 403) {
error.description = id;
error.code = ENTRY_FORBIDDEN;
error.code = ErrorCode.EntryForbidden;
error.status = 403;
throw error;
} else {
Expand Down Expand Up @@ -382,7 +381,7 @@ export class USProvider {
throw error;
} else if (error.response && error.response.status === 403) {
error.description = key;
error.code = ENTRY_FORBIDDEN;
error.code = ErrorCode.EntryForbidden;
error.status = 403;
throw error;
} else {
Expand Down Expand Up @@ -438,7 +437,7 @@ export class USProvider {
throw error;
} else if (error.response && error.response.status === 403) {
error.description = 'embedToken';
error.code = ENTRY_FORBIDDEN;
error.code = ErrorCode.EntryForbidden;
error.status = 403;
throw error;
} else {
Expand Down Expand Up @@ -496,7 +495,7 @@ export class USProvider {
throw error;
} else if (error.response && error.response.status === 403) {
error.description = 'embedToken and id';
error.code = ENTRY_FORBIDDEN;
error.code = ErrorCode.EntryForbidden;
error.status = 403;
throw error;
} else {
Expand Down Expand Up @@ -581,7 +580,7 @@ export class USProvider {
error.status = 404;
throw error;
} else if (error.response && error.response.status === 403) {
error.code = ENTRY_FORBIDDEN;
error.code = ErrorCode.EntryForbidden;
error.status = 403;
throw error;
} else {
Expand Down Expand Up @@ -666,7 +665,7 @@ export class USProvider {
error.status = 404;
throw error;
} else if (error.response && error.response.status === 403) {
error.code = ENTRY_FORBIDDEN;
error.code = ErrorCode.EntryForbidden;
error.status = 403;
throw error;
} else {
Expand Down Expand Up @@ -706,7 +705,7 @@ export class USProvider {
error.status = 404;
throw error;
} else if (error.response && error.response.status === 403) {
error.code = ENTRY_FORBIDDEN;
error.code = ErrorCode.EntryForbidden;
error.status = 403;
throw error;
} else {
Expand Down
39 changes: 24 additions & 15 deletions src/server/components/charts-engine/controllers/embedded-entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type {Request, Response} from '@gravity-ui/expresskit';
import jwt from 'jsonwebtoken';
import {isObject} from 'lodash';

import {DL_EMBED_TOKEN_HEADER} from '../../../../shared';
import {DL_EMBED_TOKEN_HEADER, EntryScope, ErrorCode} from '../../../../shared';
import {resolveConfig} from '../components/storage';
import type {EmbedResolveConfigProps, ResolveConfigError} from '../components/storage/base';

Expand All @@ -16,9 +16,9 @@ export const embeddedEntryController = (req: Request, res: Response) => {
if (!embedToken) {
ctx.log('CHARTS_ENGINE_NO_TOKEN');
res.status(400).send({
error: 'You must provide embedToken',
code: ErrorCode.InvalidTokenFormat,
extra: {message: 'You must provide embedToken', hideRetry: true},
});

return;
}

Expand All @@ -27,10 +27,9 @@ export const embeddedEntryController = (req: Request, res: Response) => {
if (!payload || typeof payload === 'string' || !('embedId' in payload)) {
ctx.log('CHARTS_ENGINE_WRONG_TOKEN');
res.status(400).send({
code: 'ERR.CHARTS.WRONG_EMBED_TOKEN',
code: ErrorCode.InvalidTokenFormat,
extra: {message: 'Wrong token format', hideRetry: true},
});

return;
}

Expand Down Expand Up @@ -85,16 +84,26 @@ export const embeddedEntryController = (req: Request, res: Response) => {
})
.then(async (response) => {
if (response && 'entry' in response) {
const {
entry: {entryId, scope, data},
} = response;

// Add only necessary fields without personal info like createdBy
res.status(200).send({
entryId,
scope,
data,
});
if (response.entry.scope === EntryScope.Dash) {
const {
entry: {entryId, scope, data},
} = response;

// Add only necessary fields without personal info like createdBy
res.status(200).send({
entryId,
scope,
data,
});
} else {
res.status(400).send({
code: ErrorCode.InvalidToken,
extra: {
message: 'Invalid token',
hideRetry: true,
},
});
}
}
})
.catch((error) => {
Expand Down
55 changes: 51 additions & 4 deletions src/server/components/charts-engine/controllers/embeds.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import type {Request, Response} from '@gravity-ui/expresskit';
import type {AxiosError} from 'axios';
import jwt from 'jsonwebtoken';
import {isObject} from 'lodash';

import type {ChartsEngine} from '..';
import {ControlType, DL_EMBED_TOKEN_HEADER, EntryScope} from '../../../../shared';
import {
ControlType,
DL_EMBED_TOKEN_HEADER,
EntryScope,
ErrorCode,
isEnabledServerFeature,
} from '../../../../shared';
import {resolveConfig} from '../components/storage';
import type {EmbedResolveConfigProps, ResolveConfigError} from '../components/storage/base';
import type {ReducedResolvedConfig} from '../components/storage/types';
import {getDuration, isDashEntry} from '../components/utils';

const isResponseError = (error: unknown): error is AxiosError<{code: string}> => {
return Boolean(isObject(error) && 'response' in error && error.response);
};

export const embedsController = (chartsEngine: ChartsEngine) => {
return function chartsRunController(req: Request, res: Response) {
const {ctx} = req;
Expand All @@ -28,7 +39,12 @@ export const embedsController = (chartsEngine: ChartsEngine) => {
if (!embedToken) {
ctx.log('CHARTS_ENGINE_NO_TOKEN');
res.status(400).send({
error: 'You must provide embedToken',
code: ErrorCode.TokenNotFound,
extra: {
message: 'You must provide embedToken',
hideRetry: true,
hideDebugInfo: true,
},
});

return;
Expand All @@ -39,7 +55,7 @@ export const embedsController = (chartsEngine: ChartsEngine) => {
if (!payload || typeof payload === 'string' || !('embedId' in payload)) {
ctx.log('CHARTS_ENGINE_WRONG_TOKEN');
res.status(400).send({
code: 'ERR.CHARTS.WRONG_EMBED_TOKEN',
code: ErrorCode.InvalidToken,
extra: {message: 'Wrong token format', hideRetry: true, hideDebugInfo: true},
});

Expand Down Expand Up @@ -79,6 +95,22 @@ export const embedsController = (chartsEngine: ChartsEngine) => {

Promise.resolve(configPromise)
.catch((err: unknown) => {
if (
isResponseError(err) &&
(err.response?.data.code === ErrorCode.IncorrectEntry ||
err.response?.data.code === ErrorCode.IncorrectDepsIds)
) {
res.status(409).send({
code: ErrorCode.OutdatedDependencies,
extra: {
message: 'Dependecies of embed are outdated',
hideRetry: true,
hideDebugInfo: true,
},
});

return;
}
const error: ResolveConfigError =
isObject(err) && 'message' in err ? (err as Error) : new Error(err as string);
const result: {
Expand Down Expand Up @@ -164,7 +196,12 @@ export const embedsController = (chartsEngine: ChartsEngine) => {
entry = embeddingInfo.entry;
} else {
return res.status(400).send({
error: 'Invalid config format',
code: ErrorCode.InvalidToken,
extra: {
message: 'Invalid token',
hideRetry: true,
hideDebugInfo: true,
},
});
}

Expand All @@ -184,6 +221,16 @@ export const embedsController = (chartsEngine: ChartsEngine) => {
});
}

if (
!isEnabledServerFeature(ctx, 'EnableChartEditor') &&
runnerFound.name === 'editor'
) {
ctx.log('CHARTS_ENGINE_EDITOR_DISABLED');
return res.status(400).send({
error: 'ChartEditor is disabled',
});
}

req.body.config = entry;
req.body.key = entry.key;

Expand Down
10 changes: 8 additions & 2 deletions src/shared/constants/error-codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,18 @@ export enum ErrorCode {
NeedReset = 'NEED_RESET',
MigrationOrgExists = 'MIGRATION_ORG_EXISTS',
MigrationDenied = 'MIGRATION_DENIED',
AccessServicePermissionDenied = 'ACCESS_SERVICE_PERMISSION_DENIED',
AccessServiceUnauthenticated = 'ACCESS_SERVICE_UNAUTHENTICATED',
EntryIsLocked = 'ERR.US.ENTRY_IS_LOCKED',
EntryAlreadyExists = 'ERR.US.ENTRY_ALREADY_EXISTS',
UsUniqViolation = 'ERR.US.DB.UNIQUE_VIOLATION',
ReadOnlyMode = 'READ_ONLY_MODE_ENABLED',
InvalidTokenFormat = 'ERR.CHARTS.INVALID_TOKEN_FORMAT',
TokenNotFound = 'ERR.CHARTS.TOKEN_NOT_FOUND',
InvalidToken = 'ERR.CHARTS.INVALID_TOKEN',
OutdatedDependencies = 'ERR.CHARTS.OUTDATED_DEPENDENCIES',
EntryForbidden = 'ERR.US.ENTRY_FORBIDDEN',

IncorrectEntry = 'INCORRECT_ENTRY_ID_FOR_EMBED',
IncorrectDepsIds = 'INCORRECT_DEPS_IDS_FOR_EMBED',
}

export const ErrorContentTypes = {
Expand Down
3 changes: 0 additions & 3 deletions src/ui/assets/icons/error-chart.svg

This file was deleted.

3 changes: 0 additions & 3 deletions src/ui/assets/icons/error-database.svg

This file was deleted.

3 changes: 0 additions & 3 deletions src/ui/assets/icons/error-lock.svg

This file was deleted.

1 change: 1 addition & 0 deletions src/ui/components/DashKit/helpers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ interface DashkitWrapperProps extends DashKitProps {
// Extended Controls props
skipReload?: boolean;
isNewRelations?: boolean;
hideErrorDetails?: boolean;
}

export const DashkitWrapper: React.FC<
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
flex-direction: column;
align-items: flex-start;
justify-content: space-around;
height: 70px;
width: 180px;
gap: 12px;
padding: 6px;
}

&_mobile {
Expand Down
Loading

0 comments on commit 57af1c6

Please sign in to comment.