Skip to content
Closed
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
Original file line number Diff line number Diff line change
Expand Up @@ -97,14 +97,19 @@ export class UrlDrilldown implements Drilldown<Config, UrlTrigger, ActionFactory
config: Config,
context: ActionFactoryContext
): config is Config => {
const { isValid } = urlDrilldownValidateUrlTemplate(config.url, this.buildEditorScope(context));
const { isValid } = urlDrilldownValidateUrlTemplate(
config.url,
this.buildEditorScope(context),
config.disableEncoding
);
return isValid;
};

public readonly isCompatible = async (config: Config, context: ActionContext) => {
const { isValid, error } = urlDrilldownValidateUrlTemplate(
config.url,
await this.buildRuntimeScope(context)
await this.buildRuntimeScope(context),
config.disableEncoding
);

if (!isValid) {
Expand All @@ -118,10 +123,18 @@ export class UrlDrilldown implements Drilldown<Config, UrlTrigger, ActionFactory
};

public readonly getHref = async (config: Config, context: ActionContext) =>
urlDrilldownCompileUrl(config.url.template, this.buildRuntimeScope(context));
urlDrilldownCompileUrl(
config.url.template,
this.buildRuntimeScope(context),
config.disableEncoding
);

public readonly execute = async (config: Config, context: ActionContext) => {
const url = urlDrilldownCompileUrl(config.url.template, this.buildRuntimeScope(context));
const url = urlDrilldownCompileUrl(
config.url.template,
this.buildRuntimeScope(context),
config.disableEncoding
);
if (config.openInNewTab) {
window.open(url, '_blank', 'noopener');
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,10 @@ export const txtUrlTemplateOpenInNewTab = i18n.translate(
defaultMessage: 'Open in new tab',
}
);

export const txtDisableEncoding = i18n.translate(
'xpack.uiActionsEnhanced.drilldowns.urlDrilldownCollectConfig.disableEncoding',
{
defaultMessage: 'Disable encoding',
}
);
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
txtUrlTemplatePlaceholder,
txtUrlTemplatePreviewLabel,
txtUrlTemplatePreviewLinkText,
txtDisableEncoding,
} from './i18n';

export interface UrlDrilldownCollectConfig {
Expand All @@ -55,11 +56,11 @@ export const UrlDrilldownCollectConfig: React.FC<UrlDrilldownCollectConfig> = ({
const urlTemplate = config.url.template ?? '';
const compiledUrl = React.useMemo(() => {
try {
return compile(urlTemplate, scope);
return compile(urlTemplate, scope, config.disableEncoding);
} catch {
return urlTemplate;
}
}, [urlTemplate, scope]);
}, [urlTemplate, scope, config.disableEncoding]);
const scopeVariables = React.useMemo(() => buildScopeSuggestions(scope), [scope]);

function updateUrlTemplate(newUrlTemplate: string) {
Expand All @@ -74,8 +75,8 @@ export const UrlDrilldownCollectConfig: React.FC<UrlDrilldownCollectConfig> = ({
}
}
const { error, isValid } = React.useMemo(
() => validateUrlTemplate({ template: urlTemplate }, scope),
[urlTemplate, scope]
() => validateUrlTemplate({ template: urlTemplate }, scope, config.disableEncoding),
[urlTemplate, scope, config.disableEncoding]
);
const isEmpty = !urlTemplate;
const isInvalid = !isValid && !isEmpty;
Expand Down Expand Up @@ -154,6 +155,15 @@ export const UrlDrilldownCollectConfig: React.FC<UrlDrilldownCollectConfig> = ({
onChange={() => onConfig({ ...config, openInNewTab: !config.openInNewTab })}
/>
</EuiFormRow>
<EuiFormRow hasChildLabel={false}>
<EuiCheckbox
id="disableEncoding"
name="disableEncoding"
label={txtDisableEncoding}
checked={config.disableEncoding}
onChange={() => onConfig({ ...config, disableEncoding: !config.disableEncoding })}
/>
</EuiFormRow>
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
export type UrlDrilldownConfig = {
url: { format?: 'handlebars_v1'; template: string };
openInNewTab: boolean;
disableEncoding?: boolean;
};

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ test('should compile url without variables', () => {
expect(compile(url, {})).toBe(url);
});

test('by default, encodes URI', () => {
const url = 'https://elastic.co?foo=head%26shoulders';
expect(compile(url, {})).not.toBe(url);
expect(compile(url, {})).toBe('https://elastic.co?foo=head%2526shoulders');
});

test('when URI encoding is disabled, should not encode URI', () => {
const url =
'https://xxxxx.service-now.com/nav_to.do?uri=incident.do%3Fsys_id%3D-1%26sysparm_query%3Dshort_description%3DHello';
expect(compile(url, {}, true)).toBe(url);
});

test('should fail on unknown syntax', () => {
const url = 'https://elastic.co/{{}';
expect(() => compile(url, {})).toThrowError();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ handlebars.registerHelper('replace', (...args) => {
return String(str).split(searchString).join(valueString);
});

export function compile(url: string, context: object): string {
export function compile(url: string, context: object, disableEncoding?: boolean): string {
const template = handlebars.compile(url, { strict: true, noEscape: true });
return encodeURI(template(context));
let uri = template(context);
if (!disableEncoding) uri = encodeURI(uri);
return uri;
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ export function validateUrl(url: string): { isValid: boolean; error?: string } {

export function validateUrlTemplate(
urlTemplate: UrlDrilldownConfig['url'],
scope: UrlDrilldownScope
scope: UrlDrilldownScope,
disableEncoding?: boolean
): { isValid: boolean; error?: string } {
if (!urlTemplate.template)
return {
Expand All @@ -60,7 +61,7 @@ export function validateUrlTemplate(
};

try {
const compiledUrl = compile(urlTemplate.template, scope);
const compiledUrl = compile(urlTemplate.template, scope, disableEncoding);
return validateUrl(compiledUrl);
} catch (e) {
return {
Expand Down