From dfdf46d9a20c5c7cb045be3e3d0452de70825e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ricks?= Date: Thu, 14 Jun 2018 15:53:30 +0200 Subject: [PATCH 01/10] Add parameter validator for icalendar The icalendar param must contain VCALENDAR data. --- gsad/src/gsad.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gsad/src/gsad.c b/gsad/src/gsad.c index f589c018c5..02827f4f7c 100644 --- a/gsad/src/gsad.c +++ b/gsad/src/gsad.c @@ -745,6 +745,7 @@ init_validator () openvas_validator_add (validator, "z_fields:value", "^[\\[\\]_[:alnum:]]{1,80}$"); openvas_validator_add (validator, "calendar_unit", "^(second|minute|hour|day|week|month|year|decade)$"); openvas_validator_add (validator, "chart_title", "(?s)^.*$"); + openvas_validator_add (validator, "icalendar", "(?s)^BEGIN:VCALENDAR.+$"); /* Beware, the rule must be defined before the alias. */ From 457835fda05d23cba8a0605ef8db412c3ed0912c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ricks?= Date: Thu, 14 Jun 2018 15:55:01 +0200 Subject: [PATCH 02/10] Update create_schedule_gmp to support icalendar When creating a new schedule expect a icalendar parameter. --- gsad/src/gsad_gmp.c | 59 ++++++--------------------------------------- 1 file changed, 8 insertions(+), 51 deletions(-) diff --git a/gsad/src/gsad_gmp.c b/gsad/src/gsad_gmp.c index 8d4f95c593..bbea7f99d1 100644 --- a/gsad/src/gsad_gmp.c +++ b/gsad/src/gsad_gmp.c @@ -16276,40 +16276,23 @@ get_schedules_gmp (gvm_connection_t *connection, credentials_t * credentials, pa * @return Enveloped XML object. */ char * -create_schedule_gmp (gvm_connection_t *connection, credentials_t * credentials, params_t *params, - cmd_response_data_t* response_data) +create_schedule_gmp (gvm_connection_t *connection, credentials_t *credentials, + params_t *params, cmd_response_data_t *response_data) { char *ret; gchar *response; - const char *name, *comment, *hour, *minute, *day_of_month, *month, *year; - const char *period, *period_unit, *duration, *duration_unit, *timezone; + const char *name, *comment, *timezone, *icalendar; entity_t entity; name = params_value (params, "name"); comment = params_value (params, "comment"); - hour = params_value (params, "hour"); - minute = params_value (params, "minute"); - day_of_month = params_value (params, "day_of_month"); - duration = params_value (params, "duration"); - duration_unit = params_value (params, "duration_unit"); - month = params_value (params, "month"); - period = params_value (params, "period"); - period_unit = params_value (params, "period_unit"); - year = params_value (params, "year"); timezone = params_value (params, "timezone"); + icalendar = params_value (params, "icalendar"); CHECK_PARAM_INVALID (name, "Create Schedule"); CHECK_PARAM_INVALID (comment, "Create Schedule"); - CHECK_PARAM_INVALID (hour, "Create Schedule"); - CHECK_PARAM_INVALID (minute, "Create Schedule"); - CHECK_PARAM_INVALID (day_of_month, "Create Schedule"); - CHECK_PARAM_INVALID (duration, "Create Schedule"); - CHECK_PARAM_INVALID (duration_unit, "Create Schedule"); - CHECK_PARAM_INVALID (month, "Create Schedule"); - CHECK_PARAM_INVALID (period, "Create Schedule"); - CHECK_PARAM_INVALID (period_unit, "period_unit"); - CHECK_PARAM_INVALID (year, "Create Schedule"); CHECK_PARAM_INVALID (timezone, "Create Schedule"); + CHECK_PARAM_INVALID (icalendar, "Create Schedule"); response = NULL; entity = NULL; @@ -16320,39 +16303,13 @@ create_schedule_gmp (gvm_connection_t *connection, credentials_t * credentials, "" "%s" "%s" - "" - "%s" - "%s" - "%s" - "%s" - "%s" - "" - "" - "%s" - "%s" - "" - "" - "%s" - "%s" - "" "%s" + "%s" "", name, comment, - hour, - minute, - day_of_month, - month, - year, - (strcmp (period_unit, "") - ? period_unit - : "second"), - period, - (strcmp (duration_unit, "") - ? duration_unit - : "second"), - duration, - timezone)) + timezone, + icalendar)) { case 0: case -1: From 9619e55ec293ac22969e372aff5f525cef506048 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ricks?= Date: Thu, 14 Jun 2018 15:59:40 +0200 Subject: [PATCH 03/10] Move Event model into an own module All ical related code is moved to an extra model module. --- ng/CMakeLists.txt | 1 + ng/src/gmp/models/event.js | 139 ++++++++++++++++++ ng/src/gmp/models/schedule.js | 111 +------------- ng/src/web/pages/schedules/component.js | 2 +- ng/src/web/pages/schedules/render.js | 2 +- .../pages/tasks/dashboard/schedulesdisplay.js | 2 +- 6 files changed, 146 insertions(+), 111 deletions(-) create mode 100644 ng/src/gmp/models/event.js diff --git a/ng/CMakeLists.txt b/ng/CMakeLists.txt index ea7c0248bd..98d5f4b335 100644 --- a/ng/CMakeLists.txt +++ b/ng/CMakeLists.txt @@ -123,6 +123,7 @@ set (NG_JS_SRC_FILES ${NG_SRC_DIR}/src/gmp/models/credential.js ${NG_SRC_DIR}/src/gmp/models/cve.js ${NG_SRC_DIR}/src/gmp/models/dfncert.js + ${NG_SRC_DIR}/src/gmp/models/event.js ${NG_SRC_DIR}/src/gmp/models/filter.js ${NG_SRC_DIR}/src/gmp/models/filter/convert.js ${NG_SRC_DIR}/src/gmp/models/filter/filterterm.js diff --git a/ng/src/gmp/models/event.js b/ng/src/gmp/models/event.js new file mode 100644 index 0000000000..7a559eaa3e --- /dev/null +++ b/ng/src/gmp/models/event.js @@ -0,0 +1,139 @@ +/* Greenbone Security Assistant + * + * Authors: + * Björn Ricks + * + * Copyright: + * Copyright (C) 2018 Greenbone Networks GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ +import moment from 'moment-timezone'; + +import ical from 'ical.js'; + +import {is_defined} from '../utils/identity'; + +const convertIcalDate = (date, timezone) => is_defined(timezone) ? + moment.unix(date.toUnixTime()).tz(timezone) : + moment.unix(date.toUnixTime()); + +export const ReccurenceFrequency = { + YEARLY: 'YEARLY', + MONTHLY: 'MONTHLY', + WEEKLY: 'WEEKLY', + DAILY: 'DAILY', + HOURLY: 'HOURLY', + MINUTELY: 'MINUTELY', + SECONDLY: 'SECONDLY', +}; + +class Event { + + constructor(icalevent, timezone) { + this.event = icalevent; + this.timezone = timezone; + } + + static fromIcal(icalendar, timezone) { + const jcal = ical.parse(icalendar); + const comp = new ical.Component(jcal); + const vevent = comp.getFirstSubcomponent('vevent'); + const event = new ical.Event(vevent); + return new Event(event, timezone); + } + + get startDate() { + return convertIcalDate(this.event.startDate, this.timezone); + } + + get duration() { + return this.event.duration; + } + + get durationInSeconds() { + const { + days = 0, + hours = 0, + minutes = 0, + weeks = 0, + seconds = 0, + } = this.event.duration; + return seconds + + minutes * 60 + + hours * 60 * 60 + + days * 24 * 60 * 60 + + weeks * 7 * 24 * 60 * 60; + } + + get recurrence() { + if (this.isRecurring()) { + const rrule = this.event.component.getFirstPropertyValue('rrule'); + return rrule === null ? undefined : rrule; + } + return undefined; + } + + get nextDate() { + if (this.isRecurring()) { + const now = ical.Time.now(); + const it = this.event.iterator(); + + while (true) { + const next = it.next(); + if (next.compare(now) >= 0) { + return convertIcalDate(next, this.timezone); + } + } + } + return undefined; + } + + getNextDates(until) { + if (this.isRecurring()) { + const now = moment(); + const it = this.event.iterator(); + const dates = []; + + while (true) { + const next = it.next(); + + if (it.completed || !next) { + return dates; + } + + const mnext = convertIcalDate(next); + + if (mnext.isAfter(until)) { + return dates; + } + + if (mnext.isSameOrAfter(now)) { + dates.push(mnext); + } + } + } + + return []; + } + + isRecurring() { + return this.event.isRecurring(); + } +} + +export default Event; + +// vim: set ts=2 sw=2 tw=80: diff --git a/ng/src/gmp/models/schedule.js b/ng/src/gmp/models/schedule.js index ac727635ce..c1721289cb 100644 --- a/ng/src/gmp/models/schedule.js +++ b/ng/src/gmp/models/schedule.js @@ -20,117 +20,12 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ -import moment from 'moment-timezone'; - -import ical from 'ical.js'; - import {is_defined} from '../utils/identity'; import {map} from '../utils/array'; -import Model from '../model.js'; - -const convertIcalDate = (date, timezone) => is_defined(timezone) ? - moment.unix(date.toUnixTime()).tz(timezone) : - moment.unix(date.toUnixTime()); - -export const ReccurenceFrequency = { - YEARLY: 'YEARLY', - MONTHLY: 'MONTHLY', - WEEKLY: 'WEEKLY', - DAILY: 'DAILY', - HOURLY: 'HOURLY', - MINUTELY: 'MINUTELY', - SECONDLY: 'SECONDLY', -}; - -class Event { - - constructor(icalendar, timezone) { - const jcal = ical.parse(icalendar); - const comp = new ical.Component(jcal); - const vevent = comp.getFirstSubcomponent('vevent'); - this.event = new ical.Event(vevent); - this.timezone = timezone; - } - - get startDate() { - return convertIcalDate(this.event.startDate, this.timezone); - } - - get duration() { - return this.event.duration; - } - - get durationInSeconds() { - const { - days = 0, - hours = 0, - minutes = 0, - weeks = 0, - seconds = 0, - } = this.event.duration; - return seconds + - minutes * 60 + - hours * 60 * 60 + - days * 24 * 60 * 60 + - weeks * 7 * 24 * 60 * 60; - } - - get recurrence() { - if (this.isRecurring()) { - const rrule = this.event.component.getFirstPropertyValue('rrule'); - return rrule === null ? undefined : rrule; - } - return undefined; - } +import Model from '../model'; - get nextDate() { - if (this.isRecurring()) { - const now = ical.Time.now(); - const it = this.event.iterator(); - - while (true) { - const next = it.next(); - if (next.compare(now) >= 0) { - return convertIcalDate(next, this.timezone); - } - } - } - return undefined; - } - - getNextDates(until) { - if (this.isRecurring()) { - const now = moment(); - const it = this.event.iterator(); - const dates = []; - - while (true) { - const next = it.next(); - - if (it.completed || !next) { - return dates; - } - - const mnext = convertIcalDate(next); - - if (mnext.isAfter(until)) { - return dates; - } - - if (mnext.isSameOrAfter(now)) { - dates.push(mnext); - } - } - } - - return []; - } - - isRecurring() { - return this.event.isRecurring(); - } -} +import Event from './event'; class Schedule extends Model { @@ -142,7 +37,7 @@ class Schedule extends Model { const {timezone, icalendar} = elem; if (is_defined(icalendar)) { - ret.event = new Event(icalendar, timezone); + ret.event = Event.fromIcal(icalendar, timezone); delete ret.icalendar; } diff --git a/ng/src/web/pages/schedules/component.js b/ng/src/web/pages/schedules/component.js index 6210fdb2bc..26a66e36bc 100644 --- a/ng/src/web/pages/schedules/component.js +++ b/ng/src/web/pages/schedules/component.js @@ -30,7 +30,7 @@ import _ from 'gmp/locale.js'; import {is_defined} from 'gmp/utils'; -import {ReccurenceFrequency} from 'gmp/models/schedule'; +import {ReccurenceFrequency} from 'gmp/models/event'; import PropTypes from '../../utils/proptypes.js'; import withGmp from '../../utils/withGmp.js'; diff --git a/ng/src/web/pages/schedules/render.js b/ng/src/web/pages/schedules/render.js index 8ec9713af2..cbc53e2843 100644 --- a/ng/src/web/pages/schedules/render.js +++ b/ng/src/web/pages/schedules/render.js @@ -22,7 +22,7 @@ */ import _ from 'gmp/locale'; -import {ReccurenceFrequency} from 'gmp/models/schedule'; +import {ReccurenceFrequency} from 'gmp/models/event'; export const renderRecurrence = ({freq, interval = 1} = {}) => { switch (freq) { diff --git a/ng/src/web/pages/tasks/dashboard/schedulesdisplay.js b/ng/src/web/pages/tasks/dashboard/schedulesdisplay.js index b307c0202e..e33301f3a8 100644 --- a/ng/src/web/pages/tasks/dashboard/schedulesdisplay.js +++ b/ng/src/web/pages/tasks/dashboard/schedulesdisplay.js @@ -28,7 +28,7 @@ import {longDate} from 'gmp/locale/date'; import {is_defined} from 'gmp/utils/identity'; import {TASKS_FILTER_FILTER} from 'gmp/models/filter'; -import {ReccurenceFrequency} from 'gmp/models/schedule'; +import {ReccurenceFrequency} from 'gmp/models/event'; import ScheduleChart from 'web/components/chart/schedule'; From 29b445a5de7ecde81d6fd0502fb0c8dfb6b427a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ricks?= Date: Thu, 14 Jun 2018 16:08:49 +0200 Subject: [PATCH 04/10] Allow to create an ical Event from current data --- ng/src/gmp/models/event.js | 89 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/ng/src/gmp/models/event.js b/ng/src/gmp/models/event.js index 7a559eaa3e..23c18e9a47 100644 --- a/ng/src/gmp/models/event.js +++ b/ng/src/gmp/models/event.js @@ -24,12 +24,33 @@ import moment from 'moment-timezone'; import ical from 'ical.js'; +import uuid from 'uuid/v4'; + import {is_defined} from '../utils/identity'; +import {is_empty} from '../utils/string'; const convertIcalDate = (date, timezone) => is_defined(timezone) ? moment.unix(date.toUnixTime()).tz(timezone) : moment.unix(date.toUnixTime()); +const setEventDuration = (event, duration) => { + // setting the duration of an event directly isn't possible in + // ical.js 1.2.2 yet. Therefore add same logic from ical.js master here + if (event.component.hasProperty('dtend')) { + event.component.removeProperty('dtend'); + } + + event._setProp('duration', duration); +}; + +const setEventRecurrence = (event, recurrence) => { + event._setProp('rrule', recurrence); +}; + +const DAYS = 'day'; +const WEEKS = 'week'; +const MONTHS = 'month'; + export const ReccurenceFrequency = { YEARLY: 'YEARLY', MONTHLY: 'MONTHLY', @@ -55,6 +76,74 @@ class Event { return new Event(event, timezone); } + static fromData({ + description, + date, + hour = 0, + minute = 0, + duration = 0, + durationUnit, + period = 0, + periodUnit, + summary, + }, timezone) { + + const event = new ical.Event(); + + const startDate = moment(date); // create copy with tz support + + if (is_defined(timezone)) { + startDate.tz(timezone); + } + + startDate.hour(hour).minute(minute); + + event.uid = uuid(); + event.startDate = ical.Time.fromJSDate(startDate.toDate(), true); + + if (duration > 0) { + const eventDuration = new ical.Duration(); + if (durationUnit === DAYS) { + eventDuration.days = duration; + } + else if (durationUnit === WEEKS) { + eventDuration.weeks = duration; + } + else { + eventDuration.hours = duration; + } + setEventDuration(event, eventDuration); + } + + if (period > 0) { + const eventRecur = new ical.Recur(); + if (periodUnit === MONTHS) { + eventRecur.freq = ReccurenceFrequency.MONTHLY; + } + else if (periodUnit === WEEKS) { + eventRecur.freq = ReccurenceFrequency.WEEKLY; + } + else if (periodUnit === DAYS) { + eventRecur.freq = ReccurenceFrequency.WEEKLY; + } + else { + eventRecur.freq = ReccurenceFrequency.HOURLY; + } + eventRecur.interval = period; + + setEventRecurrence(event, eventRecur); + } + + if (!is_empty(summary)) { + event.summary = summary; + } + if (!is_empty(description)) { + event.description = description; + } + + return new Event(event, timezone); + } + get startDate() { return convertIcalDate(this.event.startDate, this.timezone); } From 8958b14a26b420efb7e9afdeaba5fe2744a9a78a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ricks?= Date: Thu, 14 Jun 2018 16:12:19 +0200 Subject: [PATCH 05/10] Allow to return an icalendar from Event model --- ng/src/gmp/models/event.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/ng/src/gmp/models/event.js b/ng/src/gmp/models/event.js index 23c18e9a47..82456bb468 100644 --- a/ng/src/gmp/models/event.js +++ b/ng/src/gmp/models/event.js @@ -47,6 +47,9 @@ const setEventRecurrence = (event, recurrence) => { event._setProp('rrule', recurrence); }; +const PROD_ID = '-//Greenbone.net//NONSGML Greenbone Security Assistent'; +const ICAL_VERSION = '2.0'; + const DAYS = 'day'; const WEEKS = 'week'; const MONTHS = 'month'; @@ -221,6 +224,16 @@ class Event { isRecurring() { return this.event.isRecurring(); } + + toIcalString() { + const comp = new ical.Component(['vcalendar', [], []]); + comp.addPropertyWithValue('prodid', PROD_ID); + comp.addPropertyWithValue('version', ICAL_VERSION); + + const {component: vevent} = this.event; + comp.addSubcomponent(vevent); + return comp.toString(); + } } export default Event; From c0d14967be41b9872d7bd3338536a9b04e4646ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ricks?= Date: Thu, 14 Jun 2018 16:13:13 +0200 Subject: [PATCH 06/10] Update ScheduleCommand create to support icalendar data Support icalendar data when creating a new schedule instead of the legacy year, hour, duration, ... parameters. --- ng/src/gmp/commands/schedules.js | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/ng/src/gmp/commands/schedules.js b/ng/src/gmp/commands/schedules.js index fdb0d2439a..103acdd73a 100644 --- a/ng/src/gmp/commands/schedules.js +++ b/ng/src/gmp/commands/schedules.js @@ -39,33 +39,16 @@ class ScheduleCommand extends EntityCommand { const { name, comment = '', - hour, - minute, + icalendar, timezone, - date, - period, - period_unit, - duration, - duration_unit, } = args; - const day_of_month = date.date(); - const month = date.month() + 1; - const year = date.year(); log.debug('Creating new schedule', args); return this.action({ cmd: 'create_schedule', name, comment, - day_of_month, - month, - year, - hour, - minute, + icalendar, timezone, - period, - period_unit, - duration, - duration_unit, }); } From 45f1bf90e6da1d81524b6381b534ec579ccf2d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ricks?= Date: Thu, 14 Jun 2018 16:14:59 +0200 Subject: [PATCH 07/10] Update ScheduleDialog to return icalendar data on save No functionality of the ScheduleDialog has been changed yet. It just supports converting the current data into the icalendar format. --- ng/src/web/pages/schedules/dialog.js | 134 +++++++++++++++++---------- 1 file changed, 84 insertions(+), 50 deletions(-) diff --git a/ng/src/web/pages/schedules/dialog.js b/ng/src/web/pages/schedules/dialog.js index 05a7bd1ee3..9410305ccb 100644 --- a/ng/src/web/pages/schedules/dialog.js +++ b/ng/src/web/pages/schedules/dialog.js @@ -21,13 +21,16 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ - import React from 'react'; import _ from 'gmp/locale.js'; import {NO_VALUE} from 'gmp/parser'; +import {is_defined} from 'gmp/utils/identity'; + +import Event from 'gmp/models/event'; + import PropTypes from '../../utils/proptypes.js'; import SaveDialog from '../../components/dialog/savedialog.js'; @@ -68,53 +71,88 @@ TimeUnitSelect.propTypes = { month: PropTypes.bool, }; -const ScheduleDialog = ({ - comment = '', - date, - duration = NO_VALUE, - duration_unit = 'hour', - hour, - id, - minute, - name = _('Unnamed'), - period = NO_VALUE, - period_unit = 'hour', - timezone = 'UTC', - title = _('New Schedule'), - visible = true, - onClose, - onSave, -}) => { - - const data = { +class ScheduleDialog extends React.Component { + + constructor(...args) { + super(...args); + + this.handleSave = this.handleSave.bind(this); + } + + handleSave({ comment, - date, - duration, duration_unit, - hour, - id, - minute, name, - period, period_unit, timezone, - }; + ...other + }) { + const {onSave} = this.props; - return ( - - {({ - values: state, - onValueChange, - }) => { - return ( - + if (!is_defined(onSave)) { + return Promise.resolve(); + } + + const event = Event.fromData({ + summary: name, + description: comment, + durationUnit: duration_unit, + periodUnit: period_unit, + ...other, + }, timezone); + return onSave({ + name, + comment, + icalendar: event.toIcalString(), + timezone, + }); + } + + render() { + const { + comment = '', + date, + duration = NO_VALUE, + duration_unit = 'hour', + hour, + id, + minute, + name = _('Unnamed'), + period = NO_VALUE, + period_unit = 'hour', + timezone = 'UTC', + title = _('New Schedule'), + visible = true, + onClose, + } = this.props; + + const data = { + comment, + date, + duration, + duration_unit, + hour, + id, + minute, + name, + period, + period_unit, + timezone, + }; + return ( + + {({ + values: state, + onValueChange, + }) => ( + - ); - }} - - ); -}; - -ScheduleDialog.contextTypes = { - gmp: PropTypes.gmp.isRequired, -}; + )} + + ); + } +} ScheduleDialog.propTypes = { comment: PropTypes.string, From 8f33567df1d3097af7d849ab86da838ae14ccb21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ricks?= Date: Fri, 15 Jun 2018 11:52:20 +0200 Subject: [PATCH 08/10] Update gsad to use icalendar param for saving schedules When calling save_schedule command use the icalendar param and forward it to gvmd. --- gsad/src/gsad_gmp.c | 58 ++++++--------------------------------------- 1 file changed, 7 insertions(+), 51 deletions(-) diff --git a/gsad/src/gsad_gmp.c b/gsad/src/gsad_gmp.c index bbea7f99d1..244ad2f563 100644 --- a/gsad/src/gsad_gmp.c +++ b/gsad/src/gsad_gmp.c @@ -22268,42 +22268,24 @@ export_schedules_gmp (gvm_connection_t *connection, * @return Enveloped XML object. */ char * -save_schedule_gmp (gvm_connection_t *connection, credentials_t * credentials, params_t *params, - cmd_response_data_t* response_data) +save_schedule_gmp (gvm_connection_t *connection, credentials_t *credentials, + params_t *params, cmd_response_data_t *response_data) { gchar *response; entity_t entity; - const char *schedule_id, *name, *comment; - const char *hour, *minute, *day_of_month, *month, *year, *timezone; - const char *period, *period_unit, *duration, *duration_unit; + const char *schedule_id, *name, *comment, *timezone, *icalendar; char *ret; schedule_id = params_value (params, "schedule_id"); name = params_value (params, "name"); comment = params_value (params, "comment"); - hour = params_value (params, "hour"); - minute = params_value (params, "minute"); - day_of_month = params_value (params, "day_of_month"); - duration = params_value (params, "duration"); - duration_unit = params_value (params, "duration_unit"); - month = params_value (params, "month"); - period = params_value (params, "period"); - period_unit = params_value (params, "period_unit"); - year = params_value (params, "year"); + icalendar = params_value (params, "icalendar"); timezone = params_value (params, "timezone"); CHECK_PARAM_INVALID (schedule_id, "Save Schedule"); CHECK_PARAM_INVALID (name, "Save Schedule"); CHECK_PARAM_INVALID (comment, "Save Schedule"); - CHECK_PARAM_INVALID (hour, "Save Schedule"); - CHECK_PARAM_INVALID (minute, "Save Schedule"); - CHECK_PARAM_INVALID (day_of_month, "Save Schedule"); - CHECK_PARAM_INVALID (duration, "Save Schedule"); - CHECK_PARAM_INVALID (duration_unit, "Save Schedule"); - CHECK_PARAM_INVALID (month, "Save Schedule"); - CHECK_PARAM_INVALID (period, "Save Schedule"); - CHECK_PARAM_INVALID (period_unit, "Save Schedule"); - CHECK_PARAM_INVALID (year, "Save Schedule"); + CHECK_PARAM_INVALID (icalendar, "Save Schedule"); CHECK_PARAM_INVALID (timezone, "Save Schedule"); response = NULL; @@ -22315,40 +22297,14 @@ save_schedule_gmp (gvm_connection_t *connection, credentials_t * credentials, pa "" "%s" "%s" - "" - "%s" - "%s" - "%s" - "%s" - "%s" - "" "%s" - "" - "%s" - "%s" - "" - "" - "%s" - "%s" - "" + "%s" "", schedule_id, name ? name : "", comment ? comment : "", - hour, - minute, - day_of_month, - month, - year, timezone, - (strcmp (period_unit, "") - ? period_unit - : "second"), - period, - (strcmp (duration_unit, "") - ? duration_unit - : "second"), - duration)) + icalendar)) { case 0: case -1: From fa1b99bdd3563bf2de0f9f0a5017c24e254ab39b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ricks?= Date: Fri, 15 Jun 2018 11:53:42 +0200 Subject: [PATCH 09/10] Update ScheduleCommand save to use icalendar data When saving the a Schedule use the icalendar data. --- ng/src/gmp/commands/schedules.js | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/ng/src/gmp/commands/schedules.js b/ng/src/gmp/commands/schedules.js index 103acdd73a..e710ef2b5d 100644 --- a/ng/src/gmp/commands/schedules.js +++ b/ng/src/gmp/commands/schedules.js @@ -54,38 +54,20 @@ class ScheduleCommand extends EntityCommand { save(args) { const { + comment = '', + icalendar, id, name, - comment = '', - hour, - minute, timezone, - date, - period, - period_unit, - duration, - duration_unit, } = args; - const day_of_month = date.date(); - const month = date.month() + 1; - const year = date.year(); - const data = { cmd: 'save_schedule', comment, - day_of_month, - duration, - duration_unit, - hour, id, - minute, - month, + icalendar, name, - period, - period_unit, timezone, - year, }; log.debug('Saving schedule', args, data); return this.action(data); From 344e96e225a2e661906e32f617ad92104784746a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ricks?= Date: Fri, 15 Jun 2018 11:54:43 +0200 Subject: [PATCH 10/10] Allow editing Schedules again Forward the id to the onSave handler to be able to decide if saving is a create or modify/save command. --- ng/src/web/pages/schedules/dialog.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ng/src/web/pages/schedules/dialog.js b/ng/src/web/pages/schedules/dialog.js index 9410305ccb..8f8531e290 100644 --- a/ng/src/web/pages/schedules/dialog.js +++ b/ng/src/web/pages/schedules/dialog.js @@ -82,6 +82,7 @@ class ScheduleDialog extends React.Component { handleSave({ comment, duration_unit, + id, name, period_unit, timezone, @@ -102,6 +103,7 @@ class ScheduleDialog extends React.Component { }, timezone); return onSave({ + id, name, comment, icalendar: event.toIcalString(),