Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ repos:
args: [--check-untyped-defs]
exclude: ^superset-extensions-cli/
additional_dependencies: [
types-cachetools,
types-simplejson,
types-python-dateutil,
types-requests,
Expand Down
6 changes: 6 additions & 0 deletions docs/static/feature-flags.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@
"lifecycle": "testing",
"description": "Allow users to export full CSV of table viz type. Warning: Could cause server memory/compute issues with large datasets."
},
{
"name": "AWS_DATABASE_IAM_AUTH",
"default": false,
"lifecycle": "testing",
"description": "Enable AWS IAM authentication for database connections (Aurora, Redshift). Allows cross-account role assumption via STS AssumeRole. Security note: When enabled, ensure Superset's IAM role has restricted sts:AssumeRole permissions to prevent unauthorized access."
},
{
"name": "CACHE_IMPERSONATION",
"default": false,
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ ydb = ["ydb-sqlalchemy>=0.1.2"]
development = [
# no bounds for apache-superset-extensions-cli until a stable version
"apache-superset-extensions-cli",
"boto3",
"docker",
"flask-testing",
"freezegun",
Expand Down
14 changes: 14 additions & 0 deletions requirements/development.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ blinker==1.9.0
# via
# -c requirements/base-constraint.txt
# flask
boto3==1.42.39
# via apache-superset
botocore==1.42.39
# via
# boto3
# s3transfer
bottleneck==1.5.0
# via
# -c requirements/base-constraint.txt
Expand Down Expand Up @@ -460,6 +466,10 @@ jinja2==3.1.6
# apache-superset-extensions-cli
# flask
# flask-babel
jmespath==1.1.0
# via
# boto3
# botocore
jsonpath-ng==1.7.0
# via
# -c requirements/base-constraint.txt
Expand Down Expand Up @@ -812,6 +822,7 @@ python-dateutil==2.9.0.post0
# via
# -c requirements/base-constraint.txt
# apache-superset
# botocore
# celery
# croniter
# flask-appbuilder
Expand Down Expand Up @@ -915,6 +926,8 @@ rsa==4.9.1
# google-auth
ruff==0.9.7
# via apache-superset
s3transfer==0.16.0
# via boto3
secretstorage==3.5.0
# via keyring
selenium==4.32.0
Expand Down Expand Up @@ -1066,6 +1079,7 @@ url-normalize==2.2.1
urllib3==2.6.3
# via
# -c requirements/base-constraint.txt
# botocore
# docker
# requests
# requests-cache
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export { default as isEqualArray } from './isEqualArray';
export { default as makeSingleton } from './makeSingleton';
export { default as promiseTimeout } from './promiseTimeout';
export { default as removeDuplicates } from './removeDuplicates';
export { default as withLabel } from './withLabel';
export { lruCache } from './lruCache';
export { getSelectedText } from './getSelectedText';
export * from './featureFlags';
Expand Down
43 changes: 43 additions & 0 deletions superset-frontend/packages/superset-ui-core/src/utils/withLabel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import type { ValidatorFunction } from '../validator';

/**
* Wraps a validator function to prepend a label to its error message.
*
* @param validator - The validator function to wrap
* @param label - The label to prepend to error messages
* @returns A new validator function that includes the label in error messages
*
* @example
* validators: [
* withLabel(validateInteger, t('Row limit')),
* ]
* // Returns: "Row limit is expected to be an integer"
*/
export default function withLabel<V = unknown, S = unknown>(
validator: ValidatorFunction<V, S>,
label: string,
): ValidatorFunction<V, S> {
return (value: V, state?: S): string | false => {
const error = validator(value, state);
return error ? `${label} ${error}` : false;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* under the License.
*/

export * from './types';
export { default as legacyValidateInteger } from './legacyValidateInteger';
export { default as legacyValidateNumber } from './legacyValidateNumber';
export { default as validateInteger } from './validateInteger';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { t } from '@apache-superset/core';
* formerly called integer()
* @param v
*/
export default function legacyValidateInteger(v: unknown) {
export default function legacyValidateInteger(v: unknown): string | false {
if (
v &&
(Number.isNaN(Number(v)) || parseInt(v as string, 10) !== Number(v))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { t } from '@apache-superset/core';
* formerly called numeric()
* @param v
*/
export default function numeric(v: unknown) {
export default function numeric(v: unknown): string | false {
if (v && Number.isNaN(Number(v))) {
return t('is expected to be a number');
}
Expand Down
27 changes: 27 additions & 0 deletions superset-frontend/packages/superset-ui-core/src/validator/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

/**
* Type definition for a validator function.
* Returns an error message string if validation fails, or false if validation passes.
*/
export type ValidatorFunction<V = unknown, S = unknown> = (
value: V,
state?: S,
) => string | false;
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import { t } from '@apache-superset/core';

export default function validateInteger(v: unknown) {
export default function validateInteger(v: unknown): string | false {
if (
(typeof v === 'string' &&
v.trim().length > 0 &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const VALIDE_OSM_URLS = ['https://tile.osm', 'https://tile.openstreetmap'];
* Validate a [Mapbox styles URL](https://docs.mapbox.com/help/glossary/style-url/)
* @param v
*/
export default function validateMapboxStylesUrl(v: unknown) {
export default function validateMapboxStylesUrl(v: unknown): string | false {
if (typeof v === 'string') {
const trimmed_v = v.trim();
if (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@
*/
import { t } from '@apache-superset/core';

export default function validateMaxValue(v: unknown, max: number) {
export default function validateMaxValue(
v: unknown,
max: number,
): string | false {
if (Number(v) > +max) {
return t('Value cannot exceed %s', max);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import { t } from '@apache-superset/core';

export default function validateNonEmpty(v: unknown) {
export default function validateNonEmpty(v: unknown): string | false {
if (
v === null ||
typeof v === 'undefined' ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import { t } from '@apache-superset/core';

export default function validateInteger(v: any) {
export default function validateNumber(v: unknown): string | false {
if (
(typeof v === 'string' &&
v.trim().length > 0 &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default function validateServerPagination(
serverPagination: boolean,
maxValueWithoutServerPagination: number,
maxServer: number,
) {
): string | false {
if (
Number(v) > +maxValueWithoutServerPagination &&
Number(v) <= maxServer &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ import { t } from '@apache-superset/core';
import { ensureIsArray } from '../utils';

export const validateTimeComparisonRangeValues = (
timeRangeValue?: any,
controlValue?: any,
) => {
timeRangeValue?: unknown,
controlValue?: unknown,
): string[] => {
const isCustomTimeRange = timeRangeValue === ComparisonTimeRangeType.Custom;
const isCustomControlEmpty = controlValue?.every(
(val: any) => ensureIsArray(val).length === 0,
);
const isCustomControlEmpty =
Array.isArray(controlValue) &&
controlValue.every((val: unknown) => ensureIsArray(val).length === 0);
return isCustomTimeRange && isCustomControlEmpty
? [t('Filters for comparison must have a value')]
: [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
import { validateMaxValue } from '@superset-ui/core';
import './setup';

test('validateInteger returns the warning message if invalid', () => {
test('validateMaxValue returns the warning message if invalid', () => {
expect(validateMaxValue(10.1, 10)).toBeTruthy();
expect(validateMaxValue(1, 0)).toBeTruthy();
expect(validateMaxValue('2', 1)).toBeTruthy();
});

test('validateInteger returns false if the input is valid', () => {
test('validateMaxValue returns false if the input is valid', () => {
expect(validateMaxValue(0, 1)).toBeFalsy();
expect(validateMaxValue(10, 10)).toBeFalsy();
expect(validateMaxValue(undefined, 1)).toBeFalsy();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import {
SMART_DATE_ID,
validateMaxValue,
validateServerPagination,
withLabel,
} from '@superset-ui/core';
import { GenericDataType } from '@apache-superset/core/api/core';
import { isEmpty, last } from 'lodash';
Expand Down Expand Up @@ -384,7 +385,7 @@ const config: ControlPanelConfig = {
description: t('Rows per page, 0 means no pagination'),
visibility: ({ controls }: ControlPanelsContainerProps) =>
Boolean(controls?.server_pagination?.value),
validators: [validateInteger],
validators: [withLabel(validateInteger, t('Server Page Length'))],
},
},
],
Expand All @@ -403,7 +404,7 @@ const config: ControlPanelConfig = {
state?.common?.conf?.SQL_MAX_ROW,
}),
validators: [
validateInteger,
withLabel(validateInteger, t('Row limit')),
(v, state) =>
validateMaxValue(
v,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@
* under the License.
*/
import { t } from '@apache-superset/core';
import { validateInteger, validateNonEmpty } from '@superset-ui/core';
import {
validateInteger,
validateNonEmpty,
withLabel,
} from '@superset-ui/core';
import { GenericDataType } from '@apache-superset/core/api/core';
import {
ControlPanelConfig,
Expand Down Expand Up @@ -66,7 +70,7 @@ const config: ControlPanelConfig = {
default: 5,
choices: formatSelectOptionsForRange(5, 20, 5),
description: t('The number of bins for the histogram'),
validators: [validateInteger],
validators: [withLabel(validateInteger, t('Bins'))],
},
},
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import {
SMART_DATE_ID,
validateMaxValue,
validateServerPagination,
withLabel,
} from '@superset-ui/core';
import { GenericDataType } from '@apache-superset/core/api/core';
import { isEmpty, last } from 'lodash';
Expand Down Expand Up @@ -407,7 +408,7 @@ const config: ControlPanelConfig = {
description: t('Rows per page, 0 means no pagination'),
visibility: ({ controls }: ControlPanelsContainerProps) =>
Boolean(controls?.server_pagination?.value),
validators: [validateInteger],
validators: [withLabel(validateInteger, t('Server Page Length'))],
},
},
],
Expand All @@ -426,7 +427,7 @@ const config: ControlPanelConfig = {
state?.common?.conf?.SQL_MAX_ROW,
}),
validators: [
validateInteger,
withLabel(validateInteger, t('Row limit')),
(v, state) =>
validateMaxValue(
v,
Expand All @@ -448,9 +449,6 @@ const config: ControlPanelConfig = {
'Limits the number of the rows that are computed in the query that is the source of the data used for this chart.',
),
},
override: {
default: 1000,
},
},
],
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ export function applyMapStateToPropsToControl<T = ControlType>(
}
}
// If no current value, set it as default
if (state.default && value === undefined) {
// Use loose equality to catch both null and undefined
if (state.default != null && value == null) {
value = state.default;
}
// If a choice control went from multi=false to true, wrap value in array
Expand Down
6 changes: 6 additions & 0 deletions superset/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,12 @@ class D3TimeFormat(TypedDict, total=False):
# @lifecycle: testing
# @docs: https://superset.apache.org/docs/configuration/setup-ssh-tunneling
"SSH_TUNNELING": False,
# Enable AWS IAM authentication for database connections (Aurora, Redshift).
# Allows cross-account role assumption via STS AssumeRole.
# Security note: When enabled, ensure Superset's IAM role has restricted
# sts:AssumeRole permissions to prevent unauthorized access.
# @lifecycle: testing
"AWS_DATABASE_IAM_AUTH": False,
# Use analogous colors in charts
# @lifecycle: testing
"USE_ANALOGOUS_COLORS": False,
Expand Down
Loading
Loading