-
Notifications
You must be signed in to change notification settings - Fork 8.5k
Add notifications plugin, offering basic email service #143303
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
gsoldevila
merged 61 commits into
elastic:main
from
gsoldevila:kbn-140743-notifications-api-mvp
Nov 3, 2022
Merged
Changes from all commits
Commits
Show all changes
61 commits
Select commit
Hold shift + click to select a range
2a93a37
Adding unsecured actions client
ymao1 dc9829e
Merge remote-tracking branch 'remotes/ymao/actions/unsecured-client' …
gsoldevila 2fe5ce5
Removing isESOCanEncrypt check
ymao1 dbed0a8
Only getting actions client when needed in executor
ymao1 4af9bc6
Merge remote-tracking branch 'remotes/ymao/actions/unsecured-client' …
gsoldevila c3ce0b1
First draft
gsoldevila 00c611d
Changing to feature id allowlist. Adding unit tests
ymao1 b0fba11
Merge branch 'main' of https://github.com/elastic/kibana into actions…
ymao1 baf051a
Removing execution id
ymao1 96b696f
Cleanup
ymao1 6cf7a3a
Fixing unit tests
ymao1 74aa62d
Merge remote-tracking branch 'remotes/ymao/actions/unsecured-client' …
gsoldevila fa4a356
Merge branch 'main' of https://github.com/elastic/kibana into actions…
ymao1 8865a80
Removing slack from allowlist
ymao1 7c884ae
Make getUnsecuredActionsClient synchronous
ymao1 f4c1851
Add comment
ymao1 3b7a388
Merge remote-tracking branch 'remotes/ymao/actions/unsecured-client' …
gsoldevila 4b7f482
Misc enhancements following PR comments
gsoldevila 9a58040
Merge branch 'main' of https://github.com/elastic/kibana into actions…
ymao1 47f1ca9
Adding functional tests
ymao1 c87baee
Fixing types
ymao1 28c6632
Fixing tests
ymao1 db2dc2a
Merge branch 'main' of https://github.com/elastic/kibana into actions…
ymao1 d5bf4ff
Merge branch 'main' of https://github.com/elastic/kibana into actions…
ymao1 026646a
Removing unnecessary Promise.all
ymao1 ea31342
Merge remote-tracking branch 'remotes/ymao/actions/unsecured-client' …
gsoldevila 802dfa0
Cleanup
ymao1 c048225
Misc fixes and simplifications
gsoldevila f149cac
Merge remote-tracking branch 'remotes/ymao/actions/unsecured-client' …
gsoldevila cd500db
Add missing tsconfig.json
gsoldevila a293085
[CI] Auto-commit changed files from 'node scripts/build_plugin_list_d…
kibanamachine ff65387
Merge branch 'main' into kbn-140743-notifications-api-mvp
gsoldevila e241d0d
Add dependency to Actions plugin in tsconfig.json
gsoldevila 0079193
Merge branch 'main' into kbn-140743-notifications-api-mvp
gsoldevila 7f358bf
Separate setup logic from start logic
gsoldevila 8929996
Fix bulkEnqueueExecution params structure
gsoldevila fd4b2ef
Update README
gsoldevila c344a61
Add UTs
gsoldevila b02bd81
Merge branch 'main' into kbn-140743-notifications-api-mvp
gsoldevila 53575d9
Check license type >platinum for email notifications
gsoldevila 52e7c8c
Merge branch 'main' into kbn-140743-notifications-api-mvp
gsoldevila f214324
Fix incorrect UTs
gsoldevila e0dd0f7
Import types when possible
gsoldevila 8218cc4
Misc enhancements and code cleanup
gsoldevila 0ccf326
Transform factory => provider, update start contract
gsoldevila a561085
Merge branch 'main' into kbn-140743-notifications-api-mvp
gsoldevila 2d26740
Fix merge-related issues
gsoldevila 3ed6752
Code cleanup, update README
gsoldevila 9dbe577
Fix TS error
gsoldevila 0238877
Support list of spaces for each related SO
gsoldevila 06ff938
Merge branch 'main' into kbn-140743-notifications-api-mvp
gsoldevila dc4c9a6
Accept single spaceId for related SOs. Add convenience mocks
gsoldevila 2654fee
Merge branch 'main' into kbn-140743-notifications-api-mvp
gsoldevila 1467966
Merge branch 'main' into kbn-140743-notifications-api-mvp
gsoldevila 091eb74
Merge branch 'main' into kbn-140743-notifications-api-mvp
gsoldevila d6e46f5
Fix CI types error
gsoldevila 8d026c5
Address PR remarks
gsoldevila f275913
Merge branch 'main' into kbn-140743-notifications-api-mvp
gsoldevila 56f99c9
Merge branch 'main' into kbn-140743-notifications-api-mvp
gsoldevila 3aef92a
Address PR remarks #2
gsoldevila 439b3e7
Merge branch 'main' into kbn-140743-notifications-api-mvp
gsoldevila File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| # Kibana Notifications Plugin | ||
|
|
||
| The Notifications plugin provides a set of services to help Solutions and plugins send notifications to users. | ||
|
|
||
| ## Notifications Plugin public API | ||
|
|
||
| ### Start | ||
|
|
||
| The `start` function exposes the following interface: | ||
|
|
||
| - `isEmailServiceAvailable(): boolean`: | ||
| A function to check whether the deployment is properly configured and the EmailService can be correctly retrieved. | ||
| - `getEmailService(): EmailService`: | ||
| - A function to get the basic EmailService, which can be used to send plain text emails. If the EmailService is not available, trying to retrieve it will result in an Exception. | ||
|
|
||
|
|
||
| ### Usage | ||
|
|
||
| To use the exposed plugin start contract: | ||
|
|
||
| 1. Make sure `notifications` is in your `optionalPlugins` in the `kibana.json` file: | ||
|
|
||
| ```json5 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, TIL: |
||
| // <plugin>/kibana.json | ||
| { | ||
| "id": "...", | ||
| "requiredPlugins": ["notifications"] | ||
| } | ||
| ``` | ||
|
|
||
| 2. Use the exposed contract: | ||
|
|
||
| ```ts | ||
| // <plugin>/server/plugin.ts | ||
| import { NotificationsPluginStart } from '../notifications/server`; | ||
|
|
||
| interface MyPluginStartDeps { | ||
| notifications?: NotificationsPluginStart; | ||
| } | ||
|
|
||
| class MyPlugin { | ||
| public start( | ||
| core: CoreStart, | ||
| { notifications }: MyPluginStartDeps | ||
| ) { | ||
| if (notifications.isEmailServiceAvailable()) { | ||
| const emailService = notifications.getEmailService(); | ||
| emailService.sendPlainTextEmail({ | ||
| to: '[email protected]', | ||
| subject: 'Some subject', | ||
| message: 'Hello world!', | ||
| }); | ||
| } | ||
| ... | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### Requirements | ||
|
|
||
| - This plugin currently depends on the `'actions'` plugin, as it uses `Connectors` under the hood. | ||
| - Note also that for each notification channel the corresponding connector must be preconfigured. E.g. to enable email notifications, an `Email` connector must exist in the system. | ||
| - Once the appropriate connectors are preconfigured in `kibana.yaml`, you can configure the `'notifications'` plugin by adding: | ||
|
|
||
| ```yaml | ||
| notifications: | ||
| connectors: | ||
| default: | ||
| email: elastic-cloud-email # The identifier of the configured connector | ||
| ``` | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| export const PLUGIN_ID = 'notifications'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| module.exports = { | ||
| preset: '@kbn/test/jest_node', | ||
| rootDir: '../../..', | ||
| roots: ['<rootDir>/x-pack/plugins/notifications'], | ||
| coverageDirectory: '<rootDir>/target/kibana-coverage/jest/x-pack/plugins/notifications', | ||
| coverageReporters: ['text', 'html'], | ||
| collectCoverageFrom: ['<rootDir>/x-pack/plugins/notifications/{common,server}/**/*.{js,ts,tsx}'], | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| { | ||
| "id": "notifications", | ||
| "owner": { | ||
| "name": "App Services", | ||
| "githubTeam": "kibana-app-services" | ||
| }, | ||
| "version": "kibana", | ||
| "server": true, | ||
| "ui": false, | ||
| "requiredPlugins": ["actions", "licensing"], | ||
| "optionalPlugins": [] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| import { schema, type TypeOf } from '@kbn/config-schema'; | ||
| import type { PluginConfigDescriptor } from '@kbn/core/server'; | ||
|
|
||
| export const configSchema = schema.object( | ||
| { | ||
| connectors: schema.maybe( | ||
| schema.object({ | ||
| default: schema.maybe( | ||
| schema.object({ | ||
| email: schema.maybe(schema.string()), | ||
| }) | ||
| ), | ||
| }) | ||
| ), | ||
| }, | ||
| { defaultValue: {} } | ||
| ); | ||
| export type NotificationsConfigType = TypeOf<typeof configSchema>; | ||
|
|
||
| export const config: PluginConfigDescriptor<NotificationsConfigType> = { | ||
| schema: configSchema, | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| export { type NotificationsConfigType, config } from './config'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| import type { PluginInitializerContext } from '@kbn/core/server'; | ||
| import { NotificationsPlugin } from './plugin'; | ||
| export { config } from './config'; | ||
|
|
||
| // This exports static code and TypeScript types, | ||
| // as well as, Kibana Platform `plugin()` initializer. | ||
| export type { NotificationsPluginStart } from './types'; | ||
|
|
||
| export function plugin(initializerContext: PluginInitializerContext) { | ||
| return new NotificationsPlugin(initializerContext); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| import type { PublicMethodsOf } from '@kbn/utility-types'; | ||
| import type { EmailService } from './services'; | ||
| import type { NotificationsPluginStart } from './types'; | ||
| import type { NotificationsPlugin } from './plugin'; | ||
|
|
||
| const emailServiceMock: jest.Mocked<EmailService> = { | ||
| sendPlainTextEmail: jest.fn(), | ||
| }; | ||
|
|
||
| const createEmailServiceMock = () => { | ||
| return emailServiceMock; | ||
| }; | ||
|
|
||
| const startMock: jest.Mocked<NotificationsPluginStart> = { | ||
| isEmailServiceAvailable: jest.fn(), | ||
| getEmailService: jest.fn(createEmailServiceMock), | ||
| }; | ||
|
|
||
| const createStartMock = () => { | ||
| return startMock; | ||
| }; | ||
|
|
||
| const notificationsPluginMock: jest.Mocked<PublicMethodsOf<NotificationsPlugin>> = { | ||
| setup: jest.fn(), | ||
| start: jest.fn(createStartMock) as jest.Mock<NotificationsPluginStart>, | ||
| stop: jest.fn(), | ||
| }; | ||
|
|
||
| const createNotificationsPluginMock = () => { | ||
| return notificationsPluginMock; | ||
| }; | ||
|
|
||
| export const notificationsMock = { | ||
| createNotificationsPlugin: createNotificationsPluginMock, | ||
| createEmailService: createEmailServiceMock, | ||
| createStart: createStartMock, | ||
| clear: () => { | ||
| emailServiceMock.sendPlainTextEmail.mockClear(); | ||
| startMock.getEmailService.mockClear(); | ||
| startMock.isEmailServiceAvailable.mockClear(); | ||
| notificationsPluginMock.setup.mockClear(); | ||
| notificationsPluginMock.start.mockClear(); | ||
| notificationsPluginMock.stop.mockClear(); | ||
| }, | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,107 @@ | ||
| /* | ||
| * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
| * or more contributor license agreements. Licensed under the Elastic License | ||
| * 2.0; you may not use this file except in compliance with the Elastic License | ||
| * 2.0. | ||
| */ | ||
|
|
||
| import { coreMock } from '@kbn/core/server/mocks'; | ||
| import { actionsMock } from '@kbn/actions-plugin/server/mocks'; | ||
| import type { NotificationsConfigType } from './config'; | ||
| import { NotificationsPlugin } from './plugin'; | ||
| import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; | ||
| import { EmailServiceProvider } from './services/connectors_email_service_provider'; | ||
| import { EmailServiceStart } from './services'; | ||
|
|
||
| jest.mock('./services/connectors_email_service_provider'); | ||
|
|
||
| const emailServiceProviderMock = EmailServiceProvider as jest.MockedClass< | ||
| typeof EmailServiceProvider | ||
| >; | ||
|
|
||
| const validConnectorConfig = { | ||
| connectors: { | ||
| default: { | ||
| email: 'validConnectorId', | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| const createNotificationsPlugin = (config: NotificationsConfigType) => { | ||
| const context = coreMock.createPluginInitializerContext<NotificationsConfigType>(config); | ||
| const plugin = new NotificationsPlugin(context); | ||
| const coreSetup = coreMock.createSetup(); | ||
| const coreStart = coreMock.createStart(); | ||
|
|
||
| const actionsSetup = actionsMock.createSetup(); | ||
| actionsSetup.isPreconfiguredConnector.mockImplementationOnce( | ||
| (connectorId) => connectorId === 'validConnectorId' | ||
| ); | ||
| const pluginSetup = { | ||
| actions: actionsSetup, | ||
| licensing: licensingMock.createSetup(), | ||
| }; | ||
|
|
||
| const actionsStart = actionsMock.createStart(); | ||
| const pluginStart = { | ||
| actions: actionsStart, | ||
| licensing: licensingMock.createStart(), | ||
| }; | ||
|
|
||
| return { | ||
| context, | ||
| logger: context.logger.get(), | ||
| plugin, | ||
| coreSetup, | ||
| coreStart, | ||
| actionsSetup, | ||
| pluginSetup, | ||
| actionsStart, | ||
| pluginStart, | ||
| }; | ||
| }; | ||
|
|
||
| describe('Notifications Plugin', () => { | ||
| beforeEach(() => emailServiceProviderMock.mockClear()); | ||
|
|
||
| it('should create an EmailServiceProvider passing in the configuration and logger from the initializer context', () => { | ||
| const { logger } = createNotificationsPlugin(validConnectorConfig); | ||
| expect(emailServiceProviderMock).toHaveBeenCalledTimes(1); | ||
| expect(emailServiceProviderMock).toHaveBeenCalledWith(validConnectorConfig, logger); | ||
| }); | ||
|
|
||
| describe('setup()', () => { | ||
| it('should call setup() on the created EmailServiceProvider, passing in the setup plugin dependencies', () => { | ||
| const { plugin, coreSetup, pluginSetup } = createNotificationsPlugin(validConnectorConfig); | ||
| plugin.setup(coreSetup, pluginSetup); | ||
| expect(emailServiceProviderMock.mock.instances[0].setup).toHaveBeenCalledTimes(1); | ||
| expect(emailServiceProviderMock.mock.instances[0].setup).toBeCalledWith(pluginSetup); | ||
| }); | ||
| }); | ||
|
|
||
| describe('start()', () => { | ||
| it('should call start() on the created EmailServiceProvider, passing in the setup plugin dependencies', () => { | ||
| const { plugin, coreStart, pluginStart } = createNotificationsPlugin(validConnectorConfig); | ||
| plugin.start(coreStart, pluginStart); | ||
| expect(emailServiceProviderMock.mock.instances[0].start).toHaveBeenCalledTimes(1); | ||
| expect(emailServiceProviderMock.mock.instances[0].start).toBeCalledWith(pluginStart); | ||
| }); | ||
|
|
||
| it('should return EmailServiceProvider.start() contract as part of its contract', () => { | ||
| const { plugin, coreStart, pluginStart } = createNotificationsPlugin(validConnectorConfig); | ||
|
|
||
| const emailStart: EmailServiceStart = { | ||
| getEmailService: jest.fn(), | ||
| isEmailServiceAvailable: jest.fn(), | ||
| }; | ||
|
|
||
| const providerMock = emailServiceProviderMock.mock | ||
| .instances[0] as jest.Mocked<EmailServiceProvider>; | ||
| providerMock.start.mockReturnValue(emailStart); | ||
| const start = plugin.start(coreStart, pluginStart); | ||
| expect(emailServiceProviderMock.mock.instances[0].start).toHaveBeenCalledTimes(1); | ||
| expect(emailServiceProviderMock.mock.instances[0].start).toBeCalledWith(pluginStart); | ||
| expect(start).toEqual(expect.objectContaining(emailStart)); | ||
| }); | ||
| }); | ||
| }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.