Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions ee/server/calendar/google_calendar.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,30 +298,30 @@ func (c *GoogleCalendar) Configure(userEmail string) error {
}

func (c *GoogleCalendar) UpdateEventBody(event *fleet.CalendarEvent,
genBodyFn fleet.CalendarGenBodyFn) error {
genBodyFn fleet.CalendarGenBodyFn) (string, error) {
details, err := c.unmarshalDetails(event)
if err != nil {
return err
return "", err
}
gEvent, err := c.config.API.GetEvent(details.ID, "")
if err != nil {
return ctxerr.Wrap(c.config.Context, err, "retrieving Google calendar event")
return "", ctxerr.Wrap(c.config.Context, err, "retrieving Google calendar event")
}
// Check if the current description contains the conflict text
conflict := strings.Contains(gEvent.Description, fleet.CalendarEventConflictText)
var ok bool
gEvent.Description, ok, err = genBodyFn(conflict)
if err != nil {
return ctxerr.Wrap(c.config.Context, err, "generating calendar event body")
return "", ctxerr.Wrap(c.config.Context, err, "generating calendar event body")
}
if !ok {
return nil
return "", nil
}
_, err = c.config.API.UpdateEvent(gEvent)
updatedEvent, err := c.config.API.UpdateEvent(gEvent)
if err != nil {
return ctxerr.Wrap(c.config.Context, err, "updating Google calendar event")
return "", ctxerr.Wrap(c.config.Context, err, "updating Google calendar event")
}
return nil
return updatedEvent.Etag, nil
}

func (c *GoogleCalendar) GetAndUpdateEvent(event *fleet.CalendarEvent, genBodyFn fleet.CalendarGenBodyFn,
Expand Down Expand Up @@ -441,7 +441,8 @@ func (c *GoogleCalendar) GetAndUpdateEvent(event *fleet.CalendarEvent, genBodyFn
if err != nil {
return nil, false, err
}
fleetEvent, err := c.googleEventToFleetEvent(*startTime, *endTime, gEvent, event.UUID, details.ChannelID, details.ResourceID)
fleetEvent, err := c.googleEventToFleetEvent(*startTime, *endTime, gEvent, event.UUID, details.ChannelID, details.ResourceID,
details.BodyTag)
if err != nil {
return nil, false, err
}
Expand Down Expand Up @@ -674,8 +675,8 @@ func (c *GoogleCalendar) createEvent(
resourceID = opts.ResourceID
}

// Convert Google event to Fleet event
fleetEvent, err := c.googleEventToFleetEvent(eventStart, eventEnd, event, eventUUID, channelID, resourceID)
// Convert Google event to Fleet event. Body tag will be updated by the calling function.
fleetEvent, err := c.googleEventToFleetEvent(eventStart, eventEnd, event, eventUUID, channelID, resourceID, "body_tag")
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -726,8 +727,7 @@ func getLocation(tz string, config *GoogleCalendarConfig) *time.Location {
}

func (c *GoogleCalendar) googleEventToFleetEvent(startTime time.Time, endTime time.Time, event *calendar.Event, eventUUID string,
channelID string,
resourceID string) (
channelID string, resourceID string, bodyTag string) (
*fleet.CalendarEvent, error,
) {
tzName := c.location.String()
Expand All @@ -742,6 +742,7 @@ func (c *GoogleCalendar) googleEventToFleetEvent(startTime time.Time, endTime ti
ETag: event.Etag,
ChannelID: channelID,
ResourceID: resourceID,
BodyTag: bodyTag,
}
detailsJson, err := json.Marshal(details)
if err != nil {
Expand Down
4 changes: 3 additions & 1 deletion ee/server/service/calendar.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,9 @@ func (svc *Service) processCalendarEvent(ctx context.Context, eventDetails *flee
return ctxerr.Wrap(ctx, err, "set recent update flag")
}
// Event was updated, so we need to save it
err = event.SaveBodyTag(generatedTag)
if generatedTag != "" {
err = event.SaveDataItems("body_tag", generatedTag)
}
if err != nil {
return ctxerr.Wrap(ctx, err, "save calendar event body tag")
}
Expand Down
9 changes: 5 additions & 4 deletions server/cron/calendar_cron.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ func processFailingHostExistingCalendarEvent(

// Function to generate calendar event body.
var generatedTag string
var newETag string
var genBodyFn fleet.CalendarGenBodyFn = func(conflict bool) (string, bool, error) {
var body string
body, generatedTag = calendar.GenerateCalendarEventBody(ctx, ds, orgName, host, policyIDtoPolicy, conflict, logger)
Expand All @@ -409,7 +410,7 @@ func processFailingHostExistingCalendarEvent(
updatedBodyTag := getBodyTag(ctx, ds, host, policyIDtoPolicy, logger)

if currentBodyTag != updatedBodyTag && updatedBodyTag != "" {
err = userCalendar.UpdateEventBody(calendarEvent, genBodyFn)
newETag, err = userCalendar.UpdateEventBody(calendarEvent, genBodyFn)
if err != nil {
return fmt.Errorf("update event body: %w", err)
}
Expand Down Expand Up @@ -440,8 +441,8 @@ func processFailingHostExistingCalendarEvent(
}

if updated {
if generatedTag != "" {
err = updatedEvent.SaveBodyTag(generatedTag)
if generatedTag != "" && newETag != "" {
err = updatedEvent.SaveDataItems("body_tag", generatedTag, "etag", newETag)
if err != nil {
return fmt.Errorf("save calendar event body tag: %w", err)
}
Expand Down Expand Up @@ -623,7 +624,7 @@ func attemptCreatingEventOnUserCalendar(
var dee fleet.DayEndedError
switch {
case err == nil:
err = calendarEvent.SaveBodyTag(generatedTag)
err = calendarEvent.SaveDataItems("body_tag", generatedTag)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions server/fleet/calendar.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ type UserCalendar interface {
GetAndUpdateEvent(event *CalendarEvent, genBodyFn CalendarGenBodyFn,
opts CalendarGetAndUpdateEventOpts) (updatedEvent *CalendarEvent,
updated bool, err error)
// UpdateEventBody updates the body of the calendar event.
UpdateEventBody(event *CalendarEvent, genBodyFn CalendarGenBodyFn) error
// UpdateEventBody updates the body of the calendar event and returns new ETag
UpdateEventBody(event *CalendarEvent, genBodyFn CalendarGenBodyFn) (string, error)
// DeleteEvent deletes the event with the given ID.
DeleteEvent(event *CalendarEvent) error
// StopEventChannel stops the event's callback channel.
Expand Down
12 changes: 10 additions & 2 deletions server/fleet/calendar_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package fleet

import (
"encoding/json"
"errors"
"fmt"
"time"
)
Expand Down Expand Up @@ -30,7 +31,10 @@ func (ce *CalendarEvent) GetBodyTag() string {
return d.BodyTag
}

func (ce *CalendarEvent) SaveBodyTag(bodyTag string) error {
func (ce *CalendarEvent) SaveDataItems(keysAndValues ...string) error {
if len(keysAndValues)%2 != 0 {
return errors.New("SaveDataItem requires an even number of arguments")
}
var result map[string]any
if len(ce.Data) > 0 {
err := json.Unmarshal(ce.Data, &result)
Expand All @@ -40,7 +44,11 @@ func (ce *CalendarEvent) SaveBodyTag(bodyTag string) error {
} else {
result = make(map[string]any, 1)
}
result["body_tag"] = bodyTag
for i := 0; i < len(keysAndValues); i += 2 {
key := keysAndValues[i]
value := keysAndValues[i+1]
result[key] = value
}
data, err := json.Marshal(result)
if err != nil {
return fmt.Errorf("could not marshal event data: %w", err)
Expand Down
8 changes: 4 additions & 4 deletions server/fleet/calendar_events_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import (
"github.com/stretchr/testify/require"
)

func TestBodyTag(t *testing.T) {
func TestSaveDataItems(t *testing.T) {
t.Parallel()

var event CalendarEvent

assert.Equal(t, "", event.GetBodyTag())

bodyTag := "bodyTag"
require.NoError(t, event.SaveBodyTag(bodyTag))
require.NoError(t, event.SaveDataItems("body_tag", bodyTag))
assert.Equal(t, bodyTag, event.GetBodyTag())

testMap := make(map[string]any, 5)
Expand All @@ -29,11 +29,11 @@ func TestBodyTag(t *testing.T) {
event.Data = data
assert.Equal(t, oldBodyTag, event.GetBodyTag())

require.NoError(t, event.SaveBodyTag(bodyTag))
require.NoError(t, event.SaveDataItems("body_tag", bodyTag))
assert.Equal(t, bodyTag, event.GetBodyTag())

// Make sure data was not modified
require.NoError(t, event.SaveBodyTag(oldBodyTag))
require.NoError(t, event.SaveDataItems("body_tag", oldBodyTag))
var result map[string]any
require.NoError(t, json.Unmarshal(event.Data, &result))
assert.Equal(t, testMap, result)
Expand Down
34 changes: 34 additions & 0 deletions server/service/integration_enterprise_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11728,11 +11728,15 @@ func (s *integrationEnterpriseTestSuite) TestCalendarCallback() {
require.NotZero(t, event.StartTime)
require.NotZero(t, event.EndTime)
require.NotEmpty(t, event.UUID)
bodyTag := event.GetBodyTag()
assert.NotEmpty(t, bodyTag)
assert.Equal(t, 1, calendar.MockChannelsCount())

// Get channel ID
type eventDetails struct {
ChannelID string `json:"channel_id"`
BodyTag string `json:"body_tag"`
ETag string `json:"etag"`
}
var details eventDetails
err = json.Unmarshal(event.Data, &details)
Expand Down Expand Up @@ -11855,6 +11859,8 @@ func (s *integrationEnterpriseTestSuite) TestCalendarCallback() {

err = json.Unmarshal(eventRecreated.Data, &details)
require.NoError(t, err)
assert.NotEmpty(t, details.BodyTag)
bodyTag = details.BodyTag

// New event callback should work
_ = s.DoRawWithHeaders("POST", "/api/v1/fleet/calendar/webhook/"+eventRecreated.UUID, []byte(""), http.StatusOK,
Expand Down Expand Up @@ -11891,6 +11897,30 @@ func (s *integrationEnterpriseTestSuite) TestCalendarCallback() {
assert.Greater(t, eventUpdated.StartTime, eventRecreated.StartTime)
assert.Equal(t, eventRecreated.EndTime, eventUpdated.EndTime)
assert.Equal(t, 1, calendar.MockChannelsCount())
assert.Equal(t, bodyTag, eventRecreated.GetBodyTag())

// Change the body contents of event.
events = calendar.ListGoogleMockEvents()
require.Len(t, events, 1)
eTag := "description change etag"
for _, e := range events {
e.Etag = eTag
e.Description = "new description"
}
// New event callback should cause Etag to update but Body tag to remain the same
_ = s.DoRawWithHeaders("POST", "/api/v1/fleet/calendar/webhook/"+eventRecreated.UUID, []byte(""), http.StatusOK,
map[string]string{
"X-Goog-Channel-Id": details.ChannelID,
"X-Goog-Resource-State": "exists",
})
team1CalendarEvents, err = s.ds.ListCalendarEvents(ctx, &team1.ID)
require.NoError(t, err)
require.Len(t, team1CalendarEvents, 1)
eventDescUpdated := team1CalendarEvents[0]
err = json.Unmarshal(eventDescUpdated.Data, &details)
require.NoError(t, err)
assert.Equal(t, bodyTag, details.BodyTag)
assert.Equal(t, eTag, details.ETag)

// Update the time of the event again
events = calendar.ListGoogleMockEvents()
Expand All @@ -11900,6 +11930,7 @@ func (s *integrationEnterpriseTestSuite) TestCalendarCallback() {
require.NoError(t, err)
newStartTime := st.Add(5 * time.Minute).Format(time.RFC3339)
e.Start.DateTime = newStartTime
e.Etag = e.Etag + "1"
}

// Grab the lock
Expand Down Expand Up @@ -11950,6 +11981,9 @@ func (s *integrationEnterpriseTestSuite) TestCalendarCallback() {
require.NoError(t, err)
if len(team1CalendarEvents) == 1 && team1CalendarEvents[0].UUID == event.UUID &&
team1CalendarEvents[0].StartTime.After(event.StartTime) {
err = json.Unmarshal(team1CalendarEvents[0].Data, &details)
require.NoError(t, err)
assert.NotEqual(t, eTag, details.ETag, "ETag should have updated")
done <- struct{}{}
return
}
Expand Down