From 4876542124e540928c332ca24eba8f46c63408b0 Mon Sep 17 00:00:00 2001 From: kolaente Date: Wed, 16 Dec 2020 17:41:51 +0100 Subject: [PATCH] Add migration function stubs --- config.yml.sample | 10 +- go.mod | 1 + go.sum | 2 + pkg/config/config.go | 7 +- pkg/modules/migration/trello/trello.go | 125 ++++++++++++++++++++++++- 5 files changed, 132 insertions(+), 13 deletions(-) diff --git a/config.yml.sample b/config.yml.sample index c7b868338..72426cdeb 100644 --- a/config.yml.sample +++ b/config.yml.sample @@ -189,16 +189,14 @@ migration: # Wheter to enable the trello migrator or not enable: false # The client id, required for making requests to the trello api - # You need to register your vikunja instance at to get this - clientid: - # The client secret, also required for making requests to the trello api - clientsecret: + # You need to register your vikunja instance at https://trello.com/app-key (log in before you visit that link) to get this + key: # The url where clients are redirected after they authorized Vikunja to access their trello cards. # This needs to match the url you entered when registering your Vikunja instance at trello. # This is usually the frontend url where the frontend then makes a request to /migration/trello/migrate # with the code obtained from the trello api. - # Note that the vikunja frontend expects this to be /migrate/trello - redirecturl: + # Note that the vikunja frontend expects this to end on /migrate/trello. + redirecturl: /migrate/trello avatar: # When using gravatar, this is the duration in seconds until a cached gravatar user avatar expires diff --git a/go.mod b/go.mod index 5e46fe9fd..8fe2374c3 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( code.vikunja.io/web v0.0.0-20200809154828-8767618f181f dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363 // indirect gitea.com/xorm/xorm-redis-cache v0.2.0 + github.com/adlio/trello v1.8.0 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef github.com/beevik/etree v1.1.0 // indirect diff --git a/go.sum b/go.sum index d2abb5348..ec4169218 100644 --- a/go.sum +++ b/go.sum @@ -74,6 +74,8 @@ github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqR github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/adlio/trello v1.8.0 h1:VU/1zwzuRzATsFC8WiK4f8R0HHQPWpf2H658KEchsmA= +github.com/adlio/trello v1.8.0/go.mod h1:l2068AhUuUuQ9Vsb95ECMueHThYyAj4e85lWPmr2/LE= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= diff --git a/pkg/config/config.go b/pkg/config/config.go index 33cd0f7ff..53debaaad 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -119,8 +119,7 @@ const ( MigrationTodoistClientSecret Key = `migration.todoist.clientsecret` MigrationTodoistRedirectURL Key = `migration.todoist.redirecturl` MigrationTrelloEnable Key = `migration.trello.enable` - MigrationTrelloClientID Key = `migration.trello.clientid` - MigrationTrelloClientSecret Key = `migration.trello.clientsecret` + MigrationTrelloKey Key = `migration.trello.key` MigrationTrelloRedirectURL Key = `migration.trello.redirecturl` CorsEnable Key = `cors.enable` @@ -346,6 +345,10 @@ func InitConfig() { AuthOpenIDRedirectURL.Set(ServiceFrontendurl.GetString() + "auth/openid/") } + if MigrationTrelloRedirectURL.GetString() == "" { + MigrationTrelloRedirectURL.Set(ServiceFrontendurl.GetString() + "migrate/trello") + } + log.Printf("Using config file: %s", viper.ConfigFileUsed()) } diff --git a/pkg/modules/migration/trello/trello.go b/pkg/modules/migration/trello/trello.go index 3d68c9393..80fadf8c3 100644 --- a/pkg/modules/migration/trello/trello.go +++ b/pkg/modules/migration/trello/trello.go @@ -16,9 +16,36 @@ package trello -import "code.vikunja.io/api/pkg/user" +import ( + "code.vikunja.io/api/pkg/config" + "code.vikunja.io/api/pkg/log" + "code.vikunja.io/api/pkg/models" + "code.vikunja.io/api/pkg/modules/migration" + "code.vikunja.io/api/pkg/user" + "github.com/adlio/trello" +) type Migration struct { + Token string `json:"token"` +} + +var trelloColorMap map[string]string + +func init() { + trelloColorMap = make(map[string]string, 10) + trelloColorMap = map[string]string{ + "green": "61bd4f", + "yellow": "f2d600", + "orange": "ff9f1a", + "red": "eb5a46", + "sky": "00c2e0", + "lime": "51e898", + "purple": "c377e0", + "blue": "0079bf", + "pink": "ff78cb", + "black": "344563", + "transparent": "", // Empty + } } // Name is used to get the name of the trello migration - we're using the docs here to annotate the status route. @@ -44,7 +71,68 @@ func (m *Migration) Name() string { // @Failure 500 {object} models.Message "Internal server error" // @Router /migration/trello/auth [get] func (m *Migration) AuthURL() string { - panic("implement me") + return "https://trello.com/1/authorize" + + "?expiration=1hour" + + "&scope=read" + + "&callback_method=fragment" + + "&response_type=token" + + "&name=Vikunja%20Migration" + + "&key=" + config.MigrationTrelloKey.GetString() + + "&return_url=" + config.MigrationTrelloRedirectURL.GetString() +} + +func getTrelloData(token string) (trelloData []*trello.Board, err error) { + client := trello.NewClient(config.MigrationTrelloKey.GetString(), token) + client.Logger = log.GetLogger() + + trelloData, err = client.GetMyBoards(trello.Defaults()) + if err != nil { + return + } + + for _, board := range trelloData { + board.Lists, err = board.GetLists(trello.Defaults()) + if err != nil { + return + } + + listMap := make(map[string]*trello.List, len(board.Lists)) + for _, list := range board.Lists { + listMap[list.ID] = list + } + + cards, err := board.GetCards(trello.Defaults()) + if err != nil { + return nil, err + } + + for _, card := range cards { + list, exists := listMap[card.IDList] + if !exists { + continue + } + + list.Cards = append(list.Cards, card) + } + } + + return +} + +// Converts all previously obtained data from trello into the vikunja format. +// `trelloData` should contain all boards with their lists and cards respectively. +func convertTrelloDataToVikunja(trelloData []*trello.Board) (fullVikunjaHierachie []*models.NamespaceWithLists, err error) { + + // Archived Board (closed) + // Backgrounds + + // Labels + // Checklists (as markdown in description) + // Due Date + // Reminders for due dates + // Attachments + + return } // Migrate gets all tasks from trello for a user and puts them into vikunja @@ -54,10 +142,37 @@ func (m *Migration) AuthURL() string { // @Accept json // @Produce json // @Security JWTKeyAuth -// @Param migrationCode body trello.Migration true "The auth code previously obtained from the auth url. See the docs for /migration/trello/auth." +// @Param migrationCode body trello.Migration true "The auth token previously obtained from the auth url. See the docs for /migration/trello/auth." // @Success 200 {object} models.Message "A message telling you everything was migrated successfully." // @Failure 500 {object} models.Message "Internal server error" // @Router /migration/trello/migrate [post] -func (m *Migration) Migrate(user *user.User) error { - panic("implement me") +func (m *Migration) Migrate(u *user.User) (err error) { + log.Debugf("[Trello Migration] Starting migration for user %d", u.ID) + log.Debugf("[Trello Migration] Getting all trello data for user %d", u.ID) + + trelloData, err := getTrelloData(m.Token) + if err != nil { + return + } + + log.Debugf("[Trello Migration] Got all trello data for user %d", u.ID) + log.Debugf("[Trello Migration] Start converting trello data for user %d", u.ID) + + fullVikunjaHierachie, err := convertTrelloDataToVikunja(trelloData) + if err != nil { + return + } + + log.Debugf("[Trello Migration] Done migrating trello data for user %d", u.ID) + log.Debugf("[Trello Migration] Start inserting trello data for user %d", u.ID) + + err = migration.InsertFromStructure(fullVikunjaHierachie, u) + if err != nil { + return + } + + log.Debugf("[Trello Migration] Done inserting trello data for user %d", u.ID) + log.Debugf("[Trello Migration] Migration done for user %d", u.ID) + + return nil }