[8.17] [Canvas/PDF report] Allow canvas to generate PDF report (#224309) (#224340)

# Backport

This will backport the following commits from `main` to `8.17`:
- [[Canvas/PDF report] Allow canvas to generate PDF report
(#224309)](https://github.com/elastic/kibana/pull/224309)

<!--- Backport version: 10.0.1 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Tim
Sullivan","email":"tsullivan@users.noreply.github.com"},"sourceCommit":{"committedDate":"2025-06-17T22:47:22Z","message":"[Canvas/PDF
report] Allow canvas to generate PDF report (#224309)\n\n##
Summary\n\nCloses
https://github.com/elastic/kibana/issues/224275\n\n**Context:** In
https://github.com/elastic/kibana/pull/222273, we added\nrestrictions to
the \"Reporting redirect app\" to make sure it could not\nbe abused by
using unexpected locator types (such as the short URL\nlocator or the
\"legacy\" locator type) when triggering redirects in the\nReporting
headless browser. The restrictions are on the basis of a list\nof
allowed locator types, which should be a list of every analytical
app\nthat supports Reporting.\n\n**Problem:** Unfortunately that added a
regression to Canvas PDF\nreporting, because the allow-list for locator
types neglected to include\nthe Canvas locator type.\n\nThis PR solves
the problem by adding the Canvas locator type to the set\nof allowed
locator types.\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"f5dee1347f019d4e98a45070eeb80356453a9827","branchLabelMapping":{"^v9.1.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport:version","v8.15.6","v9.1.0","v8.19.0","v7.17.29","v9.0.3","v8.18.3","v8.17.8"],"title":"[Canvas/PDF
report] Allow canvas to generate PDF
report","number":224309,"url":"https://github.com/elastic/kibana/pull/224309","mergeCommit":{"message":"[Canvas/PDF
report] Allow canvas to generate PDF report (#224309)\n\n##
Summary\n\nCloses
https://github.com/elastic/kibana/issues/224275\n\n**Context:** In
https://github.com/elastic/kibana/pull/222273, we added\nrestrictions to
the \"Reporting redirect app\" to make sure it could not\nbe abused by
using unexpected locator types (such as the short URL\nlocator or the
\"legacy\" locator type) when triggering redirects in the\nReporting
headless browser. The restrictions are on the basis of a list\nof
allowed locator types, which should be a list of every analytical
app\nthat supports Reporting.\n\n**Problem:** Unfortunately that added a
regression to Canvas PDF\nreporting, because the allow-list for locator
types neglected to include\nthe Canvas locator type.\n\nThis PR solves
the problem by adding the Canvas locator type to the set\nof allowed
locator types.\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"f5dee1347f019d4e98a45070eeb80356453a9827"}},"sourceBranch":"main","suggestedTargetBranches":["8.15","7.17","9.0","8.18","8.17"],"targetPullRequestStates":[{"branch":"8.15","label":"v8.15.6","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/224309","number":224309,"mergeCommit":{"message":"[Canvas/PDF
report] Allow canvas to generate PDF report (#224309)\n\n##
Summary\n\nCloses
https://github.com/elastic/kibana/issues/224275\n\n**Context:** In
https://github.com/elastic/kibana/pull/222273, we added\nrestrictions to
the \"Reporting redirect app\" to make sure it could not\nbe abused by
using unexpected locator types (such as the short URL\nlocator or the
\"legacy\" locator type) when triggering redirects in the\nReporting
headless browser. The restrictions are on the basis of a list\nof
allowed locator types, which should be a list of every analytical
app\nthat supports Reporting.\n\n**Problem:** Unfortunately that added a
regression to Canvas PDF\nreporting, because the allow-list for locator
types neglected to include\nthe Canvas locator type.\n\nThis PR solves
the problem by adding the Canvas locator type to the set\nof allowed
locator types.\n\n---------\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"f5dee1347f019d4e98a45070eeb80356453a9827"}},{"branch":"8.19","label":"v8.19.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"url":"https://github.com/elastic/kibana/pull/224335","number":224335,"state":"OPEN"},{"branch":"7.17","label":"v7.17.29","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"9.0","label":"v9.0.3","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.18","label":"v8.18.3","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.17","label":"v8.17.8","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->
This commit is contained in:
Tim Sullivan 2025-06-18 08:47:36 -07:00 committed by GitHub
parent 86eaa660eb
commit d85acb2925
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 48 additions and 6 deletions

View file

@ -7,6 +7,8 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/
export const CANVAS_APP_LOCATOR = 'CANVAS_APP_LOCATOR';
export const DISCOVER_APP_ID = 'discover';
export const DASHBOARD_APP_ID = 'dashboards';

View file

@ -8,6 +8,7 @@
*/
export {
CANVAS_APP_LOCATOR,
DASHBOARD_APP_ID,
DISCOVER_APP_ID,
VISUALIZE_APP_ID,

View file

@ -8,6 +8,7 @@
*/
import {
CANVAS_APP_LOCATOR,
DASHBOARD_APP_LOCATOR,
LENS_APP_LOCATOR,
VISUALIZE_APP_LOCATOR,
@ -53,6 +54,7 @@ export const JOB_COMPLETION_NOTIFICATIONS_SESSION_KEY =
// Allowed locator types for reporting: the "reportable" analytical apps we expect to redirect to during screenshotting
export const REPORTING_REDIRECT_ALLOWED_LOCATOR_TYPES = [
CANVAS_APP_LOCATOR,
DASHBOARD_APP_LOCATOR,
LENS_APP_LOCATOR,
VISUALIZE_APP_LOCATOR,

View file

@ -10,4 +10,3 @@ export const UI_SETTINGS = {
};
export type { CanvasAppLocator, CanvasAppLocatorParams } from './locator';
export { CANVAS_APP_LOCATOR } from './locator';

View file

@ -6,6 +6,7 @@
*/
import type { LocatorDefinition, LocatorPublic } from '@kbn/share-plugin/common';
import { CANVAS_APP_LOCATOR } from '@kbn/deeplinks-analytics';
import { CANVAS_APP } from './lib/constants';
@ -18,8 +19,6 @@ export type CanvasAppLocatorParams = {
export type CanvasAppLocator = LocatorPublic<CanvasAppLocatorParams>;
export const CANVAS_APP_LOCATOR = 'CANVAS_APP_LOCATOR';
export class CanvasAppLocatorDefinition implements LocatorDefinition<CanvasAppLocatorParams> {
id = CANVAS_APP_LOCATOR;

View file

@ -7,7 +7,8 @@
import type { RedirectOptions } from '@kbn/share-plugin/public';
import { JobAppParamsPDFV2 } from '@kbn/reporting-export-types-pdf-common';
import { CanvasAppLocatorParams, CANVAS_APP_LOCATOR } from '../../../../common/locator';
import { CANVAS_APP_LOCATOR } from '@kbn/deeplinks-analytics';
import { CanvasAppLocatorParams } from '../../../../common/locator';
import { CanvasWorkpad } from '../../../../types';
export interface CanvasWorkpadSharingData {

View file

@ -89,7 +89,8 @@
"@kbn/presentation-containers",
"@kbn/presentation-publishing",
"@kbn/react-kibana-context-render",
"@kbn/search-types"
"@kbn/search-types",
"@kbn/deeplinks-analytics"
],
"exclude": ["target/**/*"]
}

View file

@ -21,6 +21,7 @@ export const DownloadButton = ({ getUrl, job }: Props) => {
<EuiButton
size="s"
data-test-subj="downloadCompletedReportButton"
data-test-jobId={job.id}
href={getUrl(job.id)}
target="_blank"
>

View file

@ -66,6 +66,12 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
expect(res.get('content-disposition')).to.equal(
'attachment; filename=The%20Very%20Cool%20Workpad%20for%20PDF%20Tests.pdf'
);
const jobId = await reporting.getReportJobId(60000);
const reportInfo = await reporting.getReportInfo(jobId);
// verify "completed" status (no warnings)
expect(reportInfo).to.have.property('status', 'completed');
});
});
});

View file

@ -12,7 +12,7 @@ import type SuperTest from 'supertest';
import { format as formatUrl } from 'url';
import { promisify } from 'util';
import { REPORT_TABLE_ID, REPORT_TABLE_ROW_ID } from '@kbn/reporting-common';
import { INTERNAL_ROUTES, REPORT_TABLE_ID, REPORT_TABLE_ROW_ID } from '@kbn/reporting-common';
import { FtrService } from '../ftr_provider_context';
const writeFileAsync = promisify(fs.writeFile);
@ -37,6 +37,30 @@ export class ReportingPageObject extends FtrService {
`);
}
async getReportJobId(timeout: number): Promise<string> {
this.log.debug('getReportJobId');
try {
// get the report job id from a data attribute on the download button
const jobIdElement = await this.find.byCssSelector('[data-test-jobId]', timeout);
if (!jobIdElement) {
throw new Error('Failed to find report job id.');
}
const jobId = await jobIdElement.getAttribute('data-test-jobId');
if (!jobId) {
throw new Error('Failed to find report job id.');
}
return jobId;
} catch (err) {
let errorText = 'Unknown error';
if (await this.find.existsByCssSelector('[data-test-errorText]')) {
const errorTextEl = await this.find.byCssSelector('[data-test-errorText]');
errorText = (await errorTextEl.getAttribute('data-test-errorText')) ?? errorText;
}
throw new Error(`Test report failed: ${errorText}: ${err}`, { cause: err });
}
}
async getReportURL(timeout: number) {
this.log.debug('getReportURL');
@ -77,6 +101,12 @@ export class ReportingPageObject extends FtrService {
return res ?? '';
}
async getReportInfo(jobId: string) {
this.log.debug(`getReportInfo for ${jobId}`);
const response = await this.getResponse(INTERNAL_ROUTES.JOBS.INFO_PREFIX + `/${jobId}`);
return response.body;
}
async getRawReportData(url: string): Promise<Buffer> {
this.log.debug(`getRawReportData for ${url}`);
const response = await this.getResponse(url);