Merge branch 'main' into feature/caldav-subtasks
This commit is contained in:
commit
5eb38b9ea3
76
.drone.yml
76
.drone.yml
@ -121,23 +121,12 @@ steps:
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
- name: prepare-build
|
||||
image: vikunja/golang-build:latest
|
||||
pull: always
|
||||
environment:
|
||||
GOPROXY: 'https://goproxy.kolaente.de'
|
||||
depends_on: [ mage ]
|
||||
commands:
|
||||
- ./mage-static do-the-swag
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
- name: build
|
||||
image: vikunja/golang-build:latest
|
||||
pull: always
|
||||
environment:
|
||||
GOPROXY: 'https://goproxy.kolaente.de'
|
||||
depends_on: [ prepare-build ]
|
||||
depends_on: [ mage ]
|
||||
commands:
|
||||
- ./mage-static build:build
|
||||
when:
|
||||
@ -230,7 +219,7 @@ steps:
|
||||
GOPROXY: 'https://goproxy.kolaente.de'
|
||||
commands:
|
||||
- ./mage-static test:unit
|
||||
depends_on: [ fetch-tags, prepare-build ]
|
||||
depends_on: [ fetch-tags, mage ]
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
@ -247,7 +236,7 @@ steps:
|
||||
path: /db
|
||||
commands:
|
||||
- ./mage-static test:unit
|
||||
depends_on: [ fetch-tags, prepare-build ]
|
||||
depends_on: [ fetch-tags, mage ]
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
@ -264,7 +253,7 @@ steps:
|
||||
VIKUNJA_DATABASE_DATABASE: vikunjatest
|
||||
commands:
|
||||
- ./mage-static test:unit
|
||||
depends_on: [ fetch-tags, prepare-build ]
|
||||
depends_on: [ fetch-tags, mage ]
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
@ -282,7 +271,7 @@ steps:
|
||||
VIKUNJA_DATABASE_SSLMODE: disable
|
||||
commands:
|
||||
- ./mage-static test:unit
|
||||
depends_on: [ fetch-tags, prepare-build ]
|
||||
depends_on: [ fetch-tags, mage ]
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
@ -293,7 +282,7 @@ steps:
|
||||
GOPROXY: 'https://goproxy.kolaente.de'
|
||||
commands:
|
||||
- ./mage-static test:integration
|
||||
depends_on: [ fetch-tags, prepare-build ]
|
||||
depends_on: [ fetch-tags, mage ]
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
@ -310,7 +299,7 @@ steps:
|
||||
path: /db
|
||||
commands:
|
||||
- ./mage-static test:integration
|
||||
depends_on: [ fetch-tags, prepare-build ]
|
||||
depends_on: [ fetch-tags, mage ]
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
@ -327,7 +316,7 @@ steps:
|
||||
VIKUNJA_DATABASE_DATABASE: vikunjatest
|
||||
commands:
|
||||
- ./mage-static test:integration
|
||||
depends_on: [ fetch-tags, prepare-build ]
|
||||
depends_on: [ fetch-tags, mage ]
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
@ -345,10 +334,54 @@ steps:
|
||||
VIKUNJA_DATABASE_SSLMODE: disable
|
||||
commands:
|
||||
- ./mage-static test:integration
|
||||
depends_on: [ fetch-tags, prepare-build ]
|
||||
depends_on: [ fetch-tags, mage ]
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: generate-swagger-docs
|
||||
|
||||
depends_on:
|
||||
- testing
|
||||
|
||||
workspace:
|
||||
base: /go
|
||||
path: src/code.vikunja.io/api
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
include:
|
||||
- main
|
||||
event:
|
||||
include:
|
||||
- push
|
||||
|
||||
steps:
|
||||
- name: generate-swagger-docs
|
||||
image: vikunja/golang-build:latest
|
||||
pull: always
|
||||
environment:
|
||||
GOPROXY: 'https://goproxy.kolaente.de'
|
||||
commands:
|
||||
- mage do-the-swag
|
||||
|
||||
- name: push
|
||||
pull: always
|
||||
image: appleboy/drone-git-push
|
||||
depends_on:
|
||||
- generate-swagger-docs
|
||||
settings:
|
||||
author_email: "frederik@vikunja.io"
|
||||
author_name: Frederick [Bot]
|
||||
branch: main
|
||||
commit: true
|
||||
commit_message: "[skip ci] Updated swagger docs"
|
||||
remote: "ssh://git@kolaente.dev:9022/vikunja/api.git"
|
||||
ssh_key:
|
||||
from_secret: git_push_ssh_key
|
||||
|
||||
---
|
||||
########
|
||||
# Build a release when tagging
|
||||
@ -396,7 +429,6 @@ steps:
|
||||
- export PATH=$PATH:$GOPATH/bin
|
||||
- go install github.com/magefile/mage
|
||||
- ./mage-static release:dirs
|
||||
- ./mage-static do-the-swag
|
||||
depends_on: [ fetch-tags, mage ]
|
||||
|
||||
- name: static-build-windows
|
||||
@ -743,6 +775,6 @@ steps:
|
||||
- failure
|
||||
---
|
||||
kind: signature
|
||||
hmac: d47bd1cf6f3e9be2ff3eed2039e65c8b6de2b16c1e636699f66382f941277411
|
||||
hmac: b32ea5780ab6c4e57f201ec468357340349591a3026c96efd669a0b9c10f0e34
|
||||
|
||||
...
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -27,4 +27,3 @@ vikunja-dump*
|
||||
vendor/
|
||||
os-packages/
|
||||
mage_output_file.go
|
||||
pkg/swagger/*
|
||||
|
71
go.sum
71
go.sum
@ -82,8 +82,6 @@ github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/arran4/golang-ical v0.0.0-20230425234049-f69e132f2b0c h1:bmHPCBB1T8YZpQI+Ch0RuICrozVFmPAjiBQZvAjtpRI=
|
||||
github.com/arran4/golang-ical v0.0.0-20230425234049-f69e132f2b0c/go.mod h1:BSTTrYHuM12oAL8jDdcmPdw02SBThKYWNFHQlvEG6b0=
|
||||
github.com/arran4/golang-ical v0.1.0 h1:Oz0Rd5fpeNoHNFF9B9H5uYZyt1ubuZSZ3LVdHD5KvZI=
|
||||
github.com/arran4/golang-ical v0.1.0/go.mod h1:BSTTrYHuM12oAL8jDdcmPdw02SBThKYWNFHQlvEG6b0=
|
||||
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
@ -168,8 +166,6 @@ github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustinkirkland/golang-petname v0.0.0-20191129215211-8e5a1ed0cff0 h1:90Ly+6UfUypEF6vvvW5rQIv9opIL8CbmW9FT20LDQoY=
|
||||
github.com/dustinkirkland/golang-petname v0.0.0-20191129215211-8e5a1ed0cff0/go.mod h1:V+Qd57rJe8gd4eiGzZyg4h54VLHmYVVw54iMnlAMrF8=
|
||||
github.com/dustinkirkland/golang-petname v0.0.0-20230626224747-e794b9370d49 h1:6SNWi8VxQeCSwmLuTbEvJd7xvPmdS//zvMBWweZLgck=
|
||||
github.com/dustinkirkland/golang-petname v0.0.0-20230626224747-e794b9370d49/go.mod h1:V+Qd57rJe8gd4eiGzZyg4h54VLHmYVVw54iMnlAMrF8=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
@ -193,8 +189,6 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
|
||||
github.com/getsentry/sentry-go v0.22.0 h1:XNX9zKbv7baSEI65l+H1GEJgSeIC1c7EN5kluWaP6dM=
|
||||
github.com/getsentry/sentry-go v0.22.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||
github.com/getsentry/sentry-go v0.23.0 h1:dn+QRCeJv4pPt9OjVXiMcGIBIefaTJPw/h0bZWO05nE=
|
||||
github.com/getsentry/sentry-go v0.23.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
@ -203,8 +197,6 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
|
||||
github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
|
||||
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
@ -223,9 +215,7 @@ github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgO
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
|
||||
github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
|
||||
@ -234,10 +224,10 @@ github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/a
|
||||
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
|
||||
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
@ -257,8 +247,6 @@ github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d h1:KbPOUXFUDJxwZ04v
|
||||
github.com/gocarina/gocsv v0.0.0-20230616125104-99d496ca653d/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI=
|
||||
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
|
||||
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
@ -289,6 +277,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
|
||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@ -343,7 +332,6 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@ -388,8 +376,6 @@ github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2p
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0=
|
||||
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
|
||||
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
@ -463,7 +449,6 @@ github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
@ -476,15 +461,12 @@ github.com/jszwedko/go-datemath v0.1.1-0.20230526204004-640a500621d6/go.mod h1:W
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
|
||||
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
|
||||
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
@ -507,10 +489,6 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo-jwt/v4 v4.2.0 h1:odSISV9JgcSCuhgQSV/6Io3i7nUmfM/QkBeR5GVJj5c=
|
||||
github.com/labstack/echo-jwt/v4 v4.2.0/go.mod h1:MA2RqdXdEn4/uEglx0HcUOgQSyBaTh5JcaHIan3biwU=
|
||||
github.com/labstack/echo/v4 v4.1.16/go.mod h1:awO+5TzAjvL8XpibdsfXxPgHr+orhtXZJZIQCVjogKI=
|
||||
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
|
||||
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
|
||||
github.com/labstack/echo/v4 v4.11.0 h1:4Dmi59tmrnFzOchz4EXuGjJhUfcEkU28iDKsiZVOQgw=
|
||||
github.com/labstack/echo/v4 v4.11.0/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ=
|
||||
github.com/labstack/echo/v4 v4.11.1 h1:dEpLU2FLg4UVmvCGPuk/APjlH6GDpbEPti61srUUUs4=
|
||||
github.com/labstack/echo/v4 v4.11.1/go.mod h1:YuYRTSM3CHs2ybfrL8Px48bO6BAnYIN4l8wSTMP6BDQ=
|
||||
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
|
||||
@ -561,12 +539,9 @@ github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2y
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
|
||||
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
@ -596,7 +571,6 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
||||
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
|
||||
@ -641,8 +615,6 @@ github.com/paulmach/orb v0.9.0 h1:MwA1DqOKtvCgm7u9RZ/pnYejTeDJPnr0+0oFajBbJqk=
|
||||
github.com/paulmach/orb v0.9.0/go.mod h1:SudmOk85SXtmXAB3sLGyJ6tZy/8pdfrV0o6ef98Xc30=
|
||||
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
|
||||
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
|
||||
github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
|
||||
github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
|
||||
@ -698,7 +670,6 @@ github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
|
||||
@ -760,7 +731,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
|
||||
@ -793,8 +763,6 @@ github.com/valyala/fasttemplate v1.2.0/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPU
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/wneessen/go-mail v0.3.9 h1:Q4DbCk3htT5DtDWKeMgNXCiHc4bBY/vv/XQPT6XDXzc=
|
||||
github.com/wneessen/go-mail v0.3.9/go.mod h1:zxOlafWCP/r6FEhAaRgH4IC1vg2YXxO0Nar9u0IScZ8=
|
||||
github.com/wneessen/go-mail v0.4.0 h1:Oo4HLIV8My7G9JuZkoOX6eipXQD+ACvIqURYeIzUc88=
|
||||
github.com/wneessen/go-mail v0.4.0/go.mod h1:zxOlafWCP/r6FEhAaRgH4IC1vg2YXxO0Nar9u0IScZ8=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
@ -864,10 +832,6 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@ -887,10 +851,6 @@ golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMe
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.8.0 h1:agUcRXV/+w6L9ryntYYsF2x9fQTMd4T8fiiYXAVW6Jg=
|
||||
golang.org/x/image v0.8.0/go.mod h1:PwLxp3opCYg4WR2WO9P0L6ESnsD6bLTWcw8zanLMVFM=
|
||||
golang.org/x/image v0.9.0 h1:QrzfX26snvCM20hIhBwuHI/ThTg18b/+kcKdXHvnR+g=
|
||||
golang.org/x/image v0.9.0/go.mod h1:jtrku+n79PfroUbvDdeUWMAI+heR786BofxrbiSF+J0=
|
||||
golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo=
|
||||
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@ -916,8 +876,6 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -966,10 +924,6 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
|
||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@ -981,8 +935,6 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.9.0 h1:BPpt2kU7oMRq3kCHAA1tbSEshXRw1LpG2ztgDwrzuAs=
|
||||
golang.org/x/oauth2 v0.9.0/go.mod h1:qYgFZaFiu6Wg24azG8bdV52QJXJGbZzIIsRCdVKzbLw=
|
||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -1068,20 +1020,12 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
|
||||
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
|
||||
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
|
||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
||||
golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@ -1093,10 +1037,6 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
|
||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
|
||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@ -1168,8 +1108,6 @@ golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||
golang.org/x/tools v0.11.1 h1:ojD5zOW8+7dOGzdnNgersm8aPfcDjhMp12UfG93NIMc=
|
||||
golang.org/x/tools v0.11.1/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
|
||||
@ -1282,8 +1220,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
@ -1441,15 +1377,12 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
|
||||
src.techknowlogick.com/xgo v1.7.1-0.20230606181629-494bc06f804a h1:3UOdsZC8cRR4OVlNZS8YiChlp8g7eiNUYT+DAQmZt20=
|
||||
src.techknowlogick.com/xgo v1.7.1-0.20230606181629-494bc06f804a/go.mod h1:31CE1YKtDOrKTk9PSnjTpe6YbO6W/0LTYZ1VskL09oU=
|
||||
src.techknowlogick.com/xgo v1.7.1-0.20230711181658-617d3b65dd40 h1:elzESSqGnEJoseRrOqqdYcmiZrDo0geMdkMQqb98IaE=
|
||||
src.techknowlogick.com/xgo v1.7.1-0.20230711181658-617d3b65dd40/go.mod h1:31CE1YKtDOrKTk9PSnjTpe6YbO6W/0LTYZ1VskL09oU=
|
||||
src.techknowlogick.com/xormigrate v1.5.0 h1:6mWTh8d0sWjMTLUgJqiLe0e0Teu+1j+RgI7ErAeOEV0=
|
||||
src.techknowlogick.com/xormigrate v1.5.0/go.mod h1:QOCnBeWralVncPn9eZlM4w/rglFK8o1vYpemzPenkBM=
|
||||
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/builder v0.3.12 h1:ASZYX7fQmy+o8UJdhlLHSW57JDOkM8DNhcAF5d0LiJM=
|
||||
xorm.io/builder v0.3.12/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
xorm.io/builder v0.3.13 h1:a3jmiVVL19psGeXx8GIurTp7p0IIgqeDmwhcR6BAOAo=
|
||||
xorm.io/builder v0.3.13/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||
|
10
magefile.go
10
magefile.go
@ -177,9 +177,6 @@ func init() {
|
||||
// Some variables have external dependencies (like git) which may not always be available.
|
||||
func initVars() {
|
||||
Tags = os.Getenv("TAGS")
|
||||
if !strings.Contains(Tags, "swagger") {
|
||||
Tags += " swagger"
|
||||
}
|
||||
setVersion()
|
||||
setBinLocation()
|
||||
setPkgVersion()
|
||||
@ -349,10 +346,6 @@ const swaggerDocsFolderLocation = `./pkg/swagger/`
|
||||
// Generates the swagger docs from the code annotations
|
||||
func DoTheSwag() {
|
||||
mg.Deps(initVars)
|
||||
if _, err := os.Stat(swaggerDocsFolderLocation + "swagger.json"); err == nil {
|
||||
fmt.Println("Swagger docs already generated, not generating. Remove the files in " + swaggerDocsFolderLocation + " and run this command again to regenerate them.")
|
||||
return
|
||||
}
|
||||
|
||||
checkAndInstallGoTool("swag", "github.com/swaggo/swag/cmd/swag")
|
||||
runAndStreamOutput("swag", "init", "-g", "./pkg/routes/routes.go", "--parseDependency", "-d", RootPath, "-o", RootPath+"/pkg/swagger")
|
||||
@ -469,7 +462,6 @@ func (Build) Clean() error {
|
||||
// Builds a vikunja binary, ready to run
|
||||
func (Build) Build() {
|
||||
mg.Deps(initVars)
|
||||
mg.Deps(DoTheSwag)
|
||||
runAndStreamOutput("go", "build", Goflags[0], "-tags", Tags, "-ldflags", "-s -w "+Ldflags, "-o", Executable)
|
||||
}
|
||||
|
||||
@ -479,7 +471,6 @@ type Release mg.Namespace
|
||||
func (Release) Release(ctx context.Context) error {
|
||||
mg.Deps(initVars)
|
||||
mg.Deps(Release.Dirs)
|
||||
mg.Deps(DoTheSwag)
|
||||
|
||||
// Run compiling in parallel to speed it up
|
||||
errs, _ := errgroup.WithContext(ctx)
|
||||
@ -521,7 +512,6 @@ func (Release) Dirs() error {
|
||||
|
||||
func runXgo(targets string) error {
|
||||
mg.Deps(initVars)
|
||||
mg.Deps(DoTheSwag)
|
||||
checkAndInstallGoTool("xgo", "src.techknowlogick.com/xgo")
|
||||
|
||||
extraLdflags := `-linkmode external -extldflags "-static" `
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"time"
|
||||
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/utils"
|
||||
@ -98,8 +99,12 @@ func ParseTaskFromVTODO(content string) (vTask *models.Task, err error) {
|
||||
var parsedProperties = vTodo.UnknownPropertiesIANAProperties()
|
||||
// We put the vTodo details in a map to be able to handle them more easily
|
||||
task := make(map[string]ics.IANAProperty)
|
||||
for _, c := range parsedProperties {
|
||||
var relation ics.IANAProperty
|
||||
for _, c := range vTodo.UnknownPropertiesIANAProperties() {
|
||||
task[c.IANAToken] = c
|
||||
if strings.HasPrefix(c.IANAToken, "RELATED-TO") {
|
||||
relation = c
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the priority
|
||||
@ -162,6 +167,19 @@ func ParseTaskFromVTODO(content string) (vTask *models.Task, err error) {
|
||||
DoneAt: caldavTimeToTimestamp(task["COMPLETED"]),
|
||||
}
|
||||
|
||||
if relation.Value != "" {
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
subtask, err := models.GetTaskSimpleByUUID(s, relation.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
vTask.RelatedTasks = make(map[models.RelationKind][]*models.Task)
|
||||
vTask.RelatedTasks[models.RelationKindSubtask] = []*models.Task{subtask}
|
||||
}
|
||||
|
||||
if task["STATUS"].Value == "COMPLETED" {
|
||||
vTask.Done = true
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ var dumpCmd = &cobra.Command{
|
||||
Use: "dump",
|
||||
Short: "Dump all vikunja data into a zip file. Includes config, files and db.",
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
initialize.FullInit()
|
||||
initialize.FullInitWithoutAsync()
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
filename := "vikunja-dump_" + time.Now().Format("2006-01-02_15-03-05") + ".zip"
|
||||
|
@ -32,7 +32,7 @@ var indexCmd = &cobra.Command{
|
||||
Use: "index",
|
||||
Short: "Reindex all of Vikunja's data into Typesense. This will remove any existing index.",
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
initialize.FullInit()
|
||||
initialize.FullInitWithoutAsync()
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if !config.TypesenseEnabled.GetBool() {
|
||||
@ -44,12 +44,12 @@ var indexCmd = &cobra.Command{
|
||||
|
||||
err := models.CreateTypesenseCollections()
|
||||
if err != nil {
|
||||
log.Critical(err.Error())
|
||||
log.Criticalf("Could not create Typesense collections: %s", err.Error())
|
||||
return
|
||||
}
|
||||
err = models.ReindexAllTasks()
|
||||
if err != nil {
|
||||
log.Critical(err.Error())
|
||||
log.Criticalf("Could not reindex all tasks into Typesense: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ var restoreCmd = &cobra.Command{
|
||||
Short: "Restores all vikunja data from a vikunja dump.",
|
||||
Args: cobra.ExactArgs(1),
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
initialize.FullInit()
|
||||
initialize.FullInitWithoutAsync()
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := dump.Restore(args[0]); err != nil {
|
||||
|
@ -18,7 +18,6 @@
|
||||
title: testbucket3
|
||||
project_id: 1
|
||||
created_by_id: 1
|
||||
is_done_bucket: 1
|
||||
position: 3
|
||||
created: 2020-04-18 21:13:52
|
||||
updated: 2020-04-18 21:13:52
|
||||
@ -26,7 +25,6 @@
|
||||
title: testbucket4 - other project
|
||||
project_id: 2
|
||||
created_by_id: 1
|
||||
is_done_bucket: 1
|
||||
created: 2020-04-18 21:13:52
|
||||
updated: 2020-04-18 21:13:52
|
||||
# The following are not or only partly owned by user 1
|
||||
@ -40,6 +38,7 @@
|
||||
title: testbucket6
|
||||
project_id: 6
|
||||
created_by_id: 1
|
||||
position: 1
|
||||
created: 2020-04-18 21:13:52
|
||||
updated: 2020-04-18 21:13:52
|
||||
- id: 7
|
||||
@ -137,6 +136,7 @@
|
||||
title: testbucket22
|
||||
project_id: 6
|
||||
created_by_id: 1
|
||||
position: 2
|
||||
created: 2020-04-18 21:13:52
|
||||
updated: 2020-04-18 21:13:52
|
||||
- id: 23
|
||||
|
@ -5,6 +5,7 @@
|
||||
identifier: test1
|
||||
owner_id: 1
|
||||
position: 3
|
||||
done_bucket_id: 3
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
@ -14,6 +15,7 @@
|
||||
identifier: test2
|
||||
owner_id: 3
|
||||
position: 2
|
||||
done_bucket_id: 4
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
@ -50,6 +52,7 @@
|
||||
identifier: test6
|
||||
owner_id: 6
|
||||
position: 6
|
||||
default_bucket_id: 22
|
||||
updated: 2018-12-02 15:13:12
|
||||
created: 2018-12-01 15:13:12
|
||||
-
|
||||
|
@ -60,9 +60,8 @@ func InitEngines() {
|
||||
}
|
||||
}
|
||||
|
||||
// FullInit initializes all kinds of things in the right order
|
||||
func FullInit() {
|
||||
|
||||
// FullInitWithoutAsync does a full init without any async handlers (cron or events)
|
||||
func FullInitWithoutAsync() {
|
||||
LightInit()
|
||||
|
||||
// Initialize the files handler
|
||||
@ -79,6 +78,12 @@ func FullInit() {
|
||||
|
||||
// Start the mail daemon
|
||||
mail.StartMailDaemon()
|
||||
}
|
||||
|
||||
// FullInit initializes all kinds of things in the right order
|
||||
func FullInit() {
|
||||
|
||||
FullInitWithoutAsync()
|
||||
|
||||
// Start the cron
|
||||
cron.Init()
|
||||
|
118
pkg/migration/20230903143017.go
Normal file
118
pkg/migration/20230903143017.go
Normal file
@ -0,0 +1,118 @@
|
||||
// Vikunja is a to-do list application to facilitate your life.
|
||||
// Copyright 2018-present 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
package migration
|
||||
|
||||
import (
|
||||
"src.techknowlogick.com/xormigrate"
|
||||
"xorm.io/xorm"
|
||||
"xorm.io/xorm/schemas"
|
||||
)
|
||||
|
||||
type projects20230903143017 struct {
|
||||
ID int64 `xorm:"bigint autoincr not null unique pk" json:"id" param:"project"`
|
||||
DefaultBucketID int64 `xorm:"bigint INDEX null" json:"default_bucket_id"`
|
||||
DoneBucketID int64 `xorm:"bigint INDEX null" json:"done_bucket_id"`
|
||||
}
|
||||
|
||||
func (projects20230903143017) TableName() string {
|
||||
return "projects"
|
||||
}
|
||||
|
||||
type bucket20230903143017 struct {
|
||||
ID int64 `xorm:"bigint autoincr not null unique pk" json:"id" param:"bucket"`
|
||||
IsDoneBucket bool `xorm:"BOOL" json:"is_done_bucket"`
|
||||
ProjectID int64 `xorm:"bigint not null" json:"project_id" param:"project"`
|
||||
}
|
||||
|
||||
func (bucket20230903143017) TableName() string {
|
||||
return "buckets"
|
||||
}
|
||||
|
||||
const dropIsDoneBucketColSqlite20230903143017 = `
|
||||
create table buckets_dg_tmp
|
||||
(
|
||||
id INTEGER not null
|
||||
primary key autoincrement,
|
||||
title TEXT not null,
|
||||
project_id INTEGER not null,
|
||||
"limit" INTEGER default 0,
|
||||
position REAL,
|
||||
created DATETIME not null,
|
||||
updated DATETIME not null,
|
||||
created_by_id INTEGER not null
|
||||
);
|
||||
|
||||
insert into buckets_dg_tmp(id, title, project_id, "limit", position, created, updated, created_by_id)
|
||||
select id,
|
||||
title,
|
||||
project_id,
|
||||
"limit",
|
||||
position,
|
||||
created,
|
||||
updated,
|
||||
created_by_id
|
||||
from buckets;
|
||||
|
||||
drop table buckets;
|
||||
|
||||
alter table buckets_dg_tmp
|
||||
rename to buckets;
|
||||
|
||||
create unique index UQE_buckets_id
|
||||
on buckets (id);
|
||||
`
|
||||
|
||||
func init() {
|
||||
migrations = append(migrations, &xormigrate.Migration{
|
||||
ID: "20230903143017",
|
||||
Description: "Move done bucket state to project + add default bucket setting",
|
||||
Migrate: func(tx *xorm.Engine) (err error) {
|
||||
err = tx.Sync2(projects20230903143017{})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
doneBuckets := []*bucket20230903143017{}
|
||||
err = tx.Where("is_done_bucket = true").
|
||||
Find(&doneBuckets)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, bucket := range doneBuckets {
|
||||
_, err = tx.Where("id = ?", bucket.ProjectID).
|
||||
Cols("done_bucket_id").
|
||||
Update(&projects20230903143017{
|
||||
DoneBucketID: bucket.ID,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if tx.Dialect().URI().DBType == schemas.SQLITE {
|
||||
_, err = tx.Exec(dropIsDoneBucketColSqlite20230903143017)
|
||||
return err
|
||||
}
|
||||
|
||||
return dropTableColum(tx, "buckets", "is_done_bucket")
|
||||
},
|
||||
Rollback: func(tx *xorm.Engine) error {
|
||||
return nil
|
||||
},
|
||||
})
|
||||
}
|
@ -55,6 +55,8 @@ func getRouteGroupName(path string) string {
|
||||
|
||||
finalName := strings.Join(filteredParts, "_")
|
||||
switch finalName {
|
||||
case "projects_tasks":
|
||||
fallthrough
|
||||
case "tasks_all":
|
||||
return "tasks"
|
||||
default:
|
||||
@ -129,7 +131,13 @@ func GetAvailableAPIRoutesForToken(c echo.Context) error {
|
||||
|
||||
// CanDoAPIRoute checks if a token is allowed to use the current api route
|
||||
func CanDoAPIRoute(c echo.Context, token *APIToken) (can bool) {
|
||||
path := c.Request().URL.Path
|
||||
path := c.Path()
|
||||
if path == "" {
|
||||
// c.Path() is empty during testing, but returns the path which the route used during registration
|
||||
// which is what we need.
|
||||
path = c.Request().URL.Path
|
||||
}
|
||||
|
||||
routeGroupName := getRouteGroupName(path)
|
||||
|
||||
group, hasGroup := token.Permissions[routeGroupName]
|
||||
|
@ -38,8 +38,6 @@ type Bucket struct {
|
||||
|
||||
// How many tasks can be at the same time on this board max
|
||||
Limit int64 `xorm:"default 0" json:"limit" minimum:"0" valid:"range(0|9223372036854775807)"`
|
||||
// If this bucket is the "done bucket". All tasks moved into this bucket will automatically marked as done. All tasks marked as done from elsewhere will be moved into this bucket.
|
||||
IsDoneBucket bool `xorm:"BOOL" json:"is_done_bucket"`
|
||||
|
||||
// The number of tasks currently in this bucket
|
||||
Count int64 `xorm:"-" json:"count"`
|
||||
@ -80,28 +78,21 @@ func getBucketByID(s *xorm.Session, id int64) (b *Bucket, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func getDefaultBucket(s *xorm.Session, projectID int64) (bucket *Bucket, err error) {
|
||||
bucket = &Bucket{}
|
||||
func getDefaultBucketID(s *xorm.Session, project *Project) (bucketID int64, err error) {
|
||||
if project.DefaultBucketID != 0 {
|
||||
return project.DefaultBucketID, nil
|
||||
}
|
||||
|
||||
bucket := &Bucket{}
|
||||
_, err = s.
|
||||
Where("project_id = ?", projectID).
|
||||
Where("project_id = ?", project.ID).
|
||||
OrderBy("position asc").
|
||||
Get(bucket)
|
||||
return
|
||||
}
|
||||
|
||||
func getDoneBucketForProject(s *xorm.Session, projectID int64) (bucket *Bucket, err error) {
|
||||
bucket = &Bucket{}
|
||||
exists, err := s.
|
||||
Where("project_id = ? and is_done_bucket = ?", projectID, true).
|
||||
Get(bucket)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
bucket = nil
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return
|
||||
return bucket.ID, nil
|
||||
}
|
||||
|
||||
// ReadAll returns all buckets with their tasks for a certain project
|
||||
@ -287,29 +278,11 @@ func (b *Bucket) Create(s *xorm.Session, a web.Auth) (err error) {
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /projects/{projectID}/buckets/{bucketID} [post]
|
||||
func (b *Bucket) Update(s *xorm.Session, _ web.Auth) (err error) {
|
||||
doneBucket, err := getDoneBucketForProject(s, b.ProjectID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if doneBucket != nil && doneBucket.IsDoneBucket && b.IsDoneBucket && doneBucket.ID != b.ID {
|
||||
// When the current bucket will be the new done bucket, the old one should not be the done bucket anymore
|
||||
doneBucket.IsDoneBucket = false
|
||||
_, err = s.
|
||||
Where("id = ?", doneBucket.ID).
|
||||
Cols("is_done_bucket").
|
||||
Update(doneBucket)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
_, err = s.
|
||||
Where("id = ?", b.ID).
|
||||
Cols(
|
||||
"title",
|
||||
"limit",
|
||||
"is_done_bucket",
|
||||
"position",
|
||||
).
|
||||
Update(b)
|
||||
@ -350,15 +323,19 @@ func (b *Bucket) Delete(s *xorm.Session, _ web.Auth) (err error) {
|
||||
}
|
||||
|
||||
// Get the default bucket
|
||||
defaultBucket, err := getDefaultBucket(s, b.ProjectID)
|
||||
p, err := GetProjectSimpleByID(s, b.ProjectID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defaultBucketID, err := getDefaultBucketID(s, p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove all associations of tasks to that bucket
|
||||
_, err = s.
|
||||
Where("bucket_id = ?", b.ID).
|
||||
Cols("bucket_id").
|
||||
Update(&Task{BucketID: defaultBucket.ID})
|
||||
Update(&Task{BucketID: defaultBucketID})
|
||||
return
|
||||
}
|
||||
|
@ -217,28 +217,4 @@ func TestBucket_Update(t *testing.T) {
|
||||
|
||||
testAndAssertBucketUpdate(t, b, s)
|
||||
})
|
||||
t.Run("old done bucket should be unset", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
b := &Bucket{
|
||||
ID: 1,
|
||||
ProjectID: 1,
|
||||
IsDoneBucket: true,
|
||||
}
|
||||
|
||||
err := b.Update(s, &user.User{ID: 1})
|
||||
assert.NoError(t, err)
|
||||
db.AssertExists(t, "buckets", map[string]interface{}{
|
||||
"id": 1,
|
||||
"project_id": 1,
|
||||
"is_done_bucket": true,
|
||||
}, false)
|
||||
db.AssertExists(t, "buckets", map[string]interface{}{
|
||||
"id": 3,
|
||||
"project_id": 1,
|
||||
"is_done_bucket": false,
|
||||
}, false)
|
||||
})
|
||||
}
|
||||
|
@ -51,6 +51,11 @@ type Project struct {
|
||||
ParentProjectID int64 `xorm:"bigint INDEX null" json:"parent_project_id"`
|
||||
ParentProject *Project `xorm:"-" json:"-"`
|
||||
|
||||
// The ID of the bucket where new tasks without a bucket are added to. By default, this is the leftmost bucket in a project.
|
||||
DefaultBucketID int64 `xorm:"bigint INDEX null" json:"default_bucket_id"`
|
||||
// If tasks are moved to the done bucket, they are marked as done. If they are marked as done individually, they are moved into the done bucket.
|
||||
DoneBucketID int64 `xorm:"bigint INDEX null" json:"done_bucket_id"`
|
||||
|
||||
// The user who created this project.
|
||||
Owner *user.User `xorm:"-" json:"owner" valid:"-"`
|
||||
|
||||
@ -363,18 +368,20 @@ func getUserProjectsStatement(parentProjectIDs []int64, userID int64, search str
|
||||
}
|
||||
|
||||
var parentCondition builder.Cond
|
||||
parentCondition = builder.Or(
|
||||
builder.IsNull{"l.parent_project_id"},
|
||||
builder.Eq{"l.parent_project_id": 0},
|
||||
// else check for shared sub projects with a parent
|
||||
builder.And(
|
||||
builder.Or(
|
||||
builder.NotNull{"tm2.user_id"},
|
||||
builder.NotNull{"ul.user_id"},
|
||||
if search == "" {
|
||||
parentCondition = builder.Or(
|
||||
builder.IsNull{"l.parent_project_id"},
|
||||
builder.Eq{"l.parent_project_id": 0},
|
||||
// else check for shared sub projects with a parent
|
||||
builder.And(
|
||||
builder.Or(
|
||||
builder.NotNull{"tm2.user_id"},
|
||||
builder.NotNull{"ul.user_id"},
|
||||
),
|
||||
builder.NotNull{"l.parent_project_id"},
|
||||
),
|
||||
builder.NotNull{"l.parent_project_id"},
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
projectCol := "id"
|
||||
if len(parentProjectIDs) > 0 {
|
||||
parentCondition = builder.In("l.parent_project_id", parentProjectIDs)
|
||||
@ -778,6 +785,8 @@ func UpdateProject(s *xorm.Session, project *Project, auth web.Auth, updateProje
|
||||
"hex_color",
|
||||
"parent_project_id",
|
||||
"position",
|
||||
"done_bucket_id",
|
||||
"default_bucket_id",
|
||||
}
|
||||
if project.Description != "" {
|
||||
colsToUpdate = append(colsToUpdate, "description")
|
||||
|
@ -371,6 +371,11 @@ func (bt *BulkTask) GetTasksByIDs(s *xorm.Session) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func GetTaskSimpleByUUID(s *xorm.Session, uid string) (task *Task, err error) {
|
||||
_, err = s.In("uid", uid).Get(task)
|
||||
return
|
||||
}
|
||||
|
||||
// GetTasksByUIDs gets all tasks from a bunch of uids
|
||||
func GetTasksByUIDs(s *xorm.Session, uids []string, a web.Auth) (tasks []*Task, err error) {
|
||||
tasks = []*Task{}
|
||||
@ -629,17 +634,18 @@ func checkBucketLimit(s *xorm.Session, t *Task, bucket *Bucket) (err error) {
|
||||
}
|
||||
|
||||
// Contains all the task logic to figure out what bucket to use for this task.
|
||||
func setTaskBucket(s *xorm.Session, task *Task, originalTask *Task, doCheckBucketLimit bool) (targetBucket *Bucket, err error) {
|
||||
// Make sure we have a bucket
|
||||
var bucket *Bucket
|
||||
if task.Done && originalTask != nil && !originalTask.Done {
|
||||
bucket, err := getDoneBucketForProject(s, task.ProjectID)
|
||||
func setTaskBucket(s *xorm.Session, task *Task, originalTask *Task, doCheckBucketLimit bool, project *Project) (targetBucket *Bucket, err error) {
|
||||
|
||||
if project == nil {
|
||||
project, err = GetProjectSimpleByID(s, task.ProjectID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if bucket != nil {
|
||||
task.BucketID = bucket.ID
|
||||
}
|
||||
}
|
||||
|
||||
var bucket *Bucket
|
||||
if task.Done && originalTask != nil && !originalTask.Done {
|
||||
task.BucketID = project.DoneBucketID
|
||||
}
|
||||
|
||||
if task.BucketID == 0 && originalTask != nil && originalTask.BucketID != 0 {
|
||||
@ -648,11 +654,10 @@ func setTaskBucket(s *xorm.Session, task *Task, originalTask *Task, doCheckBucke
|
||||
|
||||
// Either no bucket was provided or the task was moved between projects
|
||||
if task.BucketID == 0 || (originalTask != nil && task.ProjectID != 0 && originalTask.ProjectID != task.ProjectID) {
|
||||
bucket, err = getDefaultBucket(s, task.ProjectID)
|
||||
task.BucketID, err = getDefaultBucketID(s, project)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
task.BucketID = bucket.ID
|
||||
}
|
||||
|
||||
if bucket == nil {
|
||||
@ -676,7 +681,7 @@ func setTaskBucket(s *xorm.Session, task *Task, originalTask *Task, doCheckBucke
|
||||
}
|
||||
}
|
||||
|
||||
if bucket.IsDoneBucket && originalTask != nil && !originalTask.Done {
|
||||
if bucket.ID == project.DoneBucketID && originalTask != nil && !originalTask.Done {
|
||||
task.Done = true
|
||||
}
|
||||
|
||||
@ -717,7 +722,7 @@ func getNextTaskIndex(s *xorm.Session, projectID int64) (nextIndex int64, err er
|
||||
// @Failure 400 {object} web.HTTPError "Invalid task object provided."
|
||||
// @Failure 403 {object} web.HTTPError "The user does not have access to the project"
|
||||
// @Failure 500 {object} models.Message "Internal error"
|
||||
// @Router /projects/{id} [put]
|
||||
// @Router /projects/{id}/tasks [put]
|
||||
func (t *Task) Create(s *xorm.Session, a web.Auth) (err error) {
|
||||
return createTask(s, t, a, true)
|
||||
}
|
||||
@ -732,7 +737,7 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err
|
||||
}
|
||||
|
||||
// Check if the project exists
|
||||
l, err := GetProjectSimpleByID(s, t.ProjectID)
|
||||
p, err := GetProjectSimpleByID(s, t.ProjectID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -749,7 +754,7 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err
|
||||
}
|
||||
|
||||
// Get the default bucket and move the task there
|
||||
_, err = setTaskBucket(s, t, nil, true)
|
||||
_, err = setTaskBucket(s, t, nil, true, nil)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -781,7 +786,7 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err
|
||||
return err
|
||||
}
|
||||
|
||||
t.setIdentifier(l)
|
||||
t.setIdentifier(p)
|
||||
|
||||
if t.IsFavorite {
|
||||
if err := addToFavorites(s, t.ID, createdBy, FavoriteKindTask); err != nil {
|
||||
@ -838,14 +843,18 @@ func (t *Task) Update(s *xorm.Session, a web.Auth) (err error) {
|
||||
// Old task has the stored reminders
|
||||
ot.Reminders = reminders
|
||||
|
||||
targetBucket, err := setTaskBucket(s, t, &ot, t.BucketID != 0 && t.BucketID != ot.BucketID)
|
||||
targetBucket, err := setTaskBucket(s, t, &ot, t.BucketID != 0 && t.BucketID != ot.BucketID, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// If the task was moved into the done bucket and the task has a repeating cycle we should not update
|
||||
// the bucket.
|
||||
if targetBucket.IsDoneBucket && t.RepeatAfter > 0 {
|
||||
project, err := GetProjectSimpleByID(s, t.ProjectID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if targetBucket.ID == project.DoneBucketID && t.RepeatAfter > 0 {
|
||||
t.Done = true // This will trigger the correct re-scheduling of the task (happening in updateDone later)
|
||||
t.BucketID = ot.BucketID
|
||||
}
|
||||
|
@ -170,6 +170,23 @@ func TestTask_Create(t *testing.T) {
|
||||
assert.Error(t, err)
|
||||
assert.True(t, IsErrBucketLimitExceeded(err))
|
||||
})
|
||||
t.Run("default bucket different", func(t *testing.T) {
|
||||
db.LoadAndAssertFixtures(t)
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
task := &Task{
|
||||
Title: "Lorem",
|
||||
Description: "Lorem Ipsum Dolor",
|
||||
ProjectID: 6,
|
||||
}
|
||||
err := task.Create(s, usr)
|
||||
assert.NoError(t, err)
|
||||
db.AssertExists(t, "tasks", map[string]interface{}{
|
||||
"id": task.ID,
|
||||
"bucket_id": 22, // default bucket of project 6 but with a position of 2
|
||||
}, false)
|
||||
})
|
||||
}
|
||||
|
||||
func TestTask_Update(t *testing.T) {
|
||||
|
@ -20,17 +20,16 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.vikunja.io/api/pkg/cron"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"xorm.io/xorm"
|
||||
|
||||
"code.vikunja.io/api/pkg/config"
|
||||
"code.vikunja.io/api/pkg/cron"
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
|
||||
"github.com/typesense/typesense-go/typesense"
|
||||
"github.com/typesense/typesense-go/typesense/api"
|
||||
"github.com/typesense/typesense-go/typesense/api/pointer"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
type TypesenseSync struct {
|
||||
@ -208,46 +207,66 @@ func ReindexAllTasks() (err error) {
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
|
||||
_, err = s.Where("collection = ?", "tasks").Delete(&TypesenseSync{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not delete old sync status: %s", err.Error())
|
||||
}
|
||||
|
||||
currentSync := &TypesenseSync{
|
||||
Collection: "tasks",
|
||||
SyncStartedAt: time.Now(),
|
||||
}
|
||||
_, err = s.Insert(currentSync)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("could not update last sync: %s", err.Error())
|
||||
}
|
||||
|
||||
err = s.Find(tasks)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("could not get all tasks: %s", err.Error())
|
||||
}
|
||||
|
||||
err = reindexTasks(s, tasks)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("could not reindex all tasks: %s", err.Error())
|
||||
}
|
||||
|
||||
currentSync.SyncFinishedAt = time.Now()
|
||||
_, err = s.Where("collection = ?", "tasks").
|
||||
Cols("sync_finished_at").
|
||||
Update(currentSync)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could update last sync state: %s", err.Error())
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func reindexTasks(s *xorm.Session, tasks map[int64]*Task) (err error) {
|
||||
err = addMoreInfoToTasks(s, tasks, &user.User{ID: 1})
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("could not fetch more task info: %s", err.Error())
|
||||
}
|
||||
|
||||
projects := make(map[int64]*Project)
|
||||
|
||||
typesenseTasks := []interface{}{}
|
||||
for _, task := range tasks {
|
||||
searchTask := convertTaskToTypesenseTask(task)
|
||||
|
||||
p, has := projects[task.ProjectID]
|
||||
if !has {
|
||||
p, err = GetProjectSimpleByID(s, task.ProjectID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not fetch project %d: %s", task.ProjectID, err.Error())
|
||||
}
|
||||
projects[task.ProjectID] = p
|
||||
}
|
||||
|
||||
comment := &TaskComment{TaskID: task.ID}
|
||||
searchTask.Comments, _, _, err = comment.ReadAll(s, task.CreatedBy, "", -1, -1)
|
||||
searchTask.Comments, _, _, err = comment.ReadAll(s, &user.User{ID: p.OwnerID}, "", -1, -1)
|
||||
if err != nil {
|
||||
return err
|
||||
return fmt.Errorf("could not fetch comments for task %d: %s", task.ID, err.Error())
|
||||
}
|
||||
|
||||
typesenseTasks = append(typesenseTasks, searchTask)
|
||||
@ -260,6 +279,7 @@ func reindexTasks(s *xorm.Session, tasks map[int64]*Task) (err error) {
|
||||
BatchSize: pointer.Int(100),
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorf("Could not upsert task into Typesense", err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -52,13 +52,44 @@ func insertFromStructure(s *xorm.Session, str []*models.ProjectWithTasksAndBucke
|
||||
labels := make(map[string]*models.Label)
|
||||
archivedProjects := []int64{}
|
||||
|
||||
childRelations := make(map[int64][]int64) // old id is the key, slice of old children ids
|
||||
projectsByOldID := make(map[int64]*models.Project) // old id is the key
|
||||
// Create all projects
|
||||
for _, p := range str {
|
||||
oldID := p.ID
|
||||
|
||||
if p.ParentProjectID != 0 {
|
||||
childRelations[p.ParentProjectID] = append(childRelations[p.ParentProjectID], oldID)
|
||||
}
|
||||
|
||||
p.ID = 0
|
||||
err = createProjectWithChildren(s, p, 0, &archivedProjects, labels, user)
|
||||
err = createProject(s, p, &archivedProjects, labels, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
projectsByOldID[oldID] = &p.Project
|
||||
}
|
||||
|
||||
// parent / child relations
|
||||
for parentID, children := range childRelations {
|
||||
parent, has := projectsByOldID[parentID]
|
||||
if !has {
|
||||
log.Debugf("[creating structure] could not find parentID project with old id %d", parentID)
|
||||
continue
|
||||
}
|
||||
for _, childID := range children {
|
||||
child, has := projectsByOldID[childID]
|
||||
if !has {
|
||||
log.Debugf("[creating structure] could not find child project with old id %d for parent project with old id %d", childID, parentID)
|
||||
continue
|
||||
}
|
||||
|
||||
child.ParentProjectID = parent.ID
|
||||
err = child.Update(s, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(archivedProjects) > 0 {
|
||||
@ -76,30 +107,18 @@ func insertFromStructure(s *xorm.Session, str []*models.ProjectWithTasksAndBucke
|
||||
return nil
|
||||
}
|
||||
|
||||
func createProjectWithChildren(s *xorm.Session, project *models.ProjectWithTasksAndBuckets, parentProjectID int64, archivedProjectIDs *[]int64, labels map[string]*models.Label, user *user.User) (err error) {
|
||||
err = createProjectWithEverything(s, project, parentProjectID, archivedProjectIDs, labels, user)
|
||||
func createProject(s *xorm.Session, project *models.ProjectWithTasksAndBuckets, archivedProjectIDs *[]int64, labels map[string]*models.Label, user *user.User) (err error) {
|
||||
err = createProjectWithEverything(s, project, archivedProjectIDs, labels, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Debugf("[creating structure] Created project %d", project.ID)
|
||||
|
||||
if len(project.ChildProjects) > 0 {
|
||||
log.Debugf("[creating structure] Creating %d projects", len(project.ChildProjects))
|
||||
|
||||
// Create all projects
|
||||
for _, cp := range project.ChildProjects {
|
||||
err = createProjectWithChildren(s, cp, project.ID, archivedProjectIDs, labels, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTasksAndBuckets, parentProjectID int64, archivedProjects *[]int64, labels map[string]*models.Label, user *user.User) (err error) {
|
||||
func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTasksAndBuckets, archivedProjects *[]int64, labels map[string]*models.Label, user *user.User) (err error) {
|
||||
// The tasks and bucket slices are going to be reset during the creation of the project, so we rescue it here
|
||||
// to be able to still loop over them aftere the project was created.
|
||||
tasks := project.Tasks
|
||||
@ -114,9 +133,12 @@ func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTas
|
||||
project.IsArchived = false
|
||||
}
|
||||
|
||||
project.ParentProjectID = parentProjectID
|
||||
project.ID = 0
|
||||
err = project.Create(s, user)
|
||||
if err != nil && models.IsErrProjectIdentifierIsNotUnique(err) {
|
||||
project.Identifier = ""
|
||||
err = project.Create(s, user)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@ -174,15 +196,18 @@ func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTas
|
||||
}
|
||||
}
|
||||
|
||||
tasksByOldID := make(map[int64]*models.TaskWithComments, len(tasks))
|
||||
// Create all tasks
|
||||
for _, t := range tasks {
|
||||
setBucketOrDefault(&t.Task)
|
||||
|
||||
oldid := t.ID
|
||||
t.ProjectID = project.ID
|
||||
err = t.Create(s, user)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tasksByOldID[oldid] = t
|
||||
|
||||
log.Debugf("[creating structure] Created task %d", t.ID)
|
||||
if len(t.RelatedTasks) > 0 {
|
||||
@ -198,13 +223,15 @@ func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTas
|
||||
|
||||
for _, rt := range tasks {
|
||||
// First create the related tasks if they do not exist
|
||||
if rt.ID == 0 {
|
||||
if _, exists := tasksByOldID[rt.ID]; !exists || rt.ID == 0 {
|
||||
oldid := rt.ID
|
||||
setBucketOrDefault(rt)
|
||||
rt.ProjectID = t.ProjectID
|
||||
err = rt.Create(s, user)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
tasksByOldID[oldid] = &models.TaskWithComments{Task: *rt}
|
||||
log.Debugf("[creating structure] Created related task %d", rt.ID)
|
||||
}
|
||||
|
||||
@ -214,8 +241,11 @@ func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTas
|
||||
OtherTaskID: rt.ID,
|
||||
RelationKind: kind,
|
||||
}
|
||||
if ttt, exists := tasksByOldID[rt.ID]; exists {
|
||||
taskRel.OtherTaskID = ttt.ID
|
||||
}
|
||||
err = taskRel.Create(s, user)
|
||||
if err != nil {
|
||||
if err != nil && !models.IsErrRelationAlreadyExists(err) {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ func TestInsertFromStructure(t *testing.T) {
|
||||
testStructure := []*models.ProjectWithTasksAndBuckets{
|
||||
{
|
||||
Project: models.Project{
|
||||
ID: 1,
|
||||
Title: "Test1",
|
||||
Description: "Lorem Ipsum",
|
||||
},
|
||||
@ -45,113 +46,112 @@ func TestInsertFromStructure(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
ChildProjects: []*models.ProjectWithTasksAndBuckets{
|
||||
},
|
||||
{
|
||||
Project: models.Project{
|
||||
Title: "Testproject1",
|
||||
Description: "Something",
|
||||
ParentProjectID: 1,
|
||||
},
|
||||
Buckets: []*models.Bucket{
|
||||
{
|
||||
Project: models.Project{
|
||||
Title: "Testproject1",
|
||||
Description: "Something",
|
||||
ID: 1234,
|
||||
Title: "Test Bucket",
|
||||
},
|
||||
},
|
||||
Tasks: []*models.TaskWithComments{
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task1",
|
||||
Description: "Lorem",
|
||||
},
|
||||
Buckets: []*models.Bucket{
|
||||
{
|
||||
ID: 1234,
|
||||
Title: "Test Bucket",
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task with related tasks",
|
||||
RelatedTasks: map[models.RelationKind][]*models.Task{
|
||||
models.RelationKindSubtask: {
|
||||
{
|
||||
Title: "Related to task with related task",
|
||||
Description: "As subtask",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Tasks: []*models.TaskWithComments{
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task1",
|
||||
Description: "Lorem",
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task with related tasks",
|
||||
RelatedTasks: map[models.RelationKind][]*models.Task{
|
||||
models.RelationKindSubtask: {
|
||||
{
|
||||
Title: "Related to task with related task",
|
||||
Description: "As subtask",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task with attachments",
|
||||
Attachments: []*models.TaskAttachment{
|
||||
{
|
||||
File: &files.File{
|
||||
Name: "testfile",
|
||||
Size: 4,
|
||||
FileContent: []byte{1, 2, 3, 4},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task with attachments",
|
||||
Attachments: []*models.TaskAttachment{
|
||||
{
|
||||
File: &files.File{
|
||||
Name: "testfile",
|
||||
Size: 4,
|
||||
FileContent: []byte{1, 2, 3, 4},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task with labels",
|
||||
Labels: []*models.Label{
|
||||
{
|
||||
Title: "Label1",
|
||||
HexColor: "ff00ff",
|
||||
},
|
||||
{
|
||||
Title: "Label2",
|
||||
HexColor: "ff00ff",
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task with labels",
|
||||
Labels: []*models.Label{
|
||||
{
|
||||
Title: "Label1",
|
||||
HexColor: "ff00ff",
|
||||
},
|
||||
{
|
||||
Title: "Label2",
|
||||
HexColor: "ff00ff",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task with same label",
|
||||
Labels: []*models.Label{
|
||||
{
|
||||
Title: "Label1",
|
||||
HexColor: "ff00ff",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task in a bucket",
|
||||
BucketID: 1234,
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task in a nonexisting bucket",
|
||||
BucketID: 1111,
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task with same label",
|
||||
Labels: []*models.Label{
|
||||
{
|
||||
Title: "Label1",
|
||||
HexColor: "ff00ff",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task in a bucket",
|
||||
BucketID: 1234,
|
||||
},
|
||||
},
|
||||
{
|
||||
Task: models.Task{
|
||||
Title: "Task in a nonexisting bucket",
|
||||
BucketID: 1111,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
err := InsertFromStructure(testStructure, u)
|
||||
assert.NoError(t, err)
|
||||
db.AssertExists(t, "projects", map[string]interface{}{
|
||||
"title": testStructure[0].ChildProjects[0].Title,
|
||||
"description": testStructure[0].ChildProjects[0].Description,
|
||||
"title": testStructure[1].Title,
|
||||
"description": testStructure[1].Description,
|
||||
}, false)
|
||||
db.AssertExists(t, "tasks", map[string]interface{}{
|
||||
"title": testStructure[0].ChildProjects[0].Tasks[5].Title,
|
||||
"bucket_id": testStructure[0].ChildProjects[0].Buckets[0].ID,
|
||||
"title": testStructure[1].Tasks[5].Title,
|
||||
"bucket_id": testStructure[1].Buckets[0].ID,
|
||||
}, false)
|
||||
db.AssertMissing(t, "tasks", map[string]interface{}{
|
||||
"title": testStructure[0].ChildProjects[0].Tasks[6].Title,
|
||||
"title": testStructure[1].Tasks[6].Title,
|
||||
"bucket_id": 1111, // No task with that bucket should exist
|
||||
})
|
||||
db.AssertExists(t, "tasks", map[string]interface{}{
|
||||
"title": testStructure[0].Tasks[0].Title,
|
||||
}, false)
|
||||
assert.NotEqual(t, 0, testStructure[0].ChildProjects[0].Tasks[0].BucketID) // Should get the default bucket
|
||||
assert.NotEqual(t, 0, testStructure[0].ChildProjects[0].Tasks[6].BucketID) // Should get the default bucket
|
||||
assert.NotEqual(t, 0, testStructure[1].Tasks[0].BucketID) // Should get the default bucket
|
||||
assert.NotEqual(t, 0, testStructure[1].Tasks[6].BucketID) // Should get the default bucket
|
||||
})
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import (
|
||||
"code.vikunja.io/api/pkg/models"
|
||||
"code.vikunja.io/api/pkg/modules/migration"
|
||||
"code.vikunja.io/api/pkg/user"
|
||||
vversion "code.vikunja.io/api/pkg/version"
|
||||
|
||||
"github.com/hashicorp/go-version"
|
||||
)
|
||||
@ -119,17 +120,22 @@ func (v *FileMigrator) Migrate(user *user.User, file io.ReaderAt, size int64) er
|
||||
return fmt.Errorf("could not read version file: %w", err)
|
||||
}
|
||||
|
||||
dumpedVersion, err := version.NewVersion(bufVersion.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
minVersion, err := version.NewVersion("0.20.1+61")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
versionString := bufVersion.String()
|
||||
if versionString == "dev" && vversion.Version == "dev" {
|
||||
log.Debugf(logPrefix + "Importing from dev version")
|
||||
} else {
|
||||
dumpedVersion, err := version.NewVersion(bufVersion.String())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
minVersion, err := version.NewVersion("0.20.1+61")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if dumpedVersion.LessThan(minVersion) {
|
||||
return fmt.Errorf("export was created with an older version, need at least %s but the export needs at least %s", dumpedVersion, minVersion)
|
||||
if dumpedVersion.LessThan(minVersion) {
|
||||
return fmt.Errorf("export was created with an older version, need at least %s but the export needs at least %s", dumpedVersion, minVersion)
|
||||
}
|
||||
}
|
||||
|
||||
//////
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"code.vikunja.io/api/pkg/db"
|
||||
"code.vikunja.io/api/pkg/log"
|
||||
)
|
||||
|
||||
// Notification is a notification which can be sent via mail or db.
|
||||
@ -40,10 +41,13 @@ type NotificationWithSubject interface {
|
||||
|
||||
// Notifiable is an entity which can be notified. Usually a user.
|
||||
type Notifiable interface {
|
||||
// Should return the email address this notifiable has.
|
||||
// RouteForMail should return the email address this notifiable has.
|
||||
RouteForMail() (string, error)
|
||||
// Should return the id of the notifiable entity
|
||||
// RouteForDB should return the id of the notifiable entity to save it in the database.
|
||||
RouteForDB() int64
|
||||
// ShouldNotify provides a last-minute way to cancel a notification. It will be called immediately before
|
||||
// sending a notification.
|
||||
ShouldNotify() (should bool, err error)
|
||||
}
|
||||
|
||||
// Notify notifies a notifiable of a notification
|
||||
@ -53,6 +57,12 @@ func Notify(notifiable Notifiable, notification Notification) (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
should, err := notifiable.ShouldNotify()
|
||||
if err != nil || !should {
|
||||
log.Debugf("Not notifying user %d because they are disabled", notifiable.RouteForDB())
|
||||
return err
|
||||
}
|
||||
|
||||
err = notifyMail(notifiable, notification)
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -50,6 +50,7 @@ func (n *testNotification) Name() string {
|
||||
}
|
||||
|
||||
type testNotifiable struct {
|
||||
ShouldSendNotification bool
|
||||
}
|
||||
|
||||
// RouteForMail routes a test notification for mail
|
||||
@ -62,30 +63,64 @@ func (t *testNotifiable) RouteForDB() int64 {
|
||||
return 42
|
||||
}
|
||||
|
||||
func TestNotify(t *testing.T) {
|
||||
tn := &testNotification{
|
||||
Test: "somethingsomething",
|
||||
OtherValue: 42,
|
||||
}
|
||||
tnf := &testNotifiable{}
|
||||
|
||||
err := Notify(tnf, tn)
|
||||
|
||||
assert.NoError(t, err)
|
||||
vals := map[string]interface{}{
|
||||
"notifiable_id": 42,
|
||||
"notification": "'{\"other_value\":42,\"test\":\"somethingsomething\"}'",
|
||||
}
|
||||
|
||||
if db.Type() == schemas.POSTGRES {
|
||||
vals["notification::jsonb"] = vals["notification"].(string) + "::jsonb"
|
||||
delete(vals, "notification")
|
||||
}
|
||||
|
||||
if db.Type() == schemas.SQLITE {
|
||||
vals["CAST(notification AS BLOB)"] = "CAST(" + vals["notification"].(string) + " AS BLOB)"
|
||||
delete(vals, "notification")
|
||||
}
|
||||
|
||||
db.AssertExists(t, "notifications", vals, true)
|
||||
func (t *testNotifiable) ShouldNotify() (should bool, err error) {
|
||||
return t.ShouldSendNotification, nil
|
||||
}
|
||||
|
||||
func TestNotify(t *testing.T) {
|
||||
t.Run("normal", func(t *testing.T) {
|
||||
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
_, err := s.Exec("delete from notifications")
|
||||
assert.NoError(t, err)
|
||||
|
||||
tn := &testNotification{
|
||||
Test: "somethingsomething",
|
||||
OtherValue: 42,
|
||||
}
|
||||
tnf := &testNotifiable{
|
||||
ShouldSendNotification: true,
|
||||
}
|
||||
|
||||
err = Notify(tnf, tn)
|
||||
assert.NoError(t, err)
|
||||
vals := map[string]interface{}{
|
||||
"notifiable_id": 42,
|
||||
"notification": "'{\"other_value\":42,\"test\":\"somethingsomething\"}'",
|
||||
}
|
||||
|
||||
if db.Type() == schemas.POSTGRES {
|
||||
vals["notification::jsonb"] = vals["notification"].(string) + "::jsonb"
|
||||
delete(vals, "notification")
|
||||
}
|
||||
|
||||
if db.Type() == schemas.SQLITE {
|
||||
vals["CAST(notification AS BLOB)"] = "CAST(" + vals["notification"].(string) + " AS BLOB)"
|
||||
delete(vals, "notification")
|
||||
}
|
||||
|
||||
db.AssertExists(t, "notifications", vals, true)
|
||||
})
|
||||
t.Run("disabled notifiable", func(t *testing.T) {
|
||||
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
_, err := s.Exec("delete from notifications")
|
||||
assert.NoError(t, err)
|
||||
|
||||
tn := &testNotification{
|
||||
Test: "somethingsomething",
|
||||
OtherValue: 42,
|
||||
}
|
||||
tnf := &testNotifiable{
|
||||
ShouldSendNotification: false,
|
||||
}
|
||||
|
||||
err = Notify(tnf, tn)
|
||||
assert.NoError(t, err)
|
||||
db.AssertMissing(t, "notifications", map[string]interface{}{
|
||||
"notifiable_id": 42,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -134,9 +134,7 @@ func (vcls *VikunjaCaldavProjectStorage) GetResourcesByList(rpaths []string) ([]
|
||||
var uids []string
|
||||
for _, path := range rpaths {
|
||||
parts := strings.Split(path, "/")
|
||||
uid := []rune(parts[4]) // The 4th part is the id with ".ics" suffix
|
||||
endlen := len(uid) - len(".ics") // ".ics" are 4 bytes
|
||||
uids = append(uids, string(uid[:endlen]))
|
||||
uids = append(uids, strings.TrimSuffix(parts[4], ".ics"))
|
||||
}
|
||||
|
||||
s := db.NewSession()
|
||||
|
@ -379,7 +379,7 @@ func registerAPIRoutes(a *echo.Group) {
|
||||
return &models.Task{}
|
||||
},
|
||||
}
|
||||
a.PUT("/projects/:project", taskHandler.CreateWeb)
|
||||
a.PUT("/projects/:project/tasks", taskHandler.CreateWeb)
|
||||
a.GET("/tasks/:projecttask", taskHandler.ReadOneWeb)
|
||||
a.GET("/tasks/all", taskCollectionHandler.ReadAllWeb)
|
||||
a.DELETE("/tasks/:projecttask", taskHandler.DeleteWeb)
|
||||
|
8663
pkg/swagger/docs.go
Normal file
8663
pkg/swagger/docs.go
Normal file
File diff suppressed because it is too large
Load Diff
8638
pkg/swagger/swagger.json
Normal file
8638
pkg/swagger/swagger.json
Normal file
File diff suppressed because it is too large
Load Diff
5911
pkg/swagger/swagger.yaml
Normal file
5911
pkg/swagger/swagger.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@ -137,6 +137,17 @@ func (u *User) RouteForDB() int64 {
|
||||
return u.ID
|
||||
}
|
||||
|
||||
func (u *User) ShouldNotify() (bool, error) {
|
||||
s := db.NewSession()
|
||||
defer s.Close()
|
||||
user, err := getUser(s, &User{ID: u.ID}, true)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return user.Status != StatusDisabled, err
|
||||
}
|
||||
|
||||
// GetID implements the Auth interface
|
||||
func (u *User) GetID() int64 {
|
||||
return u.ID
|
||||
|
@ -1,26 +0,0 @@
|
||||
// Vikunja is a to-do list application to facilitate your life.
|
||||
// Copyright 2018-present2023 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 <https://www.gnu.org/licenses/>.
|
||||
//go:build swagger
|
||||
// +build swagger
|
||||
|
||||
package version
|
||||
|
||||
import "code.vikunja.io/api/pkg/swagger"
|
||||
|
||||
func init() {
|
||||
// Additional swagger information
|
||||
swagger.SwaggerInfo.Version = Version
|
||||
}
|
@ -16,8 +16,15 @@
|
||||
|
||||
package version
|
||||
|
||||
import "code.vikunja.io/api/pkg/swagger"
|
||||
|
||||
// This package holds the version info
|
||||
// It is an own package to avoid import cycles
|
||||
|
||||
// Version sets the version to be printed to the user. Gets overwritten by "make release" or "make build" with last git commit or tag.
|
||||
var Version = "dev"
|
||||
|
||||
func init() {
|
||||
// Additional swagger information
|
||||
swagger.SwaggerInfo.Version = Version
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user