diff --git a/pkg/modules/migration/microsoft-todo/microsoft_todo.go b/pkg/modules/migration/microsoft-todo/microsoft_todo.go index 64d20e41..0cf390f7 100644 --- a/pkg/modules/migration/microsoft-todo/microsoft_todo.go +++ b/pkg/modules/migration/microsoft-todo/microsoft_todo.go @@ -23,6 +23,7 @@ import ( "fmt" "net/http" "net/url" + "strings" "time" "code.vikunja.io/api/pkg/config" @@ -33,6 +34,7 @@ import ( ) const apiScopes = `tasks.read tasks.read.shared` +const apiPrefix = `https://graph.microsoft.com/v1.0/me/todo/` type Migration struct { Code string `json:"code"` @@ -92,6 +94,7 @@ type recurrence struct { type tasksResponse struct { OdataContext string `json:"@odata.context"` + Nextlink string `json:"@odata.nextLink"` Value []*task `json:"value"` } @@ -178,7 +181,7 @@ func getMicrosoftGraphAuthToken(code string) (accessToken string, err error) { } func makeAuthenticatedGetRequest(token, urlPart string, v interface{}) error { - req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, "https://graph.microsoft.com/v1.0/me/todo/"+urlPart, nil) + req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, apiPrefix+urlPart, nil) if err != nil { return err } @@ -224,17 +227,30 @@ func getMicrosoftTodoData(token string) (microsoftTodoData []*list, err error) { log.Debugf("[Microsoft Todo Migration] Got %d lists", len(lists.Value)) for _, list := range lists.Value { - tasksResponse := &tasksResponse{} - err = makeAuthenticatedGetRequest(token, "lists/"+list.ID+"/tasks", tasksResponse) - if err != nil { - log.Errorf("[Microsoft Todo Migration] Could not get tasks for list %s: %s", list.ID, err) - return + link := "lists/" + list.ID + "/tasks" + list.Tasks = []*task{} + + // Microsoft's Graph API has pagination, so we're going through all pages to get all tasks + for { + tr := &tasksResponse{} + + err = makeAuthenticatedGetRequest(token, link, tr) + if err != nil { + log.Errorf("[Microsoft Todo Migration] Could not get tasks for list %s: %s", list.ID, err) + return + } + + log.Debugf("[Microsoft Todo Migration] Got %d tasks for list %s", len(tr.Value), list.ID) + + list.Tasks = append(list.Tasks, tr.Value...) + + if tr.Nextlink == "" { + break + } + + link = strings.ReplaceAll(tr.Nextlink, apiPrefix, "") } - log.Debugf("[Microsoft Todo Migration] Got %d tasks for list %s", len(tasksResponse.Value), list.ID) - - list.Tasks = tasksResponse.Value - microsoftTodoData = append(microsoftTodoData, list) }