Skip to content

Instantly share code, notes, and snippets.

@freaktechnik
Created August 22, 2020 13:58
Show Gist options
  • Save freaktechnik/99113f8caf377310c7f1a917b3d169fa to your computer and use it in GitHub Desktop.
Save freaktechnik/99113f8caf377310c7f1a917b3d169fa to your computer and use it in GitHub Desktop.
vikunja caldav testing
diff --git a/pkg/routes/caldav/listStorageProvider.go b/pkg/routes/caldav/listStorageProvider.go
index 1abc683..967d1e3 100644
--- a/pkg/routes/caldav/listStorageProvider.go
+++ b/pkg/routes/caldav/listStorageProvider.go
@@ -17,14 +17,15 @@
package caldav
import (
+ "strconv"
+ "strings"
+ "time"
+
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/models"
user2 "code.vikunja.io/api/pkg/user"
"github.com/samedi/caldav-go/data"
"github.com/samedi/caldav-go/errs"
- "strconv"
- "strings"
- "time"
)
// DavBasePath is the base url path
@@ -47,7 +48,7 @@ type VikunjaCaldavListStorage struct {
// GetResources returns either all lists, links to the principal, or only one list, depending on the request
func (vcls *VikunjaCaldavListStorage) GetResources(rpath string, withChildren bool) ([]data.Resource, error) {
-
+ log.Debugf("[CALDAV] getResources")
// It looks like we need to have the same handler for returning both the calendar home set and the user principal
// Since the client seems to ignore the whatever is being returned in the first request and just makes a second one
// to the same url but requesting the calendar home instead
@@ -80,7 +81,7 @@ func (vcls *VikunjaCaldavListStorage) GetResources(rpath string, withChildren bo
// If vcls.list.ID is != 0, this means the user is doing a PROPFIND request to /lists/:list
// Which means we need to get only one list
if vcls.list != nil && vcls.list.ID != 0 {
- rr, err := vcls.getListRessource(true)
+ rr, err := vcls.getListResource(true)
if err != nil {
return nil, err
}
@@ -112,23 +113,47 @@ func (vcls *VikunjaCaldavListStorage) GetResources(rpath string, withChildren bo
// GetResourcesByList fetches a list of resources from a slice of paths
func (vcls *VikunjaCaldavListStorage) GetResourcesByList(rpaths []string) ([]data.Resource, error) {
-
+ log.Debugf("[CALDAV] getResourcesByList")
// Parse the set of resourcepaths into usable uids
// A path looks like this: /dav/lists/10/a6eb526d5748a5c499da202fe74f36ed1aea2aef.ics
// So we split the url in parts, take the last one and strip the ".ics" at the end
var uids []string
+ var listID int64
+ var err error
for _, path := range rpaths {
parts := strings.Split(path, "/")
- uid := []rune(parts[4]) // The 4th part is the id with ".ics" suffix
- endlen := len(uid) - 4 // ".ics" are 4 bytes
- uids = append(uids, string(uid[:endlen]))
+ listID, err = strconv.ParseInt(parts[3], 10, 64)
+ if err != nil {
+ return nil, err
+ }
+ if len(parts) > 3 {
+ uid := []rune(parts[4]) // The 4th part is the id with ".ics" suffix
+ endlen := len(uid) - 4 // ".ics" are 4 bytes
+ uids = append(uids, string(uid[:endlen]))
+ }
}
- // GetTasksByUIDs...
- // Parse these into ressources...
- tasks, err := models.GetTasksByUIDs(uids)
- if err != nil {
- return nil, err
+ var tasks []*models.Task
+ if len(uids) > 0 {
+ // GetTasksByUIDs...
+ // Parse these into ressources...
+ tasks, err = models.GetTasksByUIDs(uids)
+ if err != nil {
+ return nil, err
+ }
+ } else {
+ var tk = models.TaskCollection{
+ ListID: listID,
+ }
+ iface, _, _, err := tk.ReadAll(vcls.user, "", 1, 1000)
+ if err != nil {
+ return nil, err
+ }
+ var ok bool
+ tasks, ok = iface.([]*models.Task)
+ if !ok {
+ tasks = []*models.Task{}
+ }
}
var resources []data.Resource
@@ -146,10 +171,10 @@ func (vcls *VikunjaCaldavListStorage) GetResourcesByList(rpaths []string) ([]dat
// GetResourcesByFilters fetches a list of resources with a filter
func (vcls *VikunjaCaldavListStorage) GetResourcesByFilters(rpath string, filters *data.ResourceFilter) ([]data.Resource, error) {
-
+ log.Debugf("[CALDAV] getResourcesByFilters")
// If we already have a list saved, that means the user is making a REPORT request to find out if
// anything changed, in that case we need to return all tasks.
- // That list is coming from a previous "getListRessource" in L177
+ // That list is coming from a previous "getListResource" in L177
if vcls.list.Tasks != nil {
var resources []data.Resource
for _, t := range vcls.list.Tasks {
@@ -166,7 +191,7 @@ func (vcls *VikunjaCaldavListStorage) GetResourcesByFilters(rpath string, filter
}
// This is used to get all
- rr, err := vcls.getListRessource(false)
+ rr, err := vcls.getListResource(false)
if err != nil {
return nil, err
}
@@ -183,7 +208,7 @@ func getTaskURL(task *models.Task) string {
// GetResource fetches a single resource
func (vcls *VikunjaCaldavListStorage) GetResource(rpath string) (*data.Resource, bool, error) {
-
+ log.Debugf("[CALDAV] getResource")
// If the task is not nil, we need to get the task and not the list
if vcls.task != nil {
// save and override the updated unix date to not break any later etag checks
@@ -210,7 +235,7 @@ func (vcls *VikunjaCaldavListStorage) GetResource(rpath string) (*data.Resource,
}
// Otherwise get the list with all tasks
- rr, err := vcls.getListRessource(true)
+ rr, err := vcls.getListResource(true)
if err != nil {
return nil, false, err
}
@@ -316,8 +341,9 @@ func (vcls *VikunjaCaldavListStorage) DeleteResource(rpath string) error {
// VikunjaListResourceAdapter holds the actual resource
type VikunjaListResourceAdapter struct {
- list *models.List
- task *models.Task
+ list *models.List
+ listTasks []*models.Task
+ task *models.Task
isPrincipal bool
isCollection bool
@@ -347,18 +373,18 @@ func (vlra *VikunjaListResourceAdapter) CalculateEtag() string {
// This also returns the etag of the list, and not of the task,
// which becomes problematic because the client uses this etag (= the one from the list) to make
// Requests to update a task. These do not match and thus updating a task fails.
- return `"` + strconv.FormatInt(vlra.list.ID, 10) + `-` + strconv.FormatInt(vlra.list.Updated.Unix(), 10) + `"`
+ return `"` + strconv.FormatInt(vlra.list.ID, 10) + `-` + strconv.FormatInt(vlra.list.Updated.Unix(), 10) + `-` + strconv.Itoa(len(vlra.listTasks)) + `"`
}
// GetContent returns the content string of a resource (a task in our case)
func (vlra *VikunjaListResourceAdapter) GetContent() string {
if vlra.list != nil && vlra.list.Tasks != nil {
- return getCaldavTodosForTasks(vlra.list)
+ return getCaldavTodosForTasks(vlra.list, vlra.listTasks)
}
if vlra.task != nil {
list := models.List{Tasks: []*models.Task{vlra.task}}
- return getCaldavTodosForTasks(&list)
+ return getCaldavTodosForTasks(&list, list.Tasks)
}
return ""
@@ -382,7 +408,8 @@ func (vlra *VikunjaListResourceAdapter) GetModTime() time.Time {
return time.Time{}
}
-func (vcls *VikunjaCaldavListStorage) getListRessource(isCollection bool) (rr VikunjaListResourceAdapter, err error) {
+func (vcls *VikunjaCaldavListStorage) getListResource(isCollection bool) (rr VikunjaListResourceAdapter, err error) {
+ log.Debugf("[CALDAV] getListResource")
can, _, err := vcls.list.CanRead(vcls.user)
if err != nil {
return
@@ -392,12 +419,33 @@ func (vcls *VikunjaCaldavListStorage) getListRessource(isCollection bool) (rr Vi
return rr, models.ErrUserDoesNotHaveAccessToList{ListID: vcls.list.ID}
}
err = vcls.list.ReadOne()
+ log.Debugf("[CALDAV] readone: %v", err)
if err != nil {
return
}
+ var listTasks = vcls.list.Tasks
+ if listTasks == nil {
+ var tk = models.TaskCollection{
+ ListID: vcls.list.ID,
+ }
+ var iface interface{}
+ iface, _, _, err = tk.ReadAll(vcls.user, "", 1, 1000)
+ if err != nil {
+ return
+ }
+ var tasks, ok = iface.([]*models.Task)
+ if ok {
+ listTasks = tasks
+ vcls.list.Tasks = tasks
+ }
+ }
+
+ log.Debugf("[CALDAV] list: %v", vcls.list)
+
rr = VikunjaListResourceAdapter{
list: vcls.list,
+ listTasks: listTasks,
isCollection: isCollection,
}
diff --git a/pkg/routes/caldav/parsing.go b/pkg/routes/caldav/parsing.go
index 0439ade..455e38d 100644
--- a/pkg/routes/caldav/parsing.go
+++ b/pkg/routes/caldav/parsing.go
@@ -17,19 +17,20 @@
package caldav
import (
+ "strconv"
+ "time"
+
"code.vikunja.io/api/pkg/caldav"
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/models"
"github.com/laurent22/ical-go"
- "strconv"
- "time"
)
-func getCaldavTodosForTasks(list *models.List) string {
+func getCaldavTodosForTasks(list *models.List, listTasks []*models.Task) string {
// Make caldav todos from Vikunja todos
var caldavtodos []*caldav.Todo
- for _, t := range list.Tasks {
+ for _, t := range listTasks {
duration := t.EndDate.Sub(t.StartDate)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment