From 50d12333f7d8386aed1b088296bdcecfa267119b Mon Sep 17 00:00:00 2001 From: Timon Engelke Date: Wed, 18 Dec 2024 10:42:11 +0100 Subject: [PATCH 1/3] zep: correctly set calendarID --- internal/adapter/google/adapter.go | 14 ++++++++++---- internal/adapter/outlook_http/adapter.go | 14 +++++++++----- internal/adapter/port/interface.go | 5 +++++ internal/adapter/sink_adapter.go | 7 ++++++- internal/adapter/source_adapter.go | 7 ++++++- internal/adapter/zep/client.go | 9 +++++++++ internal/auth/model.go | 5 ++--- 7 files changed, 47 insertions(+), 14 deletions(-) diff --git a/internal/adapter/google/adapter.go b/internal/adapter/google/adapter.go index 1bdd15d..1830f39 100644 --- a/internal/adapter/google/adapter.go +++ b/internal/adapter/google/adapter.go @@ -48,8 +48,17 @@ type CalendarAPI struct { // Assert that the expected interfaces are implemented var _ port.Configurable = &CalendarAPI{} var _ port.LogSetter = &CalendarAPI{} +var _ port.CalendarIDSetter = &CalendarAPI{} var _ port.OAuth2Adapter = &CalendarAPI{} +func (c *CalendarAPI) SetCalendarID(calendarID string) error { + if calendarID == "" { + return fmt.Errorf("adapter (%s) 'calendar' cannot be empty", c.Name()) + } + c.calendarID = calendarID + return nil +} + func (c *CalendarAPI) SetupOauth2(ctx context.Context, credentials auth.Credentials, storage auth.Storage, bindPort uint) error { // Google Adapter does not need the tenantId switch { @@ -57,8 +66,6 @@ func (c *CalendarAPI) SetupOauth2(ctx context.Context, credentials auth.Credenti return fmt.Errorf("%s adapter oAuth2 'clientID' cannot be empty", c.Name()) case credentials.Client.Secret == "": return fmt.Errorf("oAuth2 adapter (%s) 'clientSecret' cannot be empty", c.Name()) - case credentials.CalendarId == "": - return fmt.Errorf("oAuth2 adapter (%s) 'calendar' cannot be empty", c.Name()) } oauthListener, err := auth.NewOAuthHandler(oauth2.Config{ @@ -72,10 +79,9 @@ func (c *CalendarAPI) SetupOauth2(ctx context.Context, credentials auth.Credenti } c.oAuthHandler = oauthListener - c.calendarID = credentials.CalendarId c.storage = storage - storedAuth, err := c.storage.ReadCalendarAuth(credentials.CalendarId) + storedAuth, err := c.storage.ReadCalendarAuth(c.calendarID) if err != nil { return err } diff --git a/internal/adapter/outlook_http/adapter.go b/internal/adapter/outlook_http/adapter.go index 0e75384..1931127 100644 --- a/internal/adapter/outlook_http/adapter.go +++ b/internal/adapter/outlook_http/adapter.go @@ -45,8 +45,16 @@ type CalendarAPI struct { // Assert that the expected interfaces are implemented var _ port.Configurable = &CalendarAPI{} var _ port.LogSetter = &CalendarAPI{} +var _ port.CalendarIDSetter = &CalendarAPI{} var _ port.OAuth2Adapter = &CalendarAPI{} +func (c *CalendarAPI) SetCalendarID(calendarID string) error { + if calendarID == "" { + return fmt.Errorf("%s adapter 'calendar' cannot be empty", c.Name()) + } + return nil +} + func (c *CalendarAPI) SetupOauth2(ctx context.Context, credentials auth.Credentials, storage auth.Storage, bindPort uint) error { // Outlook Adapter does not need the clientKey switch { @@ -54,12 +62,8 @@ func (c *CalendarAPI) SetupOauth2(ctx context.Context, credentials auth.Credenti return fmt.Errorf("%s adapter oAuth2 'clientId' cannot be empty", c.Name()) case credentials.Tenant.Id == "": return fmt.Errorf("%s adapter oAuth2 'tenantId' cannot be empty", c.Name()) - case credentials.CalendarId == "": - return fmt.Errorf("%s adapter oAuth2 'calendar' cannot be empty", c.Name()) } - c.calendarID = credentials.CalendarId - endpoint := oauth2.Endpoint{ AuthURL: fmt.Sprintf("https://login.microsoftonline.com/%s/oauth2/v2.0/authorize", credentials.Tenant.Id), TokenURL: fmt.Sprintf("https://login.microsoftonline.com/%s/oauth2/v2.0/token", credentials.Tenant.Id), @@ -81,7 +85,7 @@ func (c *CalendarAPI) SetupOauth2(ctx context.Context, credentials auth.Credenti c.storage = storage c.oAuthConfig = &oAuthConfig - storedAuth, err := c.storage.ReadCalendarAuth(credentials.CalendarId) + storedAuth, err := c.storage.ReadCalendarAuth(c.calendarID) if err != nil { return err } diff --git a/internal/adapter/port/interface.go b/internal/adapter/port/interface.go index 18bb9c6..03a9fba 100644 --- a/internal/adapter/port/interface.go +++ b/internal/adapter/port/interface.go @@ -13,6 +13,11 @@ type LogSetter interface { SetLogger(logger *log.Logger) } +// CalendarIDSetter can be implemented by a struct to allow setting the calendar ID +type CalendarIDSetter interface { + SetCalendarID(calendarID string) error +} + // Configurable is an interface which defines how arbitrary configuration data can be passed // to a struct which implements this interface. Clients should be configurable. type Configurable interface { diff --git a/internal/adapter/sink_adapter.go b/internal/adapter/sink_adapter.go index 4cf078a..257cc39 100644 --- a/internal/adapter/sink_adapter.go +++ b/internal/adapter/sink_adapter.go @@ -45,6 +45,12 @@ func NewSinkAdapterFromConfig(ctx context.Context, bindPort uint, openBrowser bo c.SetLogger(logger) } + if c, ok := client.(port.CalendarIDSetter); ok { + if err := c.SetCalendarID(config.Adapter().Calendar); err != nil { + return nil, err + } + } + if c, ok := client.(port.OAuth2Adapter); ok { if err := c.SetupOauth2(ctx, auth.Credentials{ @@ -55,7 +61,6 @@ func NewSinkAdapterFromConfig(ctx context.Context, bindPort uint, openBrowser bo Tenant: auth.Tenant{ Id: config.Adapter().OAuth.TenantID, }, - CalendarId: config.Adapter().Calendar, }, storage, bindPort, diff --git a/internal/adapter/source_adapter.go b/internal/adapter/source_adapter.go index 7184ea3..214e633 100644 --- a/internal/adapter/source_adapter.go +++ b/internal/adapter/source_adapter.go @@ -49,6 +49,12 @@ func NewSourceAdapterFromConfig(ctx context.Context, bindPort uint, openBrowser c.SetLogger(logger) } + if c, ok := client.(port.CalendarIDSetter); ok { + if err := c.SetCalendarID(config.Adapter().Calendar); err != nil { + return nil, err + } + } + if c, ok := client.(port.OAuth2Adapter); ok { if err := c.SetupOauth2(ctx, auth.Credentials{ @@ -59,7 +65,6 @@ func NewSourceAdapterFromConfig(ctx context.Context, bindPort uint, openBrowser Tenant: auth.Tenant{ Id: config.Adapter().OAuth.TenantID, }, - CalendarId: config.Adapter().Calendar, }, storage, bindPort, diff --git a/internal/adapter/zep/client.go b/internal/adapter/zep/client.go index ae3ec29..3e70c56 100644 --- a/internal/adapter/zep/client.go +++ b/internal/adapter/zep/client.go @@ -39,6 +39,15 @@ type CalendarAPI struct { // Assert that the expected interfaces are implemented var _ port.Configurable = &CalendarAPI{} +var _ port.CalendarIDSetter = &CalendarAPI{} + +func (zep *CalendarAPI) SetCalendarID(calendarID string) error { + if calendarID == "" { + return fmt.Errorf("%s adapter 'calendar' cannot be empty", zep.Name()) + } + zep.calendarID = calendarID + return nil +} func (zep *CalendarAPI) GetCalendarHash() string { var id []byte diff --git a/internal/auth/model.go b/internal/auth/model.go index 19db952..b255f1f 100644 --- a/internal/auth/model.go +++ b/internal/auth/model.go @@ -1,9 +1,8 @@ package auth type Credentials struct { - Client Client - Tenant Tenant - CalendarId string + Client Client + Tenant Tenant } type Client struct { From e9814bef90f4c5aad37cb03b0e106e4aa68dbb8f Mon Sep 17 00:00:00 2001 From: Timon Engelke Date: Wed, 18 Dec 2024 11:09:59 +0100 Subject: [PATCH 2/3] zep: correctly identify all-day events --- internal/adapter/zep/client.go | 1 + internal/adapter/zep/event.go | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/internal/adapter/zep/client.go b/internal/adapter/zep/client.go index 3e70c56..82ca496 100644 --- a/internal/adapter/zep/client.go +++ b/internal/adapter/zep/client.go @@ -112,6 +112,7 @@ func (zep *CalendarAPI) EventsInTimeframe(ctx context.Context, start time.Time, Description: v.Description, StartTime: v.Start, EndTime: v.End, + AllDay: isAllDayEvent(v), Accepted: true, Metadata: models.NewEventMetadata(v.ID, "", zep.GetCalendarHash()), }) diff --git a/internal/adapter/zep/event.go b/internal/adapter/zep/event.go index 35ba21f..8020bbc 100644 --- a/internal/adapter/zep/event.go +++ b/internal/adapter/zep/event.go @@ -6,7 +6,7 @@ import ( ) const ( - DateFormat = "02.01.2006" + DateFormat = "02.01.2006 15:04" ) // Event is a simplified representation for an event which has been entered in ZEP. @@ -23,3 +23,15 @@ type Event struct { func (a Event) String() string { return fmt.Sprintf("%s | %s | %s | %s | %s | %s", a.ID, a.Start.Format(DateFormat), a.End.Format(DateFormat), a.Category, a.Summary, a.Description) } + +func isAllDayEvent(event Event) bool { + h, m, s := event.Start.Clock() + if h != 0 || m != 0 || s != 0 { + return false + } + h, m, s = event.End.Clock() + if h != 0 || m != 0 || s != 0 { + return false + } + return true +} From 5ae0e78b2b3c1560d6089fa92cb6347d33e8bcb3 Mon Sep 17 00:00:00 2001 From: Timon Engelke Date: Wed, 18 Dec 2024 11:11:33 +0100 Subject: [PATCH 3/3] zep: rename absences to events --- internal/adapter/zep/client.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/adapter/zep/client.go b/internal/adapter/zep/client.go index 82ca496..485d38b 100644 --- a/internal/adapter/zep/client.go +++ b/internal/adapter/zep/client.go @@ -98,13 +98,13 @@ func (zep *CalendarAPI) Initialize(ctx context.Context, openBrowser bool, config } func (zep *CalendarAPI) EventsInTimeframe(ctx context.Context, start time.Time, end time.Time) ([]models.Event, error) { - absences, err := zep.ListEvents(start, end) + events, err := zep.ListEvents(start, end) if err != nil { - return nil, fmt.Errorf("could not get absences %w", err) + return nil, fmt.Errorf("could not get zep events %w", err) } var syncEvents []models.Event - for _, v := range absences { + for _, v := range events { syncEvents = append(syncEvents, models.Event{ ICalUID: v.ID,