Created
August 22, 2020 13:58
-
-
Save freaktechnik/99113f8caf377310c7f1a917b3d169fa to your computer and use it in GitHub Desktop.
vikunja caldav testing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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