diff --git a/plugins/main/public/components/settings/about/__snapshots__/appInfo.test.tsx.snap b/plugins/main/public/components/settings/about/__snapshots__/appInfo.test.tsx.snap index c9b9856ed0..eb8fe844b9 100644 --- a/plugins/main/public/components/settings/about/__snapshots__/appInfo.test.tsx.snap +++ b/plugins/main/public/components/settings/about/__snapshots__/appInfo.test.tsx.snap @@ -5,7 +5,7 @@ exports[`SettingsAboutAppInfo component should render version, revision, install

- Wazuh Dashboard version + Dashboard version

return ( <> -

Wazuh Dashboard version

+

Dashboard version

@@ -70,7 +70,7 @@ export const SettingsAboutAppInfo = ({ appInfo }: SettingsAboutAppInfoProps) => <> diff --git a/plugins/wazuh-check-updates/common/constants.ts b/plugins/wazuh-check-updates/common/constants.ts index 44532023df..1f12fcea01 100644 --- a/plugins/wazuh-check-updates/common/constants.ts +++ b/plugins/wazuh-check-updates/common/constants.ts @@ -1,47 +1,10 @@ -import path from 'path'; - export const PLUGIN_ID = 'wazuhCheckUpdates'; export const PLUGIN_NAME = 'wazuh_check_updates'; export const SAVED_OBJECT_UPDATES = 'wazuh-check-updates-available-updates'; -export const SAVED_OBJECT_SETTINGS = 'wazuh-check-updates-settings'; export const SAVED_OBJECT_USER_PREFERENCES = 'wazuh-check-updates-user-preferences'; -export const DEFAULT_SCHEDULE = '0 0 * * *'; - export enum routes { checkUpdates = '/api/wazuh-check-updates/updates', userPreferences = '/api/wazuh-check-updates/user-preferences/me', } - -// Security -export const WAZUH_SECURITY_PLUGIN_OPENSEARCH_DASHBOARDS_SECURITY = - 'OpenSearch Dashboards Security'; - -// Default Elasticsearch user name context -export const ELASTIC_NAME = 'elastic'; - -// Wazuh data path -const WAZUH_DATA_PLUGIN_PLATFORM_BASE_PATH = 'data'; -export const WAZUH_DATA_PLUGIN_PLATFORM_BASE_ABSOLUTE_PATH = path.join( - __dirname, - '../../../', - WAZUH_DATA_PLUGIN_PLATFORM_BASE_PATH -); -export const WAZUH_DATA_ABSOLUTE_PATH = path.join( - WAZUH_DATA_PLUGIN_PLATFORM_BASE_ABSOLUTE_PATH, - 'wazuh' -); - -// Wazuh data path - config -export const WAZUH_DATA_CONFIG_DIRECTORY_PATH = path.join(WAZUH_DATA_ABSOLUTE_PATH, 'config'); -export const WAZUH_DATA_CONFIG_APP_PATH = path.join(WAZUH_DATA_CONFIG_DIRECTORY_PATH, 'wazuh.yml'); - -// Wazuh data path - logs -export const MAX_MB_LOG_FILES = 100; -export const WAZUH_DATA_LOGS_DIRECTORY_PATH = path.join(WAZUH_DATA_ABSOLUTE_PATH, 'logs'); -export const WAZUH_DATA_LOGS_PLAIN_FILENAME = 'wazuhapp-plain.log'; -export const WAZUH_DATA_LOGS_RAW_FILENAME = 'wazuhapp.log'; - -// App configuration -export const WAZUH_CONFIGURATION_CACHE_TIME = 10000; // time in ms; diff --git a/plugins/wazuh-check-updates/common/types.ts b/plugins/wazuh-check-updates/common/types.ts index 9b699e1983..b98385d46f 100644 --- a/plugins/wazuh-check-updates/common/types.ts +++ b/plugins/wazuh-check-updates/common/types.ts @@ -1,6 +1,7 @@ export enum API_UPDATES_STATUS { UP_TO_DATE = 'upToDate', AVAILABLE_UPDATES = 'availableUpdates', + DISABLED = 'disabled', ERROR = 'error', } @@ -42,13 +43,9 @@ export interface UserPreferences { hide_update_notifications?: boolean; } -export interface CheckUpdatesSettings { - schedule?: string; -} - export interface AvailableUpdates { apis_available_updates: ApiAvailableUpdates[]; last_check_date: Date; } -export type savedObjectType = AvailableUpdates | UserPreferences | CheckUpdatesSettings; +export type savedObjectType = AvailableUpdates | UserPreferences; diff --git a/plugins/wazuh-check-updates/public/components/apis-update-status/__snapshots__/index.test.tsx.snap b/plugins/wazuh-check-updates/public/components/apis-update-status/__snapshots__/index.test.tsx.snap index a0bbc8a5c5..8ad58f2769 100644 --- a/plugins/wazuh-check-updates/public/components/apis-update-status/__snapshots__/index.test.tsx.snap +++ b/plugins/wazuh-check-updates/public/components/apis-update-status/__snapshots__/index.test.tsx.snap @@ -5,7 +5,7 @@ exports[`UpdatesNotification component should retrieve available updates when cl

- Wazuh APIs version + APIs version

- Wazuh APIs version + APIs version
({ })); jest.mock('./table', () => ({ - ApisUpdateTable: jest - .fn() - .mockReturnValue(
APIs Updates Table component
), + ApisUpdateTable: jest.fn().mockReturnValue(
APIs Updates Table component
), })); -jest.mock('../../../../plugin-services', () => ({ - getWazuhCore: jest - .fn() - .mockReturnValue({ - utils: { - formatUIDate: jest.fn().mockReturnValue('2023-09-18T14:00:00.000Z'), - }, - }), +jest.mock('../../plugin-services', () => ({ + getWazuhCore: jest.fn().mockReturnValue({ + utils: { + formatUIDate: jest.fn().mockReturnValue('2023-09-18T14:00:00.000Z'), + }, + }), })); const mockedUseAvailabeUpdates = useAvailableUpdates as jest.Mock; @@ -59,14 +55,12 @@ describe('UpdatesNotification component', () => { })); const { container, getByText } = render( - {}} />, + {}} /> ); expect(container).toMatchSnapshot(); - const dismissNotificationCheck = getByText( - 'Dismiss Notification Check component', - ); + const dismissNotificationCheck = getByText('Dismiss Notification Check component'); expect(dismissNotificationCheck).toBeInTheDocument(); const apisUpdateTable = getByText('APIs Updates Table component'); @@ -103,7 +97,7 @@ describe('UpdatesNotification component', () => { })); const { container, getByRole, getByText } = render( - {}} />, + {}} /> ); expect(container).toMatchSnapshot(); diff --git a/plugins/wazuh-check-updates/public/components/apis-update-status/index.tsx b/plugins/wazuh-check-updates/public/components/apis-update-status/index.tsx index 8078113c3a..8234c4a478 100644 --- a/plugins/wazuh-check-updates/public/components/apis-update-status/index.tsx +++ b/plugins/wazuh-check-updates/public/components/apis-update-status/index.tsx @@ -96,7 +96,7 @@ export const ApisUpdateStatus = ({

diff --git a/plugins/wazuh-check-updates/public/components/apis-update-status/table/__snapshots__/index.test.tsx.snap b/plugins/wazuh-check-updates/public/components/apis-update-status/table/__snapshots__/index.test.tsx.snap index e1e2536f44..bdb3672b44 100644 --- a/plugins/wazuh-check-updates/public/components/apis-update-status/table/__snapshots__/index.test.tsx.snap +++ b/plugins/wazuh-check-updates/public/components/apis-update-status/table/__snapshots__/index.test.tsx.snap @@ -35,7 +35,6 @@ exports[`ApisUpdateTable component should return the ApisUpdateTable component 1 data-test-subj="tableHeaderCell_api_id_0" role="columnheader" scope="col" - style="width: 100px;" > - - - - Last major - - - - - - - Last minor - - - - - - - Last patch - - - @@ -146,7 +89,6 @@ exports[`ApisUpdateTable component should return the ApisUpdateTable component 1 >
-
-
-
- -
-
- Available updates -
-
-
-
- - -
- Last major -
-
- - -
- Last minor -
-
- - -
- Last patch -
-
- + availableUpdates +
diff --git a/plugins/wazuh-check-updates/public/components/apis-update-status/table/columns/index.tsx b/plugins/wazuh-check-updates/public/components/apis-update-status/table/columns/index.tsx index a564175508..570fe5db0c 100644 --- a/plugins/wazuh-check-updates/public/components/apis-update-status/table/columns/index.tsx +++ b/plugins/wazuh-check-updates/public/components/apis-update-status/table/columns/index.tsx @@ -5,6 +5,25 @@ import { ApiAvailableUpdates, API_UPDATES_STATUS, Update } from '../../../../../ import { UpdateBadge } from './update-badge'; export const getApisUpdateStatusColumns = () => { + const API_UPDATES_STATUS_COLUMN = { + [API_UPDATES_STATUS.UP_TO_DATE]: { + defaultMessage: 'Up to date', + color: 'success', + }, + [API_UPDATES_STATUS.AVAILABLE_UPDATES]: { + defaultMessage: 'Available updates', + color: 'warning', + }, + [API_UPDATES_STATUS.DISABLED]: { + defaultMessage: 'Checking updates disabled', + color: 'subdued', + }, + [API_UPDATES_STATUS.ERROR]: { + defaultMessage: 'Error checking updates', + color: 'danger', + }, + }; + const baseColumns = [ { field: 'api_id', @@ -22,23 +41,11 @@ export const getApisUpdateStatusColumns = () => { width: '200px', render: (status: API_UPDATES_STATUS, api: ApiAvailableUpdates) => { const getDefaultMessage = () => { - if (status === API_UPDATES_STATUS.UP_TO_DATE) { - return 'Up to date'; - } - if (status === API_UPDATES_STATUS.AVAILABLE_UPDATES) { - return 'Available updates'; - } - return 'Error checking updates'; + return API_UPDATES_STATUS_COLUMN[status]?.defaultMessage || 'Error checking updates'; }; const getColor = () => { - if (status === API_UPDATES_STATUS.UP_TO_DATE) { - return 'success'; - } - if (status === API_UPDATES_STATUS.AVAILABLE_UPDATES) { - return 'warning'; - } - return 'danger'; + return API_UPDATES_STATUS_COLUMN[status]?.color || 'danger'; }; return ( diff --git a/plugins/wazuh-check-updates/public/components/apis-update-status/table/index.test.tsx b/plugins/wazuh-check-updates/public/components/apis-update-status/table/index.test.tsx index 9783c5daf4..573c9f08a4 100644 --- a/plugins/wazuh-check-updates/public/components/apis-update-status/table/index.test.tsx +++ b/plugins/wazuh-check-updates/public/components/apis-update-status/table/index.test.tsx @@ -11,6 +11,23 @@ jest.mock( }) ); +jest.mock('./columns', () => ({ + getApisUpdateStatusColumns: jest.fn().mockReturnValue([ + { + field: 'api_id', + name: 'ID', + }, + { + field: 'current_version', + name: 'Version', + }, + { + field: 'status', + name: 'Update status', + }, + ]), +})); + describe('ApisUpdateTable component', () => { test('should return the ApisUpdateTable component', () => { const { container, getByText } = render( @@ -42,7 +59,6 @@ describe('ApisUpdateTable component', () => { expect(getByText('api id')).toBeInTheDocument(); expect(getByText('4.3.1')).toBeInTheDocument(); - expect(getByText('Available updates')).toBeInTheDocument(); - expect(getByText('v4.3.8')).toBeInTheDocument(); + expect(getByText('availableUpdates')).toBeInTheDocument(); }); }); diff --git a/plugins/wazuh-check-updates/public/components/updates-notification.test.tsx b/plugins/wazuh-check-updates/public/components/updates-notification.test.tsx index d049206446..ed514b5dad 100644 --- a/plugins/wazuh-check-updates/public/components/updates-notification.test.tsx +++ b/plugins/wazuh-check-updates/public/components/updates-notification.test.tsx @@ -75,7 +75,7 @@ describe('UpdatesNotification component', () => { expect(container).toMatchSnapshot(); - const message = getByText('Wazuh new release is available!'); + const message = getByText('New release is available!'); expect(message).toBeInTheDocument(); const releaseNotesLink = getByRole('link', { name: 'Go to the about page for details' }); diff --git a/plugins/wazuh-check-updates/public/components/updates-notification.tsx b/plugins/wazuh-check-updates/public/components/updates-notification.tsx index 186bfdf701..37643f8120 100644 --- a/plugins/wazuh-check-updates/public/components/updates-notification.tsx +++ b/plugins/wazuh-check-updates/public/components/updates-notification.tsx @@ -88,7 +88,7 @@ export const UpdatesNotification = () => { diff --git a/plugins/wazuh-check-updates/public/hooks/available-updates.test.ts b/plugins/wazuh-check-updates/public/hooks/available-updates.test.ts index f6731fed70..50456d7152 100644 --- a/plugins/wazuh-check-updates/public/hooks/available-updates.test.ts +++ b/plugins/wazuh-check-updates/public/hooks/available-updates.test.ts @@ -35,7 +35,7 @@ jest.mock('../plugin-services', () => ({ describe('useAvailableUpdates hook', () => { test('should fetch initial data without any error', async () => { const mockAvailableUpdates: AvailableUpdates = { - last_check_date: '2023-09-30T14:00:00.000Z', + last_check_date: new Date('2023-09-30T14:00:00.000Z'), apis_available_updates: [ { api_id: 'api id', @@ -70,7 +70,7 @@ describe('useAvailableUpdates hook', () => { test('should update availableUpdates', async () => { const mockAvailableUpdates: AvailableUpdates = { - last_check_date: '2023-09-30T14:00:00.000Z', + last_check_date: new Date('2023-09-30T14:00:00.000Z'), apis_available_updates: [ { api_id: 'api id', diff --git a/plugins/wazuh-check-updates/public/hooks/available-updates.ts b/plugins/wazuh-check-updates/public/hooks/available-updates.ts index b044677fdf..68688434c4 100644 --- a/plugins/wazuh-check-updates/public/hooks/available-updates.ts +++ b/plugins/wazuh-check-updates/public/hooks/available-updates.ts @@ -13,14 +13,22 @@ export const useAvailableUpdates = () => { const refreshAvailableUpdates = async (forceUpdate = false, returnError = false) => { try { setIsLoading(true); + + const checkUpdates = sessionStorage.getItem('checkUpdates'); + const alreadyCheckUpdates = checkUpdates === 'executed'; + const response = (await getCore().http.get(routes.checkUpdates, { query: { - checkAvailableUpdates: forceUpdate, + checkAvailableUpdates: forceUpdate || !alreadyCheckUpdates, }, })) as AvailableUpdates; setApisAvailableUpdates(response?.apis_available_updates || []); setLastCheck(response?.last_check_date); setError(undefined); + + if (!alreadyCheckUpdates) { + sessionStorage.setItem('checkUpdates', 'executed'); + } } catch (error: any) { if (returnError) { return error instanceof Error diff --git a/plugins/wazuh-check-updates/server/cronjob/index.ts b/plugins/wazuh-check-updates/server/cronjob/index.ts deleted file mode 100644 index 8cfcd84597..0000000000 --- a/plugins/wazuh-check-updates/server/cronjob/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { jobSchedulerRun } from './job-scheduler-run'; diff --git a/plugins/wazuh-check-updates/server/cronjob/job-scheduler-run.test.ts b/plugins/wazuh-check-updates/server/cronjob/job-scheduler-run.test.ts deleted file mode 100644 index 8e3bcd55e2..0000000000 --- a/plugins/wazuh-check-updates/server/cronjob/job-scheduler-run.test.ts +++ /dev/null @@ -1,44 +0,0 @@ -import cron from 'node-cron'; -import { getSettings } from '../services/settings'; -import { getUpdates } from '../services/updates'; -import { jobSchedulerRun } from './job-scheduler-run'; - -const mockedCron = cron.schedule as jest.Mock; -jest.mock('node-cron'); - -const mockedGetSettings = getSettings as jest.Mock; -jest.mock('../services/settings'); - -const mockedGetUpdates = getUpdates as jest.Mock; -jest.mock('../services/updates'); - -describe('jobSchedulerRun function', () => { - test('schedule job to check updates', async () => { - mockedCron.mockImplementation(() => {}); - mockedGetSettings.mockImplementation(() => ({ schedule: '* * * * *' })); - mockedGetUpdates.mockImplementation(() => ({})); - - const response = await jobSchedulerRun(); - - expect(getUpdates).toHaveBeenCalledTimes(1); - expect(getUpdates).toHaveBeenCalledWith(true); - - expect(getSettings).toHaveBeenCalledTimes(1); - expect(getSettings).toHaveBeenCalledWith(); - - expect(cron.schedule).toHaveBeenCalledTimes(1); - expect(cron.schedule).toHaveBeenCalledWith('* * * * *', expect.any(Function)); - - expect(response).toBeUndefined(); - }); - - test('should return an error', async () => { - mockedGetSettings.mockRejectedValue(new Error('getSettings error')); - - const promise = jobSchedulerRun(); - - expect(getSettings).toHaveBeenCalledTimes(1); - - await expect(promise).rejects.toThrow('getSettings error'); - }); -}); diff --git a/plugins/wazuh-check-updates/server/cronjob/job-scheduler-run.ts b/plugins/wazuh-check-updates/server/cronjob/job-scheduler-run.ts deleted file mode 100644 index 34fef89d51..0000000000 --- a/plugins/wazuh-check-updates/server/cronjob/job-scheduler-run.ts +++ /dev/null @@ -1,27 +0,0 @@ -import cron from 'node-cron'; -import { DEFAULT_SCHEDULE } from '../../common/constants'; -import { getSettings } from '../services/settings'; -import { getUpdates } from '../services/updates'; -import { getWazuhCore } from '../plugin-services'; - -export const jobSchedulerRun = async () => { - try { - const settings = await getSettings(); - - cron.schedule(settings?.schedule || DEFAULT_SCHEDULE, () => getUpdates(true)); - } catch (error) { - const message = - error instanceof Error - ? error.message - : typeof error === 'string' - ? error - : 'Error trying to schedule a cron job to get updates'; - - const { - services: { log }, - } = getWazuhCore(); - - log('wazuh-check-updates:jobSchedulerRun', message); - return Promise.reject(error); - } -}; diff --git a/plugins/wazuh-check-updates/server/plugin.ts b/plugins/wazuh-check-updates/server/plugin.ts index f36f4ae65a..105e29eee7 100644 --- a/plugins/wazuh-check-updates/server/plugin.ts +++ b/plugins/wazuh-check-updates/server/plugin.ts @@ -13,14 +13,9 @@ import { AppPluginStartDependencies, } from './types'; import { defineRoutes } from './routes'; -import { - availableUpdatesObject, - settingsObject, - userPreferencesObject, -} from './services/saved-object/types'; +import { availableUpdatesObject, userPreferencesObject } from './services/saved-object/types'; import { setCore, setWazuhCore, setInternalSavedObjectsClient } from './plugin-services'; -import { jobSchedulerRun } from './cronjob'; -import { ISecurityFactory, SecurityObj } from './lib/security-factory'; +import { ISecurityFactory } from '../../wazuh-core/server/services/security-factory'; declare module 'opensearch-dashboards/server' { interface RequestHandlerContext { @@ -42,12 +37,10 @@ export class WazuhCheckUpdatesPlugin public async setup(core: CoreSetup, plugins: PluginSetup) { this.logger.debug('wazuh_check_updates: Setup'); - const wazuhSecurity = await SecurityObj(plugins); - core.http.registerRouteHandlerContext('wazuh_check_updates', () => { return { logger: this.logger, - security: wazuhSecurity, + security: plugins.wazuhCore.wazuhSecurity, }; }); @@ -55,7 +48,6 @@ export class WazuhCheckUpdatesPlugin // Register saved objects types core.savedObjects.registerType(availableUpdatesObject); - core.savedObjects.registerType(settingsObject); core.savedObjects.registerType(userPreferencesObject); // Register server side APIs @@ -72,9 +64,6 @@ export class WazuhCheckUpdatesPlugin setWazuhCore(plugins.wazuhCore); setInternalSavedObjectsClient(internalSavedObjectsClient); - // Scheduler - jobSchedulerRun(); - return {}; } diff --git a/plugins/wazuh-check-updates/server/routes/updates/get-updates.test.ts b/plugins/wazuh-check-updates/server/routes/updates/get-updates.test.ts index 41ffa5a9fc..5887174179 100644 --- a/plugins/wazuh-check-updates/server/routes/updates/get-updates.test.ts +++ b/plugins/wazuh-check-updates/server/routes/updates/get-updates.test.ts @@ -74,7 +74,7 @@ describe(`[endpoint] GET ${routes.checkUpdates}`, () => { test('get available updates', async () => { const mockResponse: AvailableUpdates = { - last_check_date: '2023-09-30T14:00:00.000Z', + last_check_date: new Date('2023-09-30T14:00:00.000Z'), apis_available_updates: [ { api_id: 'api id', @@ -99,6 +99,6 @@ describe(`[endpoint] GET ${routes.checkUpdates}`, () => { mockedGetUpdates.mockImplementation(() => mockResponse); const response = await axios.get(`${routes.checkUpdates}?checkAvailableUpdates=true`); - expect(response.data).toEqual(mockResponse); + expect(response.data).toEqual({ ...mockResponse, last_check_date: '2023-09-30T14:00:00.000Z' }); }); }); diff --git a/plugins/wazuh-check-updates/server/services/saved-object/get-saved-object.test.ts b/plugins/wazuh-check-updates/server/services/saved-object/get-saved-object.test.ts index 4c955569e1..bc12157705 100644 --- a/plugins/wazuh-check-updates/server/services/saved-object/get-saved-object.test.ts +++ b/plugins/wazuh-check-updates/server/services/saved-object/get-saved-object.test.ts @@ -1,7 +1,8 @@ -import { getInternalSavedObjectsClient } from '../../plugin-services'; +import { getInternalSavedObjectsClient, getWazuhCore } from '../../plugin-services'; import { getSavedObject } from './get-saved-object'; const mockedGetInternalObjectsClient = getInternalSavedObjectsClient as jest.Mock; +const mockedGetWazuhCore = getWazuhCore as jest.Mock; jest.mock('../../plugin-services'); describe('getSavedObject function', () => { @@ -23,6 +24,9 @@ describe('getSavedObject function', () => { mockedGetInternalObjectsClient.mockImplementation(() => ({ get: jest.fn().mockRejectedValue({ output: { statusCode: 404 } }), })); + mockedGetWazuhCore.mockImplementation(() => ({ + services: { log: jest.fn().mockImplementation(() => {}) }, + })); const response = await getSavedObject('type'); @@ -33,6 +37,9 @@ describe('getSavedObject function', () => { mockedGetInternalObjectsClient.mockImplementation(() => ({ get: jest.fn().mockRejectedValue(new Error('getSavedObject error')), })); + mockedGetWazuhCore.mockImplementation(() => ({ + services: { log: jest.fn().mockImplementation(() => {}) }, + })); const promise = getSavedObject('type'); diff --git a/plugins/wazuh-check-updates/server/services/saved-object/set-saved-object.test.ts b/plugins/wazuh-check-updates/server/services/saved-object/set-saved-object.test.ts index cf1464fb5e..f9e34d3197 100644 --- a/plugins/wazuh-check-updates/server/services/saved-object/set-saved-object.test.ts +++ b/plugins/wazuh-check-updates/server/services/saved-object/set-saved-object.test.ts @@ -1,7 +1,8 @@ -import { getInternalSavedObjectsClient } from '../../plugin-services'; +import { getInternalSavedObjectsClient, getWazuhCore } from '../../plugin-services'; import { setSavedObject } from './set-saved-object'; const mockedGetInternalObjectsClient = getInternalSavedObjectsClient as jest.Mock; +const mockedGetWazuhCore = getWazuhCore as jest.Mock; jest.mock('../../plugin-services'); describe('setSavedObject function', () => { @@ -11,20 +12,31 @@ describe('setSavedObject function', () => { test('should return saved object', async () => { mockedGetInternalObjectsClient.mockImplementation(() => ({ - create: () => ({ attributes: { schedule: '* * * * *' } }), + create: () => ({ attributes: { hide_update_notifications: true } }), })); - const response = await setSavedObject('settings', { schedule: '* * * * *' }); + const response = await setSavedObject( + 'wazuh-check-updates-user-preferences', + { hide_update_notifications: true }, + 'admin' + ); - expect(response).toEqual({ schedule: '* * * * *' }); + expect(response).toEqual({ hide_update_notifications: true }); }); test('should return an error', async () => { mockedGetInternalObjectsClient.mockImplementation(() => ({ create: jest.fn().mockRejectedValue(new Error('setSavedObject error')), })); + mockedGetWazuhCore.mockImplementation(() => ({ + services: { log: jest.fn().mockImplementation(() => {}) }, + })); - const promise = setSavedObject('settings', { schedule: '* * * * *' }); + const promise = setSavedObject( + 'wazuh-check-updates-user-preferences', + { hide_update_notifications: true }, + 'admin' + ); await expect(promise).rejects.toThrow('setSavedObject error'); }); diff --git a/plugins/wazuh-check-updates/server/services/saved-object/types/index.ts b/plugins/wazuh-check-updates/server/services/saved-object/types/index.ts index 062424fd05..fdd8c1463e 100644 --- a/plugins/wazuh-check-updates/server/services/saved-object/types/index.ts +++ b/plugins/wazuh-check-updates/server/services/saved-object/types/index.ts @@ -1,3 +1,2 @@ export { availableUpdatesObject } from './available-updates'; -export { settingsObject } from './settings'; export { userPreferencesObject } from './user-preferences'; diff --git a/plugins/wazuh-check-updates/server/services/saved-object/types/settings.ts b/plugins/wazuh-check-updates/server/services/saved-object/types/settings.ts deleted file mode 100644 index 401f7ccb4a..0000000000 --- a/plugins/wazuh-check-updates/server/services/saved-object/types/settings.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { SavedObjectsType } from 'opensearch-dashboards/server'; -import { SAVED_OBJECT_SETTINGS } from '../../../../common/constants'; - -export const settingsObject: SavedObjectsType = { - name: SAVED_OBJECT_SETTINGS, - hidden: false, - namespaceType: 'agnostic', - mappings: { - properties: { - schedule: { - type: 'text', - }, - }, - }, - migrations: {}, -}; diff --git a/plugins/wazuh-check-updates/server/services/settings/get-settings.test.ts b/plugins/wazuh-check-updates/server/services/settings/get-settings.test.ts deleted file mode 100644 index 5d50451145..0000000000 --- a/plugins/wazuh-check-updates/server/services/settings/get-settings.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { getSavedObject } from '../saved-object/get-saved-object'; -import { setSavedObject } from '../saved-object/set-saved-object'; -import { getSettings } from './get-settings'; -import { DEFAULT_SCHEDULE, SAVED_OBJECT_SETTINGS } from '../../../common/constants'; - -const mockedGetSavedObject = getSavedObject as jest.Mock; -jest.mock('../saved-object/get-saved-object'); - -const mockedSetSavedObject = setSavedObject as jest.Mock; -jest.mock('../saved-object/set-saved-object'); - -describe('getSettings function', () => { - afterEach(() => { - jest.clearAllMocks(); - }); - - test('should return settings', async () => { - mockedGetSavedObject.mockImplementation(() => ({ schedule: '* * * * *' })); - - const response = await getSettings(); - - expect(getSavedObject).toHaveBeenCalledTimes(1); - expect(getSavedObject).toHaveBeenCalledWith(SAVED_OBJECT_SETTINGS); - - expect(response).toEqual({ schedule: '* * * * *' }); - }); - - test('should return default settings', async () => { - mockedGetSavedObject.mockImplementation(() => ({})); - - mockedSetSavedObject.mockImplementation(() => {}); - - const response = await getSettings(); - - expect(getSavedObject).toHaveBeenCalledTimes(1); - expect(getSavedObject).toHaveBeenCalledWith(SAVED_OBJECT_SETTINGS); - - expect(response).toEqual({ schedule: DEFAULT_SCHEDULE }); - }); - - test('should return an error', async () => { - mockedGetSavedObject.mockRejectedValue(new Error('getSavedObject error')); - mockedSetSavedObject.mockRejectedValue(new Error('getSavedObject error')); - - const promise = getSettings(); - - expect(getSavedObject).toHaveBeenCalledTimes(1); - - await expect(promise).rejects.toThrow('getSavedObject error'); - }); -}); diff --git a/plugins/wazuh-check-updates/server/services/settings/get-settings.ts b/plugins/wazuh-check-updates/server/services/settings/get-settings.ts deleted file mode 100644 index 644eee5365..0000000000 --- a/plugins/wazuh-check-updates/server/services/settings/get-settings.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { DEFAULT_SCHEDULE, SAVED_OBJECT_SETTINGS } from '../../../common/constants'; -import { CheckUpdatesSettings } from '../../../common/types'; -import { getWazuhCore } from '../../plugin-services'; -import { getSavedObject, setSavedObject } from '../saved-object'; - -export const getSettings = async (): Promise => { - try { - const settings = (await getSavedObject(SAVED_OBJECT_SETTINGS)) as CheckUpdatesSettings; - - if (!settings?.schedule) { - const defaultSettings = { - schedule: DEFAULT_SCHEDULE, - }; - await setSavedObject(SAVED_OBJECT_SETTINGS, defaultSettings); - return defaultSettings; - } - - return settings; - } catch (error) { - const message = - error instanceof Error - ? error.message - : typeof error === 'string' - ? error - : 'Error trying to get settings'; - - const { - services: { log }, - } = getWazuhCore(); - - log('wazuh-check-updates:getSettings', message); - return Promise.reject(error); - } -}; diff --git a/plugins/wazuh-check-updates/server/services/settings/index.ts b/plugins/wazuh-check-updates/server/services/settings/index.ts deleted file mode 100644 index a8a60dd1b4..0000000000 --- a/plugins/wazuh-check-updates/server/services/settings/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { getSettings } from './get-settings'; -export { updateSettings } from './update-settings'; diff --git a/plugins/wazuh-check-updates/server/services/settings/update-settings.test.ts b/plugins/wazuh-check-updates/server/services/settings/update-settings.test.ts deleted file mode 100644 index ef6bf3340b..0000000000 --- a/plugins/wazuh-check-updates/server/services/settings/update-settings.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { updateSettings } from '.'; -import { getSavedObject } from '../saved-object/get-saved-object'; -import { setSavedObject } from '../saved-object/set-saved-object'; -import { SAVED_OBJECT_SETTINGS } from '../../../common/constants'; - -const mockedGetSavedObject = getSavedObject as jest.Mock; -jest.mock('../saved-object/get-saved-object'); - -const mockedSetSavedObject = setSavedObject as jest.Mock; -jest.mock('../saved-object/set-saved-object'); - -describe('updateSettings function', () => { - afterEach(() => { - jest.clearAllMocks(); - }); - - test('should return user preferences', async () => { - mockedGetSavedObject.mockImplementation(() => ({ schedule: '* * * * *' })); - - mockedSetSavedObject.mockImplementation(() => {}); - - const response = await updateSettings({ schedule: '* * * * *' }); - - expect(getSavedObject).toHaveBeenCalledTimes(1); - expect(getSavedObject).toHaveBeenCalledWith(SAVED_OBJECT_SETTINGS); - - expect(response).toEqual({ schedule: '* * * * *' }); - }); - - test('should return an error', async () => { - mockedSetSavedObject.mockRejectedValue(new Error('getSavedObject error')); - - const promise = updateSettings({ schedule: '* * * * *' }); - - expect(getSavedObject).toHaveBeenCalledTimes(1); - - await expect(promise).rejects.toThrow('getSavedObject error'); - }); -}); diff --git a/plugins/wazuh-check-updates/server/services/settings/update-settings.ts b/plugins/wazuh-check-updates/server/services/settings/update-settings.ts deleted file mode 100644 index c8f2598c19..0000000000 --- a/plugins/wazuh-check-updates/server/services/settings/update-settings.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { getSettings } from '.'; -import { SAVED_OBJECT_SETTINGS } from '../../../common/constants'; -import { CheckUpdatesSettings } from '../../../common/types'; -import { getWazuhCore } from '../../plugin-services'; -import { setSavedObject } from '../saved-object'; - -export const updateSettings = async ( - settings: Partial -): Promise => { - try { - const savedSettings = await getSettings(); - - const newSettings = { - ...savedSettings, - ...settings, - }; - - await setSavedObject(SAVED_OBJECT_SETTINGS, newSettings); - - return newSettings; - } catch (error) { - const message = - error instanceof Error - ? error.message - : typeof error === 'string' - ? error - : 'Error trying to update settings'; - - const { - services: { log }, - } = getWazuhCore(); - - log('wazuh-check-updates:updateSettings', message); - return Promise.reject(error); - } -}; diff --git a/plugins/wazuh-check-updates/server/services/updates/get-updates.test.ts b/plugins/wazuh-check-updates/server/services/updates/get-updates.test.ts new file mode 100644 index 0000000000..469d3ce014 --- /dev/null +++ b/plugins/wazuh-check-updates/server/services/updates/get-updates.test.ts @@ -0,0 +1,137 @@ +import { getSavedObject } from '../saved-object/get-saved-object'; +import { setSavedObject } from '../saved-object/set-saved-object'; +import { getWazuhCore } from '../../plugin-services'; +import { API_UPDATES_STATUS } from '../../../common/types'; +import { getUpdates } from './get-updates'; +import { SAVED_OBJECT_UPDATES } from '../../../common/constants'; + +const mockedGetSavedObject = getSavedObject as jest.Mock; +jest.mock('../saved-object/get-saved-object'); + +const mockedSetSavedObject = setSavedObject as jest.Mock; +jest.mock('../saved-object/set-saved-object'); + +const mockedGetWazuhCore = getWazuhCore as jest.Mock; +jest.mock('../../plugin-services'); + +describe('getUpdates function', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + test('should return available updates from saved object', async () => { + mockedGetSavedObject.mockImplementation(() => ({ + last_check_date: '2023-09-30T14:00:00.000Z', + apis_available_updates: [ + { + api_id: 'api id', + current_version: '4.3.1', + status: API_UPDATES_STATUS.UP_TO_DATE, + last_available_patch: { + description: + '## Manager\r\n\r\n### Fixed\r\n\r\n- Fixed a crash when overwrite rules are triggered...', + published_date: '2022-05-18T10:12:43Z', + semver: { + major: 4, + minor: 3, + patch: 8, + }, + tag: 'v4.3.8', + title: 'Wazuh v4.3.8', + }, + }, + ], + })); + + const updates = await getUpdates(); + + expect(getSavedObject).toHaveBeenCalledTimes(1); + expect(getSavedObject).toHaveBeenCalledWith(SAVED_OBJECT_UPDATES); + + expect(updates).toEqual({ + last_check_date: '2023-09-30T14:00:00.000Z', + apis_available_updates: [ + { + api_id: 'api id', + current_version: '4.3.1', + status: API_UPDATES_STATUS.UP_TO_DATE, + last_available_patch: { + description: + '## Manager\r\n\r\n### Fixed\r\n\r\n- Fixed a crash when overwrite rules are triggered...', + published_date: '2022-05-18T10:12:43Z', + semver: { + major: 4, + minor: 3, + patch: 8, + }, + tag: 'v4.3.8', + title: 'Wazuh v4.3.8', + }, + }, + ], + }); + }); + + test('should return available updates from api', async () => { + mockedGetWazuhCore.mockImplementation(() => ({ + controllers: { + WazuhHostsCtrl: jest.fn().mockImplementation(() => ({ + getHostsEntries: jest.fn().mockImplementation(() => [{ id: 'api id' }]), + })), + }, + services: { + wazuhApiClient: { + client: { + asInternalUser: { + request: jest.fn().mockImplementation(() => ({ + data: { + data: { + current_version: '4.3.1', + last_available_patch: { + description: + '## Manager\r\n\r\n### Fixed\r\n\r\n- Fixed a crash when overwrite rules are triggered...', + published_date: '2022-05-18T10:12:43Z', + semver: { + major: 4, + minor: 3, + patch: 8, + }, + tag: 'v4.3.8', + title: 'Wazuh v4.3.8', + }, + }, + }, + })), + }, + }, + }, + }, + })); + mockedSetSavedObject.mockImplementation(() => ({})); + + const updates = await getUpdates(true); + + expect(updates).toEqual({ + last_check_date: expect.any(Date), + apis_available_updates: [ + { + api_id: 'api id', + current_version: '4.3.1', + status: API_UPDATES_STATUS.AVAILABLE_UPDATES, + last_available_patch: { + description: + '## Manager\r\n\r\n### Fixed\r\n\r\n- Fixed a crash when overwrite rules are triggered...', + published_date: '2022-05-18T10:12:43Z', + semver: { + major: 4, + minor: 3, + patch: 8, + }, + tag: 'v4.3.8', + title: 'Wazuh v4.3.8', + }, + }, + ], + }); + }); +}); diff --git a/plugins/wazuh-check-updates/server/services/updates/get-updates.ts b/plugins/wazuh-check-updates/server/services/updates/get-updates.ts index 7f36140381..faea49b6b6 100644 --- a/plugins/wazuh-check-updates/server/services/updates/get-updates.ts +++ b/plugins/wazuh-check-updates/server/services/updates/get-updates.ts @@ -43,9 +43,11 @@ export const getUpdates = async (checkAvailableUpdates?: boolean): Promise { afterEach(() => { jest.clearAllMocks(); @@ -40,6 +44,10 @@ describe('getUserPreferences function', () => { test('should return an error', async () => { mockedGetSavedObject.mockRejectedValue(new Error('getSavedObject error')); + mockedGetWazuhCore.mockImplementation(() => ({ + services: { log: jest.fn().mockImplementation(() => {}) }, + })); + const promise = getUserPreferences('admin'); expect(getSavedObject).toHaveBeenCalledTimes(1); diff --git a/plugins/wazuh-check-updates/server/services/user-preferences/update-user-preferences.test.ts b/plugins/wazuh-check-updates/server/services/user-preferences/update-user-preferences.test.ts index b777bb20de..ea981ce57f 100644 --- a/plugins/wazuh-check-updates/server/services/user-preferences/update-user-preferences.test.ts +++ b/plugins/wazuh-check-updates/server/services/user-preferences/update-user-preferences.test.ts @@ -2,6 +2,7 @@ import { updateUserPreferences } from '.'; import { getSavedObject } from '../saved-object/get-saved-object'; import { setSavedObject } from '../saved-object/set-saved-object'; import { SAVED_OBJECT_USER_PREFERENCES } from '../../../common/constants'; +import { getWazuhCore } from '../../plugin-services'; const mockedGetSavedObject = getSavedObject as jest.Mock; jest.mock('../saved-object/get-saved-object'); @@ -9,6 +10,9 @@ jest.mock('../saved-object/get-saved-object'); const mockedSetSavedObject = setSavedObject as jest.Mock; jest.mock('../saved-object/set-saved-object'); +const mockedGetWazuhCore = getWazuhCore as jest.Mock; +jest.mock('../../plugin-services'); + describe('updateUserPreferences function', () => { afterEach(() => { jest.clearAllMocks(); @@ -54,6 +58,10 @@ describe('updateUserPreferences function', () => { test('should return an error', async () => { mockedSetSavedObject.mockRejectedValue(new Error('getSavedObject error')); + mockedGetWazuhCore.mockImplementation(() => ({ + services: { log: jest.fn().mockImplementation(() => {}) }, + })); + const promise = updateUserPreferences('admin', { last_dismissed_updates: [ { diff --git a/plugins/wazuh-check-updates/server/types.ts b/plugins/wazuh-check-updates/server/types.ts index bae99c6a57..477d209c12 100644 --- a/plugins/wazuh-check-updates/server/types.ts +++ b/plugins/wazuh-check-updates/server/types.ts @@ -1,14 +1,16 @@ +import { ISecurityFactory } from '../../wazuh-core/server/services/security-factory'; import { WazuhCorePluginStart } from '../../wazuh-core/server'; // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface AppPluginStartDependencies { } +export interface AppPluginStartDependencies {} // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface WazuhCheckUpdatesPluginSetup { } +export interface WazuhCheckUpdatesPluginSetup {} // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface WazuhCheckUpdatesPluginStart { } +export interface WazuhCheckUpdatesPluginStart {} export type PluginSetup = { securityDashboards?: {}; // TODO: Add OpenSearch Dashboards Security interface + wazuhCore: { wazuhSecurity: ISecurityFactory }; }; export interface AppPluginStartDependencies { diff --git a/plugins/wazuh-check-updates/translations/en-US.json b/plugins/wazuh-check-updates/translations/en-US.json index e4dfab80b7..ca84a400f2 100644 --- a/plugins/wazuh-check-updates/translations/en-US.json +++ b/plugins/wazuh-check-updates/translations/en-US.json @@ -76,17 +76,18 @@ } }, "messages": { - "wazuhCheckUpdates.updatesNotification.message": "Wazuh new release is available!", + "wazuhCheckUpdates.updatesNotification.message": "New release is available!", "wazuhCheckUpdates.updatesNotification.linkText": "Go to the about page for details", "wazuhCheckUpdates.updatesNotification.dismissCheckText": "Disable updates notifications", "wazuhCheckUpdates.updatesNotification.closeButtonText": "Close", "wazuhCheckUpdates.apisUpdateStatus.upToDate": "Up to date", "wazuhCheckUpdates.apisUpdateStatus.availableUpdates": "Available updates", "wazuhCheckUpdates.apisUpdateStatus.error": "Error checking updates", + "wazuhCheckUpdates.apisUpdateStatus.disabled": "Checking updates disabled", "wazuhCheckUpdates.apisUpdateStatus.lastCheck": "Last check", "wazuhCheckUpdates.apisUpdateStatus.buttonText": "Check updates", "wazuhCheckUpdates.apisUpdateStatus.onClickButtonError": "Error trying to get updates", - "wazuhCheckUpdates.apisUpdateStatus.tableTitle": "Wazuh APIs version", + "wazuhCheckUpdates.apisUpdateStatus.tableTitle": "APIs version", "wazuhCheckUpdates.apisUpdateStatus.errorCallOut": "Error trying to get APIs version and available updates", "wazuhCheckUpdates.dismissNotificationCheck.checkText": "Disable updates notifications", "wazuhCheckUpdates.dismissNotificationCheck.checkHelp": "This setting determines if a notification will appear every time an update is released", diff --git a/plugins/wazuh-core/server/plugin.ts b/plugins/wazuh-core/server/plugin.ts index 20fbcc896d..5cbb0b0bd6 100644 --- a/plugins/wazuh-core/server/plugin.ts +++ b/plugins/wazuh-core/server/plugin.ts @@ -6,28 +6,27 @@ import { Logger, } from 'opensearch-dashboards/server'; -import { - PluginSetup, - WazuhCorePluginSetup, - WazuhCorePluginStart, -} from './types'; +import { PluginSetup, WazuhCorePluginSetup, WazuhCorePluginStart } from './types'; import { setCore } from './plugin-services'; import * as controllers from './controllers'; import * as services from './services'; +import { SecurityObj } from './services/security-factory'; -export class WazuhCorePlugin - implements Plugin -{ +export class WazuhCorePlugin implements Plugin { private readonly logger: Logger; constructor(initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); } - public async setup(core: CoreSetup, plugins: PluginSetup) { + public async setup(core: CoreSetup, plugins: PluginSetup): Promise { this.logger.debug('wazuh_core: Setup'); - return {}; + const wazuhSecurity = await SecurityObj(plugins); + + return { + wazuhSecurity, + }; } public start(core: CoreStart): WazuhCorePluginStart { @@ -37,7 +36,7 @@ export class WazuhCorePlugin return { controllers, - services + services, }; } diff --git a/plugins/wazuh-core/server/services/index.ts b/plugins/wazuh-core/server/services/index.ts index 827d0be1e2..3890cc4326 100644 --- a/plugins/wazuh-core/server/services/index.ts +++ b/plugins/wazuh-core/server/services/index.ts @@ -11,4 +11,5 @@ */ export { log } from './logger'; -export {wazuhApiClient} from './api-client'; +export { wazuhApiClient } from './api-client'; +export * as securityFactory from './security-factory'; diff --git a/plugins/wazuh-check-updates/server/lib/security-factory/factories/default-factory.ts b/plugins/wazuh-core/server/services/security-factory/factories/default-factory.ts similarity index 100% rename from plugins/wazuh-check-updates/server/lib/security-factory/factories/default-factory.ts rename to plugins/wazuh-core/server/services/security-factory/factories/default-factory.ts diff --git a/plugins/wazuh-check-updates/server/lib/security-factory/factories/index.ts b/plugins/wazuh-core/server/services/security-factory/factories/index.ts similarity index 100% rename from plugins/wazuh-check-updates/server/lib/security-factory/factories/index.ts rename to plugins/wazuh-core/server/services/security-factory/factories/index.ts diff --git a/plugins/wazuh-check-updates/server/lib/security-factory/factories/opensearch-dashboards-security-factory.ts b/plugins/wazuh-core/server/services/security-factory/factories/opensearch-dashboards-security-factory.ts similarity index 100% rename from plugins/wazuh-check-updates/server/lib/security-factory/factories/opensearch-dashboards-security-factory.ts rename to plugins/wazuh-core/server/services/security-factory/factories/opensearch-dashboards-security-factory.ts diff --git a/plugins/wazuh-check-updates/server/lib/security-factory/index.ts b/plugins/wazuh-core/server/services/security-factory/index.ts similarity index 100% rename from plugins/wazuh-check-updates/server/lib/security-factory/index.ts rename to plugins/wazuh-core/server/services/security-factory/index.ts diff --git a/plugins/wazuh-check-updates/server/lib/security-factory/security-factory.ts b/plugins/wazuh-core/server/services/security-factory/security-factory.ts similarity index 100% rename from plugins/wazuh-check-updates/server/lib/security-factory/security-factory.ts rename to plugins/wazuh-core/server/services/security-factory/security-factory.ts diff --git a/plugins/wazuh-core/server/types.ts b/plugins/wazuh-core/server/types.ts index 839bc046bf..8d5cedb7f4 100644 --- a/plugins/wazuh-core/server/types.ts +++ b/plugins/wazuh-core/server/types.ts @@ -1,25 +1,33 @@ import { AxiosResponse } from 'axios'; import { APIInterceptorRequestOptionsInternalUser } from './services/api-interceptor'; import { WazuhHostsCtrl } from './controllers'; +import { ISecurityFactory } from './services/security-factory'; // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface WazuhCorePluginSetup {} +export interface WazuhCorePluginSetup { + wazuhSecurity: ISecurityFactory; +} // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface WazuhCorePluginStart { - controllers:{ - WazuhHostsCtrl: typeof WazuhHostsCtrl - }, - services:{ + controllers: { + WazuhHostsCtrl: typeof WazuhHostsCtrl; + }; + services: { log: (location: string, message: string, level?: string) => void; wazuhApiClient: { client: { - asInternalUser: { - authenticate: (apiHostID: string) => Promise; - request: (method: string, path: string, data: any, options: APIInterceptorRequestOptionsInternalUser) => Promise>; - }; + asInternalUser: { + authenticate: (apiHostID: string) => Promise; + request: ( + method: string, + path: string, + data: any, + options: APIInterceptorRequestOptionsInternalUser + ) => Promise>; + }; }; - } -} + }; + }; } export type PluginSetup = {