commit df1e43f379bceeb7b137656e950a0884a171a96d
parent fd570ae3106a48feb62de760c61609028757f694
Author: Andreas Gruhler <andreas.gruhler@adfinis.com>
Date: Wed, 6 Sep 2023 16:07:52 +0200
feat(server): smaller functions
Diffstat:
6 files changed, 172 insertions(+), 89 deletions(-)
diff --git a/README.md b/README.md
@@ -36,7 +36,7 @@ The application is configurable through environment variables or the
# Optional
#HIVEDAV_LISTEN_ADDRESS=127.0.0.1
#HIVEDAV_LISTEN_PORT=3737
-#HIVEDAV_CALDAV_HOMESET=0
+#HIVEDAV_CALENDAR=0
# Required
HIVEDAV_CALDAV_URI=
diff --git a/config/config.go b/config/config.go
@@ -2,13 +2,14 @@ package config
import (
"github.com/spf13/viper"
+ "log"
)
type Config struct {
ListenAddress string `mapstructure:"HIVEDAV_LISTEN_ADDRESS"`
ListenPort int `mapstructure:"HIVEDAV_LISTEN_PORT"`
CaldavUri string `mapstructure:"HIVEDAV_CALDAV_URI"`
- Homeset int `mapstructure:"HIVEDAV_CALDAV_HOMESET"`
+ Calendar int `mapstructure:"HIVEDAV_CALENDAR"`
CaldavUser string `mapstructure:"HIVEDAV_CALDAV_USER"`
CaldavPassword string `mapstructure:"HIVEDAV_CALDAV_PASSWORD"`
}
@@ -27,15 +28,17 @@ func (c *Config) LoadConfig(path string) (*Config, error) {
// define some defaults
viper.SetDefault("HIVEDAV_LISTEN_PORT", 3737)
viper.SetDefault("HIVEDAV_LISTEN_ADDRESS", "[::]")
- viper.SetDefault("HIVEDAV_CALDAV_HOMESET", 0)
+ viper.SetDefault("HIVEDAV_CALENDAR", 0)
err := viper.ReadInConfig()
if err != nil {
+ log.Println("app.env config file not found")
return nil, err
}
err = viper.Unmarshal(c)
if err != nil {
+ log.Println("Error unmarshalling config")
return nil, err
}
return c, nil
diff --git a/config/config_test.go b/config/config_test.go
@@ -11,18 +11,6 @@ func TestConfig(t *testing.T) {
_, err := conf.LoadConfig("..")
if err != nil {
- log.Fatal("error loading config: ", err)
+ log.Fatal("Error loading config: ", err)
}
-
- //if conf.ListenAddress != "[::]" {
- // log.Fatal("wrong default listening address", conf.ListenAddress)
- //}
-
- //if conf.ListenPort != 3737 {
- // log.Fatal("wrong default listening port", conf.ListenPort)
- //}
-
- //if conf.Homeset != 0 {
- // log.Fatal("wrong default calendar in homeset", conf.Homeset)
- //}
}
diff --git a/main.go b/main.go
@@ -4,18 +4,83 @@ import (
"fmt"
"log"
"net/http"
+ "hivedav/config"
+ "github.com/emersion/go-ical"
)
func main() {
- var server Server
// If exists, load config file from pwd
- server.config.LoadConfig(".")
+ conf := &config.Config{}
+ conf, err := conf.LoadConfig(".")
+ if err != nil {
+ log.Fatal("Error loading config: ", err)
+ }
- log.Printf("%+v\n", server.config)
- log.Println("Running hivedav v0.1 🍯")
- log.Println("Reading availability from:", server.config.CaldavUri)
- log.Println("Reading as user:", server.config.CaldavUser)
- log.Printf("Listening on %s:%d\n", server.config.ListenAddress, server.config.ListenPort)
+ var server *Server
+ server, err = server.NewServer(conf)
+ if err != nil {
+ log.Fatal("Error creating server with config: ", err)
+ }
- http.ListenAndServe(fmt.Sprintf("%s:%d", server.config.ListenAddress, server.config.ListenPort), &server)
+ log.Println("Starting hivedav v0.1 🍯")
+
+ log.Println("Reading availability from:", conf.CaldavUri)
+ log.Println("Reading as user:", conf.CaldavUser)
+ log.Println("Using nth calendar in homeset:", conf.Calendar)
+
+ userPrincipal, _ := server.caldavClient.FindCurrentUserPrincipal()
+ log.Println("User principal: ", userPrincipal)
+ homeSet, _ := server.caldavClient.FindCalendarHomeSet(userPrincipal)
+ log.Println("Calendar homeset: ", homeSet)
+
+ // Find all calendars in homeset
+ calendars, err := server.findCalendars(homeSet)
+ if err != nil {
+ log.Fatal(err)
+ }
+ server.calendars = calendars
+
+ objects, err := server.getAvailability(server.calendars[conf.Calendar].Path)
+ if err != nil {
+ log.Println("Unable to fetch availability")
+ }
+ server.objects = objects
+
+ log.Printf("Using calendar objects: %+v", objects)
+
+ for i, obj := range server.objects {
+ //log.Printf("%d %s\n", i, obj.Path)
+ log.Printf("%d - ", i)
+
+ // Get ics DTSTART and DTEND
+ // https://github.com/emersion/go-ical/blob/master/example_test.go
+ for _, event := range obj.Data.Events() {
+ // https://github.com/emersion/go-ical/blob/master/enums.go
+ summary, err := event.Props.Text(ical.PropSummary)
+ log.Printf("Found event: %v\n", summary)
+ //log.Printf("Found event: %+v\n", event.Props)
+
+ //localTimezone, err := time.LoadLocation("Europe/Zurich")
+
+ // Uses UTC when location is nil
+ // https://github.com/emersion/go-ical/blob/master/ical.go
+ // https://github.com/emersion/go-ical/issues/10
+ //dtstart, err := event.DateTimeStart(localTimezone)
+ dtstart, err := event.DateTimeStart(nil)
+ if err != nil {
+ log.Println("TZID not in tzdb form")
+ // https://github.com/emersion/go-ical/blob/master/example_test.go
+ event.Props.SetText(ical.PropTimezoneID, "")
+ dtstart, err = event.DateTimeStart(nil)
+ }
+
+ dtend, err := event.DateTimeEnd(nil)
+
+ log.Printf("Event DTSTART: %+v\n", dtstart)
+ log.Printf("Event DTEND: %+v\n", dtend)
+ }
+ }
+
+ http.ListenAndServe(fmt.Sprintf("%s:%d", conf.ListenAddress, conf.ListenPort), server)
+ log.Printf("Ready, listening on %s:%d\n", conf.ListenAddress, conf.ListenPort)
}
diff --git a/server.go b/server.go
@@ -1,13 +1,12 @@
package main
import (
+ "hivedav/config"
"fmt"
- "github.com/emersion/go-ical"
"github.com/in0rdr/go-webdav"
"github.com/in0rdr/go-webdav/caldav"
"github.com/pquerna/termchalk/ansistyle"
"github.com/pquerna/termchalk/prettytable"
- "hivedav/config"
"io"
"log"
"net/http"
@@ -16,12 +15,28 @@ import (
)
type Server struct {
- config config.Config
+ config *config.Config
+ caldavClient *caldav.Client
+ calendars []caldav.Calendar
+ objects []caldav.CalendarObject
}
-func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
- s.getAvailability()
+func (s *Server) NewServer(c *config.Config) (*Server, error) {
+ // with nil, http.DefaultClient is used
+ // https://godocs.io/github.com/emersion/go-webdav#HTTPClientWithBasicAuth
+ webdavClient := webdav.HTTPClientWithBasicAuth(nil, c.CaldavUser, c.CaldavPassword)
+ caldavClient, err := caldav.NewClient(webdavClient, c.CaldavUri)
+ if err != nil {
+ log.Fatal("Error creating caldav client:", err)
+ }
+ s = new(Server)
+ s.caldavClient = caldavClient
+ s.config = c
+ return s, nil
+}
+
+func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
userAgent := req.Header.Get("user-agent")
if strings.Contains(userAgent, "curl") {
w.Header().Set("Content-Type", "text/plain")
@@ -38,25 +53,18 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
}
}
-func (s *Server) getAvailability() {
- // with nil, http.DefaultClient is used
- // https://godocs.io/github.com/emersion/go-webdav#HTTPClientWithBasicAuth
- webdavClient := webdav.HTTPClientWithBasicAuth(nil,
- s.config.CaldavUser, s.config.CaldavPassword)
- caldavClient, _ := caldav.NewClient(webdavClient, s.config.CaldavUri)
- userPrincipal, _ := caldavClient.FindCurrentUserPrincipal()
- log.Println("USER PRINCIPAL: ", userPrincipal)
- homeSet, _ := caldavClient.FindCalendarHomeSet(userPrincipal)
- log.Println("CALENDAR HOMESET: ", homeSet)
-
- calendars, err := caldavClient.FindCalendars(homeSet)
+func (s *Server) findCalendars(homeSet string) ([]caldav.Calendar, error) {
+ calendars, err := s.caldavClient.FindCalendars(homeSet)
if err != nil {
- log.Fatalf("FindCalendars: %s", err)
- }
- for i, calendar := range calendars {
- log.Printf("cal %d: %s %s\n", i, calendar.Name, calendar.Path)
+ log.Printf("No calendars in homeset: %v", err)
+ return nil, err
}
+ log.Printf("Calendars in homeset: %+v", calendars)
+ return calendars, nil
+}
+// fetch availabiliy for a calendar
+func (s *Server) getAvailability(calendarPath string) ([]caldav.CalendarObject, error) {
compReq := caldav.CalendarCompRequest{
Name: "VCALENDAR",
Props: []string{"VERSION"},
@@ -84,44 +92,13 @@ func (s *Server) getAvailability() {
CompFilter: compFilter,
}
- // Query the calendar of the homeset
- objects, err := caldavClient.QueryCalendar(calendars[s.config.Homeset].Path, query)
+ // Get the calendar objects
+ objects, err := s.caldavClient.QueryCalendar(calendarPath, query)
if err != nil {
- log.Fatalf("QueryCalendar: %s", err)
- }
-
- for i, obj := range objects {
- //log.Printf("%d %s\n", i, obj.Path)
- log.Printf("%d - ", i)
-
- // Get ics DTSTART and DTEND
- // https://github.com/emersion/go-ical/blob/master/example_test.go
- for _, event := range obj.Data.Events() {
- // https://github.com/emersion/go-ical/blob/master/enums.go
- summary, err := event.Props.Text(ical.PropSummary)
- log.Printf("Found event: %v\n", summary)
- //log.Printf("Found event: %+v\n", event.Props)
-
- //localTimezone, err := time.LoadLocation("Europe/Zurich")
-
- // Uses UTC when location is nil
- // https://github.com/emersion/go-ical/blob/master/ical.go
- // https://github.com/emersion/go-ical/issues/10
- //dtstart, err := event.DateTimeStart(localTimezone)
- dtstart, err := event.DateTimeStart(nil)
- if err != nil {
- log.Println("TZID not in tzdb form")
- // https://github.com/emersion/go-ical/blob/master/example_test.go
- event.Props.SetText(ical.PropTimezoneID, "")
- dtstart, err = event.DateTimeStart(nil)
- }
-
- dtend, err := event.DateTimeEnd(nil)
-
- log.Printf("Event DTSTART: %+v\n", dtstart)
- log.Printf("Event DTEND: %+v\n", dtend)
- }
+ log.Printf("No calendar objects found: %v", err)
+ return nil, err
}
+ return objects, nil
}
func (s *Server) showCubicles() {
diff --git a/server_test.go b/server_test.go
@@ -1,23 +1,31 @@
package main
import (
- "log"
"net/http"
"net/http/httptest"
+ "github.com/in0rdr/go-webdav"
+ "github.com/in0rdr/go-webdav/caldav"
"strings"
"testing"
+ "hivedav/config"
)
-var server Server
+var server *Server
func TestServer(t *testing.T) {
- _, err := server.config.LoadConfig(".")
-
+ config := config.Config {
+ ListenAddress: "[::]",
+ ListenPort: 3737,
+ CaldavUri: "/",
+ Calendar: 0,
+ CaldavUser: "gandalf",
+ CaldavPassword: "ring",
+ }
+ server, err := server.NewServer(&config)
if err != nil {
- log.Fatal("error loading config: ", err)
+ t.Fatal("Could not create hivedav server")
}
-
// ResponseRecorder is an implementation of http.ResponseWriter that
// records its mutations for later inspection in tests.
// https://pkg.go.dev/net/http/httptest
@@ -62,7 +70,49 @@ func TestServer(t *testing.T) {
}
}
+func TestFindCalendars(t *testing.T) {
+ // TODO: test the http calls
+ //config := config.Config {
+ // ListenAddress: "[::]",
+ // ListenPort: 3737,
+ // CaldavUri: "/",
+ // Calendar: 0,
+ // CaldavUser: "gandalf",
+ // CaldavPassword: "ring",
+ //}
+ //server, err := server.NewServer(&config)
+ //if err != nil {
+ // t.Fatal("Could not create hivedav server")
+ //}
+
+ //homeSet := "/caldav/test@example.com/"
+ //_, err = server.findCalendars(homeSet)
+ //if err != nil {
+ // t.Fatal("Error fetching calendars for homeset", err)
+ //}
+}
+
func TestGetAvailability(t *testing.T) {
- server.config.LoadConfig(".")
- server.getAvailability()
+ config := config.Config {
+ ListenAddress: "[::]",
+ ListenPort: 3737,
+ CaldavUri: "/",
+ Calendar: 0,
+ CaldavUser: "gandalf",
+ CaldavPassword: "ring",
+ }
+ server, err := server.NewServer(&config)
+ if err != nil {
+ t.Fatal("Could not create hivedav server")
+ }
+ // TODO: Mock the server calender events with
+ // https://github.com/emersion/go-webdav/blob/master/caldav/server_test.go
+ webdavClient := webdav.HTTPClientWithBasicAuth(nil,
+ config.CaldavUser, config.CaldavPassword)
+ server.caldavClient, _ = caldav.NewClient(webdavClient, config.CaldavUri)
+ server.calendars = make([]caldav.Calendar, 1)
+ server.calendars[0].Path = "/"
+ server.objects = make([]caldav.CalendarObject, 1)
+
+ server.getAvailability(server.calendars[0].Path)
}