From 8c84dd298679aec082c5e016b36343f1db65d2e4 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 14:32:29 +0100 Subject: [PATCH 01/45] Add basic event setup --- go.mod | 1 + go.sum | 13 ++++++++ pkg/events/events.go | 69 +++++++++++++++++++++++++++++++++++++++++ pkg/events/listeners.go | 23 ++++++++++++++ pkg/initialize/init.go | 9 ++++++ 5 files changed, 115 insertions(+) create mode 100644 pkg/events/events.go create mode 100644 pkg/events/listeners.go diff --git a/go.mod b/go.mod index 55af9cfca..b12b836d6 100644 --- a/go.mod +++ b/go.mod @@ -21,6 +21,7 @@ require ( code.vikunja.io/web v0.0.0-20201223143420-588abb73703a dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363 // indirect gitea.com/xorm/xorm-redis-cache v0.2.0 + github.com/ThreeDotsLabs/watermill v1.1.1 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 diff --git a/go.sum b/go.sum index f564d0df5..9726bb3ef 100644 --- a/go.sum +++ b/go.sum @@ -72,6 +72,8 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko github.com/Shopify/goreferrer v0.0.0-20181106222321-ec9c9a553398/go.mod h1:a1uqRtAwp2Xwc6WNPJEufxJ7fx3npB4UV/JOLmbu5I0= 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/ThreeDotsLabs/watermill v1.1.1 h1:+9NXqWQvplzxBru2CIInvVOZeKUnM+Nysg42fInl5sY= +github.com/ThreeDotsLabs/watermill v1.1.1/go.mod h1:Qd1xNFxolCAHCzcMrm6RnjW0manbvN+DJVWc1MWRFlI= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= 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= @@ -111,7 +113,10 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBW github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2 h1:t8KYCwSKsOEZBFELI4Pn/phbp38iJ1RRAkDFNin1aak= github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v3 v3.0.0 h1:ske+9nBpD9qZsTBoF41nW5L+AIuFBKMeze18XQ3eG1c= +github.com/cenkalti/backoff/v3 v3.0.0/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= @@ -211,6 +216,7 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-errors/errors v1.1.1 h1:ljK/pL5ltg3qoN+OtN6yCv9HWSfMwxSx90GJCZQxYNg= @@ -346,6 +352,8 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= @@ -369,10 +377,12 @@ github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBt github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= @@ -526,6 +536,8 @@ github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8= github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lithammer/shortuuid/v3 v3.0.4 h1:uj4xhotfY92Y1Oa6n6HUiFn87CdoEHYUlTy0+IgbLrs= +github.com/lithammer/shortuuid/v3 v3.0.4/go.mod h1:RviRjexKqIzx/7r1peoAITm6m7gnif/h+0zmolKJjzw= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g= github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= @@ -612,6 +624,7 @@ github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8= diff --git a/pkg/events/events.go b/pkg/events/events.go new file mode 100644 index 000000000..072362395 --- /dev/null +++ b/pkg/events/events.go @@ -0,0 +1,69 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-2021 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public Licensee as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public Licensee for more details. +// +// You should have received a copy of the GNU Affero General Public Licensee +// along with this program. If not, see . + +package events + +import ( + "context" + "github.com/ThreeDotsLabs/watermill" + "github.com/ThreeDotsLabs/watermill/message" + "github.com/ThreeDotsLabs/watermill/message/router/middleware" + "github.com/ThreeDotsLabs/watermill/pubsub/gochannel" + "time" +) + +var ( + pubsub *gochannel.GoChannel + logger = watermill.NewStdLogger(false, false) +) + +func InitEvents() (err error) { + router, err := message.NewRouter( + message.RouterConfig{}, + logger, + ) + if err != nil { + return err + } + + router.AddMiddleware( + middleware.Retry{ + MaxRetries: 3, + InitialInterval: time.Millisecond * 100, + Logger: logger, + }.Middleware, + middleware.Recoverer, + ) + + pubsub = gochannel.NewGoChannel( + gochannel.Config{ + OutputChannelBuffer: 1024, + }, + logger, + ) + + for topic, funcs := range listeners { + for _, handler := range funcs { + router.AddNoPublisherHandler(topic+watermill.NewShortUUID(), topic, pubsub, handler) + } + } + + return router.Run(context.Background()) +} + +func Publish(topic string, message ...*message.Message) error { + return pubsub.Publish(topic, message...) +} diff --git a/pkg/events/listeners.go b/pkg/events/listeners.go new file mode 100644 index 000000000..3d6d692d0 --- /dev/null +++ b/pkg/events/listeners.go @@ -0,0 +1,23 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-2021 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public Licensee as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public Licensee for more details. +// +// You should have received a copy of the GNU Affero General Public Licensee +// along with this program. If not, see . + +package events + +import "github.com/ThreeDotsLabs/watermill/message" + +var listeners = map[string][]message.NoPublishHandlerFunc{ + "task.created": {}, +} diff --git a/pkg/initialize/init.go b/pkg/initialize/init.go index 5ed4bdebb..ed4c62a68 100644 --- a/pkg/initialize/init.go +++ b/pkg/initialize/init.go @@ -19,6 +19,7 @@ package initialize import ( "code.vikunja.io/api/pkg/config" "code.vikunja.io/api/pkg/cron" + "code.vikunja.io/api/pkg/events" "code.vikunja.io/api/pkg/files" "code.vikunja.io/api/pkg/log" "code.vikunja.io/api/pkg/mail" @@ -85,4 +86,12 @@ func FullInit() { // Start the cron cron.Init() models.RegisterReminderCron() + + // Start processing events + go func() { + err := events.InitEvents() + if err != nil { + log.Fatal(err.Error()) + } + }() } -- 2.40.1 From 7a00cb1f6a587f37072adc8bae351e60094c7391 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 15:08:39 +0100 Subject: [PATCH 02/45] Add handlers and listeners --- pkg/events/events.go | 25 ++++++++++++++++++++++--- pkg/events/listeners.go | 16 ++++++++++++---- pkg/initialize/init.go | 1 + pkg/models/events.go | 29 +++++++++++++++++++++++++++++ pkg/models/listeners.go | 30 ++++++++++++++++++++++++++++++ pkg/models/tasks.go | 5 +++++ 6 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 pkg/models/events.go create mode 100644 pkg/models/listeners.go diff --git a/pkg/events/events.go b/pkg/events/events.go index 072362395..26bbbbf68 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -18,6 +18,7 @@ package events import ( "context" + "encoding/json" "github.com/ThreeDotsLabs/watermill" "github.com/ThreeDotsLabs/watermill/message" "github.com/ThreeDotsLabs/watermill/message/router/middleware" @@ -30,6 +31,11 @@ var ( logger = watermill.NewStdLogger(false, false) ) +type Event interface { + TopicName() string + Message() interface{} +} + func InitEvents() (err error) { router, err := message.NewRouter( message.RouterConfig{}, @@ -57,13 +63,26 @@ func InitEvents() (err error) { for topic, funcs := range listeners { for _, handler := range funcs { - router.AddNoPublisherHandler(topic+watermill.NewShortUUID(), topic, pubsub, handler) + router.AddNoPublisherHandler(topic+watermill.NewShortUUID(), topic, pubsub, func(msg *message.Message) error { + var payload interface{} + err = json.Unmarshal(msg.Payload, payload) + if err != nil { + return err + } + return handler.Handle(payload) + }) } } return router.Run(context.Background()) } -func Publish(topic string, message ...*message.Message) error { - return pubsub.Publish(topic, message...) +func Publish(event Event) error { + content, err := json.Marshal(event.Message()) + if err != nil { + return err + } + + msg := message.NewMessage(watermill.NewUUID(), content) + return pubsub.Publish(event.TopicName(), msg) } diff --git a/pkg/events/listeners.go b/pkg/events/listeners.go index 3d6d692d0..33227cf4d 100644 --- a/pkg/events/listeners.go +++ b/pkg/events/listeners.go @@ -16,8 +16,16 @@ package events -import "github.com/ThreeDotsLabs/watermill/message" - -var listeners = map[string][]message.NoPublishHandlerFunc{ - "task.created": {}, +type Listener interface { + Handle(payload interface{}) error +} + +var listeners map[string][]Listener + +func init() { + listeners = make(map[string][]Listener) +} + +func RegisterListener(topicName string, listener Listener) { + listeners[topicName] = append(listeners[topicName], listener) } diff --git a/pkg/initialize/init.go b/pkg/initialize/init.go index ed4c62a68..be09a614d 100644 --- a/pkg/initialize/init.go +++ b/pkg/initialize/init.go @@ -89,6 +89,7 @@ func FullInit() { // Start processing events go func() { + models.RegisterListeners() err := events.InitEvents() if err != nil { log.Fatal(err.Error()) diff --git a/pkg/models/events.go b/pkg/models/events.go new file mode 100644 index 000000000..6e59dd231 --- /dev/null +++ b/pkg/models/events.go @@ -0,0 +1,29 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-2021 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public Licensee as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public Licensee for more details. +// +// You should have received a copy of the GNU Affero General Public Licensee +// along with this program. If not, see . + +package models + +type TaskCreatedEvent struct { + Task *Task +} + +func (t *TaskCreatedEvent) TopicName() string { + return "task.created" +} + +func (t *TaskCreatedEvent) Message() interface{} { + return t.Task +} diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go new file mode 100644 index 000000000..29ccc6a2d --- /dev/null +++ b/pkg/models/listeners.go @@ -0,0 +1,30 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-2021 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public Licensee as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public Licensee for more details. +// +// You should have received a copy of the GNU Affero General Public Licensee +// along with this program. If not, see . + +package models + +import "code.vikunja.io/api/pkg/events" + +func RegisterListeners() { + events.RegisterListener((&TaskCreatedEvent{}).TopicName(), &SendTaskCreatedNotification{}) +} + +type SendTaskCreatedNotification struct { +} + +func (s *SendTaskCreatedNotification) Handle(payload interface{}) error { + panic("implement me") +} diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index ff0b9165d..c5d78b5b9 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -17,6 +17,7 @@ package models import ( + "code.vikunja.io/api/pkg/events" "math" "sort" "strconv" @@ -828,6 +829,10 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err t.setIdentifier(l) + if err := events.Publish(&TaskCreatedEvent{Task: t}); err != nil { + return err + } + err = updateListLastUpdated(s, &List{ID: t.ListID}) return } -- 2.40.1 From 124cc5e54fe6f391bd6a928d74d33d97af629ed1 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 15:28:13 +0100 Subject: [PATCH 03/45] Move payload parsing to the listener --- pkg/events/events.go | 10 +++------- pkg/events/listeners.go | 4 +++- pkg/models/listeners.go | 18 +++++++++++++++--- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/pkg/events/events.go b/pkg/events/events.go index 26bbbbf68..f37448f63 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -19,11 +19,12 @@ package events import ( "context" "encoding/json" + "time" + "github.com/ThreeDotsLabs/watermill" "github.com/ThreeDotsLabs/watermill/message" "github.com/ThreeDotsLabs/watermill/message/router/middleware" "github.com/ThreeDotsLabs/watermill/pubsub/gochannel" - "time" ) var ( @@ -64,12 +65,7 @@ func InitEvents() (err error) { for topic, funcs := range listeners { for _, handler := range funcs { router.AddNoPublisherHandler(topic+watermill.NewShortUUID(), topic, pubsub, func(msg *message.Message) error { - var payload interface{} - err = json.Unmarshal(msg.Payload, payload) - if err != nil { - return err - } - return handler.Handle(payload) + return handler.Handle(msg.Payload) }) } } diff --git a/pkg/events/listeners.go b/pkg/events/listeners.go index 33227cf4d..846995426 100644 --- a/pkg/events/listeners.go +++ b/pkg/events/listeners.go @@ -16,8 +16,10 @@ package events +import "github.com/ThreeDotsLabs/watermill/message" + type Listener interface { - Handle(payload interface{}) error + Handle(payload message.Payload) error } var listeners map[string][]Listener diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index 29ccc6a2d..0c1ecfd86 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -16,7 +16,12 @@ package models -import "code.vikunja.io/api/pkg/events" +import ( + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/log" + "encoding/json" + "github.com/ThreeDotsLabs/watermill/message" +) func RegisterListeners() { events.RegisterListener((&TaskCreatedEvent{}).TopicName(), &SendTaskCreatedNotification{}) @@ -25,6 +30,13 @@ func RegisterListeners() { type SendTaskCreatedNotification struct { } -func (s *SendTaskCreatedNotification) Handle(payload interface{}) error { - panic("implement me") +func (s *SendTaskCreatedNotification) Handle(payload message.Payload) (err error) { + task := &Task{} + err = json.Unmarshal(payload, task) + if err != nil { + return err + } + + log.Debugf("task.created: %v", task) + return nil } -- 2.40.1 From 7fd33225331820f6c5b4efb407f1f302ac7c2a7c Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 15:48:02 +0100 Subject: [PATCH 04/45] Change retry --- pkg/events/events.go | 3 ++- pkg/models/listeners.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/events/events.go b/pkg/events/events.go index f37448f63..ead1ada9b 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -48,9 +48,10 @@ func InitEvents() (err error) { router.AddMiddleware( middleware.Retry{ - MaxRetries: 3, + MaxRetries: 5, InitialInterval: time.Millisecond * 100, Logger: logger, + Multiplier: 2, }.Middleware, middleware.Recoverer, ) diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index 0c1ecfd86..0881b87a0 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -17,9 +17,10 @@ package models import ( + "encoding/json" + "code.vikunja.io/api/pkg/events" "code.vikunja.io/api/pkg/log" - "encoding/json" "github.com/ThreeDotsLabs/watermill/message" ) -- 2.40.1 From c6e3e179a6f46fcb3edb2668534cdfa7483939c3 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 16:28:52 +0100 Subject: [PATCH 05/45] Add custom logger for watermill --- config.yml.sample | 4 ++ pkg/config/config.go | 4 ++ pkg/events/events.go | 8 ++-- pkg/log/logging.go | 1 + pkg/log/watermill_logger.go | 93 +++++++++++++++++++++++++++++++++++++ pkg/log/xorm_logger.go | 2 +- 6 files changed, 107 insertions(+), 5 deletions(-) create mode 100644 pkg/log/watermill_logger.go diff --git a/config.yml.sample b/config.yml.sample index 250610660..714a04aec 100644 --- a/config.yml.sample +++ b/config.yml.sample @@ -136,6 +136,10 @@ log: http: "stdout" # Echo has its own logging which usually is unnessecary, which is why it is disabled by default. Possible values are stdout, stderr, file or off to disable standard logging. echo: "off" + # Whether or not to log events. Useful for debugging. Possible values are stdout, stderr, file or off to disable events logging. + events: "stdout" + # The log level for event log messages. Possible values (case-insensitive) are ERROR, INFO, DEBUG. + eventslevel: "info" ratelimit: # whether or not to enable the rate limit diff --git a/pkg/config/config.go b/pkg/config/config.go index 4301a1a30..3ca6ffe61 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -101,6 +101,8 @@ const ( LogHTTP Key = `log.http` LogEcho Key = `log.echo` LogPath Key = `log.path` + LogEvents Key = `log.events` + LogEventsLevel Key = `log.eventslevel` RateLimitEnabled Key = `ratelimit.enabled` RateLimitKind Key = `ratelimit.kind` @@ -281,6 +283,8 @@ func InitDefaultConfig() { LogHTTP.setDefault("stdout") LogEcho.setDefault("off") LogPath.setDefault(ServiceRootpath.GetString() + "/logs") + LogEvents.setDefault("stdout") + LogEventsLevel.setDefault("INFO") // Rate Limit RateLimitEnabled.setDefault(false) RateLimitKind.setDefault("user") diff --git a/pkg/events/events.go b/pkg/events/events.go index ead1ada9b..f483ee33e 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -21,16 +21,14 @@ import ( "encoding/json" "time" + "code.vikunja.io/api/pkg/log" "github.com/ThreeDotsLabs/watermill" "github.com/ThreeDotsLabs/watermill/message" "github.com/ThreeDotsLabs/watermill/message/router/middleware" "github.com/ThreeDotsLabs/watermill/pubsub/gochannel" ) -var ( - pubsub *gochannel.GoChannel - logger = watermill.NewStdLogger(false, false) -) +var pubsub *gochannel.GoChannel type Event interface { TopicName() string @@ -38,6 +36,8 @@ type Event interface { } func InitEvents() (err error) { + logger := log.NewWatermillLogger() + router, err := message.NewRouter( message.RouterConfig{}, logger, diff --git a/pkg/log/logging.go b/pkg/log/logging.go index 705c0d002..8d85adae6 100644 --- a/pkg/log/logging.go +++ b/pkg/log/logging.go @@ -49,6 +49,7 @@ func InitLogger() { config.LogDatabase.Set("off") config.LogHTTP.Set("off") config.LogEcho.Set("off") + config.LogEvents.Set("off") return } diff --git a/pkg/log/watermill_logger.go b/pkg/log/watermill_logger.go new file mode 100644 index 000000000..15e900115 --- /dev/null +++ b/pkg/log/watermill_logger.go @@ -0,0 +1,93 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-2021 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public Licensee as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public Licensee for more details. +// +// You should have received a copy of the GNU Affero General Public Licensee +// along with this program. If not, see . + +package log + +import ( + "fmt" + "strings" + "time" + + "code.vikunja.io/api/pkg/config" + "github.com/ThreeDotsLabs/watermill" + "github.com/op/go-logging" + "xorm.io/xorm/log" +) + +const watermillFmt = `%{color}%{time:` + time.RFC3339Nano + `}: %{level}` + "\t" + `▶ [EVENTS] %{id:03x}%{color:reset} %{message}` + +const watermillLogModule = `vikunja_events` + +type WatermillLogger struct { + logger *logging.Logger + level log.LogLevel +} + +func NewWatermillLogger() *WatermillLogger { + lvl := strings.ToUpper(config.LogEventsLevel.GetString()) + level, err := logging.LogLevel(lvl) + if err != nil { + Criticalf("Error setting events log level %s: %s", lvl, err.Error()) + } + + watermillLogger := &WatermillLogger{ + logger: logging.MustGetLogger(watermillLogModule), + } + + logBackend := logging.NewLogBackend(GetLogWriter("events"), "", 0) + backend := logging.NewBackendFormatter(logBackend, logging.MustStringFormatter(watermillFmt+"\n")) + + backendLeveled := logging.AddModuleLevel(backend) + backendLeveled.SetLevel(level, watermillLogModule) + + watermillLogger.logger.SetBackend(backendLeveled) + + return watermillLogger +} + +func concatFields(fields watermill.LogFields) string { + full := "" + + for key, val := range fields { + full += fmt.Sprintf("%s=%s, ", key, val) + } + + if full != "" { + full = full[:len(full)-2] + } + + return full +} + +func (w *WatermillLogger) Error(msg string, err error, fields watermill.LogFields) { + w.logger.Errorf("%s: %s, %s", msg, err, concatFields(fields)) +} + +func (w *WatermillLogger) Info(msg string, fields watermill.LogFields) { + w.logger.Infof("%s, %s", msg, concatFields(fields)) +} + +func (w *WatermillLogger) Debug(msg string, fields watermill.LogFields) { + w.logger.Debugf("%s, %s", msg, concatFields(fields)) +} + +func (w *WatermillLogger) Trace(msg string, fields watermill.LogFields) { + w.logger.Debugf("%s, %s", msg, concatFields(fields)) +} + +func (w *WatermillLogger) With(fields watermill.LogFields) watermill.LoggerAdapter { + return w +} diff --git a/pkg/log/xorm_logger.go b/pkg/log/xorm_logger.go index 7b8109641..1af21cb18 100644 --- a/pkg/log/xorm_logger.go +++ b/pkg/log/xorm_logger.go @@ -44,7 +44,7 @@ func NewXormLogger(lvl string) *XormLogger { } level, err := logging.LogLevel(lvl) if err != nil { - Critical("Error setting database log level: %s", err.Error()) + Criticalf("Error setting database log level: %s", err.Error()) } xormLogger := &XormLogger{ -- 2.40.1 From 1313f4d2a8935d6f1e9c3452a77dce99d872937a Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 20:38:57 +0100 Subject: [PATCH 06/45] Publish doer --- pkg/models/events.go | 5 ++++- pkg/models/listeners.go | 6 +++--- pkg/models/tasks.go | 6 +++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pkg/models/events.go b/pkg/models/events.go index 6e59dd231..b48a66055 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -16,8 +16,11 @@ package models +import "code.vikunja.io/api/pkg/user" + type TaskCreatedEvent struct { Task *Task + Doer *user.User } func (t *TaskCreatedEvent) TopicName() string { @@ -25,5 +28,5 @@ func (t *TaskCreatedEvent) TopicName() string { } func (t *TaskCreatedEvent) Message() interface{} { - return t.Task + return t } diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index 0881b87a0..790afc9e1 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -32,12 +32,12 @@ type SendTaskCreatedNotification struct { } func (s *SendTaskCreatedNotification) Handle(payload message.Payload) (err error) { - task := &Task{} - err = json.Unmarshal(payload, task) + event := &TaskCreatedEvent{} + err = json.Unmarshal(payload, event) if err != nil { return err } - log.Debugf("task.created: %v", task) + log.Debugf("task.created: %v", event) return nil } diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index c5d78b5b9..0779a904e 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -829,7 +829,11 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err t.setIdentifier(l) - if err := events.Publish(&TaskCreatedEvent{Task: t}); err != nil { + err = events.Publish(&TaskCreatedEvent{ + Task: t, + Doer: t.CreatedBy, + }) + if err != nil { return err } -- 2.40.1 From 5897515ab670f3135e911b55fd0286c4e0951412 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 21:15:33 +0100 Subject: [PATCH 07/45] Add auth parameter to crud functions --- go.mod | 11 ++++++----- go.sum | 12 ++++++++++++ pkg/events/events.go | 2 +- pkg/models/bulk_task.go | 2 +- pkg/models/events.go | 13 +++++++++++++ pkg/models/kanban.go | 4 ++-- pkg/models/label.go | 8 ++++---- pkg/models/label_task.go | 2 +- pkg/models/link_sharing.go | 4 ++-- pkg/models/list.go | 14 +++++++------- pkg/models/list_duplicate.go | 2 +- pkg/models/list_team.go | 4 ++-- pkg/models/list_users.go | 4 ++-- pkg/models/listeners.go | 2 -- pkg/models/namespace.go | 6 +++--- pkg/models/namespace_team.go | 4 ++-- pkg/models/namespace_users.go | 4 ++-- pkg/models/saved_filters.go | 6 +++--- pkg/models/task_assignees.go | 2 +- pkg/models/task_attachment.go | 6 +++--- pkg/models/task_comments.go | 6 +++--- pkg/models/task_relation.go | 2 +- pkg/models/tasks.go | 13 ++++++++++--- pkg/models/team_members.go | 4 ++-- pkg/models/teams.go | 6 +++--- pkg/modules/migration/create_from_structure.go | 2 +- pkg/routes/api/v1/login.go | 2 +- pkg/routes/api/v1/task_attachment.go | 2 +- pkg/routes/caldav/listStorageProvider.go | 6 +++--- 29 files changed, 93 insertions(+), 62 deletions(-) diff --git a/go.mod b/go.mod index b12b836d6..a435090e4 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ module code.vikunja.io/api require ( 4d63.com/tz v1.2.0 - code.vikunja.io/web v0.0.0-20201223143420-588abb73703a + code.vikunja.io/web v0.0.0-20210131201003-26386be9a9ae dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363 // indirect gitea.com/xorm/xorm-redis-cache v0.2.0 github.com/ThreeDotsLabs/watermill v1.1.1 @@ -80,11 +80,12 @@ require ( golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad golang.org/x/image v0.0.0-20201208152932-35266b937fa6 golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 - golang.org/x/net v0.0.0-20201216054612-986b41b23924 // indirect + golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect golang.org/x/oauth2 v0.0.0-20210126194326-f9ce19ea3013 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a - golang.org/x/sys v0.0.0-20201223074533-0d417f636930 // indirect + golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf + golang.org/x/text v0.3.5 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/d4l3k/messagediff.v1 v1.2.1 @@ -95,9 +96,9 @@ require ( honnef.co/go/tools v0.0.1-2020.1.5 src.techknowlogick.com/xgo v1.2.1-0.20201205054505-b97762e7a76b src.techknowlogick.com/xormigrate v1.4.0 - xorm.io/builder v0.3.7 + xorm.io/builder v0.3.8 xorm.io/core v0.7.3 - xorm.io/xorm v1.0.5 + xorm.io/xorm v1.0.7 ) replace ( diff --git a/go.sum b/go.sum index 9726bb3ef..67538bb13 100644 --- a/go.sum +++ b/go.sum @@ -44,6 +44,8 @@ code.vikunja.io/web v0.0.0-20201222144643-6fa2fb587215 h1:O5zMWgcnVDVLaQUawgdsv/ code.vikunja.io/web v0.0.0-20201222144643-6fa2fb587215/go.mod h1:OgFO06HN1KpA4S7Dw/QAIeygiUPSeGJJn1ykz/sjZdU= code.vikunja.io/web v0.0.0-20201223143420-588abb73703a h1:LaWCucY5Pp30EIMgGOvdVFNss5OhIAwrAO8PuFVRUfw= code.vikunja.io/web v0.0.0-20201223143420-588abb73703a/go.mod h1:OgFO06HN1KpA4S7Dw/QAIeygiUPSeGJJn1ykz/sjZdU= +code.vikunja.io/web v0.0.0-20210131201003-26386be9a9ae h1:qqgwoWjKrpIOdrIR0FPawiHLZTRYwS9MBgwH1eZJJqA= +code.vikunja.io/web v0.0.0-20210131201003-26386be9a9ae/go.mod h1:OgFO06HN1KpA4S7Dw/QAIeygiUPSeGJJn1ykz/sjZdU= dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363 h1:o4lAkfETerCnr1kF9/qwkwjICnU+YLHNDCM8h2xj7as= dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363/go.mod h1:WG7q7swWsS2f9PYpt5DoEP/EBYWx8We5UoRltn9vJl8= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -997,6 +999,8 @@ golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/Lt golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201216054612-986b41b23924 h1:QsnDpLLOKwHBBDa8nDws4DYNc/ryVW2vCpxCs09d4PY= golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= @@ -1095,6 +1099,8 @@ golang.org/x/sys v0.0.0-20201221093633-bc327ba9c2f0 h1:n+DPcgTwkgWzIFpLmoimYR2K2 golang.org/x/sys v0.0.0-20201221093633-bc327ba9c2f0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo= golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1110,6 +1116,8 @@ golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1347,6 +1355,8 @@ src.techknowlogick.com/xormigrate v1.4.0 h1:gAfLoDwcVfMiFhSXg5Qwm7LNnG1iUbBVDUNf src.techknowlogick.com/xormigrate v1.4.0/go.mod h1:xCtbAK00lJ0v4zP2O6VBVMG3RHm7W5Yo1Dz0r9kL/ho= xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI= xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= +xorm.io/builder v0.3.8 h1:P/wPgRqa9kX5uE0aA1/ukJ23u9KH0aSRpHLwDKXigSE= +xorm.io/builder v0.3.8/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= xorm.io/core v0.7.3 h1:W8ws1PlrnkS1CZU1YWaYLMQcQilwAmQXU0BJDJon+H0= xorm.io/core v0.7.3/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM= xorm.io/xorm v1.0.1 h1:/lITxpJtkZauNpdzj+L9CN/3OQxZaABrbergMcJu+Cw= @@ -1355,3 +1365,5 @@ xorm.io/xorm v1.0.2 h1:kZlCh9rqd1AzGwWitcrEEqHE1h1eaZE/ujU5/2tWEtg= xorm.io/xorm v1.0.2/go.mod h1:o4vnEsQ5V2F1/WK6w4XTwmiWJeGj82tqjAnHe44wVHY= xorm.io/xorm v1.0.5 h1:LRr5PfOUb4ODPR63YwbowkNDwcolT2LnkwP/TUaMaB0= xorm.io/xorm v1.0.5/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4= +xorm.io/xorm v1.0.7 h1:26yBTDVI+CfQpVz2Y88fISh+aiJXIPP4eNoTJlwzsC4= +xorm.io/xorm v1.0.7/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4= diff --git a/pkg/events/events.go b/pkg/events/events.go index f483ee33e..4ab2e4968 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -65,7 +65,7 @@ func InitEvents() (err error) { for topic, funcs := range listeners { for _, handler := range funcs { - router.AddNoPublisherHandler(topic+watermill.NewShortUUID(), topic, pubsub, func(msg *message.Message) error { + router.AddNoPublisherHandler(topic+"."+watermill.NewShortUUID(), topic, pubsub, func(msg *message.Message) error { return handler.Handle(msg.Payload) }) } diff --git a/pkg/models/bulk_task.go b/pkg/models/bulk_task.go index 36241047d..615d540db 100644 --- a/pkg/models/bulk_task.go +++ b/pkg/models/bulk_task.go @@ -78,7 +78,7 @@ func (bt *BulkTask) CanUpdate(s *xorm.Session, a web.Auth) (bool, error) { // @Failure 403 {object} web.HTTPError "The user does not have access to the task (aka its list)" // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/bulk [post] -func (bt *BulkTask) Update(s *xorm.Session) (err error) { +func (bt *BulkTask) Update(s *xorm.Session, a web.Auth) (err error) { for _, oldtask := range bt.Tasks { // When a repeating task is marked as done, we update all deadlines and reminders and set it as undone diff --git a/pkg/models/events.go b/pkg/models/events.go index b48a66055..2b8c85a2f 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -30,3 +30,16 @@ func (t *TaskCreatedEvent) TopicName() string { func (t *TaskCreatedEvent) Message() interface{} { return t } + +type TaskUpdatedEvent struct { + Task *Task + Doer *user.User +} + +func (t *TaskUpdatedEvent) TopicName() string { + return "task.updated" +} + +func (t *TaskUpdatedEvent) Message() interface{} { + return t +} diff --git a/pkg/models/kanban.go b/pkg/models/kanban.go index 1424086c9..60516f1ff 100644 --- a/pkg/models/kanban.go +++ b/pkg/models/kanban.go @@ -190,7 +190,7 @@ func (b *Bucket) Create(s *xorm.Session, a web.Auth) (err error) { // @Failure 404 {object} web.HTTPError "The bucket does not exist." // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{listID}/buckets/{bucketID} [post] -func (b *Bucket) Update(s *xorm.Session) (err error) { +func (b *Bucket) Update(s *xorm.Session, a web.Auth) (err error) { _, err = s. Where("id = ?", b.ID). Cols("title", "limit"). @@ -211,7 +211,7 @@ func (b *Bucket) Update(s *xorm.Session) (err error) { // @Failure 404 {object} web.HTTPError "The bucket does not exist." // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{listID}/buckets/{bucketID} [delete] -func (b *Bucket) Delete(s *xorm.Session) (err error) { +func (b *Bucket) Delete(s *xorm.Session, a web.Auth) (err error) { // Prevent removing the last bucket total, err := s.Where("list_id = ?", b.ListID).Count(&Bucket{}) diff --git a/pkg/models/label.go b/pkg/models/label.go index 783f8c1f7..653dc5381 100644 --- a/pkg/models/label.go +++ b/pkg/models/label.go @@ -93,7 +93,7 @@ func (l *Label) Create(s *xorm.Session, a web.Auth) (err error) { // @Failure 404 {object} web.HTTPError "Label not found." // @Failure 500 {object} models.Message "Internal error" // @Router /labels/{id} [put] -func (l *Label) Update(s *xorm.Session) (err error) { +func (l *Label) Update(s *xorm.Session, a web.Auth) (err error) { _, err = s. ID(l.ID). Cols( @@ -106,7 +106,7 @@ func (l *Label) Update(s *xorm.Session) (err error) { return } - err = l.ReadOne(s) + err = l.ReadOne(s, a) return } @@ -123,7 +123,7 @@ func (l *Label) Update(s *xorm.Session) (err error) { // @Failure 404 {object} web.HTTPError "Label not found." // @Failure 500 {object} models.Message "Internal error" // @Router /labels/{id} [delete] -func (l *Label) Delete(s *xorm.Session) (err error) { +func (l *Label) Delete(s *xorm.Session, a web.Auth) (err error) { _, err = s.ID(l.ID).Delete(&Label{}) return err } @@ -178,7 +178,7 @@ func (l *Label) ReadAll(s *xorm.Session, a web.Auth, search string, page int, pe // @Failure 404 {object} web.HTTPError "Label not found" // @Failure 500 {object} models.Message "Internal error" // @Router /labels/{id} [get] -func (l *Label) ReadOne(s *xorm.Session) (err error) { +func (l *Label) ReadOne(s *xorm.Session, a web.Auth) (err error) { label, err := getLabelByIDSimple(s, l.ID) if err != nil { return err diff --git a/pkg/models/label_task.go b/pkg/models/label_task.go index b06c0fe35..801fdff65 100644 --- a/pkg/models/label_task.go +++ b/pkg/models/label_task.go @@ -61,7 +61,7 @@ func (LabelTask) TableName() string { // @Failure 404 {object} web.HTTPError "Label not found." // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{task}/labels/{label} [delete] -func (lt *LabelTask) Delete(s *xorm.Session) (err error) { +func (lt *LabelTask) Delete(s *xorm.Session, a web.Auth) (err error) { _, err = s.Delete(&LabelTask{LabelID: lt.LabelID, TaskID: lt.TaskID}) return err } diff --git a/pkg/models/link_sharing.go b/pkg/models/link_sharing.go index d9b96ff5d..41ca1e3aa 100644 --- a/pkg/models/link_sharing.go +++ b/pkg/models/link_sharing.go @@ -127,7 +127,7 @@ func (share *LinkSharing) Create(s *xorm.Session, a web.Auth) (err error) { // @Failure 404 {object} web.HTTPError "Share Link not found." // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{list}/shares/{share} [get] -func (share *LinkSharing) ReadOne(s *xorm.Session) (err error) { +func (share *LinkSharing) ReadOne(s *xorm.Session, a web.Auth) (err error) { exists, err := s.Where("id = ?", share.ID).Get(share) if err != nil { return err @@ -216,7 +216,7 @@ func (share *LinkSharing) ReadAll(s *xorm.Session, a web.Auth, search string, pa // @Failure 404 {object} web.HTTPError "Share Link not found." // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{list}/shares/{share} [delete] -func (share *LinkSharing) Delete(s *xorm.Session) (err error) { +func (share *LinkSharing) Delete(s *xorm.Session, a web.Auth) (err error) { _, err = s.Where("id = ?", share.ID).Delete(share) return } diff --git a/pkg/models/list.go b/pkg/models/list.go index 59f982dd6..72d3c7588 100644 --- a/pkg/models/list.go +++ b/pkg/models/list.go @@ -186,7 +186,7 @@ func (l *List) ReadAll(s *xorm.Session, a web.Auth, search string, page int, per // @Failure 403 {object} web.HTTPError "The user does not have access to the list" // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{id} [get] -func (l *List) ReadOne(s *xorm.Session) (err error) { +func (l *List) ReadOne(s *xorm.Session, a web.Auth) (err error) { if l.ID == FavoritesPseudoList.ID { // Already "built" the list in CanRead @@ -466,7 +466,7 @@ func (l *List) CheckIsArchived(s *xorm.Session) (err error) { } // CreateOrUpdateList updates a list or creates it if it doesn't exist -func CreateOrUpdateList(s *xorm.Session, list *List) (err error) { +func CreateOrUpdateList(s *xorm.Session, list *List, auth web.Auth) (err error) { // Check if the namespace exists if list.NamespaceID != 0 && list.NamespaceID != FavoritesPseudoNamespace.ID { @@ -522,7 +522,7 @@ func CreateOrUpdateList(s *xorm.Session, list *List) (err error) { } *list = *l - err = list.ReadOne(s) + err = list.ReadOne(s, auth) return } @@ -541,8 +541,8 @@ func CreateOrUpdateList(s *xorm.Session, list *List) (err error) { // @Failure 403 {object} web.HTTPError "The user does not have access to the list" // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{id} [post] -func (l *List) Update(s *xorm.Session) (err error) { - return CreateOrUpdateList(s, l) +func (l *List) Update(s *xorm.Session, a web.Auth) (err error) { + return CreateOrUpdateList(s, l, a) } func updateListLastUpdated(s *xorm.Session, list *List) error { @@ -589,7 +589,7 @@ func (l *List) Create(s *xorm.Session, a web.Auth) (err error) { l.Owner = doer l.ID = 0 // Otherwise only the first time a new list would be created - err = CreateOrUpdateList(s, l) + err = CreateOrUpdateList(s, l, a) if err != nil { return } @@ -614,7 +614,7 @@ func (l *List) Create(s *xorm.Session, a web.Auth) (err error) { // @Failure 403 {object} web.HTTPError "The user does not have access to the list" // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{id} [delete] -func (l *List) Delete(s *xorm.Session) (err error) { +func (l *List) Delete(s *xorm.Session, a web.Auth) (err error) { // Delete the list _, err = s.ID(l.ID).Delete(&List{}) diff --git a/pkg/models/list_duplicate.go b/pkg/models/list_duplicate.go index 5051b1d41..5113f1768 100644 --- a/pkg/models/list_duplicate.go +++ b/pkg/models/list_duplicate.go @@ -75,7 +75,7 @@ func (ld *ListDuplicate) Create(s *xorm.Session, a web.Auth) (err error) { ld.List.Identifier = "" // Reset the identifier to trigger regenerating a new one // Set the owner to the current user ld.List.OwnerID = a.GetID() - if err := CreateOrUpdateList(s, ld.List); err != nil { + if err := CreateOrUpdateList(s, ld.List, a); err != nil { // If there is no available unique list identifier, just reset it. if IsErrListIdentifierIsNotUnique(err) { ld.List.Identifier = "" diff --git a/pkg/models/list_team.go b/pkg/models/list_team.go index 8c9a57b73..a1bfdea00 100644 --- a/pkg/models/list_team.go +++ b/pkg/models/list_team.go @@ -122,7 +122,7 @@ func (tl *TeamList) Create(s *xorm.Session, a web.Auth) (err error) { // @Failure 404 {object} web.HTTPError "Team or list does not exist." // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{listID}/teams/{teamID} [delete] -func (tl *TeamList) Delete(s *xorm.Session) (err error) { +func (tl *TeamList) Delete(s *xorm.Session, a web.Auth) (err error) { // Check if the team exists _, err = GetTeamByID(s, tl.TeamID) @@ -234,7 +234,7 @@ func (tl *TeamList) ReadAll(s *xorm.Session, a web.Auth, search string, page int // @Failure 404 {object} web.HTTPError "Team or list does not exist." // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{listID}/teams/{teamID} [post] -func (tl *TeamList) Update(s *xorm.Session) (err error) { +func (tl *TeamList) Update(s *xorm.Session, a web.Auth) (err error) { // Check if the right is valid if err := tl.Right.isValid(); err != nil { diff --git a/pkg/models/list_users.go b/pkg/models/list_users.go index fed512057..01737b2d3 100644 --- a/pkg/models/list_users.go +++ b/pkg/models/list_users.go @@ -129,7 +129,7 @@ func (lu *ListUser) Create(s *xorm.Session, a web.Auth) (err error) { // @Failure 404 {object} web.HTTPError "user or list does not exist." // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{listID}/users/{userID} [delete] -func (lu *ListUser) Delete(s *xorm.Session) (err error) { +func (lu *ListUser) Delete(s *xorm.Session, a web.Auth) (err error) { // Check if the user exists u, err := user.GetUserByUsername(s, lu.Username) @@ -231,7 +231,7 @@ func (lu *ListUser) ReadAll(s *xorm.Session, a web.Auth, search string, page int // @Failure 404 {object} web.HTTPError "User or list does not exist." // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{listID}/users/{userID} [post] -func (lu *ListUser) Update(s *xorm.Session) (err error) { +func (lu *ListUser) Update(s *xorm.Session, a web.Auth) (err error) { // Check if the right is valid if err := lu.Right.isValid(); err != nil { diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index 790afc9e1..21264f309 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -20,7 +20,6 @@ import ( "encoding/json" "code.vikunja.io/api/pkg/events" - "code.vikunja.io/api/pkg/log" "github.com/ThreeDotsLabs/watermill/message" ) @@ -38,6 +37,5 @@ func (s *SendTaskCreatedNotification) Handle(payload message.Payload) (err error return err } - log.Debugf("task.created: %v", event) return nil } diff --git a/pkg/models/namespace.go b/pkg/models/namespace.go index b87733d1c..277f452d8 100644 --- a/pkg/models/namespace.go +++ b/pkg/models/namespace.go @@ -159,7 +159,7 @@ func (n *Namespace) CheckIsArchived(s *xorm.Session) error { // @Failure 403 {object} web.HTTPError "The user does not have access to that namespace." // @Failure 500 {object} models.Message "Internal error" // @Router /namespaces/{id} [get] -func (n *Namespace) ReadOne(s *xorm.Session) (err error) { +func (n *Namespace) ReadOne(s *xorm.Session, a web.Auth) (err error) { nn, err := GetNamespaceByID(s, n.ID) if err != nil { return err @@ -504,7 +504,7 @@ func CreateNewNamespaceForUser(s *xorm.Session, user *user.User) (err error) { // @Failure 403 {object} web.HTTPError "The user does not have access to the namespace" // @Failure 500 {object} models.Message "Internal error" // @Router /namespaces/{id} [delete] -func (n *Namespace) Delete(s *xorm.Session) (err error) { +func (n *Namespace) Delete(s *xorm.Session, a web.Auth) (err error) { // Check if the namespace exists _, err = GetNamespaceByID(s, n.ID) @@ -562,7 +562,7 @@ func (n *Namespace) Delete(s *xorm.Session) (err error) { // @Failure 403 {object} web.HTTPError "The user does not have access to the namespace" // @Failure 500 {object} models.Message "Internal error" // @Router /namespace/{id} [post] -func (n *Namespace) Update(s *xorm.Session) (err error) { +func (n *Namespace) Update(s *xorm.Session, a web.Auth) (err error) { // Check if we have at least a name if n.Title == "" { return ErrNamespaceNameCannotBeEmpty{NamespaceID: n.ID} diff --git a/pkg/models/namespace_team.go b/pkg/models/namespace_team.go index 9f8234d98..3a1e5f139 100644 --- a/pkg/models/namespace_team.go +++ b/pkg/models/namespace_team.go @@ -112,7 +112,7 @@ func (tn *TeamNamespace) Create(s *xorm.Session, a web.Auth) (err error) { // @Failure 404 {object} web.HTTPError "team or namespace does not exist." // @Failure 500 {object} models.Message "Internal error" // @Router /namespaces/{namespaceID}/teams/{teamID} [delete] -func (tn *TeamNamespace) Delete(s *xorm.Session) (err error) { +func (tn *TeamNamespace) Delete(s *xorm.Session, a web.Auth) (err error) { // Check if the team exists _, err = GetTeamByID(s, tn.TeamID) @@ -219,7 +219,7 @@ func (tn *TeamNamespace) ReadAll(s *xorm.Session, a web.Auth, search string, pag // @Failure 404 {object} web.HTTPError "Team or namespace does not exist." // @Failure 500 {object} models.Message "Internal error" // @Router /namespaces/{namespaceID}/teams/{teamID} [post] -func (tn *TeamNamespace) Update(s *xorm.Session) (err error) { +func (tn *TeamNamespace) Update(s *xorm.Session, a web.Auth) (err error) { // Check if the right is valid if err := tn.Right.isValid(); err != nil { diff --git a/pkg/models/namespace_users.go b/pkg/models/namespace_users.go index 5af99cbf0..89be44839 100644 --- a/pkg/models/namespace_users.go +++ b/pkg/models/namespace_users.go @@ -122,7 +122,7 @@ func (nu *NamespaceUser) Create(s *xorm.Session, a web.Auth) (err error) { // @Failure 404 {object} web.HTTPError "user or namespace does not exist." // @Failure 500 {object} models.Message "Internal error" // @Router /namespaces/{namespaceID}/users/{userID} [delete] -func (nu *NamespaceUser) Delete(s *xorm.Session) (err error) { +func (nu *NamespaceUser) Delete(s *xorm.Session, a web.Auth) (err error) { // Check if the user exists user, err := user2.GetUserByUsername(s, nu.Username) @@ -220,7 +220,7 @@ func (nu *NamespaceUser) ReadAll(s *xorm.Session, a web.Auth, search string, pag // @Failure 404 {object} web.HTTPError "User or namespace does not exist." // @Failure 500 {object} models.Message "Internal error" // @Router /namespaces/{namespaceID}/users/{userID} [post] -func (nu *NamespaceUser) Update(s *xorm.Session) (err error) { +func (nu *NamespaceUser) Update(s *xorm.Session, a web.Auth) (err error) { // Check if the right is valid if err := nu.Right.isValid(); err != nil { diff --git a/pkg/models/saved_filters.go b/pkg/models/saved_filters.go index 02ab1816d..cc75e4e49 100644 --- a/pkg/models/saved_filters.go +++ b/pkg/models/saved_filters.go @@ -133,7 +133,7 @@ func getSavedFilterSimpleByID(s *xorm.Session, id int64) (sf *SavedFilter, err e // @Failure 403 {object} web.HTTPError "The user does not have access to that saved filter." // @Failure 500 {object} models.Message "Internal error" // @Router /filters/{id} [get] -func (sf *SavedFilter) ReadOne(s *xorm.Session) error { +func (sf *SavedFilter) ReadOne(s *xorm.Session, a web.Auth) error { // s already contains almost the full saved filter from the rights check, we only need to add the user u, err := user.GetUserByID(s, sf.OwnerID) sf.Owner = u @@ -153,7 +153,7 @@ func (sf *SavedFilter) ReadOne(s *xorm.Session) error { // @Failure 404 {object} web.HTTPError "The saved filter does not exist." // @Failure 500 {object} models.Message "Internal error" // @Router /filters/{id} [post] -func (sf *SavedFilter) Update(s *xorm.Session) error { +func (sf *SavedFilter) Update(s *xorm.Session, a web.Auth) error { _, err := s. Where("id = ?", sf.ID). Cols( @@ -178,7 +178,7 @@ func (sf *SavedFilter) Update(s *xorm.Session) error { // @Failure 404 {object} web.HTTPError "The saved filter does not exist." // @Failure 500 {object} models.Message "Internal error" // @Router /filters/{id} [delete] -func (sf *SavedFilter) Delete(s *xorm.Session) error { +func (sf *SavedFilter) Delete(s *xorm.Session, a web.Auth) error { _, err := s. Where("id = ?", sf.ID). Delete(sf) diff --git a/pkg/models/task_assignees.go b/pkg/models/task_assignees.go index 06f804b17..4b318fbe6 100644 --- a/pkg/models/task_assignees.go +++ b/pkg/models/task_assignees.go @@ -166,7 +166,7 @@ func (t *Task) setTaskAssignees(assignees []*user.User) { // @Failure 403 {object} web.HTTPError "Not allowed to delete the assignee." // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{taskID}/assignees/{userID} [delete] -func (la *TaskAssginee) Delete(s *xorm.Session) (err error) { +func (la *TaskAssginee) Delete(s *xorm.Session, a web.Auth) (err error) { _, err = s.Delete(&TaskAssginee{TaskID: la.TaskID, UserID: la.UserID}) if err != nil { return err diff --git a/pkg/models/task_attachment.go b/pkg/models/task_attachment.go index f8b68d750..b07775f4b 100644 --- a/pkg/models/task_attachment.go +++ b/pkg/models/task_attachment.go @@ -80,7 +80,7 @@ func (ta *TaskAttachment) NewAttachment(s *xorm.Session, f io.ReadCloser, realna } // ReadOne returns a task attachment -func (ta *TaskAttachment) ReadOne(s *xorm.Session) (err error) { +func (ta *TaskAttachment) ReadOne(s *xorm.Session, a web.Auth) (err error) { exists, err := s.Where("id = ?", ta.ID).Get(ta) if err != nil { return @@ -176,9 +176,9 @@ func (ta *TaskAttachment) ReadAll(s *xorm.Session, a web.Auth, search string, pa // @Failure 404 {object} models.Message "The task does not exist." // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{id}/attachments/{attachmentID} [delete] -func (ta *TaskAttachment) Delete(s *xorm.Session) error { +func (ta *TaskAttachment) Delete(s *xorm.Session, a web.Auth) error { // Load the attachment - err := ta.ReadOne(s) + err := ta.ReadOne(s, a) if err != nil && !files.IsErrFileDoesNotExist(err) { return err } diff --git a/pkg/models/task_comments.go b/pkg/models/task_comments.go index d9ab529ef..f1c4486ee 100644 --- a/pkg/models/task_comments.go +++ b/pkg/models/task_comments.go @@ -88,7 +88,7 @@ func (tc *TaskComment) Create(s *xorm.Session, a web.Auth) (err error) { // @Failure 404 {object} web.HTTPError "The task comment was not found." // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{taskID}/comments/{commentID} [delete] -func (tc *TaskComment) Delete(s *xorm.Session) error { +func (tc *TaskComment) Delete(s *xorm.Session, a web.Auth) error { deleted, err := s. ID(tc.ID). NoAutoCondition(). @@ -113,7 +113,7 @@ func (tc *TaskComment) Delete(s *xorm.Session) error { // @Failure 404 {object} web.HTTPError "The task comment was not found." // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{taskID}/comments/{commentID} [post] -func (tc *TaskComment) Update(s *xorm.Session) error { +func (tc *TaskComment) Update(s *xorm.Session, a web.Auth) error { updated, err := s. ID(tc.ID). Cols("comment"). @@ -138,7 +138,7 @@ func (tc *TaskComment) Update(s *xorm.Session) error { // @Failure 404 {object} web.HTTPError "The task comment was not found." // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{taskID}/comments/{commentID} [get] -func (tc *TaskComment) ReadOne(s *xorm.Session) (err error) { +func (tc *TaskComment) ReadOne(s *xorm.Session, a web.Auth) (err error) { exists, err := s.Get(tc) if err != nil { return diff --git a/pkg/models/task_relation.go b/pkg/models/task_relation.go index 0d6d1329a..c24d977bc 100644 --- a/pkg/models/task_relation.go +++ b/pkg/models/task_relation.go @@ -201,7 +201,7 @@ func (rel *TaskRelation) Create(s *xorm.Session, a web.Auth) error { // @Failure 404 {object} web.HTTPError "The task relation was not found." // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{taskID}/relations [delete] -func (rel *TaskRelation) Delete(s *xorm.Session) error { +func (rel *TaskRelation) Delete(s *xorm.Session, a web.Auth) error { // Check if the relation exists exists, err := s. Cols("task_id", "other_task_id", "relation_kind"). diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index 0779a904e..e7af2725f 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -856,7 +856,7 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{id} [post] //nolint:gocyclo -func (t *Task) Update(s *xorm.Session) (err error) { +func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) { // Check if the task exists and get the old values ot, err := GetTaskByIDSimple(s, t.ID) @@ -1037,6 +1037,13 @@ func (t *Task) Update(s *xorm.Session) (err error) { } t.Updated = nt.Updated + err = events.Publish(&TaskUpdatedEvent{ + Task: t, + }) + if err != nil { + return err + } + return updateListLastUpdated(s, &List{ID: t.ListID}) } @@ -1175,7 +1182,7 @@ func (t *Task) updateReminders(s *xorm.Session, reminders []time.Time) (err erro // @Failure 403 {object} web.HTTPError "The user does not have access to the list" // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{id} [delete] -func (t *Task) Delete(s *xorm.Session) (err error) { +func (t *Task) Delete(s *xorm.Session, a web.Auth) (err error) { if _, err = s.ID(t.ID).Delete(Task{}); err != nil { return err @@ -1204,7 +1211,7 @@ func (t *Task) Delete(s *xorm.Session) (err error) { // @Failure 404 {object} models.Message "Task not found" // @Failure 500 {object} models.Message "Internal error" // @Router /tasks/{ID} [get] -func (t *Task) ReadOne(s *xorm.Session) (err error) { +func (t *Task) ReadOne(s *xorm.Session, a web.Auth) (err error) { taskMap := make(map[int64]*Task, 1) taskMap[t.ID] = &Task{} diff --git a/pkg/models/team_members.go b/pkg/models/team_members.go index 52beda4a2..665454d90 100644 --- a/pkg/models/team_members.go +++ b/pkg/models/team_members.go @@ -78,7 +78,7 @@ func (tm *TeamMember) Create(s *xorm.Session, a web.Auth) (err error) { // @Success 200 {object} models.Message "The user was successfully removed from the team." // @Failure 500 {object} models.Message "Internal error" // @Router /teams/{id}/members/{userID} [delete] -func (tm *TeamMember) Delete(s *xorm.Session) (err error) { +func (tm *TeamMember) Delete(s *xorm.Session, a web.Auth) (err error) { total, err := s.Where("team_id = ?", tm.TeamID).Count(&TeamMember{}) if err != nil { @@ -110,7 +110,7 @@ func (tm *TeamMember) Delete(s *xorm.Session) (err error) { // @Success 200 {object} models.Message "The member right was successfully changed." // @Failure 500 {object} models.Message "Internal error" // @Router /teams/{id}/members/{userID}/admin [post] -func (tm *TeamMember) Update(s *xorm.Session) (err error) { +func (tm *TeamMember) Update(s *xorm.Session, a web.Auth) (err error) { // Find the numeric user id user, err := user2.GetUserByUsername(s, tm.Username) if err != nil { diff --git a/pkg/models/teams.go b/pkg/models/teams.go index db548c9a4..39a877177 100644 --- a/pkg/models/teams.go +++ b/pkg/models/teams.go @@ -177,7 +177,7 @@ func addMoreInfoToTeams(s *xorm.Session, teams []*Team) (err error) { // @Failure 403 {object} web.HTTPError "The user does not have access to the team" // @Failure 500 {object} models.Message "Internal error" // @Router /teams/{id} [get] -func (t *Team) ReadOne(s *xorm.Session) (err error) { +func (t *Team) ReadOne(s *xorm.Session, a web.Auth) (err error) { team, err := GetTeamByID(s, t.ID) if team != nil { *t = *team @@ -285,7 +285,7 @@ func (t *Team) Create(s *xorm.Session, a web.Auth) (err error) { // @Failure 400 {object} web.HTTPError "Invalid team object provided." // @Failure 500 {object} models.Message "Internal error" // @Router /teams/{id} [delete] -func (t *Team) Delete(s *xorm.Session) (err error) { +func (t *Team) Delete(s *xorm.Session, a web.Auth) (err error) { // Delete the team _, err = s.ID(t.ID).Delete(&Team{}) @@ -328,7 +328,7 @@ func (t *Team) Delete(s *xorm.Session) (err error) { // @Failure 400 {object} web.HTTPError "Invalid team object provided." // @Failure 500 {object} models.Message "Internal error" // @Router /teams/{id} [post] -func (t *Team) Update(s *xorm.Session) (err error) { +func (t *Team) Update(s *xorm.Session, a web.Auth) (err error) { // Check if we have a name if t.Name == "" { return ErrTeamNameCannotBeEmpty{} diff --git a/pkg/modules/migration/create_from_structure.go b/pkg/modules/migration/create_from_structure.go index f15683540..1b7e8c4be 100644 --- a/pkg/modules/migration/create_from_structure.go +++ b/pkg/modules/migration/create_from_structure.go @@ -226,7 +226,7 @@ func InsertFromStructure(str []*models.NamespaceWithLists, user *user.User) (err return err } buckets := bucketsIn.([]*models.Bucket) - err = buckets[0].Delete(s) + err = buckets[0].Delete(s, user) if err != nil { _ = s.Rollback() return err diff --git a/pkg/routes/api/v1/login.go b/pkg/routes/api/v1/login.go index 18eaba591..ce3fda0f9 100644 --- a/pkg/routes/api/v1/login.go +++ b/pkg/routes/api/v1/login.go @@ -104,7 +104,7 @@ func RenewToken(c echo.Context) (err error) { if typ == auth.AuthTypeLinkShare { share := &models.LinkSharing{} share.ID = int64(claims["id"].(float64)) - err := share.ReadOne(s) + err := share.ReadOne(s, share) if err != nil { _ = s.Rollback() return handler.HandleHTTPError(err, c) diff --git a/pkg/routes/api/v1/task_attachment.go b/pkg/routes/api/v1/task_attachment.go index a06d568fe..6f07c567b 100644 --- a/pkg/routes/api/v1/task_attachment.go +++ b/pkg/routes/api/v1/task_attachment.go @@ -147,7 +147,7 @@ func GetTaskAttachment(c echo.Context) error { } // Get the attachment incl file - err = taskAttachment.ReadOne(s) + err = taskAttachment.ReadOne(s, auth) if err != nil { _ = s.Rollback() return handler.HandleHTTPError(err, c) diff --git a/pkg/routes/caldav/listStorageProvider.go b/pkg/routes/caldav/listStorageProvider.go index f1e741102..fbb87aeb0 100644 --- a/pkg/routes/caldav/listStorageProvider.go +++ b/pkg/routes/caldav/listStorageProvider.go @@ -318,7 +318,7 @@ func (vcls *VikunjaCaldavListStorage) UpdateResource(rpath, content string) (*da } // Update the task - err = vTask.Update(s) + err = vTask.Update(s, vcls.user) if err != nil { _ = s.Rollback() return nil, err @@ -354,7 +354,7 @@ func (vcls *VikunjaCaldavListStorage) DeleteResource(rpath string) error { } // Delete it - err = vcls.task.Delete(s) + err = vcls.task.Delete(s, vcls.user) if err != nil { _ = s.Rollback() return err @@ -458,7 +458,7 @@ func (vcls *VikunjaCaldavListStorage) getListRessource(isCollection bool) (rr Vi log.Errorf("User %v tried to access a caldav resource (List %v) which they are not allowed to access", vcls.user.Username, vcls.list.ID) return rr, models.ErrUserDoesNotHaveAccessToList{ListID: vcls.list.ID} } - err = vcls.list.ReadOne(s) + err = vcls.list.ReadOne(s, vcls.user) if err != nil { _ = s.Rollback() return -- 2.40.1 From a93aab60240558666fcd8e1964f9c023aa95aff5 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 21:16:48 +0100 Subject: [PATCH 08/45] Set doer when updating a task --- pkg/models/tasks.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index e7af2725f..9713b05b7 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -1037,8 +1037,13 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) { } t.Updated = nt.Updated + doer, err := user.GetFromAuth(a) + if err != nil { + return err + } err = events.Publish(&TaskUpdatedEvent{ Task: t, + Doer: doer, }) if err != nil { return err -- 2.40.1 From 73bed1ce312dd38083e84f5de8fbab2b285c6338 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 21:22:54 +0100 Subject: [PATCH 09/45] Add task assignee created event --- pkg/models/bulk_task.go | 2 +- pkg/models/events.go | 18 +++++++++++++++++- pkg/models/list_duplicate.go | 18 +++++++++--------- pkg/models/task_assignees.go | 25 ++++++++++++++++++++----- pkg/models/tasks.go | 4 ++-- 5 files changed, 49 insertions(+), 18 deletions(-) diff --git a/pkg/models/bulk_task.go b/pkg/models/bulk_task.go index 615d540db..c3e7247c6 100644 --- a/pkg/models/bulk_task.go +++ b/pkg/models/bulk_task.go @@ -85,7 +85,7 @@ func (bt *BulkTask) Update(s *xorm.Session, a web.Auth) (err error) { updateDone(oldtask, &bt.Task) // Update the assignees - if err := oldtask.updateTaskAssignees(s, bt.Assignees); err != nil { + if err := oldtask.updateTaskAssignees(s, bt.Assignees, a); err != nil { return err } diff --git a/pkg/models/events.go b/pkg/models/events.go index 2b8c85a2f..c18f4c4b0 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -16,7 +16,9 @@ package models -import "code.vikunja.io/api/pkg/user" +import ( + "code.vikunja.io/api/pkg/user" +) type TaskCreatedEvent struct { Task *Task @@ -43,3 +45,17 @@ func (t *TaskUpdatedEvent) TopicName() string { func (t *TaskUpdatedEvent) Message() interface{} { return t } + +type TaskAssigneeCreatedEvent struct { + Task *Task + Assignee *user.User + Doer *user.User +} + +func (t *TaskAssigneeCreatedEvent) TopicName() string { + return "task.assignee.created" +} + +func (t *TaskAssigneeCreatedEvent) Message() interface{} { + return t +} diff --git a/pkg/models/list_duplicate.go b/pkg/models/list_duplicate.go index 5113f1768..cdf1163bb 100644 --- a/pkg/models/list_duplicate.go +++ b/pkg/models/list_duplicate.go @@ -67,15 +67,15 @@ func (ld *ListDuplicate) CanCreate(s *xorm.Session, a web.Auth) (canCreate bool, // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{listID}/duplicate [put] //nolint:gocyclo -func (ld *ListDuplicate) Create(s *xorm.Session, a web.Auth) (err error) { +func (ld *ListDuplicate) Create(s *xorm.Session, doer web.Auth) (err error) { log.Debugf("Duplicating list %d", ld.ListID) ld.List.ID = 0 ld.List.Identifier = "" // Reset the identifier to trigger regenerating a new one // Set the owner to the current user - ld.List.OwnerID = a.GetID() - if err := CreateOrUpdateList(s, ld.List, a); err != nil { + ld.List.OwnerID = doer.GetID() + if err := CreateOrUpdateList(s, ld.List, doer); err != nil { // If there is no available unique list identifier, just reset it. if IsErrListIdentifierIsNotUnique(err) { ld.List.Identifier = "" @@ -99,7 +99,7 @@ func (ld *ListDuplicate) Create(s *xorm.Session, a web.Auth) (err error) { oldID := b.ID b.ID = 0 b.ListID = ld.List.ID - if err := b.Create(s, a); err != nil { + if err := b.Create(s, doer); err != nil { return err } bucketMap[oldID] = b.ID @@ -108,7 +108,7 @@ func (ld *ListDuplicate) Create(s *xorm.Session, a web.Auth) (err error) { log.Debugf("Duplicated all buckets from list %d into %d", ld.ListID, ld.List.ID) // Get all tasks + all task details - tasks, _, _, err := getTasksForLists(s, []*List{{ID: ld.ListID}}, a, &taskOptions{}) + tasks, _, _, err := getTasksForLists(s, []*List{{ID: ld.ListID}}, doer, &taskOptions{}) if err != nil { return err } @@ -124,7 +124,7 @@ func (ld *ListDuplicate) Create(s *xorm.Session, a web.Auth) (err error) { t.ListID = ld.List.ID t.BucketID = bucketMap[t.BucketID] t.UID = "" - err := createTask(s, t, a, false) + err := createTask(s, t, doer, false) if err != nil { return err } @@ -163,7 +163,7 @@ func (ld *ListDuplicate) Create(s *xorm.Session, a web.Auth) (err error) { return err } - err := attachment.NewAttachment(s, attachment.File.File, attachment.File.Name, attachment.File.Size, a) + err := attachment.NewAttachment(s, attachment.File.File, attachment.File.Name, attachment.File.Size, doer) if err != nil { return err } @@ -206,7 +206,7 @@ func (ld *ListDuplicate) Create(s *xorm.Session, a web.Auth) (err error) { ID: taskMap[a.TaskID], ListID: ld.List.ID, } - if err := t.addNewAssigneeByID(s, a.UserID, ld.List); err != nil { + if err := t.addNewAssigneeByID(s, a.UserID, ld.List, doer); err != nil { if IsErrUserDoesNotHaveAccessToList(err) { continue } @@ -269,7 +269,7 @@ func (ld *ListDuplicate) Create(s *xorm.Session, a web.Auth) (err error) { } defer f.File.Close() - file, err := files.Create(f.File, f.Name, f.Size, a) + file, err := files.Create(f.File, f.Name, f.Size, doer) if err != nil { return err } diff --git a/pkg/models/task_assignees.go b/pkg/models/task_assignees.go index 4b318fbe6..7b7f1dab3 100644 --- a/pkg/models/task_assignees.go +++ b/pkg/models/task_assignees.go @@ -17,6 +17,7 @@ package models import ( + "code.vikunja.io/api/pkg/events" "time" "code.vikunja.io/api/pkg/user" @@ -57,7 +58,7 @@ func getRawTaskAssigneesForTasks(s *xorm.Session, taskIDs []int64) (taskAssignee } // Create or update a bunch of task assignees -func (t *Task) updateTaskAssignees(s *xorm.Session, assignees []*user.User) (err error) { +func (t *Task) updateTaskAssignees(s *xorm.Session, assignees []*user.User, doer web.Auth) (err error) { // Load the current assignees currentAssignees, err := getRawTaskAssigneesForTasks(s, []int64{t.ID}) @@ -132,7 +133,7 @@ func (t *Task) updateTaskAssignees(s *xorm.Session, assignees []*user.User) (err } // Add the new assignee - err = t.addNewAssigneeByID(s, u.ID, list) + err = t.addNewAssigneeByID(s, u.ID, list, doer) if err != nil { return err } @@ -198,10 +199,10 @@ func (la *TaskAssginee) Create(s *xorm.Session, a web.Auth) (err error) { } task := &Task{ID: la.TaskID} - return task.addNewAssigneeByID(s, la.UserID, list) + return task.addNewAssigneeByID(s, la.UserID, list, a) } -func (t *Task) addNewAssigneeByID(s *xorm.Session, newAssigneeID int64, list *List) (err error) { +func (t *Task) addNewAssigneeByID(s *xorm.Session, newAssigneeID int64, list *List, auth web.Auth) (err error) { // Check if the user exists and has access to the list newAssignee, err := user.GetUserByID(s, newAssigneeID) if err != nil { @@ -223,6 +224,20 @@ func (t *Task) addNewAssigneeByID(s *xorm.Session, newAssigneeID int64, list *Li return err } + doer, err := user.GetFromAuth(auth) + if err != nil { + return err + } + + err = events.Publish(&TaskAssigneeCreatedEvent{ + Task: t, + Assignee: newAssignee, + Doer: doer, + }) + if err != nil { + return err + } + err = updateListLastUpdated(s, &List{ID: t.ListID}) return } @@ -313,6 +328,6 @@ func (ba *BulkAssignees) Create(s *xorm.Session, a web.Auth) (err error) { task.Assignees = append(task.Assignees, &a.User) } - err = task.updateTaskAssignees(s, ba.Assignees) + err = task.updateTaskAssignees(s, ba.Assignees, a) return } diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index 9713b05b7..c5cc94bc7 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -815,7 +815,7 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err // Update the assignees if updateAssignees { - if err := t.updateTaskAssignees(s, t.Assignees); err != nil { + if err := t.updateTaskAssignees(s, t.Assignees, a); err != nil { return err } } @@ -879,7 +879,7 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) { updateDone(&ot, t) // Update the assignees - if err := ot.updateTaskAssignees(s, t.Assignees); err != nil { + if err := ot.updateTaskAssignees(s, t.Assignees, a); err != nil { return err } -- 2.40.1 From d29beac89817d5116bfadc8ebb03b51e85e44d5a Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 21:51:06 +0100 Subject: [PATCH 10/45] Add task comment created event --- pkg/models/events.go | 14 ++++++++++++++ pkg/models/task_comments.go | 17 ++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/pkg/models/events.go b/pkg/models/events.go index c18f4c4b0..6c0605035 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -59,3 +59,17 @@ func (t *TaskAssigneeCreatedEvent) TopicName() string { func (t *TaskAssigneeCreatedEvent) Message() interface{} { return t } + +type TaskCommentCreatedEvent struct { + Task *Task + Comment *TaskComment + Doer *user.User +} + +func (t *TaskCommentCreatedEvent) TopicName() string { + return "task.comment.created" +} + +func (t *TaskCommentCreatedEvent) Message() interface{} { + return t +} diff --git a/pkg/models/task_comments.go b/pkg/models/task_comments.go index f1c4486ee..38babdb7c 100644 --- a/pkg/models/task_comments.go +++ b/pkg/models/task_comments.go @@ -17,6 +17,7 @@ package models import ( + "code.vikunja.io/api/pkg/events" "time" "xorm.io/xorm" @@ -60,7 +61,7 @@ func (tc *TaskComment) TableName() string { // @Router /tasks/{taskID}/comments [put] func (tc *TaskComment) Create(s *xorm.Session, a web.Auth) (err error) { // Check if the task exists - _, err = GetTaskSimple(s, &Task{ID: tc.TaskID}) + task, err := GetTaskSimple(s, &Task{ID: tc.TaskID}) if err != nil { return err } @@ -70,6 +71,20 @@ func (tc *TaskComment) Create(s *xorm.Session, a web.Auth) (err error) { if err != nil { return } + + doer, err := user.GetFromAuth(a) + if err != nil { + return err + } + err = events.Publish(&TaskCommentCreatedEvent{ + Task: &task, + Comment: tc, + Doer: doer, + }) + if err != nil { + return err + } + tc.Author, err = user.GetUserByID(s, a.GetID()) return } -- 2.40.1 From 3e0f8f3174133b5020ff32ded3a0353bee61acda Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 21:52:03 +0100 Subject: [PATCH 11/45] Cleanupo --- pkg/events/events.go | 3 +-- pkg/models/events.go | 16 ---------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/pkg/events/events.go b/pkg/events/events.go index 4ab2e4968..bc034e175 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -32,7 +32,6 @@ var pubsub *gochannel.GoChannel type Event interface { TopicName() string - Message() interface{} } func InitEvents() (err error) { @@ -75,7 +74,7 @@ func InitEvents() (err error) { } func Publish(event Event) error { - content, err := json.Marshal(event.Message()) + content, err := json.Marshal(event) if err != nil { return err } diff --git a/pkg/models/events.go b/pkg/models/events.go index 6c0605035..faa1994d1 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -29,10 +29,6 @@ func (t *TaskCreatedEvent) TopicName() string { return "task.created" } -func (t *TaskCreatedEvent) Message() interface{} { - return t -} - type TaskUpdatedEvent struct { Task *Task Doer *user.User @@ -42,10 +38,6 @@ func (t *TaskUpdatedEvent) TopicName() string { return "task.updated" } -func (t *TaskUpdatedEvent) Message() interface{} { - return t -} - type TaskAssigneeCreatedEvent struct { Task *Task Assignee *user.User @@ -56,10 +48,6 @@ func (t *TaskAssigneeCreatedEvent) TopicName() string { return "task.assignee.created" } -func (t *TaskAssigneeCreatedEvent) Message() interface{} { - return t -} - type TaskCommentCreatedEvent struct { Task *Task Comment *TaskComment @@ -69,7 +57,3 @@ type TaskCommentCreatedEvent struct { func (t *TaskCommentCreatedEvent) TopicName() string { return "task.comment.created" } - -func (t *TaskCommentCreatedEvent) Message() interface{} { - return t -} -- 2.40.1 From 39635cc487631fb827d7638c4f03a775ef9e16fc Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 21:55:10 +0100 Subject: [PATCH 12/45] Add namespace created event --- pkg/models/events.go | 9 +++++++++ pkg/models/namespace.go | 13 +++++++++++++ 2 files changed, 22 insertions(+) diff --git a/pkg/models/events.go b/pkg/models/events.go index faa1994d1..3aa7c7346 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -57,3 +57,12 @@ type TaskCommentCreatedEvent struct { func (t *TaskCommentCreatedEvent) TopicName() string { return "task.comment.created" } + +type NamespaceCreatedEvent struct { + Namespace *Namespace + Doer *user.User +} + +func (n *NamespaceCreatedEvent) TopicName() string { + return "namespace.created" +} diff --git a/pkg/models/namespace.go b/pkg/models/namespace.go index 277f452d8..2896f7186 100644 --- a/pkg/models/namespace.go +++ b/pkg/models/namespace.go @@ -17,6 +17,7 @@ package models import ( + "code.vikunja.io/api/pkg/events" "sort" "strconv" "strings" @@ -478,6 +479,18 @@ func (n *Namespace) Create(s *xorm.Session, a web.Auth) (err error) { return err } + doer, err := user.GetFromAuth(a) + if err != nil { + return err + } + err = events.Publish(&NamespaceCreatedEvent{ + Namespace: n, + Doer: doer, + }) + if err != nil { + return err + } + metrics.UpdateCount(1, metrics.NamespaceCountKey) return } -- 2.40.1 From 94b0555de3f2f00094ec5c3dd8e59f881f480f98 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 21:59:03 +0100 Subject: [PATCH 13/45] Add namespace updated event --- pkg/models/events.go | 17 +++++++++++++++++ pkg/models/namespace.go | 13 ++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/pkg/models/events.go b/pkg/models/events.go index 3aa7c7346..283d404b6 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -20,6 +20,10 @@ import ( "code.vikunja.io/api/pkg/user" ) +///////////////// +// Task Events // +///////////////// + type TaskCreatedEvent struct { Task *Task Doer *user.User @@ -58,6 +62,10 @@ func (t *TaskCommentCreatedEvent) TopicName() string { return "task.comment.created" } +////////////////////// +// Namespace Events // +////////////////////// + type NamespaceCreatedEvent struct { Namespace *Namespace Doer *user.User @@ -66,3 +74,12 @@ type NamespaceCreatedEvent struct { func (n *NamespaceCreatedEvent) TopicName() string { return "namespace.created" } + +type NamespaceUpdatedEvent struct { + Namespace *Namespace + Doer *user.User +} + +func (n *NamespaceUpdatedEvent) TopicName() string { + return "namespace.updated" +} diff --git a/pkg/models/namespace.go b/pkg/models/namespace.go index 2896f7186..a55ca14cc 100644 --- a/pkg/models/namespace.go +++ b/pkg/models/namespace.go @@ -618,5 +618,16 @@ func (n *Namespace) Update(s *xorm.Session, a web.Auth) (err error) { ID(currentNamespace.ID). Cols(colsToUpdate...). Update(n) - return + if err != nil { + return err + } + + doer, err := user.GetFromAuth(a) + if err != nil { + return err + } + return events.Publish(&NamespaceUpdatedEvent{ + Namespace: n, + Doer: doer, + }) } -- 2.40.1 From 90ec98ed2387b43a4daf4cca6c2a86dea4c1dde8 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 22:01:34 +0100 Subject: [PATCH 14/45] Add list created event --- pkg/models/events.go | 13 +++++++++++++ pkg/models/list.go | 11 ++++++++++- pkg/models/namespace.go | 6 +----- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/pkg/models/events.go b/pkg/models/events.go index 283d404b6..0c8c89905 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -83,3 +83,16 @@ type NamespaceUpdatedEvent struct { func (n *NamespaceUpdatedEvent) TopicName() string { return "namespace.updated" } + +///////////////// +// List Events // +///////////////// + +type ListCreatedEvent struct { + List *List + Doer *user.User +} + +func (l *ListCreatedEvent) TopicName() string { + return "list.created" +} diff --git a/pkg/models/list.go b/pkg/models/list.go index 72d3c7588..01a27f376 100644 --- a/pkg/models/list.go +++ b/pkg/models/list.go @@ -17,6 +17,7 @@ package models import ( + "code.vikunja.io/api/pkg/events" "strconv" "strings" "time" @@ -599,7 +600,15 @@ func (l *List) Create(s *xorm.Session, a web.Auth) (err error) { ListID: l.ID, Title: "New Bucket", } - return b.Create(s, a) + err = b.Create(s, a) + if err != nil { + return + } + + return events.Publish(&ListCreatedEvent{ + List: l, + Doer: doer, + }) } // Delete implements the delete method of CRUDable diff --git a/pkg/models/namespace.go b/pkg/models/namespace.go index a55ca14cc..2a9fc97b1 100644 --- a/pkg/models/namespace.go +++ b/pkg/models/namespace.go @@ -479,13 +479,9 @@ func (n *Namespace) Create(s *xorm.Session, a web.Auth) (err error) { return err } - doer, err := user.GetFromAuth(a) - if err != nil { - return err - } err = events.Publish(&NamespaceCreatedEvent{ Namespace: n, - Doer: doer, + Doer: n.Owner, }) if err != nil { return err -- 2.40.1 From 1c5dfb024bac4c24a7e47c7967d2a8e025ad5274 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 22:03:33 +0100 Subject: [PATCH 15/45] Add list updated event --- pkg/models/events.go | 9 +++++++++ pkg/models/list.go | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/pkg/models/events.go b/pkg/models/events.go index 0c8c89905..73a7cd21c 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -96,3 +96,12 @@ type ListCreatedEvent struct { func (l *ListCreatedEvent) TopicName() string { return "list.created" } + +type ListUpdatedEvent struct { + List *List + Doer *user.User +} + +func (l *ListUpdatedEvent) TopicName() string { + return "list.updated" +} diff --git a/pkg/models/list.go b/pkg/models/list.go index 01a27f376..b9cb17244 100644 --- a/pkg/models/list.go +++ b/pkg/models/list.go @@ -543,7 +543,20 @@ func CreateOrUpdateList(s *xorm.Session, list *List, auth web.Auth) (err error) // @Failure 500 {object} models.Message "Internal error" // @Router /lists/{id} [post] func (l *List) Update(s *xorm.Session, a web.Auth) (err error) { - return CreateOrUpdateList(s, l, a) + err = CreateOrUpdateList(s, l, a) + if err != nil { + return err + } + + doer, err := user.GetFromAuth(a) + if err != nil { + return err + } + + return events.Publish(&ListUpdatedEvent{ + List: l, + Doer: doer, + }) } func updateListLastUpdated(s *xorm.Session, list *List) error { -- 2.40.1 From 3f4fda1548327029202832b15b2ee53ae88ca2bf Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 22:06:23 +0100 Subject: [PATCH 16/45] Add list shared with user event --- pkg/models/events.go | 14 ++++++++++++++ pkg/models/list_users.go | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/pkg/models/events.go b/pkg/models/events.go index 73a7cd21c..521254da8 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -105,3 +105,17 @@ type ListUpdatedEvent struct { func (l *ListUpdatedEvent) TopicName() string { return "list.updated" } + +//////////////////// +// Sharing Events // +//////////////////// + +type ListSharedWithUserEvent struct { + List *List + User *user.User + Doer *user.User +} + +func (l *ListSharedWithUserEvent) TopicName() string { + return "list.shared.user" +} diff --git a/pkg/models/list_users.go b/pkg/models/list_users.go index 01737b2d3..351748954 100644 --- a/pkg/models/list_users.go +++ b/pkg/models/list_users.go @@ -17,6 +17,7 @@ package models import ( + "code.vikunja.io/api/pkg/events" "time" "code.vikunja.io/api/pkg/user" @@ -112,6 +113,19 @@ func (lu *ListUser) Create(s *xorm.Session, a web.Auth) (err error) { return err } + doer, err := user.GetFromAuth(a) + if err != nil { + return err + } + err = events.Publish(&ListSharedWithUserEvent{ + List: l, + User: u, + Doer: doer, + }) + if err != nil { + return err + } + err = updateListLastUpdated(s, l) return } -- 2.40.1 From e8f2d577c26653c5e8722d81c4d4ced40d0fe2de Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 22:08:43 +0100 Subject: [PATCH 17/45] Add list shared with team event --- pkg/models/events.go | 10 ++++++++++ pkg/models/list_team.go | 16 ++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/pkg/models/events.go b/pkg/models/events.go index 521254da8..fddd80ded 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -119,3 +119,13 @@ type ListSharedWithUserEvent struct { func (l *ListSharedWithUserEvent) TopicName() string { return "list.shared.user" } + +type ListSharedWithTeamEvent struct { + List *List + Team *Team + Doer *user.User +} + +func (l *ListSharedWithTeamEvent) TopicName() string { + return "list.shared.team" +} diff --git a/pkg/models/list_team.go b/pkg/models/list_team.go index a1bfdea00..2f762822f 100644 --- a/pkg/models/list_team.go +++ b/pkg/models/list_team.go @@ -17,6 +17,8 @@ package models import ( + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/user" "time" "code.vikunja.io/web" @@ -77,9 +79,9 @@ func (tl *TeamList) Create(s *xorm.Session, a web.Auth) (err error) { } // Check if the team exists - _, err = GetTeamByID(s, tl.TeamID) + team, err := GetTeamByID(s, tl.TeamID) if err != nil { - return + return err } // Check if the list exists @@ -105,6 +107,16 @@ func (tl *TeamList) Create(s *xorm.Session, a web.Auth) (err error) { return err } + doer, err := user.GetFromAuth(a) + if err != nil { + return err + } + err = events.Publish(&ListSharedWithTeamEvent{ + List: l, + Team: team, + Doer: doer, + }) + err = updateListLastUpdated(s, l) return } -- 2.40.1 From 405f3771b1624e6a1dfdd0aee357ee79da03496a Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 22:20:25 +0100 Subject: [PATCH 18/45] Add namespace sharing events --- pkg/models/events.go | 20 ++++++++++++++++++++ pkg/models/namespace_team.go | 24 +++++++++++++++++++----- pkg/models/namespace_users.go | 18 +++++++++++++++--- 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/pkg/models/events.go b/pkg/models/events.go index fddd80ded..fff1662fb 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -129,3 +129,23 @@ type ListSharedWithTeamEvent struct { func (l *ListSharedWithTeamEvent) TopicName() string { return "list.shared.team" } + +type NamespaceSharedWithUserEvent struct { + Namespace *Namespace + User *user.User + Doer *user.User +} + +func (n *NamespaceSharedWithUserEvent) TopicName() string { + return "namespace.shared.user" +} + +type NamespaceSharedWithTeamEvent struct { + Namespace *Namespace + Team *Team + Doer *user.User +} + +func (n *NamespaceSharedWithTeamEvent) TopicName() string { + return "namespace.shared.team" +} diff --git a/pkg/models/namespace_team.go b/pkg/models/namespace_team.go index 3a1e5f139..445c490e9 100644 --- a/pkg/models/namespace_team.go +++ b/pkg/models/namespace_team.go @@ -17,6 +17,8 @@ package models import ( + "code.vikunja.io/api/pkg/events" + user2 "code.vikunja.io/api/pkg/user" "time" "code.vikunja.io/web" @@ -71,15 +73,15 @@ func (tn *TeamNamespace) Create(s *xorm.Session, a web.Auth) (err error) { } // Check if the team exists - _, err = GetTeamByID(s, tn.TeamID) + team, err := GetTeamByID(s, tn.TeamID) if err != nil { - return + return err } // Check if the namespace exists - _, err = GetNamespaceByID(s, tn.NamespaceID) + namespace, err := GetNamespaceByID(s, tn.NamespaceID) if err != nil { - return + return err } // Check if the team already has access to the namespace @@ -96,7 +98,19 @@ func (tn *TeamNamespace) Create(s *xorm.Session, a web.Auth) (err error) { // Insert the new team _, err = s.Insert(tn) - return + if err != nil { + return err + } + + doer, err := user2.GetFromAuth(a) + if err != nil { + return err + } + return events.Publish(&NamespaceSharedWithTeamEvent{ + Namespace: namespace, + Team: team, + Doer: doer, + }) } // Delete deletes a team <-> namespace relation based on the namespace & team id diff --git a/pkg/models/namespace_users.go b/pkg/models/namespace_users.go index 89be44839..af78e38ce 100644 --- a/pkg/models/namespace_users.go +++ b/pkg/models/namespace_users.go @@ -17,6 +17,7 @@ package models import ( + "code.vikunja.io/api/pkg/events" "time" user2 "code.vikunja.io/api/pkg/user" @@ -75,7 +76,7 @@ func (nu *NamespaceUser) Create(s *xorm.Session, a web.Auth) (err error) { } // Check if the namespace exists - l, err := GetNamespaceByID(s, nu.NamespaceID) + n, err := GetNamespaceByID(s, nu.NamespaceID) if err != nil { return } @@ -89,7 +90,7 @@ func (nu *NamespaceUser) Create(s *xorm.Session, a web.Auth) (err error) { // Check if the user already has access or is owner of that namespace // We explicitly DO NOT check for teams here - if l.OwnerID == nu.UserID { + if n.OwnerID == nu.UserID { return ErrUserAlreadyHasNamespaceAccess{UserID: nu.UserID, NamespaceID: nu.NamespaceID} } @@ -105,8 +106,19 @@ func (nu *NamespaceUser) Create(s *xorm.Session, a web.Auth) (err error) { // Insert user <-> namespace relation _, err = s.Insert(nu) + if err != nil { + return err + } - return + doer, err := user2.GetFromAuth(a) + if err != nil { + return err + } + return events.Publish(&NamespaceSharedWithUserEvent{ + Namespace: n, + User: user, + Doer: doer, + }) } // Delete deletes a namespace <-> user relation -- 2.40.1 From 51024a595dfb47e753018a62c6c1a85de2526638 Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 22:23:58 +0100 Subject: [PATCH 19/45] Add team member added event --- pkg/models/events.go | 14 ++++++++++++++ pkg/models/team_members.go | 19 ++++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/pkg/models/events.go b/pkg/models/events.go index fff1662fb..fb225b837 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -149,3 +149,17 @@ type NamespaceSharedWithTeamEvent struct { func (n *NamespaceSharedWithTeamEvent) TopicName() string { return "namespace.shared.team" } + +///////////////// +// Team Events // +///////////////// + +type TeamMemberAddedEvent struct { + Team *Team + Member *user.User + Doer *user.User +} + +func (t *TeamMemberAddedEvent) TopicName() string { + return "team.member.added" +} diff --git a/pkg/models/team_members.go b/pkg/models/team_members.go index 665454d90..5f52a0343 100644 --- a/pkg/models/team_members.go +++ b/pkg/models/team_members.go @@ -17,6 +17,7 @@ package models import ( + "code.vikunja.io/api/pkg/events" user2 "code.vikunja.io/api/pkg/user" "code.vikunja.io/web" "xorm.io/xorm" @@ -39,9 +40,9 @@ import ( func (tm *TeamMember) Create(s *xorm.Session, a web.Auth) (err error) { // Check if the team extst - _, err = GetTeamByID(s, tm.TeamID) + team, err := GetTeamByID(s, tm.TeamID) if err != nil { - return + return err } // Check if the user exists @@ -64,7 +65,19 @@ func (tm *TeamMember) Create(s *xorm.Session, a web.Auth) (err error) { // Insert the user _, err = s.Insert(tm) - return + if err != nil { + return err + } + + doer, err := user2.GetFromAuth(a) + if err != nil { + return err + } + return events.Publish(&TeamMemberAddedEvent{ + Team: team, + Member: user, + Doer: doer, + }) } // Delete deletes a user from a team -- 2.40.1 From be40033886499396cc313dcf3c62817136b881bf Mon Sep 17 00:00:00 2001 From: kolaente Date: Sun, 31 Jan 2021 23:03:41 +0100 Subject: [PATCH 20/45] Expose watermill metrics through the default metrics endpoint --- config.yml.sample | 4 ++-- go.sum | 1 + pkg/events/events.go | 7 +++++- pkg/events/listeners.go | 1 + pkg/metrics/metrics.go | 49 ++++++++++++++++++++++++++++++++--------- pkg/models/listeners.go | 4 ++++ pkg/routes/metrics.go | 2 +- 7 files changed, 54 insertions(+), 14 deletions(-) diff --git a/config.yml.sample b/config.yml.sample index 714a04aec..9851e4e72 100644 --- a/config.yml.sample +++ b/config.yml.sample @@ -137,9 +137,9 @@ log: # Echo has its own logging which usually is unnessecary, which is why it is disabled by default. Possible values are stdout, stderr, file or off to disable standard logging. echo: "off" # Whether or not to log events. Useful for debugging. Possible values are stdout, stderr, file or off to disable events logging. - events: "stdout" + events: "stdout" # The log level for event log messages. Possible values (case-insensitive) are ERROR, INFO, DEBUG. - eventslevel: "info" + eventslevel: "info" ratelimit: # whether or not to enable the rate limit diff --git a/go.sum b/go.sum index 67538bb13..6b472d4a5 100644 --- a/go.sum +++ b/go.sum @@ -218,6 +218,7 @@ github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= +github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs= github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= diff --git a/pkg/events/events.go b/pkg/events/events.go index bc034e175..aebfbc837 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -22,7 +22,9 @@ import ( "time" "code.vikunja.io/api/pkg/log" + vmetrics "code.vikunja.io/api/pkg/metrics" "github.com/ThreeDotsLabs/watermill" + "github.com/ThreeDotsLabs/watermill/components/metrics" "github.com/ThreeDotsLabs/watermill/message" "github.com/ThreeDotsLabs/watermill/message/router/middleware" "github.com/ThreeDotsLabs/watermill/pubsub/gochannel" @@ -55,6 +57,9 @@ func InitEvents() (err error) { middleware.Recoverer, ) + metricsBuilder := metrics.NewPrometheusMetricsBuilder(vmetrics.GetRegistry(), "", "") + metricsBuilder.AddPrometheusRouterMetrics(router) + pubsub = gochannel.NewGoChannel( gochannel.Config{ OutputChannelBuffer: 1024, @@ -64,7 +69,7 @@ func InitEvents() (err error) { for topic, funcs := range listeners { for _, handler := range funcs { - router.AddNoPublisherHandler(topic+"."+watermill.NewShortUUID(), topic, pubsub, func(msg *message.Message) error { + router.AddNoPublisherHandler(topic+"."+handler.Name(), topic, pubsub, func(msg *message.Message) error { return handler.Handle(msg.Payload) }) } diff --git a/pkg/events/listeners.go b/pkg/events/listeners.go index 846995426..3368c9a07 100644 --- a/pkg/events/listeners.go +++ b/pkg/events/listeners.go @@ -20,6 +20,7 @@ import "github.com/ThreeDotsLabs/watermill/message" type Listener interface { Handle(payload message.Payload) error + Name() string } var listeners map[string][]Listener diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 5f51b038c..da5240182 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -41,6 +41,18 @@ const ( TeamCountKey = `teamcount` ) +var registry *prometheus.Registry + +func GetRegistry() *prometheus.Registry { + if registry == nil { + registry = prometheus.NewRegistry() + registry.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{})) + registry.MustRegister(prometheus.NewGoCollector()) + } + + return registry +} + // InitMetrics Initializes the metrics func InitMetrics() { // init active users, sometimes we'll have garbage from previous runs in redis instead @@ -48,50 +60,67 @@ func InitMetrics() { log.Fatalf("Could not set initial count for active users, error was %s", err) } + GetRegistry() + // Register total list count metric - promauto.NewGaugeFunc(prometheus.GaugeOpts{ + err := registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{ Name: "vikunja_list_count", Help: "The number of lists on this instance", }, func() float64 { count, _ := GetCount(ListCountKey) return float64(count) - }) + })) + if err != nil { + log.Criticalf("Could not register metrics for %s: %s", ListCountKey, err) + } // Register total user count metric - promauto.NewGaugeFunc(prometheus.GaugeOpts{ + err = registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{ Name: "vikunja_user_count", Help: "The total number of users on this instance", }, func() float64 { count, _ := GetCount(UserCountKey) return float64(count) - }) + })) + if err != nil { + log.Criticalf("Could not register metrics for %s: %s", UserCountKey, err) + } // Register total Namespaces count metric - promauto.NewGaugeFunc(prometheus.GaugeOpts{ + err = registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{ Name: "vikunja_namespcae_count", Help: "The total number of namespaces on this instance", }, func() float64 { count, _ := GetCount(NamespaceCountKey) return float64(count) - }) + })) + if err != nil { + log.Criticalf("Could not register metrics for %s: %s", NamespaceCountKey, err) + } // Register total Tasks count metric - promauto.NewGaugeFunc(prometheus.GaugeOpts{ + err = registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{ Name: "vikunja_task_count", Help: "The total number of tasks on this instance", }, func() float64 { count, _ := GetCount(TaskCountKey) return float64(count) - }) + })) + if err != nil { + log.Criticalf("Could not register metrics for %s: %s", TaskCountKey, err) + } // Register total user count metric - promauto.NewGaugeFunc(prometheus.GaugeOpts{ + err = registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{ Name: "vikunja_team_count", Help: "The total number of teams on this instance", }, func() float64 { count, _ := GetCount(TeamCountKey) return float64(count) - }) + })) + if err != nil { + log.Criticalf("Could not register metrics for %s: %s", TeamCountKey, err) + } } // GetCount returns the current count from redis diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index 21264f309..fce83ad3e 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -30,6 +30,10 @@ func RegisterListeners() { type SendTaskCreatedNotification struct { } +func (s *SendTaskCreatedNotification) Name() string { + return "task.created.notification" +} + func (s *SendTaskCreatedNotification) Handle(payload message.Payload) (err error) { event := &TaskCreatedEvent{} err = json.Unmarshal(payload, event) diff --git a/pkg/routes/metrics.go b/pkg/routes/metrics.go index 2c1045f00..c6ca0f1c2 100644 --- a/pkg/routes/metrics.go +++ b/pkg/routes/metrics.go @@ -71,7 +71,7 @@ func setupMetrics(a *echo.Group) { } } - a.GET("/metrics", echo.WrapHandler(promhttp.Handler())) + a.GET("/metrics", echo.WrapHandler(promhttp.HandlerFor(metrics.GetRegistry(), promhttp.HandlerOpts{}))) } func setupMetricsMiddleware(a *echo.Group) { -- 2.40.1 From 5dac13c6c808131ca71c269f67a64350e35e6687 Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 1 Feb 2021 18:06:10 +0100 Subject: [PATCH 21/45] Add command to generate a new event --- magefile.go | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/magefile.go b/magefile.go index 39ffa899d..83590f43c 100644 --- a/magefile.go +++ b/magefile.go @@ -24,6 +24,7 @@ import ( "context" "crypto/sha256" "fmt" + "github.com/iancoleman/strcase" "io" "io/ioutil" "os" @@ -294,6 +295,13 @@ func moveFile(src, dst string) error { return nil } +const InfoColor = "\033[1;32m%s\033[0m" + +func printSuccess(text string, args ...interface{}) { + text = fmt.Sprintf(text, args...) + fmt.Printf(InfoColor+"\n", text) +} + // Formats the code using go fmt func Fmt() { mg.Deps(initVars) @@ -747,14 +755,56 @@ func init() { }) } ` - f, err := os.Create(RootPath + "/pkg/migration/" + date + ".go") + filename := "/pkg/migration/" + date + ".go" + f, err := os.Create(RootPath + filename) defer f.Close() if err != nil { return err } - _, err = f.WriteString(migration) - return err + if _, err := f.WriteString(migration); err != nil { + return err + } + + printSuccess("Migration has been created at %s!", filename) + + return nil +} + +// Create a new event. Takes the name of the event as the first argument and the module where the event should be created as the second argument. Events will be appended to the pkg//events.go file. +func (Dev) CreateEvent(name, module string) error { + + name = strcase.ToCamel(name) + + if !strings.HasSuffix(name, "Event") { + name += "Event" + } + + eventName := strings.ReplaceAll(strcase.ToDelimited(name, '.'), ".event", "") + + newEventCode := ` +type ` + name + ` struct { +} + +func (t *` + name + `) TopicName() string { + return "` + eventName + `" +} +` + filename := "./pkg/" + module + "/events.go" + f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + return err + } + + defer f.Close() + + if _, err = f.WriteString(newEventCode); err != nil { + return err + } + + printSuccess("The new event has been created successfully! Head over to %s and adjust its content.", filename) + + return nil } type configOption struct { -- 2.40.1 From 3f21b3610e416c682cbb8e4233dae0578dc7816a Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 1 Feb 2021 18:37:34 +0100 Subject: [PATCH 22/45] Add command to generate a new listener for an event --- go.mod | 1 + magefile.go | 105 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 94 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index a435090e4..97ccdf896 100644 --- a/go.mod +++ b/go.mod @@ -86,6 +86,7 @@ require ( golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf golang.org/x/text v0.3.5 // indirect + google.golang.org/protobuf v1.25.0 gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/d4l3k/messagediff.v1 v1.2.1 diff --git a/magefile.go b/magefile.go index 83590f43c..7e009e91a 100644 --- a/magefile.go +++ b/magefile.go @@ -61,13 +61,15 @@ var ( // Aliases are mage aliases of targets Aliases = map[string]interface{}{ - "build": Build.Build, - "do-the-swag": DoTheSwag, - "check:got-swag": Check.GotSwag, - "release:os-package": Release.OsPackage, - "dev:create-migration": Dev.CreateMigration, - "generate-docs": GenerateDocs, - "check:golangci-fix": Check.GolangciFix, + "build": Build.Build, + "do-the-swag": DoTheSwag, + "check:got-swag": Check.GotSwag, + "release:os-package": Release.OsPackage, + "dev:make-migration": Dev.MakeMigration, + "dev:make-event": Dev.MakeEvent, + "dev:make-listener": Dev.MakeListener, + "generate-docs": GenerateDocs, + "check:golangci-fix": Check.GolangciFix, } ) @@ -295,6 +297,18 @@ func moveFile(src, dst string) error { return nil } +func appendToFile(filename, content string) error { + f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) + if err != nil { + return err + } + + defer f.Close() + + _, err = f.WriteString(content) + return err +} + const InfoColor = "\033[1;32m%s\033[0m" func printSuccess(text string, args ...interface{}) { @@ -703,7 +717,7 @@ func (Release) Packages() error { type Dev mg.Namespace // Creates a new bare db migration skeleton in pkg/migration with the current date -func (Dev) CreateMigration() error { +func (Dev) MakeMigration() error { reader := bufio.NewReader(os.Stdin) fmt.Print("Enter the name of the struct: ") @@ -772,7 +786,7 @@ func init() { } // Create a new event. Takes the name of the event as the first argument and the module where the event should be created as the second argument. Events will be appended to the pkg//events.go file. -func (Dev) CreateEvent(name, module string) error { +func (Dev) MakeEvent(name, module string) error { name = strcase.ToCamel(name) @@ -791,18 +805,85 @@ func (t *` + name + `) TopicName() string { } ` filename := "./pkg/" + module + "/events.go" - f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) + if err := appendToFile(filename, newEventCode); err != nil { + return err + } + + printSuccess("The new event has been created successfully! Head over to %s and adjust its content.", filename) + + return nil +} + +func (Dev) MakeListener(name, event, module string) error { + name = strcase.ToCamel(name) + listenerName := strcase.ToDelimited(name, '.') + listenerCode := ` +type ` + name + ` struct { +} + +func (s *` + name + `) Name() string { + return "` + listenerName + `" +} + +func (s *` + name + `) Handle(payload message.Payload) (err error) { + event := &` + event + `{} + err = json.Unmarshal(payload, event) + if err != nil { + return err + } + + return nil +} +` + filename := "./pkg/" + module + "/listeners.go" + + ////// + // Register the listener + + file, err := os.Open(filename) + if err != nil { + return err + } + + scanner := bufio.NewScanner(file) + var idx int64 = 0 + for scanner.Scan() { + if scanner.Text() == "}" { + //idx -= int64(len(scanner.Text())) + break + } + idx += int64(len(scanner.Bytes()) + 1) + } + file.Close() + + registerListenerCode := ` events.RegisterListener((&` + event + `{}).TopicName(), &` + name + `{}) +` + + f, err := os.OpenFile(filename, os.O_RDWR, 0600) if err != nil { return err } defer f.Close() - if _, err = f.WriteString(newEventCode); err != nil { + if _, err := f.Seek(idx, 0); err != nil { + return err + } + remainder, err := ioutil.ReadAll(f) + if err != nil { + return err + } + f.Seek(idx, 0) + f.Write([]byte(registerListenerCode)) + f.Write(remainder) + + /////// + // Append the listener code + if err := appendToFile(filename, listenerCode); err != nil { return err } - printSuccess("The new event has been created successfully! Head over to %s and adjust its content.", filename) + printSuccess("The new listener has been created successfully! Head over to %s and adjust its content.", filename) return nil } -- 2.40.1 From 83f48dd175baf208e62f38197efdbe1a521bd96c Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 1 Feb 2021 21:05:53 +0100 Subject: [PATCH 23/45] Increase and decrease the list metrics counter with events --- pkg/metrics/metrics.go | 2 +- pkg/models/events.go | 9 +++++++++ pkg/models/list.go | 18 +++++++++++++----- pkg/models/listeners.go | 30 ++++++++++++++++++++++++++++++ 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index da5240182..fe40a9d29 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -155,7 +155,7 @@ func UpdateCount(update int64, key string) { } } if update < 0 { - err := keyvalue.DecrBy(key, update) + err := keyvalue.DecrBy(key, update*-1) if err != nil { log.Error(err.Error()) } diff --git a/pkg/models/events.go b/pkg/models/events.go index fb225b837..bd0128992 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -106,6 +106,15 @@ func (l *ListUpdatedEvent) TopicName() string { return "list.updated" } +type ListDeletedEvent struct { + List *List + Doer *user.User +} + +func (t *ListDeletedEvent) TopicName() string { + return "list.deleted" +} + //////////////////// // Sharing Events // //////////////////// diff --git a/pkg/models/list.go b/pkg/models/list.go index b9cb17244..c08d1922c 100644 --- a/pkg/models/list.go +++ b/pkg/models/list.go @@ -25,7 +25,6 @@ import ( "code.vikunja.io/api/pkg/log" "code.vikunja.io/api/pkg/files" - "code.vikunja.io/api/pkg/metrics" "code.vikunja.io/api/pkg/user" "code.vikunja.io/web" "xorm.io/builder" @@ -493,7 +492,6 @@ func CreateOrUpdateList(s *xorm.Session, list *List, auth web.Auth) (err error) if list.ID == 0 { _, err = s.Insert(list) - metrics.UpdateCount(1, metrics.ListCountKey) } else { // We need to specify the cols we want to update here to be able to un-archive lists colsToUpdate := []string{ @@ -643,11 +641,21 @@ func (l *List) Delete(s *xorm.Session, a web.Auth) (err error) { if err != nil { return } - metrics.UpdateCount(-1, metrics.ListCountKey) - // Delete all todotasks on that list + // Delete all tasks on that list _, err = s.Where("list_id = ?", l.ID).Delete(&Task{}) - return + if err != nil { + return + } + + doer, err := user.GetFromAuth(a) + if err != nil { + return err + } + return events.Publish(&ListDeletedEvent{ + List: l, + Doer: doer, + }) } // SetListBackground sets a background file as list background in the db diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index fce83ad3e..b158efd75 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -17,6 +17,7 @@ package models import ( + "code.vikunja.io/api/pkg/metrics" "encoding/json" "code.vikunja.io/api/pkg/events" @@ -25,6 +26,8 @@ import ( func RegisterListeners() { events.RegisterListener((&TaskCreatedEvent{}).TopicName(), &SendTaskCreatedNotification{}) + events.RegisterListener((&ListCreatedEvent{}).TopicName(), &IncreaseListCounter{}) + events.RegisterListener((&ListDeletedEvent{}).TopicName(), &DecreaseListCounter{}) } type SendTaskCreatedNotification struct { @@ -43,3 +46,30 @@ func (s *SendTaskCreatedNotification) Handle(payload message.Payload) (err error return nil } + +/////// +// List Event Listeners + +type IncreaseListCounter struct { +} + +func (s *IncreaseListCounter) Name() string { + return "increase.list.counter" +} + +func (s *IncreaseListCounter) Handle(payload message.Payload) (err error) { + metrics.UpdateCount(1, metrics.ListCountKey) + return nil +} + +type DecreaseListCounter struct { +} + +func (s *DecreaseListCounter) Name() string { + return "decrease.list.counter" +} + +func (s *DecreaseListCounter) Handle(payload message.Payload) (err error) { + metrics.UpdateCount(-1, metrics.ListCountKey) + return nil +} -- 2.40.1 From 35f9a47e4a291d74df868fd21660d61db4aa1d8f Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 1 Feb 2021 21:08:49 +0100 Subject: [PATCH 24/45] Add comments to magefile code generation commands --- magefile.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/magefile.go b/magefile.go index 7e009e91a..1a0ecb0c9 100644 --- a/magefile.go +++ b/magefile.go @@ -797,9 +797,11 @@ func (Dev) MakeEvent(name, module string) error { eventName := strings.ReplaceAll(strcase.ToDelimited(name, '.'), ".event", "") newEventCode := ` +// ` + name + ` represents a ` + name + ` event type ` + name + ` struct { } +// TopicName defines the name for ` + name + ` func (t *` + name + `) TopicName() string { return "` + eventName + `" } @@ -818,13 +820,16 @@ func (Dev) MakeListener(name, event, module string) error { name = strcase.ToCamel(name) listenerName := strcase.ToDelimited(name, '.') listenerCode := ` +// ` + name + ` represents a listener type ` + name + ` struct { } +// Name defines the name for the ` + name + ` listener func (s *` + name + `) Name() string { return "` + listenerName + `" } +// Hanlde is executed when the event ` + name + ` listens on is fired func (s *` + name + `) Handle(payload message.Payload) (err error) { event := &` + event + `{} err = json.Unmarshal(payload, event) -- 2.40.1 From 56c712e6b6ad0929c6b44fa68aa372509aeafcd5 Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 1 Feb 2021 21:15:21 +0100 Subject: [PATCH 25/45] Increase and decrease the namespace metrics counter with events --- pkg/metrics/metrics.go | 2 +- pkg/models/events.go | 11 +++++++++++ pkg/models/listeners.go | 39 +++++++++++++++++++++++++++++++++++++-- pkg/models/namespace.go | 13 ++++++++----- 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index fe40a9d29..69899d890 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -88,7 +88,7 @@ func InitMetrics() { // Register total Namespaces count metric err = registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{ - Name: "vikunja_namespcae_count", + Name: "vikunja_namespace_count", Help: "The total number of namespaces on this instance", }, func() float64 { count, _ := GetCount(NamespaceCountKey) diff --git a/pkg/models/events.go b/pkg/models/events.go index bd0128992..8c7d06845 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -84,6 +84,17 @@ func (n *NamespaceUpdatedEvent) TopicName() string { return "namespace.updated" } +// NamespaceDeletedEvent represents a NamespaceDeletedEvent event +type NamespaceDeletedEvent struct { + Namespace *Namespace + Doer *user.User +} + +// TopicName defines the name for NamespaceDeletedEvent +func (t *NamespaceDeletedEvent) TopicName() string { + return "namespace.deleted" +} + ///////////////// // List Events // ///////////////// diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index b158efd75..d39fd3c84 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -28,6 +28,8 @@ func RegisterListeners() { events.RegisterListener((&TaskCreatedEvent{}).TopicName(), &SendTaskCreatedNotification{}) events.RegisterListener((&ListCreatedEvent{}).TopicName(), &IncreaseListCounter{}) events.RegisterListener((&ListDeletedEvent{}).TopicName(), &DecreaseListCounter{}) + events.RegisterListener((&NamespaceCreatedEvent{}).TopicName(), &IncreaseNamespaceCounter{}) + events.RegisterListener((&NamespaceDeletedEvent{}).TopicName(), &DecreaseNamespaceCounter{}) } type SendTaskCreatedNotification struct { @@ -54,7 +56,7 @@ type IncreaseListCounter struct { } func (s *IncreaseListCounter) Name() string { - return "increase.list.counter" + return "list.counter.increase" } func (s *IncreaseListCounter) Handle(payload message.Payload) (err error) { @@ -66,10 +68,43 @@ type DecreaseListCounter struct { } func (s *DecreaseListCounter) Name() string { - return "decrease.list.counter" + return "list.counter.decrease" } func (s *DecreaseListCounter) Handle(payload message.Payload) (err error) { metrics.UpdateCount(-1, metrics.ListCountKey) return nil } + +////// +// Namespace events + +// IncreaseNamespaceCounter represents a listener +type IncreaseNamespaceCounter struct { +} + +// Name defines the name for the IncreaseNamespaceCounter listener +func (s *IncreaseNamespaceCounter) Name() string { + return "namespace.counter.increase" +} + +// Hanlde is executed when the event IncreaseNamespaceCounter listens on is fired +func (s *IncreaseNamespaceCounter) Handle(payload message.Payload) (err error) { + metrics.UpdateCount(1, metrics.NamespaceCountKey) + return nil +} + +// DecreaseNamespaceCounter represents a listener +type DecreaseNamespaceCounter struct { +} + +// Name defines the name for the DecreaseNamespaceCounter listener +func (s *DecreaseNamespaceCounter) Name() string { + return "namespace.counter.decrease" +} + +// Hanlde is executed when the event DecreaseNamespaceCounter listens on is fired +func (s *DecreaseNamespaceCounter) Handle(payload message.Payload) (err error) { + metrics.UpdateCount(-1, metrics.NamespaceCountKey) + return nil +} diff --git a/pkg/models/namespace.go b/pkg/models/namespace.go index 2a9fc97b1..e7d03b047 100644 --- a/pkg/models/namespace.go +++ b/pkg/models/namespace.go @@ -24,7 +24,6 @@ import ( "time" "code.vikunja.io/api/pkg/log" - "code.vikunja.io/api/pkg/metrics" "code.vikunja.io/api/pkg/user" "code.vikunja.io/web" "xorm.io/builder" @@ -487,7 +486,6 @@ func (n *Namespace) Create(s *xorm.Session, a web.Auth) (err error) { return err } - metrics.UpdateCount(1, metrics.NamespaceCountKey) return } @@ -552,9 +550,14 @@ func (n *Namespace) Delete(s *xorm.Session, a web.Auth) (err error) { return } - metrics.UpdateCount(-1, metrics.NamespaceCountKey) - - return + doer, err := user.GetFromAuth(a) + if err != nil { + return err + } + return events.Publish(&NamespaceDeletedEvent{ + Namespace: n, + Doer: doer, + }) } // Update implements the update method via the interface -- 2.40.1 From dfbb3fe6f4f4b21b56a576e0df1d36b149438872 Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 1 Feb 2021 21:27:37 +0100 Subject: [PATCH 26/45] Increase and decrease the task metrics counter with events --- pkg/models/events.go | 11 +++++++++++ pkg/models/listeners.go | 41 ++++++++++++++++++++++++++++------------- pkg/models/tasks.go | 15 +++++++++++---- 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/pkg/models/events.go b/pkg/models/events.go index 8c7d06845..1cd8e341c 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -42,6 +42,17 @@ func (t *TaskUpdatedEvent) TopicName() string { return "task.updated" } +// TaskDeletedEvent represents a TaskDeletedEvent event +type TaskDeletedEvent struct { + Task *Task + Doer *user.User +} + +// TopicName defines the name for TaskDeletedEvent +func (t *TaskDeletedEvent) TopicName() string { + return "task.deleted" +} + type TaskAssigneeCreatedEvent struct { Task *Task Assignee *user.User diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index d39fd3c84..02ffab457 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -17,35 +17,50 @@ package models import ( - "code.vikunja.io/api/pkg/metrics" - "encoding/json" - "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/metrics" "github.com/ThreeDotsLabs/watermill/message" ) func RegisterListeners() { - events.RegisterListener((&TaskCreatedEvent{}).TopicName(), &SendTaskCreatedNotification{}) events.RegisterListener((&ListCreatedEvent{}).TopicName(), &IncreaseListCounter{}) events.RegisterListener((&ListDeletedEvent{}).TopicName(), &DecreaseListCounter{}) events.RegisterListener((&NamespaceCreatedEvent{}).TopicName(), &IncreaseNamespaceCounter{}) events.RegisterListener((&NamespaceDeletedEvent{}).TopicName(), &DecreaseNamespaceCounter{}) + events.RegisterListener((&TaskCreatedEvent{}).TopicName(), &IncreaseTaskCounter{}) + events.RegisterListener((&TaskDeletedEvent{}).TopicName(), &DecreaseTaskCounter{}) } -type SendTaskCreatedNotification struct { +////// +// Task Events + +// IncreaseTaskCounter represents a listener +type IncreaseTaskCounter struct { } -func (s *SendTaskCreatedNotification) Name() string { - return "task.created.notification" +// Name defines the name for the IncreaseTaskCounter listener +func (s *IncreaseTaskCounter) Name() string { + return "increase.task.counter" } -func (s *SendTaskCreatedNotification) Handle(payload message.Payload) (err error) { - event := &TaskCreatedEvent{} - err = json.Unmarshal(payload, event) - if err != nil { - return err - } +// Hanlde is executed when the event IncreaseTaskCounter listens on is fired +func (s *IncreaseTaskCounter) Handle(payload message.Payload) (err error) { + metrics.UpdateCount(1, metrics.TaskCountKey) + return nil +} +// DecreaseTaskCounter represents a listener +type DecreaseTaskCounter struct { +} + +// Name defines the name for the DecreaseTaskCounter listener +func (s *DecreaseTaskCounter) Name() string { + return "decrease.task.counter" +} + +// Hanlde is executed when the event DecreaseTaskCounter listens on is fired +func (s *DecreaseTaskCounter) Handle(payload message.Payload) (err error) { + metrics.UpdateCount(-1, metrics.TaskCountKey) return nil } diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index c5cc94bc7..f56793d3c 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -26,7 +26,6 @@ import ( "code.vikunja.io/api/pkg/db" "code.vikunja.io/api/pkg/config" - "code.vikunja.io/api/pkg/metrics" "code.vikunja.io/api/pkg/user" "code.vikunja.io/api/pkg/utils" "code.vikunja.io/web" @@ -825,8 +824,6 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err return err } - metrics.UpdateCount(1, metrics.TaskCountKey) - t.setIdentifier(l) err = events.Publish(&TaskCreatedEvent{ @@ -1198,7 +1195,17 @@ func (t *Task) Delete(s *xorm.Session, a web.Auth) (err error) { return err } - metrics.UpdateCount(-1, metrics.TaskCountKey) + doer, err := user.GetFromAuth(a) + if err != nil { + return err + } + err = events.Publish(&TaskDeletedEvent{ + Task: t, + Doer: doer, + }) + if err != nil { + return + } err = updateListLastUpdated(s, &List{ID: t.ListID}) return -- 2.40.1 From c3de561c297a240b2b536028926c3ff7ec2df32a Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 1 Feb 2021 21:33:22 +0100 Subject: [PATCH 27/45] Increase and decrease the team metrics counter with events --- pkg/models/events.go | 22 ++++++++++++++++++++++ pkg/models/listeners.go | 35 +++++++++++++++++++++++++++++++++++ pkg/models/teams.go | 18 +++++++++++++----- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/pkg/models/events.go b/pkg/models/events.go index 1cd8e341c..a17c6b98f 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -194,3 +194,25 @@ type TeamMemberAddedEvent struct { func (t *TeamMemberAddedEvent) TopicName() string { return "team.member.added" } + +// TeamCreatedEvent represents a TeamCreatedEvent event +type TeamCreatedEvent struct { + Team *Team + Doer *user.User +} + +// TopicName defines the name for TeamCreatedEvent +func (t *TeamCreatedEvent) TopicName() string { + return "team.created" +} + +// TeamDeletedEvent represents a TeamDeletedEvent event +type TeamDeletedEvent struct { + Team *Team + Doer *user.User +} + +// TopicName defines the name for TeamDeletedEvent +func (t *TeamDeletedEvent) TopicName() string { + return "team.deleted" +} diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index 02ffab457..0874f869b 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -29,6 +29,8 @@ func RegisterListeners() { events.RegisterListener((&NamespaceDeletedEvent{}).TopicName(), &DecreaseNamespaceCounter{}) events.RegisterListener((&TaskCreatedEvent{}).TopicName(), &IncreaseTaskCounter{}) events.RegisterListener((&TaskDeletedEvent{}).TopicName(), &DecreaseTaskCounter{}) + events.RegisterListener((&TeamDeletedEvent{}).TopicName(), &DecreaseTeamCounter{}) + events.RegisterListener((&TeamCreatedEvent{}).TopicName(), &IncreaseTeamCounter{}) } ////// @@ -123,3 +125,36 @@ func (s *DecreaseNamespaceCounter) Handle(payload message.Payload) (err error) { metrics.UpdateCount(-1, metrics.NamespaceCountKey) return nil } + +/////// +// Team Events + +// IncreaseTeamCounter represents a listener +type IncreaseTeamCounter struct { +} + +// Name defines the name for the IncreaseTeamCounter listener +func (s *IncreaseTeamCounter) Name() string { + return "team.counter.increase" +} + +// Hanlde is executed when the event IncreaseTeamCounter listens on is fired +func (s *IncreaseTeamCounter) Handle(payload message.Payload) (err error) { + metrics.UpdateCount(1, metrics.TeamCountKey) + return nil +} + +// DecreaseTeamCounter represents a listener +type DecreaseTeamCounter struct { +} + +// Name defines the name for the DecreaseTeamCounter listener +func (s *DecreaseTeamCounter) Name() string { + return "team.counter.decrease" +} + +// Hanlde is executed when the event DecreaseTeamCounter listens on is fired +func (s *DecreaseTeamCounter) Handle(payload message.Payload) (err error) { + metrics.UpdateCount(-1, metrics.TeamCountKey) + return nil +} diff --git a/pkg/models/teams.go b/pkg/models/teams.go index 39a877177..49798ac7d 100644 --- a/pkg/models/teams.go +++ b/pkg/models/teams.go @@ -17,11 +17,11 @@ package models import ( + "code.vikunja.io/api/pkg/events" "time" "xorm.io/xorm" - "code.vikunja.io/api/pkg/metrics" "code.vikunja.io/api/pkg/user" "code.vikunja.io/web" "xorm.io/builder" @@ -270,8 +270,10 @@ func (t *Team) Create(s *xorm.Session, a web.Auth) (err error) { return err } - metrics.UpdateCount(1, metrics.TeamCountKey) - return + return events.Publish(&TeamCreatedEvent{ + Team: t, + Doer: doer, + }) } // Delete deletes a team @@ -311,8 +313,14 @@ func (t *Team) Delete(s *xorm.Session, a web.Auth) (err error) { return } - metrics.UpdateCount(-1, metrics.TeamCountKey) - return + doer, err := user.GetFromAuth(a) + if err != nil { + return err + } + return events.Publish(&TeamDeletedEvent{ + Team: t, + Doer: doer, + }) } // Update is the handler to create a team -- 2.40.1 From 4b2007d3d91dac67f40c20a808ae5801a94ecaba Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 1 Feb 2021 21:40:07 +0100 Subject: [PATCH 28/45] Increase the user metrics counter with events --- pkg/initialize/init.go | 1 + pkg/user/events.go | 27 +++++++++++++++++++++++++ pkg/user/listeners.go | 45 +++++++++++++++++++++++++++++++++++++++++ pkg/user/user_create.go | 12 +++++++---- 4 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 pkg/user/events.go create mode 100644 pkg/user/listeners.go diff --git a/pkg/initialize/init.go b/pkg/initialize/init.go index be09a614d..7a6141135 100644 --- a/pkg/initialize/init.go +++ b/pkg/initialize/init.go @@ -90,6 +90,7 @@ func FullInit() { // Start processing events go func() { models.RegisterListeners() + user.RegisterListeners() err := events.InitEvents() if err != nil { log.Fatal(err.Error()) diff --git a/pkg/user/events.go b/pkg/user/events.go new file mode 100644 index 000000000..cc9401086 --- /dev/null +++ b/pkg/user/events.go @@ -0,0 +1,27 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-2021 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public Licensee as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public Licensee for more details. +// +// You should have received a copy of the GNU Affero General Public Licensee +// along with this program. If not, see . + +package user + +// UserCreatedEvent represents a UserCreatedEvent event +type UserCreatedEvent struct { + User *User +} + +// TopicName defines the name for UserCreatedEvent +func (t *UserCreatedEvent) TopicName() string { + return "user.created" +} diff --git a/pkg/user/listeners.go b/pkg/user/listeners.go new file mode 100644 index 000000000..479211982 --- /dev/null +++ b/pkg/user/listeners.go @@ -0,0 +1,45 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-2021 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public Licensee as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public Licensee for more details. +// +// You should have received a copy of the GNU Affero General Public Licensee +// along with this program. If not, see . + +package user + +import ( + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/metrics" + "github.com/ThreeDotsLabs/watermill/message" +) + +func RegisterListeners() { + events.RegisterListener((&UserCreatedEvent{}).TopicName(), &IncreaseUserCounter{}) +} + +/////// +// User Events + +// IncreaseUserCounter represents a listener +type IncreaseUserCounter struct { +} + +// Name defines the name for the IncreaseUserCounter listener +func (s *IncreaseUserCounter) Name() string { + return "increase.user.counter" +} + +// Hanlde is executed when the event IncreaseUserCounter listens on is fired +func (s *IncreaseUserCounter) Handle(payload message.Payload) (err error) { + metrics.UpdateCount(1, metrics.UserCountKey) + return nil +} diff --git a/pkg/user/user_create.go b/pkg/user/user_create.go index a7f4d9c0f..d74bccfed 100644 --- a/pkg/user/user_create.go +++ b/pkg/user/user_create.go @@ -18,8 +18,8 @@ package user import ( "code.vikunja.io/api/pkg/config" + "code.vikunja.io/api/pkg/events" "code.vikunja.io/api/pkg/mail" - "code.vikunja.io/api/pkg/metrics" "code.vikunja.io/api/pkg/utils" "golang.org/x/crypto/bcrypt" "xorm.io/xorm" @@ -70,15 +70,19 @@ func CreateUser(s *xorm.Session, user *User) (newUser *User, err error) { return nil, err } - // Update the metrics - metrics.UpdateCount(1, metrics.ActiveUsersKey) - // Get the full new User newUserOut, err := GetUserByID(s, user.ID) if err != nil { return nil, err } + err = events.Publish(&UserCreatedEvent{ + User: newUserOut, + }) + if err != nil { + return nil, err + } + sendConfirmEmail(user) return newUserOut, err -- 2.40.1 From 694dab9295cca449776faf31ebc086a09fbb67df Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 1 Feb 2021 21:43:32 +0100 Subject: [PATCH 29/45] Cleanup --- pkg/metrics/metrics.go | 20 -------------------- pkg/models/listeners.go | 25 +++++++++---------------- pkg/user/listeners.go | 4 ++-- 3 files changed, 11 insertions(+), 38 deletions(-) diff --git a/pkg/metrics/metrics.go b/pkg/metrics/metrics.go index 69899d890..c4cb51973 100644 --- a/pkg/metrics/metrics.go +++ b/pkg/metrics/metrics.go @@ -17,7 +17,6 @@ package metrics import ( - "code.vikunja.io/api/pkg/config" "code.vikunja.io/api/pkg/log" "code.vikunja.io/api/pkg/modules/keyvalue" "github.com/prometheus/client_golang/prometheus" @@ -142,22 +141,3 @@ func GetCount(key string) (count int64, err error) { func SetCount(count int64, key string) error { return keyvalue.Put(key, count) } - -// UpdateCount updates a count with a given amount -func UpdateCount(update int64, key string) { - if !config.ServiceEnableMetrics.GetBool() { - return - } - if update > 0 { - err := keyvalue.IncrBy(key, update) - if err != nil { - log.Error(err.Error()) - } - } - if update < 0 { - err := keyvalue.DecrBy(key, update*-1) - if err != nil { - log.Error(err.Error()) - } - } -} diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index 0874f869b..665894125 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -19,6 +19,7 @@ package models import ( "code.vikunja.io/api/pkg/events" "code.vikunja.io/api/pkg/metrics" + "code.vikunja.io/api/pkg/modules/keyvalue" "github.com/ThreeDotsLabs/watermill/message" ) @@ -47,8 +48,7 @@ func (s *IncreaseTaskCounter) Name() string { // Hanlde is executed when the event IncreaseTaskCounter listens on is fired func (s *IncreaseTaskCounter) Handle(payload message.Payload) (err error) { - metrics.UpdateCount(1, metrics.TaskCountKey) - return nil + return keyvalue.IncrBy(metrics.TaskCountKey, 1) } // DecreaseTaskCounter represents a listener @@ -62,8 +62,7 @@ func (s *DecreaseTaskCounter) Name() string { // Hanlde is executed when the event DecreaseTaskCounter listens on is fired func (s *DecreaseTaskCounter) Handle(payload message.Payload) (err error) { - metrics.UpdateCount(-1, metrics.TaskCountKey) - return nil + return keyvalue.DecrBy(metrics.TaskCountKey, 1) } /////// @@ -77,8 +76,7 @@ func (s *IncreaseListCounter) Name() string { } func (s *IncreaseListCounter) Handle(payload message.Payload) (err error) { - metrics.UpdateCount(1, metrics.ListCountKey) - return nil + return keyvalue.IncrBy(metrics.ListCountKey, 1) } type DecreaseListCounter struct { @@ -89,8 +87,7 @@ func (s *DecreaseListCounter) Name() string { } func (s *DecreaseListCounter) Handle(payload message.Payload) (err error) { - metrics.UpdateCount(-1, metrics.ListCountKey) - return nil + return keyvalue.DecrBy(metrics.ListCountKey, 1) } ////// @@ -107,8 +104,7 @@ func (s *IncreaseNamespaceCounter) Name() string { // Hanlde is executed when the event IncreaseNamespaceCounter listens on is fired func (s *IncreaseNamespaceCounter) Handle(payload message.Payload) (err error) { - metrics.UpdateCount(1, metrics.NamespaceCountKey) - return nil + return keyvalue.IncrBy(metrics.NamespaceCountKey, 1) } // DecreaseNamespaceCounter represents a listener @@ -122,8 +118,7 @@ func (s *DecreaseNamespaceCounter) Name() string { // Hanlde is executed when the event DecreaseNamespaceCounter listens on is fired func (s *DecreaseNamespaceCounter) Handle(payload message.Payload) (err error) { - metrics.UpdateCount(-1, metrics.NamespaceCountKey) - return nil + return keyvalue.DecrBy(metrics.NamespaceCountKey, 1) } /////// @@ -140,8 +135,7 @@ func (s *IncreaseTeamCounter) Name() string { // Hanlde is executed when the event IncreaseTeamCounter listens on is fired func (s *IncreaseTeamCounter) Handle(payload message.Payload) (err error) { - metrics.UpdateCount(1, metrics.TeamCountKey) - return nil + return keyvalue.IncrBy(metrics.TeamCountKey, 1) } // DecreaseTeamCounter represents a listener @@ -155,6 +149,5 @@ func (s *DecreaseTeamCounter) Name() string { // Hanlde is executed when the event DecreaseTeamCounter listens on is fired func (s *DecreaseTeamCounter) Handle(payload message.Payload) (err error) { - metrics.UpdateCount(-1, metrics.TeamCountKey) - return nil + return keyvalue.DecrBy(metrics.TeamCountKey, 1) } diff --git a/pkg/user/listeners.go b/pkg/user/listeners.go index 479211982..36592385e 100644 --- a/pkg/user/listeners.go +++ b/pkg/user/listeners.go @@ -19,6 +19,7 @@ package user import ( "code.vikunja.io/api/pkg/events" "code.vikunja.io/api/pkg/metrics" + "code.vikunja.io/api/pkg/modules/keyvalue" "github.com/ThreeDotsLabs/watermill/message" ) @@ -40,6 +41,5 @@ func (s *IncreaseUserCounter) Name() string { // Hanlde is executed when the event IncreaseUserCounter listens on is fired func (s *IncreaseUserCounter) Handle(payload message.Payload) (err error) { - metrics.UpdateCount(1, metrics.UserCountKey) - return nil + return keyvalue.IncrBy(metrics.UserCountKey, 1) } -- 2.40.1 From bd104298ad772c0189f147fc30d40647ea4bbfcc Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 1 Feb 2021 21:48:47 +0100 Subject: [PATCH 30/45] Add booted event after full init has been run --- pkg/initialize/events.go | 29 +++++++++++++++++++++++++++++ pkg/initialize/init.go | 8 ++++++++ 2 files changed, 37 insertions(+) create mode 100644 pkg/initialize/events.go diff --git a/pkg/initialize/events.go b/pkg/initialize/events.go new file mode 100644 index 000000000..305287aa9 --- /dev/null +++ b/pkg/initialize/events.go @@ -0,0 +1,29 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-2021 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public Licensee as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public Licensee for more details. +// +// You should have received a copy of the GNU Affero General Public Licensee +// along with this program. If not, see . + +package initialize + +import "time" + +// BootedEvent represents a BootedEvent event +type BootedEvent struct { + BootedAt time.Time +} + +// TopicName defines the name for BootedEvent +func (t *BootedEvent) TopicName() string { + return "booted" +} diff --git a/pkg/initialize/init.go b/pkg/initialize/init.go index 7a6141135..f805d182d 100644 --- a/pkg/initialize/init.go +++ b/pkg/initialize/init.go @@ -29,6 +29,7 @@ import ( migrator "code.vikunja.io/api/pkg/modules/migration" "code.vikunja.io/api/pkg/red" "code.vikunja.io/api/pkg/user" + "time" ) // LightInit will only fullInit config, redis, logger but no db connection. @@ -95,5 +96,12 @@ func FullInit() { if err != nil { log.Fatal(err.Error()) } + + err = events.Publish(&BootedEvent{ + BootedAt: time.Now(), + }) + if err != nil { + log.Fatal(err) + } }() } -- 2.40.1 From 037295cd1a4094b577a2e026893f5d283dc6f3bb Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 1 Feb 2021 22:17:46 +0100 Subject: [PATCH 31/45] Fix tests --- pkg/models/bulk_task_test.go | 2 +- pkg/models/kanban_test.go | 8 +++++--- pkg/models/label_task_test.go | 2 +- pkg/models/label_test.go | 6 +++--- pkg/models/list_team_test.go | 10 ++++++---- pkg/models/list_test.go | 6 +++--- pkg/models/list_users_test.go | 4 ++-- pkg/models/main_test.go | 3 +++ pkg/models/namespace_team_test.go | 8 ++++---- pkg/models/namespace_test.go | 22 ++++++++++++++-------- pkg/models/namespace_users_test.go | 4 ++-- pkg/models/saved_filters_test.go | 6 +++--- pkg/models/task_attachment_test.go | 16 ++++++++++------ pkg/models/task_comments_test.go | 18 ++++++++++++------ pkg/models/task_relation_test.go | 6 ++++-- pkg/models/tasks_test.go | 18 +++++++++++------- pkg/models/team_members_test.go | 8 +++++--- pkg/models/teams_test.go | 20 +++++++++++++------- pkg/modules/auth/openid/main_test.go | 2 ++ 19 files changed, 104 insertions(+), 65 deletions(-) diff --git a/pkg/models/bulk_task_test.go b/pkg/models/bulk_task_test.go index 4f64a354b..5840f4eb9 100644 --- a/pkg/models/bulk_task_test.go +++ b/pkg/models/bulk_task_test.go @@ -84,7 +84,7 @@ func TestBulkTask_Update(t *testing.T) { if !allowed != tt.wantForbidden { t.Errorf("BulkTask.Update() want forbidden, got %v, want %v", allowed, tt.wantForbidden) } - if err := bt.Update(s); (err != nil) != tt.wantErr { + if err := bt.Update(s, tt.fields.User); (err != nil) != tt.wantErr { t.Errorf("BulkTask.Update() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/pkg/models/kanban_test.go b/pkg/models/kanban_test.go index 7bd1eceef..d9ad87b07 100644 --- a/pkg/models/kanban_test.go +++ b/pkg/models/kanban_test.go @@ -92,6 +92,8 @@ func TestBucket_ReadAll(t *testing.T) { } func TestBucket_Delete(t *testing.T) { + user := &user.User{ID: 1} + t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() @@ -101,7 +103,7 @@ func TestBucket_Delete(t *testing.T) { ID: 2, // The second bucket only has 3 tasks ListID: 1, } - err := b.Delete(s) + err := b.Delete(s, user) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -125,7 +127,7 @@ func TestBucket_Delete(t *testing.T) { ID: 34, ListID: 18, } - err := b.Delete(s) + err := b.Delete(s, user) assert.Error(t, err) assert.True(t, IsErrCannotRemoveLastBucket(err)) err = s.Commit() @@ -141,7 +143,7 @@ func TestBucket_Delete(t *testing.T) { func TestBucket_Update(t *testing.T) { testAndAssertBucketUpdate := func(t *testing.T, b *Bucket, s *xorm.Session) { - err := b.Update(s) + err := b.Update(s, &user.User{ID: 1}) assert.NoError(t, err) err = s.Commit() diff --git a/pkg/models/label_task_test.go b/pkg/models/label_task_test.go index 68fdb6570..890ac634f 100644 --- a/pkg/models/label_task_test.go +++ b/pkg/models/label_task_test.go @@ -318,7 +318,7 @@ func TestLabelTask_Delete(t *testing.T) { if !allowed && !tt.wantForbidden { t.Errorf("LabelTask.CanDelete() forbidden, want %v", tt.wantForbidden) } - err := l.Delete(s) + err := l.Delete(s, tt.auth) if (err != nil) != tt.wantErr { t.Errorf("LabelTask.Delete() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/pkg/models/label_test.go b/pkg/models/label_test.go index cac2d0729..db0eadbdc 100644 --- a/pkg/models/label_test.go +++ b/pkg/models/label_test.go @@ -257,7 +257,7 @@ func TestLabel_ReadOne(t *testing.T) { if !allowed && !tt.wantForbidden { t.Errorf("Label.CanRead() forbidden, want %v", tt.wantForbidden) } - err := l.ReadOne(s) + err := l.ReadOne(s, tt.auth) if (err != nil) != tt.wantErr { t.Errorf("Label.ReadOne() error = %v, wantErr %v", err, tt.wantErr) } @@ -419,7 +419,7 @@ func TestLabel_Update(t *testing.T) { if !allowed && !tt.wantForbidden { t.Errorf("Label.CanUpdate() forbidden, want %v", tt.wantForbidden) } - if err := l.Update(s); (err != nil) != tt.wantErr { + if err := l.Update(s, tt.auth); (err != nil) != tt.wantErr { t.Errorf("Label.Update() error = %v, wantErr %v", err, tt.wantErr) } if !tt.wantErr && !tt.wantForbidden { @@ -505,7 +505,7 @@ func TestLabel_Delete(t *testing.T) { if !allowed && !tt.wantForbidden { t.Errorf("Label.CanDelete() forbidden, want %v", tt.wantForbidden) } - if err := l.Delete(s); (err != nil) != tt.wantErr { + if err := l.Delete(s, tt.auth); (err != nil) != tt.wantErr { t.Errorf("Label.Delete() error = %v, wantErr %v", err, tt.wantErr) } if !tt.wantErr && !tt.wantForbidden { diff --git a/pkg/models/list_team_test.go b/pkg/models/list_team_test.go index 5eb62cedc..472513076 100644 --- a/pkg/models/list_team_test.go +++ b/pkg/models/list_team_test.go @@ -158,6 +158,8 @@ func TestTeamList_Create(t *testing.T) { } func TestTeamList_Delete(t *testing.T) { + user := &user.User{ID: 1} + t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() @@ -165,7 +167,7 @@ func TestTeamList_Delete(t *testing.T) { TeamID: 1, ListID: 3, } - err := tl.Delete(s) + err := tl.Delete(s, user) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -181,7 +183,7 @@ func TestTeamList_Delete(t *testing.T) { TeamID: 9999, ListID: 1, } - err := tl.Delete(s) + err := tl.Delete(s, user) assert.Error(t, err) assert.True(t, IsErrTeamDoesNotExist(err)) _ = s.Close() @@ -193,7 +195,7 @@ func TestTeamList_Delete(t *testing.T) { TeamID: 1, ListID: 9999, } - err := tl.Delete(s) + err := tl.Delete(s, user) assert.Error(t, err) assert.True(t, IsErrTeamDoesNotHaveAccessToList(err)) _ = s.Close() @@ -267,7 +269,7 @@ func TestTeamList_Update(t *testing.T) { CRUDable: tt.fields.CRUDable, Rights: tt.fields.Rights, } - err := tl.Update(s) + err := tl.Update(s, &user.User{ID: 1}) if (err != nil) != tt.wantErr { t.Errorf("TeamList.Update() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/pkg/models/list_test.go b/pkg/models/list_test.go index e30b3b588..7b399c41f 100644 --- a/pkg/models/list_test.go +++ b/pkg/models/list_test.go @@ -125,7 +125,7 @@ func TestList_CreateOrUpdate(t *testing.T) { NamespaceID: 1, } list.Description = "Lorem Ipsum dolor sit amet." - err := list.Update(s) + err := list.Update(s, usr) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -143,7 +143,7 @@ func TestList_CreateOrUpdate(t *testing.T) { ID: 99999999, Title: "test", } - err := list.Update(s) + err := list.Update(s, usr) assert.Error(t, err) assert.True(t, IsErrListDoesNotExist(err)) _ = s.Close() @@ -172,7 +172,7 @@ func TestList_Delete(t *testing.T) { list := List{ ID: 1, } - err := list.Delete(s) + err := list.Delete(s, &user.User{ID: 1}) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) diff --git a/pkg/models/list_users_test.go b/pkg/models/list_users_test.go index 106d4e21e..4fea4d142 100644 --- a/pkg/models/list_users_test.go +++ b/pkg/models/list_users_test.go @@ -311,7 +311,7 @@ func TestListUser_Update(t *testing.T) { CRUDable: tt.fields.CRUDable, Rights: tt.fields.Rights, } - err := lu.Update(s) + err := lu.Update(s, &user.User{ID: 1}) if (err != nil) != tt.wantErr { t.Errorf("ListUser.Update() error = %v, wantErr %v", err, tt.wantErr) } @@ -393,7 +393,7 @@ func TestListUser_Delete(t *testing.T) { CRUDable: tt.fields.CRUDable, Rights: tt.fields.Rights, } - err := lu.Delete(s) + err := lu.Delete(s, &user.User{ID: 1}) if (err != nil) != tt.wantErr { t.Errorf("ListUser.Delete() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/pkg/models/main_test.go b/pkg/models/main_test.go index ed1b3a7f4..9dcf28cff 100644 --- a/pkg/models/main_test.go +++ b/pkg/models/main_test.go @@ -17,6 +17,7 @@ package models import ( + "code.vikunja.io/api/pkg/events" "fmt" "os" "testing" @@ -64,5 +65,7 @@ func TestMain(m *testing.M) { SetupTests() + events.Fake() + os.Exit(m.Run()) } diff --git a/pkg/models/namespace_team_test.go b/pkg/models/namespace_team_test.go index c47fef8ca..718450de3 100644 --- a/pkg/models/namespace_team_test.go +++ b/pkg/models/namespace_team_test.go @@ -157,7 +157,7 @@ func TestTeamNamespace_Delete(t *testing.T) { s := db.NewSession() allowed, _ := tn.CanDelete(s, u) assert.True(t, allowed) - err := tn.Delete(s) + err := tn.Delete(s, u) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -174,7 +174,7 @@ func TestTeamNamespace_Delete(t *testing.T) { } db.LoadAndAssertFixtures(t) s := db.NewSession() - err := tn.Delete(s) + err := tn.Delete(s, u) assert.Error(t, err) assert.True(t, IsErrTeamDoesNotExist(err)) _ = s.Close() @@ -186,7 +186,7 @@ func TestTeamNamespace_Delete(t *testing.T) { } db.LoadAndAssertFixtures(t) s := db.NewSession() - err := tn.Delete(s) + err := tn.Delete(s, u) assert.Error(t, err) assert.True(t, IsErrTeamDoesNotHaveAccessToNamespace(err)) _ = s.Close() @@ -260,7 +260,7 @@ func TestTeamNamespace_Update(t *testing.T) { CRUDable: tt.fields.CRUDable, Rights: tt.fields.Rights, } - err := tl.Update(s) + err := tl.Update(s, &user.User{ID: 1}) if (err != nil) != tt.wantErr { t.Errorf("TeamNamespace.Update() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/pkg/models/namespace_test.go b/pkg/models/namespace_test.go index 57a19ca1a..a1a135a94 100644 --- a/pkg/models/namespace_test.go +++ b/pkg/models/namespace_test.go @@ -69,11 +69,13 @@ func TestNamespace_Create(t *testing.T) { } func TestNamespace_ReadOne(t *testing.T) { + u := &user.User{ID: 1} + t.Run("normal", func(t *testing.T) { n := &Namespace{ID: 1} db.LoadAndAssertFixtures(t) s := db.NewSession() - err := n.ReadOne(s) + err := n.ReadOne(s, u) assert.NoError(t, err) assert.Equal(t, n.Title, "testnamespace") _ = s.Close() @@ -82,7 +84,7 @@ func TestNamespace_ReadOne(t *testing.T) { n := &Namespace{ID: 99999} db.LoadAndAssertFixtures(t) s := db.NewSession() - err := n.ReadOne(s) + err := n.ReadOne(s, u) assert.Error(t, err) assert.True(t, IsErrNamespaceDoesNotExist(err)) _ = s.Close() @@ -90,6 +92,8 @@ func TestNamespace_ReadOne(t *testing.T) { } func TestNamespace_Update(t *testing.T) { + u := &user.User{ID: 1} + t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() @@ -97,7 +101,7 @@ func TestNamespace_Update(t *testing.T) { ID: 1, Title: "Lorem Ipsum", } - err := n.Update(s) + err := n.Update(s, u) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -114,7 +118,7 @@ func TestNamespace_Update(t *testing.T) { ID: 99999, Title: "Lorem Ipsum", } - err := n.Update(s) + err := n.Update(s, u) assert.Error(t, err) assert.True(t, IsErrNamespaceDoesNotExist(err)) _ = s.Close() @@ -127,7 +131,7 @@ func TestNamespace_Update(t *testing.T) { Title: "Lorem Ipsum", Owner: &user.User{ID: 99999}, } - err := n.Update(s) + err := n.Update(s, u) assert.Error(t, err) assert.True(t, user.IsErrUserDoesNotExist(err)) _ = s.Close() @@ -138,7 +142,7 @@ func TestNamespace_Update(t *testing.T) { n := &Namespace{ ID: 1, } - err := n.Update(s) + err := n.Update(s, u) assert.Error(t, err) assert.True(t, IsErrNamespaceNameCannotBeEmpty(err)) _ = s.Close() @@ -146,13 +150,15 @@ func TestNamespace_Update(t *testing.T) { } func TestNamespace_Delete(t *testing.T) { + u := &user.User{ID: 1} + t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() n := &Namespace{ ID: 1, } - err := n.Delete(s) + err := n.Delete(s, u) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -167,7 +173,7 @@ func TestNamespace_Delete(t *testing.T) { n := &Namespace{ ID: 9999, } - err := n.Delete(s) + err := n.Delete(s, u) assert.Error(t, err) assert.True(t, IsErrNamespaceDoesNotExist(err)) _ = s.Close() diff --git a/pkg/models/namespace_users_test.go b/pkg/models/namespace_users_test.go index b85b6aa76..f31a2e61e 100644 --- a/pkg/models/namespace_users_test.go +++ b/pkg/models/namespace_users_test.go @@ -315,7 +315,7 @@ func TestNamespaceUser_Update(t *testing.T) { CRUDable: tt.fields.CRUDable, Rights: tt.fields.Rights, } - err := nu.Update(s) + err := nu.Update(s, &user.User{ID: 1}) if (err != nil) != tt.wantErr { t.Errorf("NamespaceUser.Update() error = %v, wantErr %v", err, tt.wantErr) } @@ -396,7 +396,7 @@ func TestNamespaceUser_Delete(t *testing.T) { CRUDable: tt.fields.CRUDable, Rights: tt.fields.Rights, } - err := nu.Delete(s) + err := nu.Delete(s, &user.User{ID: 1}) if (err != nil) != tt.wantErr { t.Errorf("NamespaceUser.Delete() error = %v, wantErr %v", err, tt.wantErr) } diff --git a/pkg/models/saved_filters_test.go b/pkg/models/saved_filters_test.go index cfe67575e..238858fd3 100644 --- a/pkg/models/saved_filters_test.go +++ b/pkg/models/saved_filters_test.go @@ -86,7 +86,7 @@ func TestSavedFilter_ReadOne(t *testing.T) { // canRead pre-populates the struct _, _, err := sf.CanRead(s, user1) assert.NoError(t, err) - err = sf.ReadOne(s) + err = sf.ReadOne(s, user1) assert.NoError(t, err) assert.NotNil(t, sf.Owner) } @@ -102,7 +102,7 @@ func TestSavedFilter_Update(t *testing.T) { Description: "", // Explicitly reset the description Filters: &TaskCollection{}, } - err := sf.Update(s) + err := sf.Update(s, &user.User{ID: 1}) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -121,7 +121,7 @@ func TestSavedFilter_Delete(t *testing.T) { sf := &SavedFilter{ ID: 1, } - err := sf.Delete(s) + err := sf.Delete(s, &user.User{ID: 1}) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) diff --git a/pkg/models/task_attachment_test.go b/pkg/models/task_attachment_test.go index 691ab7a9d..3e73befa9 100644 --- a/pkg/models/task_attachment_test.go +++ b/pkg/models/task_attachment_test.go @@ -30,6 +30,8 @@ import ( ) func TestTaskAttachment_ReadOne(t *testing.T) { + u := &user.User{ID: 1} + t.Run("Normal File", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() @@ -39,7 +41,7 @@ func TestTaskAttachment_ReadOne(t *testing.T) { ta := &TaskAttachment{ ID: 1, } - err := ta.ReadOne(s) + err := ta.ReadOne(s, u) assert.NoError(t, err) assert.NotNil(t, ta.File) assert.True(t, ta.File.ID == ta.FileID && ta.FileID != 0) @@ -63,7 +65,7 @@ func TestTaskAttachment_ReadOne(t *testing.T) { ta := &TaskAttachment{ ID: 9999, } - err := ta.ReadOne(s) + err := ta.ReadOne(s, u) assert.Error(t, err) assert.True(t, IsErrTaskAttachmentDoesNotExist(err)) }) @@ -76,7 +78,7 @@ func TestTaskAttachment_ReadOne(t *testing.T) { ta := &TaskAttachment{ ID: 2, } - err := ta.ReadOne(s) + err := ta.ReadOne(s, u) assert.Error(t, err) assert.EqualError(t, err, "file 9999 does not exist") }) @@ -153,10 +155,12 @@ func TestTaskAttachment_Delete(t *testing.T) { s := db.NewSession() defer s.Close() + u := &user.User{ID: 1} + files.InitTestFileFixtures(t) t.Run("Normal", func(t *testing.T) { ta := &TaskAttachment{ID: 1} - err := ta.Delete(s) + err := ta.Delete(s, u) assert.NoError(t, err) // Check if the file itself was deleted _, err = files.FileStat("/1") // The new file has the id 2 since it's the second attachment @@ -165,14 +169,14 @@ func TestTaskAttachment_Delete(t *testing.T) { t.Run("Nonexisting", func(t *testing.T) { files.InitTestFileFixtures(t) ta := &TaskAttachment{ID: 9999} - err := ta.Delete(s) + err := ta.Delete(s, u) assert.Error(t, err) assert.True(t, IsErrTaskAttachmentDoesNotExist(err)) }) t.Run("Existing attachment, nonexisting file", func(t *testing.T) { files.InitTestFileFixtures(t) ta := &TaskAttachment{ID: 2} - err := ta.Delete(s) + err := ta.Delete(s, u) assert.NoError(t, err) }) } diff --git a/pkg/models/task_comments_test.go b/pkg/models/task_comments_test.go index 53886e3c2..7af874eba 100644 --- a/pkg/models/task_comments_test.go +++ b/pkg/models/task_comments_test.go @@ -65,13 +65,15 @@ func TestTaskComment_Create(t *testing.T) { } func TestTaskComment_Delete(t *testing.T) { + u := &user.User{ID: 1} + t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() defer s.Close() tc := &TaskComment{ID: 1} - err := tc.Delete(s) + err := tc.Delete(s, u) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -86,13 +88,15 @@ func TestTaskComment_Delete(t *testing.T) { defer s.Close() tc := &TaskComment{ID: 9999} - err := tc.Delete(s) + err := tc.Delete(s, u) assert.Error(t, err) assert.True(t, IsErrTaskCommentDoesNotExist(err)) }) } func TestTaskComment_Update(t *testing.T) { + u := &user.User{ID: 1} + t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() @@ -102,7 +106,7 @@ func TestTaskComment_Update(t *testing.T) { ID: 1, Comment: "testing", } - err := tc.Update(s) + err := tc.Update(s, u) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -120,20 +124,22 @@ func TestTaskComment_Update(t *testing.T) { tc := &TaskComment{ ID: 9999, } - err := tc.Update(s) + err := tc.Update(s, u) assert.Error(t, err) assert.True(t, IsErrTaskCommentDoesNotExist(err)) }) } func TestTaskComment_ReadOne(t *testing.T) { + u := &user.User{ID: 1} + t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() defer s.Close() tc := &TaskComment{ID: 1} - err := tc.ReadOne(s) + err := tc.ReadOne(s, u) assert.NoError(t, err) assert.Equal(t, "Lorem Ipsum Dolor Sit Amet", tc.Comment) assert.NotEmpty(t, tc.Author.ID) @@ -144,7 +150,7 @@ func TestTaskComment_ReadOne(t *testing.T) { defer s.Close() tc := &TaskComment{ID: 9999} - err := tc.ReadOne(s) + err := tc.ReadOne(s, u) assert.Error(t, err) assert.True(t, IsErrTaskCommentDoesNotExist(err)) }) diff --git a/pkg/models/task_relation_test.go b/pkg/models/task_relation_test.go index 0749f20cd..91bf48051 100644 --- a/pkg/models/task_relation_test.go +++ b/pkg/models/task_relation_test.go @@ -97,6 +97,8 @@ func TestTaskRelation_Create(t *testing.T) { } func TestTaskRelation_Delete(t *testing.T) { + u := &user.User{ID: 1} + t.Run("Normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() @@ -107,7 +109,7 @@ func TestTaskRelation_Delete(t *testing.T) { OtherTaskID: 29, RelationKind: RelationKindSubtask, } - err := rel.Delete(s) + err := rel.Delete(s, u) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -127,7 +129,7 @@ func TestTaskRelation_Delete(t *testing.T) { OtherTaskID: 3, RelationKind: RelationKindSubtask, } - err := rel.Delete(s) + err := rel.Delete(s, u) assert.Error(t, err) assert.True(t, IsErrRelationDoesNotExist(err)) }) diff --git a/pkg/models/tasks_test.go b/pkg/models/tasks_test.go index 36a243934..f37817c8e 100644 --- a/pkg/models/tasks_test.go +++ b/pkg/models/tasks_test.go @@ -127,6 +127,8 @@ func TestTask_Create(t *testing.T) { } func TestTask_Update(t *testing.T) { + u := &user.User{ID: 1} + t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() @@ -138,7 +140,7 @@ func TestTask_Update(t *testing.T) { Description: "Lorem Ipsum Dolor", ListID: 1, } - err := task.Update(s) + err := task.Update(s, u) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -161,7 +163,7 @@ func TestTask_Update(t *testing.T) { Description: "Lorem Ipsum Dolor", ListID: 1, } - err := task.Update(s) + err := task.Update(s, u) assert.Error(t, err) assert.True(t, IsErrTaskDoesNotExist(err)) }) @@ -177,7 +179,7 @@ func TestTask_Update(t *testing.T) { ListID: 1, BucketID: 2, // Bucket 2 already has 3 tasks and a limit of 3 } - err := task.Update(s) + err := task.Update(s, u) assert.Error(t, err) assert.True(t, IsErrBucketLimitExceeded(err)) }) @@ -194,7 +196,7 @@ func TestTask_Update(t *testing.T) { ListID: 1, BucketID: 2, // Bucket 2 already has 3 tasks and a limit of 3 } - err := task.Update(s) + err := task.Update(s, u) assert.NoError(t, err) }) } @@ -208,7 +210,7 @@ func TestTask_Delete(t *testing.T) { task := &Task{ ID: 1, } - err := task.Delete(s) + err := task.Delete(s, &user.User{ID: 1}) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -440,13 +442,15 @@ func TestUpdateDone(t *testing.T) { } func TestTask_ReadOne(t *testing.T) { + u := &user.User{ID: 1} + t.Run("default", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() defer s.Close() task := &Task{ID: 1} - err := task.ReadOne(s) + err := task.ReadOne(s, u) assert.NoError(t, err) assert.Equal(t, "task #1", task.Title) }) @@ -456,7 +460,7 @@ func TestTask_ReadOne(t *testing.T) { defer s.Close() task := &Task{ID: 99999} - err := task.ReadOne(s) + err := task.ReadOne(s, u) assert.Error(t, err) assert.True(t, IsErrTaskDoesNotExist(err)) }) diff --git a/pkg/models/team_members_test.go b/pkg/models/team_members_test.go index cf8896b5a..56e67b819 100644 --- a/pkg/models/team_members_test.go +++ b/pkg/models/team_members_test.go @@ -101,7 +101,7 @@ func TestTeamMember_Delete(t *testing.T) { TeamID: 1, Username: "user1", } - err := tm.Delete(s) + err := tm.Delete(s, &user.User{ID: 1}) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -114,6 +114,8 @@ func TestTeamMember_Delete(t *testing.T) { } func TestTeamMember_Update(t *testing.T) { + u := &user.User{ID: 1} + t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() @@ -124,7 +126,7 @@ func TestTeamMember_Update(t *testing.T) { Username: "user1", Admin: true, } - err := tm.Update(s) + err := tm.Update(s, u) assert.NoError(t, err) assert.False(t, tm.Admin) // Since this endpoint toggles the right, we should get a false for admin back. err = s.Commit() @@ -148,7 +150,7 @@ func TestTeamMember_Update(t *testing.T) { Username: "user1", Admin: true, } - err := tm.Update(s) + err := tm.Update(s, u) assert.NoError(t, err) assert.False(t, tm.Admin) err = s.Commit() diff --git a/pkg/models/teams_test.go b/pkg/models/teams_test.go index c0d386a2b..fa3d2a4e2 100644 --- a/pkg/models/teams_test.go +++ b/pkg/models/teams_test.go @@ -62,13 +62,15 @@ func TestTeam_Create(t *testing.T) { } func TestTeam_ReadOne(t *testing.T) { + u := &user.User{ID: 1} + t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() defer s.Close() team := &Team{ID: 1} - err := team.ReadOne(s) + err := team.ReadOne(s, u) assert.NoError(t, err) assert.Equal(t, "testteam1", team.Name) assert.Equal(t, "Lorem Ipsum", team.Description) @@ -81,7 +83,7 @@ func TestTeam_ReadOne(t *testing.T) { defer s.Close() team := &Team{ID: -1} - err := team.ReadOne(s) + err := team.ReadOne(s, u) assert.Error(t, err) assert.True(t, IsErrTeamDoesNotExist(err)) }) @@ -91,7 +93,7 @@ func TestTeam_ReadOne(t *testing.T) { defer s.Close() team := &Team{ID: 99999} - err := team.ReadOne(s) + err := team.ReadOne(s, u) assert.Error(t, err) assert.True(t, IsErrTeamDoesNotExist(err)) }) @@ -113,6 +115,8 @@ func TestTeam_ReadAll(t *testing.T) { } func TestTeam_Update(t *testing.T) { + u := &user.User{ID: 1} + t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() @@ -122,7 +126,7 @@ func TestTeam_Update(t *testing.T) { ID: 1, Name: "SomethingNew", } - err := team.Update(s) + err := team.Update(s, u) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) @@ -140,7 +144,7 @@ func TestTeam_Update(t *testing.T) { ID: 1, Name: "", } - err := team.Update(s) + err := team.Update(s, u) assert.Error(t, err) assert.True(t, IsErrTeamNameCannotBeEmpty(err)) }) @@ -153,13 +157,15 @@ func TestTeam_Update(t *testing.T) { ID: 9999, Name: "SomethingNew", } - err := team.Update(s) + err := team.Update(s, u) assert.Error(t, err) assert.True(t, IsErrTeamDoesNotExist(err)) }) } func TestTeam_Delete(t *testing.T) { + u := &user.User{ID: 1} + t.Run("normal", func(t *testing.T) { db.LoadAndAssertFixtures(t) s := db.NewSession() @@ -168,7 +174,7 @@ func TestTeam_Delete(t *testing.T) { team := &Team{ ID: 1, } - err := team.Delete(s) + err := team.Delete(s, u) assert.NoError(t, err) err = s.Commit() assert.NoError(t, err) diff --git a/pkg/modules/auth/openid/main_test.go b/pkg/modules/auth/openid/main_test.go index 3ffb3a07f..41c04fa74 100644 --- a/pkg/modules/auth/openid/main_test.go +++ b/pkg/modules/auth/openid/main_test.go @@ -17,6 +17,7 @@ package openid import ( + "code.vikunja.io/api/pkg/events" "os" "testing" @@ -30,5 +31,6 @@ func TestMain(m *testing.M) { user.InitTests() files.InitTests() models.SetupTests() + events.Fake() os.Exit(m.Run()) } -- 2.40.1 From 627add5ee9ada4f2d7f90a696b1b60e83fe59cb6 Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 1 Feb 2021 22:18:00 +0100 Subject: [PATCH 32/45] Add test faker --- pkg/events/events.go | 4 ++++ pkg/events/testing.go | 26 ++++++++++++++++++++++++++ pkg/integrations/integrations.go | 2 ++ pkg/modules/migration/main_test.go | 2 ++ pkg/user/test.go | 3 +++ 5 files changed, 37 insertions(+) create mode 100644 pkg/events/testing.go diff --git a/pkg/events/events.go b/pkg/events/events.go index aebfbc837..7bac20188 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -79,6 +79,10 @@ func InitEvents() (err error) { } func Publish(event Event) error { + if isUnderTest { + return nil + } + content, err := json.Marshal(event) if err != nil { return err diff --git a/pkg/events/testing.go b/pkg/events/testing.go new file mode 100644 index 000000000..500a5cf87 --- /dev/null +++ b/pkg/events/testing.go @@ -0,0 +1,26 @@ +// Vikunja is a to-do list application to facilitate your life. +// Copyright 2018-2021 Vikunja and contributors. All rights reserved. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public Licensee as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public Licensee for more details. +// +// You should have received a copy of the GNU Affero General Public Licensee +// along with this program. If not, see . + +package events + +var isUnderTest bool + +// Fake sets up the "test mode" of the events package. Typically you'd call this function in the TestMain function +// in the package you're testing. It will prevent any events from being fired, instead they will be recorded and be +// available for assertions. +func Fake() { + isUnderTest = true +} diff --git a/pkg/integrations/integrations.go b/pkg/integrations/integrations.go index a24045011..33c081933 100644 --- a/pkg/integrations/integrations.go +++ b/pkg/integrations/integrations.go @@ -17,6 +17,7 @@ package integrations import ( + "code.vikunja.io/api/pkg/events" "net/http" "net/http/httptest" "net/url" @@ -85,6 +86,7 @@ func setupTestEnv() (e *echo.Echo, err error) { files.InitTests() user.InitTests() models.SetupTests() + events.Fake() err = db.LoadFixtures() if err != nil { diff --git a/pkg/modules/migration/main_test.go b/pkg/modules/migration/main_test.go index 4dee87927..7e09c32f5 100644 --- a/pkg/modules/migration/main_test.go +++ b/pkg/modules/migration/main_test.go @@ -17,6 +17,7 @@ package migration import ( + "code.vikunja.io/api/pkg/events" "os" "testing" @@ -37,5 +38,6 @@ func TestMain(m *testing.M) { files.InitTests() user.InitTests() models.SetupTests() + events.Fake() os.Exit(m.Run()) } diff --git a/pkg/user/test.go b/pkg/user/test.go index fd726b01e..45d339f01 100644 --- a/pkg/user/test.go +++ b/pkg/user/test.go @@ -18,6 +18,7 @@ package user import ( "code.vikunja.io/api/pkg/db" + "code.vikunja.io/api/pkg/events" "code.vikunja.io/api/pkg/log" ) @@ -37,4 +38,6 @@ func InitTests() { if err != nil { log.Fatal(err) } + + events.Fake() } -- 2.40.1 From 3280aace9df4c4f4f4b37eabf03e7a76e18b0e81 Mon Sep 17 00:00:00 2001 From: kolaente Date: Mon, 1 Feb 2021 22:24:20 +0100 Subject: [PATCH 33/45] Directly pass in auth objects when publishing events --- pkg/models/events.go | 37 ++++++++++++++++++----------------- pkg/models/list.go | 15 +++----------- pkg/models/list_team.go | 7 +------ pkg/models/list_users.go | 6 +----- pkg/models/namespace.go | 14 +++---------- pkg/models/namespace_team.go | 7 +------ pkg/models/namespace_users.go | 6 +----- pkg/models/task_assignees.go | 7 +------ pkg/models/task_comments.go | 6 +----- pkg/models/tasks.go | 14 +++---------- pkg/models/team_members.go | 6 +----- pkg/models/teams.go | 8 ++------ 12 files changed, 37 insertions(+), 96 deletions(-) diff --git a/pkg/models/events.go b/pkg/models/events.go index a17c6b98f..a7fb7ba96 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -18,6 +18,7 @@ package models import ( "code.vikunja.io/api/pkg/user" + "code.vikunja.io/web" ) ///////////////// @@ -26,7 +27,7 @@ import ( type TaskCreatedEvent struct { Task *Task - Doer *user.User + Doer web.Auth } func (t *TaskCreatedEvent) TopicName() string { @@ -35,7 +36,7 @@ func (t *TaskCreatedEvent) TopicName() string { type TaskUpdatedEvent struct { Task *Task - Doer *user.User + Doer web.Auth } func (t *TaskUpdatedEvent) TopicName() string { @@ -45,7 +46,7 @@ func (t *TaskUpdatedEvent) TopicName() string { // TaskDeletedEvent represents a TaskDeletedEvent event type TaskDeletedEvent struct { Task *Task - Doer *user.User + Doer web.Auth } // TopicName defines the name for TaskDeletedEvent @@ -56,7 +57,7 @@ func (t *TaskDeletedEvent) TopicName() string { type TaskAssigneeCreatedEvent struct { Task *Task Assignee *user.User - Doer *user.User + Doer web.Auth } func (t *TaskAssigneeCreatedEvent) TopicName() string { @@ -66,7 +67,7 @@ func (t *TaskAssigneeCreatedEvent) TopicName() string { type TaskCommentCreatedEvent struct { Task *Task Comment *TaskComment - Doer *user.User + Doer web.Auth } func (t *TaskCommentCreatedEvent) TopicName() string { @@ -79,7 +80,7 @@ func (t *TaskCommentCreatedEvent) TopicName() string { type NamespaceCreatedEvent struct { Namespace *Namespace - Doer *user.User + Doer web.Auth } func (n *NamespaceCreatedEvent) TopicName() string { @@ -88,7 +89,7 @@ func (n *NamespaceCreatedEvent) TopicName() string { type NamespaceUpdatedEvent struct { Namespace *Namespace - Doer *user.User + Doer web.Auth } func (n *NamespaceUpdatedEvent) TopicName() string { @@ -98,7 +99,7 @@ func (n *NamespaceUpdatedEvent) TopicName() string { // NamespaceDeletedEvent represents a NamespaceDeletedEvent event type NamespaceDeletedEvent struct { Namespace *Namespace - Doer *user.User + Doer web.Auth } // TopicName defines the name for NamespaceDeletedEvent @@ -112,7 +113,7 @@ func (t *NamespaceDeletedEvent) TopicName() string { type ListCreatedEvent struct { List *List - Doer *user.User + Doer web.Auth } func (l *ListCreatedEvent) TopicName() string { @@ -121,7 +122,7 @@ func (l *ListCreatedEvent) TopicName() string { type ListUpdatedEvent struct { List *List - Doer *user.User + Doer web.Auth } func (l *ListUpdatedEvent) TopicName() string { @@ -130,7 +131,7 @@ func (l *ListUpdatedEvent) TopicName() string { type ListDeletedEvent struct { List *List - Doer *user.User + Doer web.Auth } func (t *ListDeletedEvent) TopicName() string { @@ -144,7 +145,7 @@ func (t *ListDeletedEvent) TopicName() string { type ListSharedWithUserEvent struct { List *List User *user.User - Doer *user.User + Doer web.Auth } func (l *ListSharedWithUserEvent) TopicName() string { @@ -154,7 +155,7 @@ func (l *ListSharedWithUserEvent) TopicName() string { type ListSharedWithTeamEvent struct { List *List Team *Team - Doer *user.User + Doer web.Auth } func (l *ListSharedWithTeamEvent) TopicName() string { @@ -164,7 +165,7 @@ func (l *ListSharedWithTeamEvent) TopicName() string { type NamespaceSharedWithUserEvent struct { Namespace *Namespace User *user.User - Doer *user.User + Doer web.Auth } func (n *NamespaceSharedWithUserEvent) TopicName() string { @@ -174,7 +175,7 @@ func (n *NamespaceSharedWithUserEvent) TopicName() string { type NamespaceSharedWithTeamEvent struct { Namespace *Namespace Team *Team - Doer *user.User + Doer web.Auth } func (n *NamespaceSharedWithTeamEvent) TopicName() string { @@ -188,7 +189,7 @@ func (n *NamespaceSharedWithTeamEvent) TopicName() string { type TeamMemberAddedEvent struct { Team *Team Member *user.User - Doer *user.User + Doer web.Auth } func (t *TeamMemberAddedEvent) TopicName() string { @@ -198,7 +199,7 @@ func (t *TeamMemberAddedEvent) TopicName() string { // TeamCreatedEvent represents a TeamCreatedEvent event type TeamCreatedEvent struct { Team *Team - Doer *user.User + Doer web.Auth } // TopicName defines the name for TeamCreatedEvent @@ -209,7 +210,7 @@ func (t *TeamCreatedEvent) TopicName() string { // TeamDeletedEvent represents a TeamDeletedEvent event type TeamDeletedEvent struct { Team *Team - Doer *user.User + Doer web.Auth } // TopicName defines the name for TeamDeletedEvent diff --git a/pkg/models/list.go b/pkg/models/list.go index c08d1922c..318a94701 100644 --- a/pkg/models/list.go +++ b/pkg/models/list.go @@ -546,14 +546,9 @@ func (l *List) Update(s *xorm.Session, a web.Auth) (err error) { return err } - doer, err := user.GetFromAuth(a) - if err != nil { - return err - } - return events.Publish(&ListUpdatedEvent{ List: l, - Doer: doer, + Doer: a, }) } @@ -618,7 +613,7 @@ func (l *List) Create(s *xorm.Session, a web.Auth) (err error) { return events.Publish(&ListCreatedEvent{ List: l, - Doer: doer, + Doer: a, }) } @@ -648,13 +643,9 @@ func (l *List) Delete(s *xorm.Session, a web.Auth) (err error) { return } - doer, err := user.GetFromAuth(a) - if err != nil { - return err - } return events.Publish(&ListDeletedEvent{ List: l, - Doer: doer, + Doer: a, }) } diff --git a/pkg/models/list_team.go b/pkg/models/list_team.go index 2f762822f..63e0d7e94 100644 --- a/pkg/models/list_team.go +++ b/pkg/models/list_team.go @@ -18,7 +18,6 @@ package models import ( "code.vikunja.io/api/pkg/events" - "code.vikunja.io/api/pkg/user" "time" "code.vikunja.io/web" @@ -107,14 +106,10 @@ func (tl *TeamList) Create(s *xorm.Session, a web.Auth) (err error) { return err } - doer, err := user.GetFromAuth(a) - if err != nil { - return err - } err = events.Publish(&ListSharedWithTeamEvent{ List: l, Team: team, - Doer: doer, + Doer: a, }) err = updateListLastUpdated(s, l) diff --git a/pkg/models/list_users.go b/pkg/models/list_users.go index 351748954..a17304b48 100644 --- a/pkg/models/list_users.go +++ b/pkg/models/list_users.go @@ -113,14 +113,10 @@ func (lu *ListUser) Create(s *xorm.Session, a web.Auth) (err error) { return err } - doer, err := user.GetFromAuth(a) - if err != nil { - return err - } err = events.Publish(&ListSharedWithUserEvent{ List: l, User: u, - Doer: doer, + Doer: a, }) if err != nil { return err diff --git a/pkg/models/namespace.go b/pkg/models/namespace.go index e7d03b047..d46a2817c 100644 --- a/pkg/models/namespace.go +++ b/pkg/models/namespace.go @@ -480,7 +480,7 @@ func (n *Namespace) Create(s *xorm.Session, a web.Auth) (err error) { err = events.Publish(&NamespaceCreatedEvent{ Namespace: n, - Doer: n.Owner, + Doer: a, }) if err != nil { return err @@ -550,13 +550,9 @@ func (n *Namespace) Delete(s *xorm.Session, a web.Auth) (err error) { return } - doer, err := user.GetFromAuth(a) - if err != nil { - return err - } return events.Publish(&NamespaceDeletedEvent{ Namespace: n, - Doer: doer, + Doer: a, }) } @@ -621,12 +617,8 @@ func (n *Namespace) Update(s *xorm.Session, a web.Auth) (err error) { return err } - doer, err := user.GetFromAuth(a) - if err != nil { - return err - } return events.Publish(&NamespaceUpdatedEvent{ Namespace: n, - Doer: doer, + Doer: a, }) } diff --git a/pkg/models/namespace_team.go b/pkg/models/namespace_team.go index 445c490e9..fffd0ebb7 100644 --- a/pkg/models/namespace_team.go +++ b/pkg/models/namespace_team.go @@ -18,7 +18,6 @@ package models import ( "code.vikunja.io/api/pkg/events" - user2 "code.vikunja.io/api/pkg/user" "time" "code.vikunja.io/web" @@ -102,14 +101,10 @@ func (tn *TeamNamespace) Create(s *xorm.Session, a web.Auth) (err error) { return err } - doer, err := user2.GetFromAuth(a) - if err != nil { - return err - } return events.Publish(&NamespaceSharedWithTeamEvent{ Namespace: namespace, Team: team, - Doer: doer, + Doer: a, }) } diff --git a/pkg/models/namespace_users.go b/pkg/models/namespace_users.go index af78e38ce..fea0741fd 100644 --- a/pkg/models/namespace_users.go +++ b/pkg/models/namespace_users.go @@ -110,14 +110,10 @@ func (nu *NamespaceUser) Create(s *xorm.Session, a web.Auth) (err error) { return err } - doer, err := user2.GetFromAuth(a) - if err != nil { - return err - } return events.Publish(&NamespaceSharedWithUserEvent{ Namespace: n, User: user, - Doer: doer, + Doer: a, }) } diff --git a/pkg/models/task_assignees.go b/pkg/models/task_assignees.go index 7b7f1dab3..8419c9e7a 100644 --- a/pkg/models/task_assignees.go +++ b/pkg/models/task_assignees.go @@ -224,15 +224,10 @@ func (t *Task) addNewAssigneeByID(s *xorm.Session, newAssigneeID int64, list *Li return err } - doer, err := user.GetFromAuth(auth) - if err != nil { - return err - } - err = events.Publish(&TaskAssigneeCreatedEvent{ Task: t, Assignee: newAssignee, - Doer: doer, + Doer: auth, }) if err != nil { return err diff --git a/pkg/models/task_comments.go b/pkg/models/task_comments.go index 38babdb7c..2070af81b 100644 --- a/pkg/models/task_comments.go +++ b/pkg/models/task_comments.go @@ -72,14 +72,10 @@ func (tc *TaskComment) Create(s *xorm.Session, a web.Auth) (err error) { return } - doer, err := user.GetFromAuth(a) - if err != nil { - return err - } err = events.Publish(&TaskCommentCreatedEvent{ Task: &task, Comment: tc, - Doer: doer, + Doer: a, }) if err != nil { return err diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index f56793d3c..b668ff15b 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -828,7 +828,7 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err err = events.Publish(&TaskCreatedEvent{ Task: t, - Doer: t.CreatedBy, + Doer: a, }) if err != nil { return err @@ -1034,13 +1034,9 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) { } t.Updated = nt.Updated - doer, err := user.GetFromAuth(a) - if err != nil { - return err - } err = events.Publish(&TaskUpdatedEvent{ Task: t, - Doer: doer, + Doer: a, }) if err != nil { return err @@ -1195,13 +1191,9 @@ func (t *Task) Delete(s *xorm.Session, a web.Auth) (err error) { return err } - doer, err := user.GetFromAuth(a) - if err != nil { - return err - } err = events.Publish(&TaskDeletedEvent{ Task: t, - Doer: doer, + Doer: a, }) if err != nil { return diff --git a/pkg/models/team_members.go b/pkg/models/team_members.go index 5f52a0343..ad79f8b96 100644 --- a/pkg/models/team_members.go +++ b/pkg/models/team_members.go @@ -69,14 +69,10 @@ func (tm *TeamMember) Create(s *xorm.Session, a web.Auth) (err error) { return err } - doer, err := user2.GetFromAuth(a) - if err != nil { - return err - } return events.Publish(&TeamMemberAddedEvent{ Team: team, Member: user, - Doer: doer, + Doer: a, }) } diff --git a/pkg/models/teams.go b/pkg/models/teams.go index 49798ac7d..4ffcff8d2 100644 --- a/pkg/models/teams.go +++ b/pkg/models/teams.go @@ -272,7 +272,7 @@ func (t *Team) Create(s *xorm.Session, a web.Auth) (err error) { return events.Publish(&TeamCreatedEvent{ Team: t, - Doer: doer, + Doer: a, }) } @@ -313,13 +313,9 @@ func (t *Team) Delete(s *xorm.Session, a web.Auth) (err error) { return } - doer, err := user.GetFromAuth(a) - if err != nil { - return err - } return events.Publish(&TeamDeletedEvent{ Team: t, - Doer: doer, + Doer: a, }) } -- 2.40.1 From 217a09f7235b9a44a430bca9c804023fa4ab4e2f Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 2 Feb 2021 19:46:45 +0100 Subject: [PATCH 34/45] Add method to assert an event has been dispatched --- pkg/events/events.go | 1 + pkg/events/testing.go | 24 +++++++++++++++++++++++- pkg/models/tasks_test.go | 2 ++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/pkg/events/events.go b/pkg/events/events.go index 7bac20188..6852b596f 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -80,6 +80,7 @@ func InitEvents() (err error) { func Publish(event Event) error { if isUnderTest { + dispatchedTestEvents = append(dispatchedTestEvents, event) return nil } diff --git a/pkg/events/testing.go b/pkg/events/testing.go index 500a5cf87..b91409450 100644 --- a/pkg/events/testing.go +++ b/pkg/events/testing.go @@ -16,11 +16,33 @@ package events -var isUnderTest bool +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +var ( + isUnderTest bool + dispatchedTestEvents []Event +) // Fake sets up the "test mode" of the events package. Typically you'd call this function in the TestMain function // in the package you're testing. It will prevent any events from being fired, instead they will be recorded and be // available for assertions. func Fake() { isUnderTest = true + dispatchedTestEvents = nil +} + +// AssertDispatched asserts an event has been dispatched. +func AssertDispatched(t *testing.T, event Event) { + var found bool + for _, testEvent := range dispatchedTestEvents { + if event.TopicName() == testEvent.TopicName() { + found = true + break + } + } + + assert.True(t, found, "Failed to assert "+event.TopicName()+" has been dispatched.") } diff --git a/pkg/models/tasks_test.go b/pkg/models/tasks_test.go index f37817c8e..722478b61 100644 --- a/pkg/models/tasks_test.go +++ b/pkg/models/tasks_test.go @@ -17,6 +17,7 @@ package models import ( + "code.vikunja.io/api/pkg/events" "testing" "time" @@ -65,6 +66,7 @@ func TestTask_Create(t *testing.T) { "bucket_id": 1, }, false) + events.AssertDispatched(t, &TaskCreatedEvent{}) }) t.Run("empty title", func(t *testing.T) { db.LoadAndAssertFixtures(t) -- 2.40.1 From 8de81194bd3d4102eb1da8c009d0b2368c71618c Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 2 Feb 2021 19:47:33 +0100 Subject: [PATCH 35/45] Rename Publish to Dispatch --- pkg/events/events.go | 2 +- pkg/initialize/init.go | 2 +- pkg/models/list.go | 6 +++--- pkg/models/list_team.go | 2 +- pkg/models/list_users.go | 2 +- pkg/models/namespace.go | 6 +++--- pkg/models/namespace_team.go | 2 +- pkg/models/namespace_users.go | 2 +- pkg/models/task_assignees.go | 2 +- pkg/models/task_comments.go | 2 +- pkg/models/tasks.go | 6 +++--- pkg/models/team_members.go | 2 +- pkg/models/teams.go | 4 ++-- pkg/user/user_create.go | 2 +- 14 files changed, 21 insertions(+), 21 deletions(-) diff --git a/pkg/events/events.go b/pkg/events/events.go index 6852b596f..c554dfefb 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -78,7 +78,7 @@ func InitEvents() (err error) { return router.Run(context.Background()) } -func Publish(event Event) error { +func Dispatch(event Event) error { if isUnderTest { dispatchedTestEvents = append(dispatchedTestEvents, event) return nil diff --git a/pkg/initialize/init.go b/pkg/initialize/init.go index f805d182d..26582b95c 100644 --- a/pkg/initialize/init.go +++ b/pkg/initialize/init.go @@ -97,7 +97,7 @@ func FullInit() { log.Fatal(err.Error()) } - err = events.Publish(&BootedEvent{ + err = events.Dispatch(&BootedEvent{ BootedAt: time.Now(), }) if err != nil { diff --git a/pkg/models/list.go b/pkg/models/list.go index 318a94701..0064103d6 100644 --- a/pkg/models/list.go +++ b/pkg/models/list.go @@ -546,7 +546,7 @@ func (l *List) Update(s *xorm.Session, a web.Auth) (err error) { return err } - return events.Publish(&ListUpdatedEvent{ + return events.Dispatch(&ListUpdatedEvent{ List: l, Doer: a, }) @@ -611,7 +611,7 @@ func (l *List) Create(s *xorm.Session, a web.Auth) (err error) { return } - return events.Publish(&ListCreatedEvent{ + return events.Dispatch(&ListCreatedEvent{ List: l, Doer: a, }) @@ -643,7 +643,7 @@ func (l *List) Delete(s *xorm.Session, a web.Auth) (err error) { return } - return events.Publish(&ListDeletedEvent{ + return events.Dispatch(&ListDeletedEvent{ List: l, Doer: a, }) diff --git a/pkg/models/list_team.go b/pkg/models/list_team.go index 63e0d7e94..f0611f84e 100644 --- a/pkg/models/list_team.go +++ b/pkg/models/list_team.go @@ -106,7 +106,7 @@ func (tl *TeamList) Create(s *xorm.Session, a web.Auth) (err error) { return err } - err = events.Publish(&ListSharedWithTeamEvent{ + err = events.Dispatch(&ListSharedWithTeamEvent{ List: l, Team: team, Doer: a, diff --git a/pkg/models/list_users.go b/pkg/models/list_users.go index a17304b48..5131eb074 100644 --- a/pkg/models/list_users.go +++ b/pkg/models/list_users.go @@ -113,7 +113,7 @@ func (lu *ListUser) Create(s *xorm.Session, a web.Auth) (err error) { return err } - err = events.Publish(&ListSharedWithUserEvent{ + err = events.Dispatch(&ListSharedWithUserEvent{ List: l, User: u, Doer: a, diff --git a/pkg/models/namespace.go b/pkg/models/namespace.go index d46a2817c..cd1197077 100644 --- a/pkg/models/namespace.go +++ b/pkg/models/namespace.go @@ -478,7 +478,7 @@ func (n *Namespace) Create(s *xorm.Session, a web.Auth) (err error) { return err } - err = events.Publish(&NamespaceCreatedEvent{ + err = events.Dispatch(&NamespaceCreatedEvent{ Namespace: n, Doer: a, }) @@ -550,7 +550,7 @@ func (n *Namespace) Delete(s *xorm.Session, a web.Auth) (err error) { return } - return events.Publish(&NamespaceDeletedEvent{ + return events.Dispatch(&NamespaceDeletedEvent{ Namespace: n, Doer: a, }) @@ -617,7 +617,7 @@ func (n *Namespace) Update(s *xorm.Session, a web.Auth) (err error) { return err } - return events.Publish(&NamespaceUpdatedEvent{ + return events.Dispatch(&NamespaceUpdatedEvent{ Namespace: n, Doer: a, }) diff --git a/pkg/models/namespace_team.go b/pkg/models/namespace_team.go index fffd0ebb7..d18c70824 100644 --- a/pkg/models/namespace_team.go +++ b/pkg/models/namespace_team.go @@ -101,7 +101,7 @@ func (tn *TeamNamespace) Create(s *xorm.Session, a web.Auth) (err error) { return err } - return events.Publish(&NamespaceSharedWithTeamEvent{ + return events.Dispatch(&NamespaceSharedWithTeamEvent{ Namespace: namespace, Team: team, Doer: a, diff --git a/pkg/models/namespace_users.go b/pkg/models/namespace_users.go index fea0741fd..33f4e3ac4 100644 --- a/pkg/models/namespace_users.go +++ b/pkg/models/namespace_users.go @@ -110,7 +110,7 @@ func (nu *NamespaceUser) Create(s *xorm.Session, a web.Auth) (err error) { return err } - return events.Publish(&NamespaceSharedWithUserEvent{ + return events.Dispatch(&NamespaceSharedWithUserEvent{ Namespace: n, User: user, Doer: a, diff --git a/pkg/models/task_assignees.go b/pkg/models/task_assignees.go index 8419c9e7a..ee8e90166 100644 --- a/pkg/models/task_assignees.go +++ b/pkg/models/task_assignees.go @@ -224,7 +224,7 @@ func (t *Task) addNewAssigneeByID(s *xorm.Session, newAssigneeID int64, list *Li return err } - err = events.Publish(&TaskAssigneeCreatedEvent{ + err = events.Dispatch(&TaskAssigneeCreatedEvent{ Task: t, Assignee: newAssignee, Doer: auth, diff --git a/pkg/models/task_comments.go b/pkg/models/task_comments.go index 2070af81b..4dac977e9 100644 --- a/pkg/models/task_comments.go +++ b/pkg/models/task_comments.go @@ -72,7 +72,7 @@ func (tc *TaskComment) Create(s *xorm.Session, a web.Auth) (err error) { return } - err = events.Publish(&TaskCommentCreatedEvent{ + err = events.Dispatch(&TaskCommentCreatedEvent{ Task: &task, Comment: tc, Doer: a, diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index b668ff15b..85a33f275 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -826,7 +826,7 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err t.setIdentifier(l) - err = events.Publish(&TaskCreatedEvent{ + err = events.Dispatch(&TaskCreatedEvent{ Task: t, Doer: a, }) @@ -1034,7 +1034,7 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) { } t.Updated = nt.Updated - err = events.Publish(&TaskUpdatedEvent{ + err = events.Dispatch(&TaskUpdatedEvent{ Task: t, Doer: a, }) @@ -1191,7 +1191,7 @@ func (t *Task) Delete(s *xorm.Session, a web.Auth) (err error) { return err } - err = events.Publish(&TaskDeletedEvent{ + err = events.Dispatch(&TaskDeletedEvent{ Task: t, Doer: a, }) diff --git a/pkg/models/team_members.go b/pkg/models/team_members.go index ad79f8b96..962d90a9f 100644 --- a/pkg/models/team_members.go +++ b/pkg/models/team_members.go @@ -69,7 +69,7 @@ func (tm *TeamMember) Create(s *xorm.Session, a web.Auth) (err error) { return err } - return events.Publish(&TeamMemberAddedEvent{ + return events.Dispatch(&TeamMemberAddedEvent{ Team: team, Member: user, Doer: a, diff --git a/pkg/models/teams.go b/pkg/models/teams.go index 4ffcff8d2..487d310d8 100644 --- a/pkg/models/teams.go +++ b/pkg/models/teams.go @@ -270,7 +270,7 @@ func (t *Team) Create(s *xorm.Session, a web.Auth) (err error) { return err } - return events.Publish(&TeamCreatedEvent{ + return events.Dispatch(&TeamCreatedEvent{ Team: t, Doer: a, }) @@ -313,7 +313,7 @@ func (t *Team) Delete(s *xorm.Session, a web.Auth) (err error) { return } - return events.Publish(&TeamDeletedEvent{ + return events.Dispatch(&TeamDeletedEvent{ Team: t, Doer: a, }) diff --git a/pkg/user/user_create.go b/pkg/user/user_create.go index d74bccfed..bc865d8da 100644 --- a/pkg/user/user_create.go +++ b/pkg/user/user_create.go @@ -76,7 +76,7 @@ func CreateUser(s *xorm.Session, user *User) (newUser *User, err error) { return nil, err } - err = events.Publish(&UserCreatedEvent{ + err = events.Dispatch(&UserCreatedEvent{ User: newUserOut, }) if err != nil { -- 2.40.1 From a2396a093b5a0207fc2f024d6a68406f7fc90998 Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 2 Feb 2021 19:49:17 +0100 Subject: [PATCH 36/45] Rename event name --- magefile.go | 6 +++--- pkg/events/events.go | 4 ++-- pkg/events/testing.go | 4 ++-- pkg/initialize/events.go | 2 +- pkg/models/events.go | 36 ++++++++++++++++++------------------ pkg/models/listeners.go | 16 ++++++++-------- pkg/user/events.go | 2 +- pkg/user/listeners.go | 2 +- 8 files changed, 36 insertions(+), 36 deletions(-) diff --git a/magefile.go b/magefile.go index 1a0ecb0c9..97d9662b9 100644 --- a/magefile.go +++ b/magefile.go @@ -801,8 +801,8 @@ func (Dev) MakeEvent(name, module string) error { type ` + name + ` struct { } -// TopicName defines the name for ` + name + ` -func (t *` + name + `) TopicName() string { +// Name defines the name for ` + name + ` +func (t *` + name + `) Name() string { return "` + eventName + `" } ` @@ -861,7 +861,7 @@ func (s *` + name + `) Handle(payload message.Payload) (err error) { } file.Close() - registerListenerCode := ` events.RegisterListener((&` + event + `{}).TopicName(), &` + name + `{}) + registerListenerCode := ` events.RegisterListener((&` + event + `{}).Name(), &` + name + `{}) ` f, err := os.OpenFile(filename, os.O_RDWR, 0600) diff --git a/pkg/events/events.go b/pkg/events/events.go index c554dfefb..98c126ee7 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -33,7 +33,7 @@ import ( var pubsub *gochannel.GoChannel type Event interface { - TopicName() string + Name() string } func InitEvents() (err error) { @@ -90,5 +90,5 @@ func Dispatch(event Event) error { } msg := message.NewMessage(watermill.NewUUID(), content) - return pubsub.Publish(event.TopicName(), msg) + return pubsub.Publish(event.Name(), msg) } diff --git a/pkg/events/testing.go b/pkg/events/testing.go index b91409450..4cf759f2c 100644 --- a/pkg/events/testing.go +++ b/pkg/events/testing.go @@ -38,11 +38,11 @@ func Fake() { func AssertDispatched(t *testing.T, event Event) { var found bool for _, testEvent := range dispatchedTestEvents { - if event.TopicName() == testEvent.TopicName() { + if event.Name() == testEvent.Name() { found = true break } } - assert.True(t, found, "Failed to assert "+event.TopicName()+" has been dispatched.") + assert.True(t, found, "Failed to assert "+event.Name()+" has been dispatched.") } diff --git a/pkg/initialize/events.go b/pkg/initialize/events.go index 305287aa9..c5c52a34c 100644 --- a/pkg/initialize/events.go +++ b/pkg/initialize/events.go @@ -24,6 +24,6 @@ type BootedEvent struct { } // TopicName defines the name for BootedEvent -func (t *BootedEvent) TopicName() string { +func (t *BootedEvent) Name() string { return "booted" } diff --git a/pkg/models/events.go b/pkg/models/events.go index a7fb7ba96..705c14f2b 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -30,7 +30,7 @@ type TaskCreatedEvent struct { Doer web.Auth } -func (t *TaskCreatedEvent) TopicName() string { +func (t *TaskCreatedEvent) Name() string { return "task.created" } @@ -39,7 +39,7 @@ type TaskUpdatedEvent struct { Doer web.Auth } -func (t *TaskUpdatedEvent) TopicName() string { +func (t *TaskUpdatedEvent) Name() string { return "task.updated" } @@ -50,7 +50,7 @@ type TaskDeletedEvent struct { } // TopicName defines the name for TaskDeletedEvent -func (t *TaskDeletedEvent) TopicName() string { +func (t *TaskDeletedEvent) Name() string { return "task.deleted" } @@ -60,7 +60,7 @@ type TaskAssigneeCreatedEvent struct { Doer web.Auth } -func (t *TaskAssigneeCreatedEvent) TopicName() string { +func (t *TaskAssigneeCreatedEvent) Name() string { return "task.assignee.created" } @@ -70,7 +70,7 @@ type TaskCommentCreatedEvent struct { Doer web.Auth } -func (t *TaskCommentCreatedEvent) TopicName() string { +func (t *TaskCommentCreatedEvent) Name() string { return "task.comment.created" } @@ -83,7 +83,7 @@ type NamespaceCreatedEvent struct { Doer web.Auth } -func (n *NamespaceCreatedEvent) TopicName() string { +func (n *NamespaceCreatedEvent) Name() string { return "namespace.created" } @@ -92,7 +92,7 @@ type NamespaceUpdatedEvent struct { Doer web.Auth } -func (n *NamespaceUpdatedEvent) TopicName() string { +func (n *NamespaceUpdatedEvent) Name() string { return "namespace.updated" } @@ -103,7 +103,7 @@ type NamespaceDeletedEvent struct { } // TopicName defines the name for NamespaceDeletedEvent -func (t *NamespaceDeletedEvent) TopicName() string { +func (t *NamespaceDeletedEvent) Name() string { return "namespace.deleted" } @@ -116,7 +116,7 @@ type ListCreatedEvent struct { Doer web.Auth } -func (l *ListCreatedEvent) TopicName() string { +func (l *ListCreatedEvent) Name() string { return "list.created" } @@ -125,7 +125,7 @@ type ListUpdatedEvent struct { Doer web.Auth } -func (l *ListUpdatedEvent) TopicName() string { +func (l *ListUpdatedEvent) Name() string { return "list.updated" } @@ -134,7 +134,7 @@ type ListDeletedEvent struct { Doer web.Auth } -func (t *ListDeletedEvent) TopicName() string { +func (t *ListDeletedEvent) Name() string { return "list.deleted" } @@ -148,7 +148,7 @@ type ListSharedWithUserEvent struct { Doer web.Auth } -func (l *ListSharedWithUserEvent) TopicName() string { +func (l *ListSharedWithUserEvent) Name() string { return "list.shared.user" } @@ -158,7 +158,7 @@ type ListSharedWithTeamEvent struct { Doer web.Auth } -func (l *ListSharedWithTeamEvent) TopicName() string { +func (l *ListSharedWithTeamEvent) Name() string { return "list.shared.team" } @@ -168,7 +168,7 @@ type NamespaceSharedWithUserEvent struct { Doer web.Auth } -func (n *NamespaceSharedWithUserEvent) TopicName() string { +func (n *NamespaceSharedWithUserEvent) Name() string { return "namespace.shared.user" } @@ -178,7 +178,7 @@ type NamespaceSharedWithTeamEvent struct { Doer web.Auth } -func (n *NamespaceSharedWithTeamEvent) TopicName() string { +func (n *NamespaceSharedWithTeamEvent) Name() string { return "namespace.shared.team" } @@ -192,7 +192,7 @@ type TeamMemberAddedEvent struct { Doer web.Auth } -func (t *TeamMemberAddedEvent) TopicName() string { +func (t *TeamMemberAddedEvent) Name() string { return "team.member.added" } @@ -203,7 +203,7 @@ type TeamCreatedEvent struct { } // TopicName defines the name for TeamCreatedEvent -func (t *TeamCreatedEvent) TopicName() string { +func (t *TeamCreatedEvent) Name() string { return "team.created" } @@ -214,6 +214,6 @@ type TeamDeletedEvent struct { } // TopicName defines the name for TeamDeletedEvent -func (t *TeamDeletedEvent) TopicName() string { +func (t *TeamDeletedEvent) Name() string { return "team.deleted" } diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index 665894125..2a6849e19 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -24,14 +24,14 @@ import ( ) func RegisterListeners() { - events.RegisterListener((&ListCreatedEvent{}).TopicName(), &IncreaseListCounter{}) - events.RegisterListener((&ListDeletedEvent{}).TopicName(), &DecreaseListCounter{}) - events.RegisterListener((&NamespaceCreatedEvent{}).TopicName(), &IncreaseNamespaceCounter{}) - events.RegisterListener((&NamespaceDeletedEvent{}).TopicName(), &DecreaseNamespaceCounter{}) - events.RegisterListener((&TaskCreatedEvent{}).TopicName(), &IncreaseTaskCounter{}) - events.RegisterListener((&TaskDeletedEvent{}).TopicName(), &DecreaseTaskCounter{}) - events.RegisterListener((&TeamDeletedEvent{}).TopicName(), &DecreaseTeamCounter{}) - events.RegisterListener((&TeamCreatedEvent{}).TopicName(), &IncreaseTeamCounter{}) + events.RegisterListener((&ListCreatedEvent{}).Name(), &IncreaseListCounter{}) + events.RegisterListener((&ListDeletedEvent{}).Name(), &DecreaseListCounter{}) + events.RegisterListener((&NamespaceCreatedEvent{}).Name(), &IncreaseNamespaceCounter{}) + events.RegisterListener((&NamespaceDeletedEvent{}).Name(), &DecreaseNamespaceCounter{}) + events.RegisterListener((&TaskCreatedEvent{}).Name(), &IncreaseTaskCounter{}) + events.RegisterListener((&TaskDeletedEvent{}).Name(), &DecreaseTaskCounter{}) + events.RegisterListener((&TeamDeletedEvent{}).Name(), &DecreaseTeamCounter{}) + events.RegisterListener((&TeamCreatedEvent{}).Name(), &IncreaseTeamCounter{}) } ////// diff --git a/pkg/user/events.go b/pkg/user/events.go index cc9401086..10d2104dd 100644 --- a/pkg/user/events.go +++ b/pkg/user/events.go @@ -22,6 +22,6 @@ type UserCreatedEvent struct { } // TopicName defines the name for UserCreatedEvent -func (t *UserCreatedEvent) TopicName() string { +func (t *UserCreatedEvent) Name() string { return "user.created" } diff --git a/pkg/user/listeners.go b/pkg/user/listeners.go index 36592385e..37a74f4a5 100644 --- a/pkg/user/listeners.go +++ b/pkg/user/listeners.go @@ -24,7 +24,7 @@ import ( ) func RegisterListeners() { - events.RegisterListener((&UserCreatedEvent{}).TopicName(), &IncreaseUserCounter{}) + events.RegisterListener((&UserCreatedEvent{}).Name(), &IncreaseUserCounter{}) } /////// -- 2.40.1 From 8b84105db1711ceca7e1418c73c8d233f2a940f2 Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 2 Feb 2021 20:14:15 +0100 Subject: [PATCH 37/45] Fix lint --- pkg/events/events.go | 3 +++ pkg/events/listeners.go | 6 +++-- pkg/events/testing.go | 3 ++- pkg/initialize/init.go | 3 ++- pkg/integrations/integrations.go | 3 ++- pkg/log/watermill_logger.go | 2 -- pkg/models/events.go | 34 +++++++++++++++++++++++++--- pkg/models/list.go | 3 ++- pkg/models/list_team.go | 6 ++++- pkg/models/list_users.go | 3 ++- pkg/models/main_test.go | 3 ++- pkg/models/namespace.go | 3 ++- pkg/models/namespace_team.go | 3 ++- pkg/models/namespace_users.go | 3 ++- pkg/models/task_assignees.go | 3 ++- pkg/models/task_comments.go | 3 ++- pkg/models/tasks.go | 3 ++- pkg/models/tasks_test.go | 3 ++- pkg/models/teams.go | 3 ++- pkg/modules/auth/openid/main_test.go | 3 ++- pkg/modules/migration/main_test.go | 3 ++- pkg/user/events.go | 8 +++---- pkg/user/listeners.go | 2 +- pkg/user/user_create.go | 2 +- 24 files changed, 81 insertions(+), 30 deletions(-) diff --git a/pkg/events/events.go b/pkg/events/events.go index 98c126ee7..72fbfd8c9 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -32,10 +32,12 @@ import ( var pubsub *gochannel.GoChannel +// Event represents the event interface used by all events type Event interface { Name() string } +// InitEvents sets up everything needed to work with events func InitEvents() (err error) { logger := log.NewWatermillLogger() @@ -78,6 +80,7 @@ func InitEvents() (err error) { return router.Run(context.Background()) } +// Dispatch dispatches an event func Dispatch(event Event) error { if isUnderTest { dispatchedTestEvents = append(dispatchedTestEvents, event) diff --git a/pkg/events/listeners.go b/pkg/events/listeners.go index 3368c9a07..f0b1f4266 100644 --- a/pkg/events/listeners.go +++ b/pkg/events/listeners.go @@ -18,6 +18,7 @@ package events import "github.com/ThreeDotsLabs/watermill/message" +// Listener represents something that listens to events type Listener interface { Handle(payload message.Payload) error Name() string @@ -29,6 +30,7 @@ func init() { listeners = make(map[string][]Listener) } -func RegisterListener(topicName string, listener Listener) { - listeners[topicName] = append(listeners[topicName], listener) +// RegisterListener is used to register a listener when a specific event happens +func RegisterListener(name string, listener Listener) { + listeners[name] = append(listeners[name], listener) } diff --git a/pkg/events/testing.go b/pkg/events/testing.go index 4cf759f2c..bf105e110 100644 --- a/pkg/events/testing.go +++ b/pkg/events/testing.go @@ -17,8 +17,9 @@ package events import ( - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" ) var ( diff --git a/pkg/initialize/init.go b/pkg/initialize/init.go index 26582b95c..24f9fae32 100644 --- a/pkg/initialize/init.go +++ b/pkg/initialize/init.go @@ -17,6 +17,8 @@ package initialize import ( + "time" + "code.vikunja.io/api/pkg/config" "code.vikunja.io/api/pkg/cron" "code.vikunja.io/api/pkg/events" @@ -29,7 +31,6 @@ import ( migrator "code.vikunja.io/api/pkg/modules/migration" "code.vikunja.io/api/pkg/red" "code.vikunja.io/api/pkg/user" - "time" ) // LightInit will only fullInit config, redis, logger but no db connection. diff --git a/pkg/integrations/integrations.go b/pkg/integrations/integrations.go index 33c081933..f9161e792 100644 --- a/pkg/integrations/integrations.go +++ b/pkg/integrations/integrations.go @@ -17,7 +17,6 @@ package integrations import ( - "code.vikunja.io/api/pkg/events" "net/http" "net/http/httptest" "net/url" @@ -25,6 +24,8 @@ import ( "strings" "testing" + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/config" "code.vikunja.io/api/pkg/db" "code.vikunja.io/api/pkg/files" diff --git a/pkg/log/watermill_logger.go b/pkg/log/watermill_logger.go index 15e900115..4a6c4e418 100644 --- a/pkg/log/watermill_logger.go +++ b/pkg/log/watermill_logger.go @@ -24,7 +24,6 @@ import ( "code.vikunja.io/api/pkg/config" "github.com/ThreeDotsLabs/watermill" "github.com/op/go-logging" - "xorm.io/xorm/log" ) const watermillFmt = `%{color}%{time:` + time.RFC3339Nano + `}: %{level}` + "\t" + `▶ [EVENTS] %{id:03x}%{color:reset} %{message}` @@ -33,7 +32,6 @@ const watermillLogModule = `vikunja_events` type WatermillLogger struct { logger *logging.Logger - level log.LogLevel } func NewWatermillLogger() *WatermillLogger { diff --git a/pkg/models/events.go b/pkg/models/events.go index 705c14f2b..8b37fa0de 100644 --- a/pkg/models/events.go +++ b/pkg/models/events.go @@ -25,20 +25,24 @@ import ( // Task Events // ///////////////// +// TaskCreatedEvent represents an event where a task has been created type TaskCreatedEvent struct { Task *Task Doer web.Auth } +// Name defines the name for TaskCreatedEvent func (t *TaskCreatedEvent) Name() string { return "task.created" } +// TaskUpdatedEvent represents an event where a task has been updated type TaskUpdatedEvent struct { Task *Task Doer web.Auth } +// Name defines the name for TaskUpdatedEvent func (t *TaskUpdatedEvent) Name() string { return "task.updated" } @@ -49,27 +53,31 @@ type TaskDeletedEvent struct { Doer web.Auth } -// TopicName defines the name for TaskDeletedEvent +// Name defines the name for TaskDeletedEvent func (t *TaskDeletedEvent) Name() string { return "task.deleted" } +// TaskAssigneeCreatedEvent represents an event where a task has been assigned to a user type TaskAssigneeCreatedEvent struct { Task *Task Assignee *user.User Doer web.Auth } +// Name defines the name for TaskAssigneeCreatedEvent func (t *TaskAssigneeCreatedEvent) Name() string { return "task.assignee.created" } +// TaskCommentCreatedEvent represents an event where a task comment has been created type TaskCommentCreatedEvent struct { Task *Task Comment *TaskComment Doer web.Auth } +// Name defines the name for TaskCommentCreatedEvent func (t *TaskCommentCreatedEvent) Name() string { return "task.comment.created" } @@ -78,20 +86,24 @@ func (t *TaskCommentCreatedEvent) Name() string { // Namespace Events // ////////////////////// +// NamespaceCreatedEvent represents an event where a namespace has been created type NamespaceCreatedEvent struct { Namespace *Namespace Doer web.Auth } +// Name defines the name for NamespaceCreatedEvent func (n *NamespaceCreatedEvent) Name() string { return "namespace.created" } +// NamespaceUpdatedEvent represents an event where a namespace has been updated type NamespaceUpdatedEvent struct { Namespace *Namespace Doer web.Auth } +// Name defines the name for NamespaceUpdatedEvent func (n *NamespaceUpdatedEvent) Name() string { return "namespace.updated" } @@ -111,29 +123,35 @@ func (t *NamespaceDeletedEvent) Name() string { // List Events // ///////////////// +// ListCreatedEvent represents an event where a list has been created type ListCreatedEvent struct { List *List Doer web.Auth } +// Name defines the name for ListCreatedEvent func (l *ListCreatedEvent) Name() string { return "list.created" } +// ListUpdatedEvent represents an event where a list has been updated type ListUpdatedEvent struct { List *List Doer web.Auth } +// Name defines the name for ListUpdatedEvent func (l *ListUpdatedEvent) Name() string { return "list.updated" } +// ListDeletedEvent represents an event where a list has been deleted type ListDeletedEvent struct { List *List Doer web.Auth } +// Name defines the name for ListDeletedEvent func (t *ListDeletedEvent) Name() string { return "list.deleted" } @@ -142,42 +160,50 @@ func (t *ListDeletedEvent) Name() string { // Sharing Events // //////////////////// +// ListSharedWithUserEvent represents an event where a list has been shared with a user type ListSharedWithUserEvent struct { List *List User *user.User Doer web.Auth } +// Name defines the name for ListSharedWithUserEvent func (l *ListSharedWithUserEvent) Name() string { return "list.shared.user" } +// ListSharedWithTeamEvent represents an event where a list has been shared with a team type ListSharedWithTeamEvent struct { List *List Team *Team Doer web.Auth } +// Name defines the name for ListSharedWithTeamEvent func (l *ListSharedWithTeamEvent) Name() string { return "list.shared.team" } +// NamespaceSharedWithUserEvent represents an event where a namespace has been shared with a user type NamespaceSharedWithUserEvent struct { Namespace *Namespace User *user.User Doer web.Auth } +// Name defines the name for NamespaceSharedWithUserEvent func (n *NamespaceSharedWithUserEvent) Name() string { return "namespace.shared.user" } +// NamespaceSharedWithTeamEvent represents an event where a namespace has been shared with a team type NamespaceSharedWithTeamEvent struct { Namespace *Namespace Team *Team Doer web.Auth } +// Name defines the name for NamespaceSharedWithTeamEvent func (n *NamespaceSharedWithTeamEvent) Name() string { return "namespace.shared.team" } @@ -186,12 +212,14 @@ func (n *NamespaceSharedWithTeamEvent) Name() string { // Team Events // ///////////////// +// TeamMemberAddedEvent defines an event where a user is added to a team type TeamMemberAddedEvent struct { Team *Team Member *user.User Doer web.Auth } +// Name defines the name for TeamMemberAddedEvent func (t *TeamMemberAddedEvent) Name() string { return "team.member.added" } @@ -202,7 +230,7 @@ type TeamCreatedEvent struct { Doer web.Auth } -// TopicName defines the name for TeamCreatedEvent +// Name defines the name for TeamCreatedEvent func (t *TeamCreatedEvent) Name() string { return "team.created" } @@ -213,7 +241,7 @@ type TeamDeletedEvent struct { Doer web.Auth } -// TopicName defines the name for TeamDeletedEvent +// Name defines the name for TeamDeletedEvent func (t *TeamDeletedEvent) Name() string { return "team.deleted" } diff --git a/pkg/models/list.go b/pkg/models/list.go index 0064103d6..bfb31eba8 100644 --- a/pkg/models/list.go +++ b/pkg/models/list.go @@ -17,11 +17,12 @@ package models import ( - "code.vikunja.io/api/pkg/events" "strconv" "strings" "time" + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/log" "code.vikunja.io/api/pkg/files" diff --git a/pkg/models/list_team.go b/pkg/models/list_team.go index f0611f84e..5826e12fa 100644 --- a/pkg/models/list_team.go +++ b/pkg/models/list_team.go @@ -17,9 +17,10 @@ package models import ( - "code.vikunja.io/api/pkg/events" "time" + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/web" "xorm.io/xorm" ) @@ -111,6 +112,9 @@ func (tl *TeamList) Create(s *xorm.Session, a web.Auth) (err error) { Team: team, Doer: a, }) + if err != nil { + return err + } err = updateListLastUpdated(s, l) return diff --git a/pkg/models/list_users.go b/pkg/models/list_users.go index 5131eb074..e94ffca3c 100644 --- a/pkg/models/list_users.go +++ b/pkg/models/list_users.go @@ -17,9 +17,10 @@ package models import ( - "code.vikunja.io/api/pkg/events" "time" + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/user" "code.vikunja.io/web" "xorm.io/xorm" diff --git a/pkg/models/main_test.go b/pkg/models/main_test.go index 9dcf28cff..b16e3c629 100644 --- a/pkg/models/main_test.go +++ b/pkg/models/main_test.go @@ -17,12 +17,13 @@ package models import ( - "code.vikunja.io/api/pkg/events" "fmt" "os" "testing" "time" + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/config" "code.vikunja.io/api/pkg/files" "code.vikunja.io/api/pkg/user" diff --git a/pkg/models/namespace.go b/pkg/models/namespace.go index cd1197077..1ae379644 100644 --- a/pkg/models/namespace.go +++ b/pkg/models/namespace.go @@ -17,12 +17,13 @@ package models import ( - "code.vikunja.io/api/pkg/events" "sort" "strconv" "strings" "time" + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/log" "code.vikunja.io/api/pkg/user" "code.vikunja.io/web" diff --git a/pkg/models/namespace_team.go b/pkg/models/namespace_team.go index d18c70824..7df57ecca 100644 --- a/pkg/models/namespace_team.go +++ b/pkg/models/namespace_team.go @@ -17,9 +17,10 @@ package models import ( - "code.vikunja.io/api/pkg/events" "time" + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/web" "xorm.io/xorm" ) diff --git a/pkg/models/namespace_users.go b/pkg/models/namespace_users.go index 33f4e3ac4..5a13760b3 100644 --- a/pkg/models/namespace_users.go +++ b/pkg/models/namespace_users.go @@ -17,9 +17,10 @@ package models import ( - "code.vikunja.io/api/pkg/events" "time" + "code.vikunja.io/api/pkg/events" + user2 "code.vikunja.io/api/pkg/user" "code.vikunja.io/web" "xorm.io/xorm" diff --git a/pkg/models/task_assignees.go b/pkg/models/task_assignees.go index ee8e90166..8efa4b210 100644 --- a/pkg/models/task_assignees.go +++ b/pkg/models/task_assignees.go @@ -17,9 +17,10 @@ package models import ( - "code.vikunja.io/api/pkg/events" "time" + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/user" "code.vikunja.io/web" "xorm.io/xorm" diff --git a/pkg/models/task_comments.go b/pkg/models/task_comments.go index 4dac977e9..5ff3f7600 100644 --- a/pkg/models/task_comments.go +++ b/pkg/models/task_comments.go @@ -17,9 +17,10 @@ package models import ( - "code.vikunja.io/api/pkg/events" "time" + "code.vikunja.io/api/pkg/events" + "xorm.io/xorm" "code.vikunja.io/api/pkg/user" diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index 85a33f275..a71c0e143 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -17,12 +17,13 @@ package models import ( - "code.vikunja.io/api/pkg/events" "math" "sort" "strconv" "time" + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/db" "code.vikunja.io/api/pkg/config" diff --git a/pkg/models/tasks_test.go b/pkg/models/tasks_test.go index 722478b61..6b070ba7a 100644 --- a/pkg/models/tasks_test.go +++ b/pkg/models/tasks_test.go @@ -17,10 +17,11 @@ package models import ( - "code.vikunja.io/api/pkg/events" "testing" "time" + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/db" "code.vikunja.io/api/pkg/user" "github.com/stretchr/testify/assert" diff --git a/pkg/models/teams.go b/pkg/models/teams.go index 487d310d8..717dd1b83 100644 --- a/pkg/models/teams.go +++ b/pkg/models/teams.go @@ -17,9 +17,10 @@ package models import ( - "code.vikunja.io/api/pkg/events" "time" + "code.vikunja.io/api/pkg/events" + "xorm.io/xorm" "code.vikunja.io/api/pkg/user" diff --git a/pkg/modules/auth/openid/main_test.go b/pkg/modules/auth/openid/main_test.go index 41c04fa74..051c2b14d 100644 --- a/pkg/modules/auth/openid/main_test.go +++ b/pkg/modules/auth/openid/main_test.go @@ -17,10 +17,11 @@ package openid import ( - "code.vikunja.io/api/pkg/events" "os" "testing" + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/files" "code.vikunja.io/api/pkg/models" "code.vikunja.io/api/pkg/user" diff --git a/pkg/modules/migration/main_test.go b/pkg/modules/migration/main_test.go index 7e09c32f5..6c4908f0f 100644 --- a/pkg/modules/migration/main_test.go +++ b/pkg/modules/migration/main_test.go @@ -17,10 +17,11 @@ package migration import ( - "code.vikunja.io/api/pkg/events" "os" "testing" + "code.vikunja.io/api/pkg/events" + "code.vikunja.io/api/pkg/config" "code.vikunja.io/api/pkg/files" "code.vikunja.io/api/pkg/models" diff --git a/pkg/user/events.go b/pkg/user/events.go index 10d2104dd..0b07c9ea3 100644 --- a/pkg/user/events.go +++ b/pkg/user/events.go @@ -16,12 +16,12 @@ package user -// UserCreatedEvent represents a UserCreatedEvent event -type UserCreatedEvent struct { +// CreatedEvent represents a CreatedEvent event +type CreatedEvent struct { User *User } -// TopicName defines the name for UserCreatedEvent -func (t *UserCreatedEvent) Name() string { +// TopicName defines the name for CreatedEvent +func (t *CreatedEvent) Name() string { return "user.created" } diff --git a/pkg/user/listeners.go b/pkg/user/listeners.go index 37a74f4a5..572461b2c 100644 --- a/pkg/user/listeners.go +++ b/pkg/user/listeners.go @@ -24,7 +24,7 @@ import ( ) func RegisterListeners() { - events.RegisterListener((&UserCreatedEvent{}).Name(), &IncreaseUserCounter{}) + events.RegisterListener((&CreatedEvent{}).Name(), &IncreaseUserCounter{}) } /////// diff --git a/pkg/user/user_create.go b/pkg/user/user_create.go index bc865d8da..a1c6a757a 100644 --- a/pkg/user/user_create.go +++ b/pkg/user/user_create.go @@ -76,7 +76,7 @@ func CreateUser(s *xorm.Session, user *User) (newUser *User, err error) { return nil, err } - err = events.Dispatch(&UserCreatedEvent{ + err = events.Dispatch(&CreatedEvent{ User: newUserOut, }) if err != nil { -- 2.40.1 From b4ebeef8aaa76e756cb795113ef07c59e837b5f1 Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 2 Feb 2021 20:23:12 +0100 Subject: [PATCH 38/45] Sync dependencies --- go.mod | 5 +---- go.sum | 58 ---------------------------------------------------------- 2 files changed, 1 insertion(+), 62 deletions(-) diff --git a/go.mod b/go.mod index 71656f41e..9df054bb0 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,6 @@ module code.vikunja.io/api require ( 4d63.com/tz v1.2.0 code.vikunja.io/web v0.0.0-20210131201003-26386be9a9ae - dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363 // indirect gitea.com/xorm/xorm-redis-cache v0.2.0 github.com/ThreeDotsLabs/watermill v1.1.1 github.com/adlio/trello v1.8.0 @@ -29,7 +28,6 @@ require ( github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2 github.com/client9/misspell v0.3.4 github.com/coreos/go-oidc v2.2.1+incompatible - github.com/coreos/go-oidc/v3 v3.0.0 github.com/cweill/gotests v1.6.0 github.com/d4l3k/messagediff v1.2.1 github.com/dgrijalva/jwt-go v3.2.0+incompatible @@ -38,7 +36,7 @@ require ( github.com/fzipp/gocyclo v0.3.1 github.com/gabriel-vasile/mimetype v1.1.2 github.com/getsentry/sentry-go v0.9.0 - github.com/go-errors/errors v1.1.1 + github.com/go-errors/errors v1.1.1 // indirect github.com/go-redis/redis/v8 v8.4.11 github.com/go-sql-driver/mysql v1.5.0 github.com/go-testfixtures/testfixtures/v3 v3.5.0 @@ -86,7 +84,6 @@ require ( golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf golang.org/x/text v0.3.5 // indirect - google.golang.org/protobuf v1.25.0 gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/d4l3k/messagediff.v1 v1.2.1 diff --git a/go.sum b/go.sum index aa252c2c8..ec3307a0f 100644 --- a/go.sum +++ b/go.sum @@ -38,16 +38,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -code.vikunja.io/web v0.0.0-20201218134444-505d0e77fac7 h1:iS3TFA+y1If6DEbqzad5Ge7TI1NxZr9BevC/dU4ygEo= -code.vikunja.io/web v0.0.0-20201218134444-505d0e77fac7/go.mod h1:vDWiCtftF6LNCCrem7mjstPWMgzLUvMW/L4YwIQ1Voo= -code.vikunja.io/web v0.0.0-20201222144643-6fa2fb587215 h1:O5zMWgcnVDVLaQUawgdsv/jX/4SUUAvSedvRR+5+x2o= -code.vikunja.io/web v0.0.0-20201222144643-6fa2fb587215/go.mod h1:OgFO06HN1KpA4S7Dw/QAIeygiUPSeGJJn1ykz/sjZdU= -code.vikunja.io/web v0.0.0-20201223143420-588abb73703a h1:LaWCucY5Pp30EIMgGOvdVFNss5OhIAwrAO8PuFVRUfw= -code.vikunja.io/web v0.0.0-20201223143420-588abb73703a/go.mod h1:OgFO06HN1KpA4S7Dw/QAIeygiUPSeGJJn1ykz/sjZdU= code.vikunja.io/web v0.0.0-20210131201003-26386be9a9ae h1:qqgwoWjKrpIOdrIR0FPawiHLZTRYwS9MBgwH1eZJJqA= code.vikunja.io/web v0.0.0-20210131201003-26386be9a9ae/go.mod h1:OgFO06HN1KpA4S7Dw/QAIeygiUPSeGJJn1ykz/sjZdU= -dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363 h1:o4lAkfETerCnr1kF9/qwkwjICnU+YLHNDCM8h2xj7as= -dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363/go.mod h1:WG7q7swWsS2f9PYpt5DoEP/EBYWx8We5UoRltn9vJl8= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= @@ -141,7 +133,6 @@ github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk= github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= -github.com/coreos/go-oidc/v3 v3.0.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= @@ -154,8 +145,6 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/cweill/gotests v1.5.3 h1:k3t4wW/x/YNixWZJhUIn+mivmK5iV1tJVOwVYkx0UcU= -github.com/cweill/gotests v1.5.3/go.mod h1:XZYOJkGVkCRoymaIzmp9Wyi3rUgfA3oOnkuljYrjFV8= github.com/cweill/gotests v1.6.0 h1:KJx+/p4EweijYzqPb4Y/8umDCip1Cv6hEVyOx0mE9W8= github.com/cweill/gotests v1.6.0/go.mod h1:CaRYbxQZGQOxXDvM9l0XJVV2Tjb2E5H53vq+reR2GrA= github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U= @@ -250,18 +239,6 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-redis/redis/v8 v8.4.2 h1:gKRo1KZ+O3kXRfxeRblV5Tr470d2YJZJVIAv2/S8960= github.com/go-redis/redis/v8 v8.4.2/go.mod h1:A1tbYoHSa1fXwN+//ljcCYYJeLmVrwL9hbQN45Jdy0M= -github.com/go-redis/redis/v8 v8.4.4 h1:fGqgxCTR1sydaKI00oQf3OmkU/DIe/I/fYXvGklCIuc= -github.com/go-redis/redis/v8 v8.4.4/go.mod h1:nA0bQuF0i5JFx4Ta9RZxGKXFrQ8cRWntra97f0196iY= -github.com/go-redis/redis/v8 v8.4.6 h1:a4i+zYK6Mq2A2qAz0R6n6xo9dfnh7HdlRU/QvrlpfPI= -github.com/go-redis/redis/v8 v8.4.6/go.mod h1:nA0bQuF0i5JFx4Ta9RZxGKXFrQ8cRWntra97f0196iY= -github.com/go-redis/redis/v8 v8.4.7 h1:l0/Hkj3HLA46eJSvHGLhnF+KHBrmsyipK84ycJXFZxw= -github.com/go-redis/redis/v8 v8.4.7/go.mod h1:nA0bQuF0i5JFx4Ta9RZxGKXFrQ8cRWntra97f0196iY= -github.com/go-redis/redis/v8 v8.4.8 h1:sEG4g6Jq4hvQzbrNsVDNTDdxFCUnFC0jxuOp6tgALlA= -github.com/go-redis/redis/v8 v8.4.8/go.mod h1:/cTZsrSn1DPqRuOnSDuyH2OSvd9iX0iUGT0s7hYGIAg= -github.com/go-redis/redis/v8 v8.4.9 h1:ixEQSxNnzo6zh/dmoZIHl9DmyX3mHV5a2p6OasPR93k= -github.com/go-redis/redis/v8 v8.4.9/go.mod h1:d5yY/TlkQyYBSBHnXUmnf1OrHbyQere5JV4dLKwvXmo= -github.com/go-redis/redis/v8 v8.4.10 h1:fWdl0RBmVibUDOp8bqz1e2Yy9dShOeIeWsiAifYk06Y= -github.com/go-redis/redis/v8 v8.4.10/go.mod h1:d5yY/TlkQyYBSBHnXUmnf1OrHbyQere5JV4dLKwvXmo= github.com/go-redis/redis/v8 v8.4.11 h1:t2lToev01VTrqYQcv+QFbxtGgcf64K+VUMgf9Ap6A/E= github.com/go-redis/redis/v8 v8.4.11/go.mod h1:d5yY/TlkQyYBSBHnXUmnf1OrHbyQere5JV4dLKwvXmo= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -270,8 +247,6 @@ github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/go-testfixtures/testfixtures/v3 v3.4.1 h1:Qz9y0wUOXPHzKhK6C79A/menChtEu/xd0Dn5ngVyMD0= -github.com/go-testfixtures/testfixtures/v3 v3.4.1/go.mod h1:P4L3WxgOsCLbAeUC50qX5rdj1ULZfUMqgCbqah3OH5U= github.com/go-testfixtures/testfixtures/v3 v3.5.0 h1:fFJGHhFdcwy48oTLHvr0WRQ09rGiZE+as9ElvbRWS+c= github.com/go-testfixtures/testfixtures/v3 v3.5.0/go.mod h1:P4L3WxgOsCLbAeUC50qX5rdj1ULZfUMqgCbqah3OH5U= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= @@ -361,8 +336,6 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= -github.com/gordonklaus/ineffassign v0.0.0-20201107091007-3b93a8888063 h1:dKprcOvlsvqfWn/iGvz+oYuC2axESeSMuF8dDrWMNsE= -github.com/gordonklaus/ineffassign v0.0.0-20201107091007-3b93a8888063/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= github.com/gordonklaus/ineffassign v0.0.0-20210104184537-8eed68eb605f h1:wHGrcNkjqm/QJeljJ9bkFWtND9I0ASarwpBlRcwRymk= github.com/gordonklaus/ineffassign v0.0.0-20210104184537-8eed68eb605f/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= @@ -403,8 +376,6 @@ github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0m github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= -github.com/iancoleman/strcase v0.1.2 h1:gnomlvw9tnV3ITTAxzKSgTF+8kFWcU/f+TgttpXGz1U= -github.com/iancoleman/strcase v0.1.2/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/iancoleman/strcase v0.1.3 h1:dJBk1m2/qjL1twPLf68JND55vvivMupZ4wIzE8CTdBw= github.com/iancoleman/strcase v0.1.3/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -542,8 +513,6 @@ github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0U github.com/lithammer/shortuuid/v3 v3.0.4 h1:uj4xhotfY92Y1Oa6n6HUiFn87CdoEHYUlTy0+IgbLrs= github.com/lithammer/shortuuid/v3 v3.0.4/go.mod h1:RviRjexKqIzx/7r1peoAITm6m7gnif/h+0zmolKJjzw= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g= -github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magefile/mage v1.11.0 h1:C/55Ywp9BpgVVclD3lRnSYCwXTYxmSppIgLeDYlNuls= github.com/magefile/mage v1.11.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= @@ -585,8 +554,6 @@ github.com/mattn/go-sqlite3 v1.14.0 h1:mLyGNKR8+Vv9CAU7PphKa2hkEqxxhn8i32J6FPj1/ github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= github.com/mattn/go-sqlite3 v1.14.4 h1:4rQjbDxdu9fSgI/r3KN72G3c2goxknAqHHgPWWs8UlI= github.com/mattn/go-sqlite3 v1.14.4/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= -github.com/mattn/go-sqlite3 v1.14.5 h1:1IdxlwTNazvbKJQSxoJ5/9ECbEeaTTyeU7sEAZ5KKTQ= -github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= @@ -875,8 +842,6 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/otel v0.14.0 h1:YFBEfjCk9MTjaytCNSUkp9Q8lF7QJezA06T71FbQxLQ= go.opentelemetry.io/otel v0.14.0/go.mod h1:vH5xEuwy7Rts0GNtsCW3HYQoZDY+OmBJ6t1bFGGlxgw= -go.opentelemetry.io/otel v0.15.0 h1:CZFy2lPhxd4HlhZnYK8gRyDotksO3Ip9rBweY1vVYJw= -go.opentelemetry.io/otel v0.15.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA= go.opentelemetry.io/otel v0.16.0 h1:uIWEbdeb4vpKPGITLsRVUS44L5oDbDUCZxn8lkxhmgw= go.opentelemetry.io/otel v0.16.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -981,7 +946,6 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200505041828-1ed23360d12c/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -1000,26 +964,12 @@ golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/Lt golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201216054612-986b41b23924 h1:QsnDpLLOKwHBBDa8nDws4DYNc/ryVW2vCpxCs09d4PY= golang.org/x/net v0.0.0-20201216054612-986b41b23924/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5 h1:Lm4OryKCca1vehdsWogr9N4t7NfZxLbJoc/H0w4K4S4= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210112200429-01de73cf58bd h1:0n2rzLq6xLtV9OFaT0BF2syUkjOwRrJ1zvXY5hH7Kkc= -golang.org/x/oauth2 v0.0.0-20210112200429-01de73cf58bd/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210113160501-8b1d76fa0423 h1:/hEknzWkMPCjTo7StMHRrBRa8YBbXuBWfck8680k3RE= -golang.org/x/oauth2 v0.0.0-20210113160501-8b1d76fa0423/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3 h1:BaN3BAqnopnKjvl+15DYP6LLrbBHfbfmlFYzmFj/Q9Q= -golang.org/x/oauth2 v0.0.0-20210113205817-d3ed898aa8a3/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210125201302-af13f521f196 h1:w0u30BeG/TALEc6xVf1Klaz2+etRR4K6jxhRkWCqt4g= -golang.org/x/oauth2 v0.0.0-20210125201302-af13f521f196/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210126194326-f9ce19ea3013 h1:55H5j7lotzuFCEOKDsMch+fRNUQ9DgtyHOUP31FNqKc= -golang.org/x/oauth2 v0.0.0-20210126194326-f9ce19ea3013/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210201163806-010130855d6c h1:HiAZXo96zOhVhtFHchj/ojzoxCFiPrp9/j0GtS38V3g= golang.org/x/oauth2 v0.0.0-20210201163806-010130855d6c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1098,10 +1048,6 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuF golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e h1:AyodaIpKjppX+cBfTASF2E1US3H2JFBj920Ot3rtDjs= golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201221093633-bc327ba9c2f0 h1:n+DPcgTwkgWzIFpLmoimYR2K2b0Ga5+Os4kayIN0vGo= -golang.org/x/sys v0.0.0-20201221093633-bc327ba9c2f0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201223074533-0d417f636930 h1:vRgIt+nup/B/BwIS0g2oC0haq0iqbV3ZA+u6+0TlNCo= -golang.org/x/sys v0.0.0-20201223074533-0d417f636930/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= @@ -1144,8 +1090,6 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628034336-212fb13d595e h1:ZlQjfVdpDxeqxRfmO30CdqWWzTvgRCj0MxaUVfxEG1k= -golang.org/x/tools v0.0.0-20190628034336-212fb13d595e/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1364,8 +1308,6 @@ xorm.io/core v0.7.3 h1:W8ws1PlrnkS1CZU1YWaYLMQcQilwAmQXU0BJDJon+H0= xorm.io/core v0.7.3/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM= xorm.io/xorm v1.0.1 h1:/lITxpJtkZauNpdzj+L9CN/3OQxZaABrbergMcJu+Cw= xorm.io/xorm v1.0.1/go.mod h1:o4vnEsQ5V2F1/WK6w4XTwmiWJeGj82tqjAnHe44wVHY= -xorm.io/xorm v1.0.2 h1:kZlCh9rqd1AzGwWitcrEEqHE1h1eaZE/ujU5/2tWEtg= -xorm.io/xorm v1.0.2/go.mod h1:o4vnEsQ5V2F1/WK6w4XTwmiWJeGj82tqjAnHe44wVHY= xorm.io/xorm v1.0.5 h1:LRr5PfOUb4ODPR63YwbowkNDwcolT2LnkwP/TUaMaB0= xorm.io/xorm v1.0.5/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4= xorm.io/xorm v1.0.7 h1:26yBTDVI+CfQpVz2Y88fISh+aiJXIPP4eNoTJlwzsC4= -- 2.40.1 From 0a504a0c5b7a5ece9b76b2a4196d1c8f6cdf8748 Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 2 Feb 2021 21:30:58 +0100 Subject: [PATCH 39/45] Add docs --- .../doc/development/events-and-listeners.md | 195 ++++++++++++++++++ magefile.go | 1 + pkg/models/listeners.go | 5 +- 3 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 docs/content/doc/development/events-and-listeners.md diff --git a/docs/content/doc/development/events-and-listeners.md b/docs/content/doc/development/events-and-listeners.md new file mode 100644 index 000000000..6886cd0ce --- /dev/null +++ b/docs/content/doc/development/events-and-listeners.md @@ -0,0 +1,195 @@ +--- +date: 2018-10-13T19:26:34+02:00 +title: "Events and Listeners" +draft: false +menu: + sidebar: + parent: "development" +--- + +# Events and Listeners + +Vikunja provides a simple observer pattern mechanism through events and listeners. +The basic principle of events is always the same: Something happens (=An event is fired) and something reacts to it (=A listener is called). + +Vikunja supports this principle through the `events` package. +It is built upon the excellent [watermill](https://watermill.io) library. + +Currently, it only supports dispatching events through Go Channels which makes it configuration-less. +More methods of dispatching events (like kafka or rabbitmq) are available in watermill and could be enabled with a PR. + +This document explains how events and listeners work in Vikunja, how to use them and how to create new ones. + +{{< table_of_contents >}} + +## Events + +### Definition + +Each event has to implement this interface: + +```golang +type Event interface { + Name() string +} +``` + +An event can contain whatever data you need. + +When an event is dispatched, all of the data it contains will be marshaled into json for dispatching. +You then get the event with all its data back in the listener, see below. + +#### Naming Convention + +Event names should roughly have the entity they're dealing with on the left and the action on the right of the name, separated by `.`. +There's no limit to how "deep" or specifig an event name can be. + +The name should have the most general concept it's describing at the left, getting more specific on the right of it. + +#### Location + +All events for a package should be declared in the `events.go` file of that package. + +### Creating a New Event + +The easiest way to create a new event is to generate it with mage: + +``` +mage dev:make-event +``` + +The function takes the name of the event as the first argument and the package where the event should be created as the second argument. +Events will be appended to the `pkg//events.go` file. +Both parameters are mandatory. + +The event type name is automatically camel-cased and gets the `Event` suffix if the provided name does not already have one. +The event name is derived from the type name and stripped of the `.event` suffix. + +The generated event will look something like the example below. + +### Dispatching events + +To dispatch an event, simply call the `events.Dispatch` method and pass in the event as parameter. + +### Example + +The `TaskCreatedEvent` is declared in the `pkg/models/events.go` file as follows: + +```golang +// TaskCreatedEvent represents an event where a task has been created +type TaskCreatedEvent struct { + Task *Task + Doer web.Auth +} + +// Name defines the name for TaskCreatedEvent +func (t *TaskCreatedEvent) Name() string { + return "task.created" +} +``` + +It is dispatched in the `createTask` function of the `models` package: + +```golang +func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err error) { + + // ... + + err = events.Dispatch(&TaskCreatedEvent{ + Task: t, + Doer: a, + }) + + // ... +} +``` + +As you can see, the curent task and doer are injected into it. + +### Special Events + +#### `BootedEvent` + +Once Vikunja is fully initialized, right before the api web server is started, this event is fired. + +## Listeners + +A listener is a piece of code that gets executed asynchronously when an event is dispatched. + +A single event can have multiple listeners who are independent of each other. + +### Definition + +All listeners must implement this interface: + +```golang +// Listener represents something that listens to events +type Listener interface { + Handle(payload message.Payload) error + Name() string +} +``` + +The `Handle` method is executed when the event this listener listens on is dispatched. +* As the single parameter, it gets the payload of the event, which is the event struct when it was dispatched decoded as json object and passed as a slice of bytes. +To use it you'll need to unmarshal it. Unfortunately there's no way to pass an already populated event object to the function because we would not know what type it has when parsing it. +* If the handler returns an error, the listener is retried 5 times, with an exponentional back-off period in between retries. +If it still fails after the fifth retry, the event is nack'd and it's up to the event dispatcher to resend it. +You can learn more about this mechanism in the [watermill documentation](https://watermill.io/docs/middlewares/#retry). + +The `Name` method needs to return a unique listener name for this listener. +It should follow the same convention as event names, see above. + +### Creating a New Listener + +The easiest way to create a new listener for an event is with mage: + +``` +mage dev:make-listener +``` + +This will create a new listener type in the `pkg//listners.go` file and implement the `Handle` and `Name` methods. +It will also pre-generate some boilerplate code to unmarshal the event from the payload. + +Furthermore, it will register the listener for its event in the `RegisterListeners()` method of the same file. +This function is called at startup and has to contain all events you want to listen for. + +### Listening for Events + +To listen for an event, you need to register the listener for the event it should be called for. +This usually happens in the `RegisterListeners()` method in `pkg//listners.go` which is called at start up. + +The listener will never be executed if it hasn't been registered. + +See the example below. + +### Example + +```golang +// RegisterListeners registers all event listeners +func RegisterListeners() { + events.RegisterListener((&ListCreatedEvent{}).Name(), &IncreaseListCounter{}) +} + +// IncreaseTaskCounter represents a listener +type IncreaseTaskCounter struct {} + +// Name defines the name for the IncreaseTaskCounter listener +func (s *IncreaseTaskCounter) Name() string { + return "task.counter.increase" +} + +// Hanlde is executed when the event IncreaseTaskCounter listens on is fired +func (s *IncreaseTaskCounter) Handle(payload message.Payload) (err error) { + return keyvalue.IncrBy(metrics.TaskCountKey, 1) +} +``` + +## Testing + +When testing, you should call the `events.Fake()` method in the `TestMain` function of the package you want to test. +This prevents any events from being fired and lets you assert an event has been dispatched like so: + +```golang +events.AssertDispatched(t, &TaskCreatedEvent{}) +``` diff --git a/magefile.go b/magefile.go index 9433185d5..31176ad2a 100644 --- a/magefile.go +++ b/magefile.go @@ -816,6 +816,7 @@ func (t *` + name + `) Name() string { return nil } +// Create a new listener for an event. Takes the name of the listener, the name of the event to listen to and the module where everything should be placed as parameters. func (Dev) MakeListener(name, event, module string) error { name = strcase.ToCamel(name) listenerName := strcase.ToDelimited(name, '.') diff --git a/pkg/models/listeners.go b/pkg/models/listeners.go index 2a6849e19..74826f76a 100644 --- a/pkg/models/listeners.go +++ b/pkg/models/listeners.go @@ -23,6 +23,7 @@ import ( "github.com/ThreeDotsLabs/watermill/message" ) +// RegisterListeners registers all event listeners func RegisterListeners() { events.RegisterListener((&ListCreatedEvent{}).Name(), &IncreaseListCounter{}) events.RegisterListener((&ListDeletedEvent{}).Name(), &DecreaseListCounter{}) @@ -43,7 +44,7 @@ type IncreaseTaskCounter struct { // Name defines the name for the IncreaseTaskCounter listener func (s *IncreaseTaskCounter) Name() string { - return "increase.task.counter" + return "task.counter.increase" } // Hanlde is executed when the event IncreaseTaskCounter listens on is fired @@ -57,7 +58,7 @@ type DecreaseTaskCounter struct { // Name defines the name for the DecreaseTaskCounter listener func (s *DecreaseTaskCounter) Name() string { - return "decrease.task.counter" + return "task.counter.decrease" } // Hanlde is executed when the event DecreaseTaskCounter listens on is fired -- 2.40.1 From fc544bb90e6c1e99484961c08d1e73a82a53f24e Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 2 Feb 2021 21:31:20 +0100 Subject: [PATCH 40/45] Update theme --- docs/themes/vikunja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/themes/vikunja b/docs/themes/vikunja index 958219fc8..3e9a5c467 160000 --- a/docs/themes/vikunja +++ b/docs/themes/vikunja @@ -1 +1 @@ -Subproject commit 958219fc84db455ed58d7a4380bbffc8d04fd5cf +Subproject commit 3e9a5c467c97183fab0aeed800d7de0ce7822e3e -- 2.40.1 From 9c3bf3d15f35007c098fe056880750636e2ad354 Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 2 Feb 2021 21:34:31 +0100 Subject: [PATCH 41/45] Generate docs --- docs/content/doc/setup/config.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/content/doc/setup/config.md b/docs/content/doc/setup/config.md index 4850c9f20..85c561e31 100644 --- a/docs/content/doc/setup/config.md +++ b/docs/content/doc/setup/config.md @@ -446,6 +446,18 @@ Echo has its own logging which usually is unnessecary, which is why it is disabl Default: `off` +### events + +Whether or not to log events. Useful for debugging. Possible values are stdout, stderr, file or off to disable events logging. + +Default: `stdout` + +### eventslevel + +The log level for event log messages. Possible values (case-insensitive) are ERROR, INFO, DEBUG. + +Default: `info` + --- ## ratelimit -- 2.40.1 From f210e915b80a1acdb1bfc069badfe0b6c05b96cf Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 2 Feb 2021 21:40:52 +0100 Subject: [PATCH 42/45] Update theme --- docs/themes/vikunja | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/themes/vikunja b/docs/themes/vikunja index 3e9a5c467..1ebcbbb64 160000 --- a/docs/themes/vikunja +++ b/docs/themes/vikunja @@ -1 +1 @@ -Subproject commit 3e9a5c467c97183fab0aeed800d7de0ce7822e3e +Subproject commit 1ebcbbb645ad20ea683feef2804314a6c658799b -- 2.40.1 From 1635beda5655fb75f54a8f0eb1868cfec209693c Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 2 Feb 2021 22:20:10 +0100 Subject: [PATCH 43/45] Fix getting task attachments and related tasks if none are available --- pkg/models/task_attachment.go | 4 ++++ pkg/models/tasks.go | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/pkg/models/task_attachment.go b/pkg/models/task_attachment.go index 4c557cb71..6d7e70925 100644 --- a/pkg/models/task_attachment.go +++ b/pkg/models/task_attachment.go @@ -209,6 +209,10 @@ func getTaskAttachmentsByTaskIDs(s *xorm.Session, taskIDs []int64) (attachments return } + if len(attachments) == 0 { + return + } + fileIDs := []int64{} userIDs := []int64{} for _, a := range attachments { diff --git a/pkg/models/tasks.go b/pkg/models/tasks.go index 94a6a6081..3ee2edc65 100644 --- a/pkg/models/tasks.go +++ b/pkg/models/tasks.go @@ -597,6 +597,11 @@ func addRelatedTasksToTasks(s *xorm.Session, taskIDs []int64, taskMap map[int64] for _, rt := range relatedTasks { relatedTaskIDs = append(relatedTaskIDs, rt.OtherTaskID) } + + if len(relatedTaskIDs) == 0 { + return + } + fullRelatedTasks := make(map[int64]*Task) err = s.In("id", relatedTaskIDs).Find(&fullRelatedTasks) if err != nil { -- 2.40.1 From cfb15a27f08aa50844ef155fd2c95debc258a06b Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 2 Feb 2021 23:10:50 +0100 Subject: [PATCH 44/45] Fix getting labels, lists or teams if none are available --- pkg/models/label_task.go | 4 ++++ pkg/models/list.go | 8 ++++++++ pkg/models/namespace.go | 8 ++++++++ pkg/models/teams.go | 5 +++++ 4 files changed, 25 insertions(+) diff --git a/pkg/models/label_task.go b/pkg/models/label_task.go index a23cb5163..de5be5c1f 100644 --- a/pkg/models/label_task.go +++ b/pkg/models/label_task.go @@ -208,6 +208,10 @@ func getLabelsByTaskIDs(s *xorm.Session, opts *LabelByTaskIDsOptions) (ls []*lab return nil, 0, 0, err } + if len(labels) == 0 { + return nil, 0, 0, nil + } + // Get all created by users var userids []int64 for _, l := range labels { diff --git a/pkg/models/list.go b/pkg/models/list.go index 4a1616d87..6d65af10d 100644 --- a/pkg/models/list.go +++ b/pkg/models/list.go @@ -389,6 +389,10 @@ func getRawListsForUser(s *xorm.Session, opts *listOptions) (lists []*List, resu // addListDetails adds owner user objects and list tasks to all lists in the slice func addListDetails(s *xorm.Session, lists []*List) (err error) { + if len(lists) == 0 { + return + } + var ownerIDs []int64 for _, l := range lists { ownerIDs = append(ownerIDs, l.OwnerID) @@ -412,6 +416,10 @@ func addListDetails(s *xorm.Session, lists []*List) (err error) { fileIDs = append(fileIDs, l.BackgroundFileID) } + if len(fileIDs) == 0 { + return + } + // Unsplash background file info us := []*UnsplashPhoto{} err = s.In("file_id", fileIDs).Find(&us) diff --git a/pkg/models/namespace.go b/pkg/models/namespace.go index 40460ae85..7f4f00c36 100644 --- a/pkg/models/namespace.go +++ b/pkg/models/namespace.go @@ -531,6 +531,14 @@ func (n *Namespace) Delete(s *xorm.Session, a web.Auth) (err error) { if err != nil { return } + + if len(lists) == 0 { + return events.Dispatch(&NamespaceDeletedEvent{ + Namespace: n, + Doer: a, + }) + } + var listIDs []int64 // We need to do that for here because we need the list ids to delete two times: // 1) to delete the lists itself diff --git a/pkg/models/teams.go b/pkg/models/teams.go index afa1c6ce6..e0727721b 100644 --- a/pkg/models/teams.go +++ b/pkg/models/teams.go @@ -120,6 +120,11 @@ func GetTeamByID(s *xorm.Session, id int64) (team *Team, err error) { } func addMoreInfoToTeams(s *xorm.Session, teams []*Team) (err error) { + + if len(teams) == 0 { + return nil + } + // Put the teams in a map to make assigning more info to it more efficient teamMap := make(map[int64]*Team, len(teams)) var teamIDs []int64 -- 2.40.1 From 27a73cc1ca6b33438357c0ff0ec66a508b9f96a2 Mon Sep 17 00:00:00 2001 From: kolaente Date: Tue, 2 Feb 2021 23:34:46 +0100 Subject: [PATCH 45/45] Increase golangci timeout --- .golangci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index 512b895ef..967ba5d1a 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,5 +1,5 @@ run: - timeout: 5m + timeout: 15m tests: true linters: -- 2.40.1