Skip to content

Commit

Permalink
[Reporting] Convert Export Type Definitions to Typescript (#51643)
Browse files Browse the repository at this point in the history
* simplify ts

* fix generate_png + get_full_url

* fix pdf execute job

* fix pdf create job

* fix decrypt job headers

* fix generate pdf / generate png

* remove log

* export consts

* move export type registration to ts

* more export type registration to ts

* ts generics

* remove console.log

* use generics

* fix ts

* fix ts

* fix ts

* fix ts

* Multi-type handling readability fix

* Support createJob's jobParams

* i18n fixes

* track down mysterious field

* revisit ts-ignores

* remove an any type in get_conditional_headers

* ts fixes

* typed export treatment for csv_from_savedobject#executeJob

* refactor helper function plain bonkers signature

* i18n merge fix

* add error handling test

* todo

* fix .headers type def

* Reduce number of loc change

* remove unused params from generic signatures

* Remove as/any

* hoist out GenericWorkerFn for naming

* remove unnecessary fields from JobDocPayloadPanelCsv

* Introduce user defined type guard
  • Loading branch information
tsullivan authored Dec 3, 2019
1 parent c4143b2 commit 45ef370
Show file tree
Hide file tree
Showing 45 changed files with 421 additions and 367 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/

// @ts-ignore
import { cryptoFactory } from '../../../server/lib/crypto';
import { createMockServer } from '../../../test_helpers/create_mock_server';
import { decryptJobHeaders } from './index';
import { Logger } from '../../../types';
import { decryptJobHeaders } from './decrypt_job_headers';

let mockServer: any;
beforeEach(() => {
Expand All @@ -24,17 +24,16 @@ describe('headers', () => {
await expect(
decryptJobHeaders({
job: {
title: 'cool-job-bro',
type: 'csv',
jobParams: {
savedObjectId: 'abc-123',
isImmediate: false,
savedObjectType: 'search',
},
headers: 'Q53+9A+zf+Xe+ceR/uB/aR/Sw/8e+M+qR+WiG+8z+EY+mo+HiU/zQL+Xn',
},
logger: ({
error: jest.fn(),
} as unknown) as Logger,
server: mockServer,
})
).rejects.toBeDefined();
).rejects.toMatchInlineSnapshot(
`[Error: Failed to decrypt report job data. Please ensure that xpack.reporting.encryptionKey is set and re-generate this report. Error: Invalid IV length]`
);
});

test(`passes back decrypted headers that were passed in`, async () => {
Expand All @@ -48,13 +47,9 @@ describe('headers', () => {
job: {
title: 'cool-job-bro',
type: 'csv',
jobParams: {
savedObjectId: 'abc-123',
isImmediate: false,
savedObjectType: 'search',
},
headers: encryptedHeaders,
},
logger: {} as Logger,
server: mockServer,
});
expect(decryptedHeaders).toEqual(headers);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,48 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
// @ts-ignore

import { i18n } from '@kbn/i18n';
import { cryptoFactory } from '../../../server/lib/crypto';
import { CryptoFactory, JobDocPayload, ServerFacade } from '../../../types';
import { CryptoFactory, ServerFacade, Logger } from '../../../types';

interface HasEncryptedHeaders {
headers?: string;
}

export const decryptJobHeaders = async ({
// TODO merge functionality with CSV execute job
export const decryptJobHeaders = async <
JobParamsType,
JobDocPayloadType extends HasEncryptedHeaders
>({
job,
server,
logger,
}: {
job: JobDocPayload;
job: JobDocPayloadType;
server: ServerFacade;
}) => {
logger: Logger;
}): Promise<{
job: JobDocPayloadType;
server: ServerFacade;
decryptedHeaders: Record<string, string>;
}> => {
const crypto: CryptoFactory = cryptoFactory(server);
const decryptedHeaders: string = await crypto.decrypt(job.headers);
return { job, decryptedHeaders, server };
try {
const decryptedHeaders: Record<string, string> = await crypto.decrypt(job.headers);
return { job, decryptedHeaders, server };
} catch (err) {
logger.error(err);

throw new Error(
i18n.translate(
'xpack.reporting.exportTypes.common.failedToDecryptReportJobDataErrorMessage',
{
defaultMessage:
'Failed to decrypt report job data. Please ensure that {encryptionKey} is set and re-generate this report. {err}',
values: { encryptionKey: 'xpack.reporting.encryptionKey', err: err.toString() },
}
)
);
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ describe('conditions', () => {
};

const { conditionalHeaders } = await getConditionalHeaders({
job: {} as JobDocPayload,
job: {} as JobDocPayload<any>,
filteredHeaders: permittedHeaders,
server: mockServer,
});
Expand All @@ -45,7 +45,7 @@ describe('conditions', () => {
};

const { conditionalHeaders } = await getConditionalHeaders({
job: {} as JobDocPayload,
job: {} as JobDocPayload<any>,
filteredHeaders: permittedHeaders,
server: mockServer,
});
Expand All @@ -66,7 +66,7 @@ describe('conditions', () => {
};

const { conditionalHeaders } = await getConditionalHeaders({
job: {} as JobDocPayload,
job: {} as JobDocPayload<any>,
filteredHeaders: permittedHeaders,
server: mockServer,
});
Expand All @@ -83,7 +83,7 @@ describe('conditions', () => {
};

const { conditionalHeaders } = await getConditionalHeaders({
job: {} as JobDocPayload,
job: {} as JobDocPayload<any>,
filteredHeaders: permittedHeaders,
server: mockServer,
});
Expand All @@ -98,7 +98,7 @@ describe('conditions', () => {
};

const { conditionalHeaders } = await getConditionalHeaders({
job: {} as JobDocPayload,
job: {} as JobDocPayload<any>,
filteredHeaders: permittedHeaders,
server: mockServer,
});
Expand All @@ -121,7 +121,7 @@ describe('conditions', () => {
};

const { conditionalHeaders } = await getConditionalHeaders({
job: {} as JobDocPayload,
job: {} as JobDocPayload<any>,
filteredHeaders: permittedHeaders,
server: mockServer,
});
Expand All @@ -138,7 +138,7 @@ describe('conditions', () => {
};

const { conditionalHeaders } = await getConditionalHeaders({
job: {} as JobDocPayload,
job: {} as JobDocPayload<any>,
filteredHeaders: permittedHeaders,
server: mockServer,
});
Expand All @@ -154,7 +154,7 @@ test('uses basePath from job when creating saved object service', async () => {
};

const { conditionalHeaders } = await getConditionalHeaders({
job: {} as JobDocPayload,
job: {} as JobDocPayload<any>,
filteredHeaders: permittedHeaders,
server: mockServer,
});
Expand All @@ -181,7 +181,7 @@ test(`uses basePath from server if job doesn't have a basePath when creating sav
};

const { conditionalHeaders } = await getConditionalHeaders({
job: {} as JobDocPayload,
job: {} as JobDocPayload<any>,
filteredHeaders: permittedHeaders,
server: mockServer,
});
Expand All @@ -204,7 +204,7 @@ describe('config formatting', () => {
test(`lowercases server.host`, async () => {
mockServer = createMockServer({ settings: { 'server.host': 'COOL-HOSTNAME' } });
const { conditionalHeaders } = await getConditionalHeaders({
job: {} as JobDocPayload,
job: {} as JobDocPayload<any>,
filteredHeaders: {},
server: mockServer,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { ConditionalHeaders, JobDocPayload, ServerFacade } from '../../../types';
import { ConditionalHeaders, ServerFacade } from '../../../types';

export const getConditionalHeaders = ({
export const getConditionalHeaders = <JobDocPayloadType>({
job,
filteredHeaders,
server,
}: {
job: JobDocPayload;
job: JobDocPayloadType;
filteredHeaders: Record<string, string>;
server: ServerFacade;
}) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,17 @@
*/

import { createMockServer } from '../../../test_helpers/create_mock_server';
import { ServerFacade } from '../../../types';
import { JobDocPayloadPNG } from '../../png/types';
import { JobDocPayloadPDF } from '../../printable_pdf/types';
import { getFullUrls } from './get_full_urls';

interface FullUrlsOpts {
job: JobDocPayloadPNG & JobDocPayloadPDF;
server: ServerFacade;
conditionalHeaders: any;
}

let mockServer: any;
beforeEach(() => {
mockServer = createMockServer('');
Expand All @@ -17,9 +24,9 @@ beforeEach(() => {
test(`fails if no URL is passed`, async () => {
await expect(
getFullUrls({
job: {} as JobDocPayloadPNG,
job: {},
server: mockServer,
})
} as FullUrlsOpts)
).rejects.toMatchInlineSnapshot(
`[Error: No valid URL fields found in Job Params! Expected \`job.relativeUrl\` or \`job.objects[{ relativeUrl }]\`]`
);
Expand All @@ -33,9 +40,9 @@ test(`fails if URLs are file-protocols for PNGs`, async () => {
job: {
relativeUrl,
forceNow,
} as JobDocPayloadPNG,
},
server: mockServer,
})
} as FullUrlsOpts)
).rejects.toMatchInlineSnapshot(
`[Error: Found invalid URL(s), all URLs must be relative: ${relativeUrl}]`
);
Expand All @@ -50,9 +57,9 @@ test(`fails if URLs are absolute for PNGs`, async () => {
job: {
relativeUrl,
forceNow,
} as JobDocPayloadPNG,
},
server: mockServer,
})
} as FullUrlsOpts)
).rejects.toMatchInlineSnapshot(
`[Error: Found invalid URL(s), all URLs must be relative: ${relativeUrl}]`
);
Expand All @@ -70,9 +77,9 @@ test(`fails if URLs are file-protocols for PDF`, async () => {
},
],
forceNow,
} as JobDocPayloadPDF,
},
server: mockServer,
})
} as FullUrlsOpts)
).rejects.toMatchInlineSnapshot(
`[Error: Found invalid URL(s), all URLs must be relative: ${relativeUrl}]`
);
Expand All @@ -91,9 +98,9 @@ test(`fails if URLs are absolute for PDF`, async () => {
},
],
forceNow,
} as JobDocPayloadPDF,
},
server: mockServer,
})
} as FullUrlsOpts)
).rejects.toMatchInlineSnapshot(
`[Error: Found invalid URL(s), all URLs must be relative: ${relativeUrl}]`
);
Expand All @@ -118,9 +125,9 @@ test(`fails if any URLs are absolute or file's for PDF`, async () => {
job: {
objects,
forceNow,
} as JobDocPayloadPDF,
},
server: mockServer,
})
} as FullUrlsOpts)
).rejects.toMatchInlineSnapshot(
`[Error: Found invalid URL(s), all URLs must be relative: ${objects[1].relativeUrl} ${objects[2].relativeUrl}]`
);
Expand All @@ -131,9 +138,9 @@ test(`fails if URL does not route to a visualization`, async () => {
getFullUrls({
job: {
relativeUrl: '/app/phoney',
} as JobDocPayloadPNG,
},
server: mockServer,
})
} as FullUrlsOpts)
).rejects.toMatchInlineSnapshot(
`[Error: No valid hash in the URL! A hash is expected for the application to route to the intended visualization.]`
);
Expand All @@ -145,9 +152,9 @@ test(`adds forceNow to hash's query, if it exists`, async () => {
job: {
relativeUrl: '/app/kibana#/something',
forceNow,
} as JobDocPayloadPNG,
},
server: mockServer,
});
} as FullUrlsOpts);

expect(urls[0]).toEqual(
'http://localhost:5601/sbp/app/kibana#/something?forceNow=2000-01-01T00%3A00%3A00.000Z'
Expand All @@ -161,9 +168,9 @@ test(`appends forceNow to hash's query, if it exists`, async () => {
job: {
relativeUrl: '/app/kibana#/something?_g=something',
forceNow,
} as JobDocPayloadPNG,
},
server: mockServer,
});
} as FullUrlsOpts);

expect(urls[0]).toEqual(
'http://localhost:5601/sbp/app/kibana#/something?_g=something&forceNow=2000-01-01T00%3A00%3A00.000Z'
Expand All @@ -174,9 +181,9 @@ test(`doesn't append forceNow query to url, if it doesn't exists`, async () => {
const { urls } = await getFullUrls({
job: {
relativeUrl: '/app/kibana#/something',
} as JobDocPayloadPNG,
},
server: mockServer,
});
} as FullUrlsOpts);

expect(urls[0]).toEqual('http://localhost:5601/sbp/app/kibana#/something');
});
Expand All @@ -192,9 +199,9 @@ test(`adds forceNow to each of multiple urls`, async () => {
{ relativeUrl: '/app/kibana#/something_ddd' },
],
forceNow,
} as JobDocPayloadPDF,
},
server: mockServer,
});
} as FullUrlsOpts);

expect(urls).toEqual([
'http://localhost:5601/sbp/app/kibana#/something_aaa?forceNow=2000-01-01T00%3A00%3A00.000Z',
Expand Down
Loading

0 comments on commit 45ef370

Please sign in to comment.