From f708a39bf15aab899a1f07d7878eed76ab105a57 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sat, 4 Sep 2021 21:11:39 +0200 Subject: [PATCH] Add docs for file based migrator --- docs/config.yml | 4 +- docs/content/doc/development/migration.md | 54 +++++++++++++++++++---- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/docs/config.yml b/docs/config.yml index c92270fdc..9e1ae7943 100644 --- a/docs/config.yml +++ b/docs/config.yml @@ -31,10 +31,10 @@ menu: url: https://vikunja.io/en/ weight: 10 - name: Features - url: https://vikunja.io/en/features + url: https://vikunja.io/features weight: 20 - name: Download - url: https://vikunja.io/en/download + url: https://vikunja.io/download weight: 30 - name: Docs url: https://vikunja.io/docs diff --git a/docs/content/doc/development/migration.md b/docs/content/doc/development/migration.md index b05f5c0e9..610ab8036 100644 --- a/docs/content/doc/development/migration.md +++ b/docs/content/doc/development/migration.md @@ -14,7 +14,17 @@ It is possible to migrate data from other to-do services to Vikunja. To make this easier, we have put together a few helpers which are documented on this page. In general, each migrator implements a migrator interface which is then called from a client. -The interface makes it possible to use helper methods which handle http an focus only on the implementation of the migrator itself. +The interface makes it possible to use helper methods which handle http and focus only on the implementation of the migrator itself. + +There are two ways of migrating data from another service: +1. Through the auth-based flow where the user gives you access to their data at the third-party service through an + oauth flow. You can then call the service's api on behalf of your user to get all the data. + The Todoist, Trello and Microsoft To-Do Migrators use this pattern. +2. A file migration where the user uploads a file obtained from some third-party service. In your migrator, you need + to parse the file and create the lists, tasks etc. + The Vikunja File Import uses this pattern. + +To differentiate the two, there are two different interfaces you must implement. {{< table_of_contents >}} @@ -23,13 +33,16 @@ The interface makes it possible to use helper methods which handle http an focus All migrator implementations live in their own package in `pkg/modules/migration/`. When creating a new migrator, you should place all related code inside that module. -## Migrator interface +## Migrator Interface The migrator interface is defined as follows: ```go // Migrator is the basic migrator interface which is shared among all migrators type Migrator interface { + // Name holds the name of the migration. + // This is used to show the name to users and to keep track of users who already migrated. + Name() string // Migrate is the interface used to migrate a user's tasks from another platform to vikunja. // The user object is the user who's tasks will be migrated. Migrate(user *models.User) error @@ -37,9 +50,20 @@ type Migrator interface { // The use case for this are Oauth flows, where the server token should remain hidden and not // known to the frontend. AuthURL() string +} +``` + +## File Migrator Interface + +```go +// FileMigrator handles importing Vikunja data from a file. The implementation of it determines the format. +type FileMigrator interface { // Name holds the name of the migration. // This is used to show the name to users and to keep track of users who already migrated. Name() string + // Migrate is the interface used to migrate a user's tasks, list and other things from a file to vikunja. + // The user object is the user who's tasks will be migrated. + Migrate(user *user.User, file io.ReaderAt, size int64) error } ``` @@ -54,15 +78,26 @@ authUrl, Status and Migrate methods. ```go // This is an example for the Wunderlist migrator if config.MigrationWunderlistEnable.GetBool() { - wunderlistMigrationHandler := &migrationHandler.MigrationWeb{ + wunderlistMigrationHandler := &migrationHandler.MigrationWeb{ MigrationStruct: func() migration.Migrator { return &wunderlist.Migration{} }, } - wunderlistMigrationHandler.RegisterRoutes(m) + wunderlistMigrationHandler.RegisterRoutes(m) } ``` +And for the file migrator: + +```go +vikunjaFileMigrationHandler := &migrationHandler.FileMigratorWeb{ + MigrationStruct: func() migration.FileMigrator { + return &vikunja_file.FileMigrator{} + }, +} +vikunjaFileMigrationHandler.RegisterRoutes(m) +``` + You should also document the routes with [swagger annotations]({{< ref "swagger-docs.md" >}}). ## Insertion helper method @@ -70,7 +105,8 @@ You should also document the routes with [swagger annotations]({{< ref "swagger- There is a method available in the `migration` package which takes a fully nested Vikunja structure and creates it with all relations. This means you start by adding a namespace, then add lists inside of that namespace, then tasks in the lists and so on. -The root structure must be present as `[]*models.NamespaceWithLists`. +The root structure must be present as `[]*models.NamespaceWithListsAndTasks`. It allows to represent all of Vikunja's +hierachie as a single data structure. Then call the method like so: @@ -85,14 +121,16 @@ err = migration.InsertFromStructure(fullVikunjaHierachie, user) ## Configuration -You should add at least an option to enable or disable the migration. +If your migrator is an oauth-based one, you should add at least an option to enable or disable it. Chances are, you'll need some more options for things like client ID and secret (if the other service uses oAuth as an authentication flow). The easiest way to implement an on/off switch is to check whether your migration service is enabled or not when -registering the routes, and then simply don't registering the routes in the case it is disabled. +registering the routes, and then simply don't registering the routes in case it is disabled. + +File based migrators can always be enabled. ### Making the migrator public in `/info` You should make your migrator available in the `/info` endpoint so that frontends can display options to enable them or not. -To do this, add an entry to `pkg/routes/api/v1/info.go`. +To do this, add an entry to the `AvailableMigrators` field in `pkg/routes/api/v1/info.go`.