Compare commits

..

34 Commits

Author SHA1 Message Date
renovate 46182489fe chore(deps): update goreleaser/nfpm docker tag to v2.35.3
continuous-integration/drone/pr Build is pending Details
2024-01-31 18:04:39 +00:00
renovate 415683e9b2 fix(deps): update module github.com/mattn/go-sqlite3 to v1.14.21
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is failing Details
2024-01-31 15:05:03 +00:00
kolaente 7f46914d5e
fix(project): pass user id to error message
continuous-integration/drone/push Build is failing Details
2024-01-31 13:50:21 +01:00
renovate 78353d1ffe fix(deps): update module github.com/arran4/golang-ical to v0.2.4
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-01-29 00:05:15 +00:00
kolaente 0dbf3b45f0
docs: mention flatpack in how to release
continuous-integration/drone/push Build is passing Details
2024-01-28 20:28:18 +01:00
kolaente a0a98bac3b
chore: release preparation
continuous-integration/drone/push Build is passing Details
2024-01-28 17:45:00 +01:00
Frederick [Bot] ba0cb022b1 [skip ci] Updated swagger docs 2024-01-28 14:43:54 +00:00
kolaente 96b4f2d1db
fix(projects): don't remove parent project id if the parent project is available in the same run
continuous-integration/drone/push Build is passing Details
Resolves https://github.com/go-vikunja/frontend/issues/139
2024-01-28 15:28:08 +01:00
kolaente 30a2dcd04c
fix: lint 2024-01-28 15:27:14 +01:00
kolaente 0d24ba12bb
chore: rename function
continuous-integration/drone/push Build is failing Details
2024-01-28 13:36:13 +01:00
kolaente d9875e476c
fix(assignees): make sure task assignee created event contains the full task
continuous-integration/drone/push Build is failing Details
2024-01-28 13:23:27 +01:00
kolaente e4fec01d52
fix(assignees): subscribe assigned users directly to the task, not async
continuous-integration/drone/push Build is failing Details
Resolves https://community.vikunja.io/t/richer-email-notifications/1891
2024-01-28 13:15:43 +01:00
kolaente b2970c6c04
fix(assignees): prevent double notifications for assignees 2024-01-28 13:11:50 +01:00
kolaente e03920b84a
fix(assignees): improve wording for assignee emails 2024-01-28 13:11:37 +01:00
kolaente ce53663a88
fix(openid): use the calculated redirect url when authenticating with openid providers
continuous-integration/drone/push Build is failing Details
2024-01-28 12:41:35 +01:00
kolaente a20f6ac815
fix(task): delete the task after all related attributes to prevent task not found errors
continuous-integration/drone/push Build is passing Details
2024-01-28 12:23:25 +01:00
kolaente 1630e4fc08
fix: tests
continuous-integration/drone/push Build is failing Details
2024-01-28 11:52:16 +01:00
kolaente 90ad975ca0
fix(typesense): update tasks in Typesense directly when the change happened
Resolves https://community.vikunja.io/t/no-filters-working-assignee-date-task-done-etc/1910
2024-01-28 11:47:17 +01:00
kolaente ae9b382963
fix(webhooks): make sure all events with tasks have the full task
continuous-integration/drone/push Build is failing Details
Resolves vikunja/api#1676
2024-01-27 00:16:17 +01:00
kolaente d38050f2b8
fix(subscriptions): don't crash when a project is already deleted
continuous-integration/drone/push Build is passing Details
2024-01-26 23:53:22 +01:00
kolaente 33a47b7f43
fix(relations): don't allow creating relations which already exist
continuous-integration/drone/push Build is failing Details
Resolves https://github.com/go-vikunja/frontend/issues/144
2024-01-26 23:37:59 +01:00
renovate 314b101280 fix(deps): update module github.com/mattn/go-sqlite3 to v1.14.20
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-01-25 15:04:56 +00:00
renovate 8c5039db5b fix(deps): update src.techknowlogick.com/xgo digest to 77ac23f
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-01-24 21:05:28 +00:00
renovate 007c8aa612 fix(deps): update module github.com/google/uuid to v1.6.0
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-01-23 19:04:32 +00:00
renovate 1a3b699f66 fix(deps): update module xorm.io/xorm to v1.3.7
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-01-22 09:05:01 +00:00
kolaente ad8fa93cae
fix(user): make disable command actually work
continuous-integration/drone/push Build is passing Details
2024-01-21 12:24:41 +01:00
kolaente 3ff4d81618
fix(migration): ignore tasks with empty titles
continuous-integration/drone/push Build is passing Details
2024-01-19 23:04:24 +01:00
renovate 774859b577 fix(deps): update module golang.org/x/sync to v0.6.0
continuous-integration/drone/pr Build is passing Details
continuous-integration/drone/push Build is passing Details
2024-01-16 16:04:22 +00:00
renovate 00231b9bf7 fix(deps): update module github.com/labstack/echo/v4 to v4.11.4
continuous-integration/drone/push Build is passing Details
2024-01-16 15:23:38 +00:00
kolaente 282686c207 chore(ci): sign drone config
continuous-integration/drone/push Build is failing Details
2024-01-16 15:23:34 +00:00
renovate 8753f16a7c chore(deps): update goreleaser/nfpm docker tag to v2.35.2 2024-01-16 15:23:34 +00:00
renovate 72f5f027f1 fix(deps): update module github.com/getsentry/sentry-go to v0.26.0
continuous-integration/drone/push Build is failing Details
2024-01-16 15:23:06 +00:00
renovate 00cc1e8c69 fix(deps): update module github.com/redis/go-redis/v9 to v9.4.0
continuous-integration/drone/push Build is failing Details
2024-01-16 15:23:03 +00:00
renovate b9950afbc9 fix(deps): update module golang.org/x/oauth2 to v0.16.0
continuous-integration/drone/push Build is passing Details
2024-01-16 15:07:43 +00:00
33 changed files with 330 additions and 153 deletions

View File

@ -551,7 +551,7 @@ steps:
# Build os packages and push it to our bucket
- name: build-os-packages-unstable
image: goreleaser/nfpm:v2.35.2
image: goreleaser/nfpm:v2.35.3
pull: always
commands:
- apk add git go
@ -567,7 +567,7 @@ steps:
depends_on: [ after-build-compress ]
- name: build-os-packages-version
image: goreleaser/nfpm:v2.35.2
image: goreleaser/nfpm:v2.35.3
pull: always
commands:
- apk add git go

View File

@ -7,6 +7,62 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
All releases can be found on https://code.vikunja.io/api/releases.
## [0.22.1] - 2024-01-28
### Bug Fixes
* *(api)* Make sure permission to read all tasks work for reading all tasks per project
* *(assignees)* Improve wording for assignee emails
* *(assignees)* Prevent double notifications for assignees
* *(assignees)* Subscribe assigned users directly to the task, not async
* *(assignees)* Make sure task assignee created event contains the full task
* *(auth)* Don't reset user settings when updating name or email from external auth provider
* *(migration)* Ignore tasks with empty titles
* *(openid)* Use the calculated redirect url when authenticating with openid providers
* *(projects)* Don't remove parent project id if the parent project is available in the same run
* *(relations)* Don't allow creating relations which already exist
* *(subscriptions)* Don't crash when a project is already deleted
* *(task)* Delete the task after all related attributes to prevent task not found errors
* *(typesense)* Update tasks in Typesense directly when the change happened
* *(user)* Make disable command actually work
* *(webhooks)* Make sure all events with tasks have the full task* Create webhooks table for fresh installation ([09696ae](09696aec1bea647a5bfc7be16b31054626d721e4))
* Lint ([2c84688](2c84688a4013a816eca02caabba8c634a03d3d57))
* Convert everything which looks like an url to a <a href html element ([27a5f68](27a5f6862b1748ec10ca9282e0fe1a64f9ccf910))
* Update function signatures ([4d48d81](4d48d814c95244f21454219c1004b6298744e076))
* Tests ([1630e4f](1630e4fc08bc5fccff191a6cc4afe936543635d8))
* Lint ([30a2dcd](30a2dcd04c8379291a2ae5068ec0cab07bc9a7fb))
### Dependencies
* *(deps)* Update dessant/repo-lockdown action to v4
* *(deps)* Update alpine docker tag to v3.19
* *(deps)* Update module github.com/arran4/golang-ical to v0.2.3 (#1669)
* *(deps)* Update module github.com/labstack/gommon to v0.4.2
* *(deps)* Update module xorm.io/xorm to v1.3.6
* *(deps)* Update module golang.org/x/term to v0.16.0
* *(deps)* Update module golang.org/x/image to v0.15.0
* *(deps)* Update module github.com/prometheus/client_golang to v1.18.0
* *(deps)* Update module github.com/typesense/typesense-go to v1
* *(deps)* Update module golang.org/x/oauth2 to v0.16.0
* *(deps)* Update module github.com/redis/go-redis/v9 to v9.4.0
* *(deps)* Update module github.com/getsentry/sentry-go to v0.26.0
* *(deps)* Update goreleaser/nfpm docker tag to v2.35.2
* *(deps)* Update module github.com/labstack/echo/v4 to v4.11.4
* *(deps)* Update module golang.org/x/sync to v0.6.0
* *(deps)* Update module xorm.io/xorm to v1.3.7
* *(deps)* Update module github.com/google/uuid to v1.6.0
* *(deps)* Update src.techknowlogick.com/xgo digest to 77ac23f
* *(deps)* Update module github.com/mattn/go-sqlite3 to v1.14.20
### Features
* *(reminders)* Persist reminders in the db
### Miscellaneous Tasks
* Check if import zip contains a VERSION file ([ec6e3e9](ec6e3e99e0d6f2d8a9c889c7261e0d16b4ebea7d))
* Rename function ([0d24ba1](0d24ba12bb85078afd8c821bae61926fd81f163e))
## [0.22.0] - 2023-12-19
### Bug Fixes

View File

@ -2,7 +2,7 @@
[![Build Status](https://drone.kolaente.de/api/badges/vikunja/api/status.svg)](https://drone.kolaente.de/vikunja/api)
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](LICENSE)
[![Download](https://img.shields.io/badge/download-v0.22.0-brightgreen.svg)](https://dl.vikunja.io)
[![Download](https://img.shields.io/badge/download-v0.22.1-brightgreen.svg)](https://dl.vikunja.io)
[![Docker Pulls](https://img.shields.io/docker/pulls/vikunja/api.svg)](https://hub.docker.com/r/vikunja/api/)
[![Swagger Docs](https://img.shields.io/badge/swagger-docs-brightgreen.svg)](https://try.vikunja.io/api/v1/docs)
[![Go Report Card](https://goreportcard.com/badge/kolaente.dev/vikunja/api)](https://goreportcard.com/report/kolaente.dev/vikunja/api)

View File

@ -292,17 +292,14 @@ auth:
# **Note:** Some openid providers (like gitlab) only make the email of the user available through openid claims if they have set it to be publicly visible.
# If the email is not public in those cases, authenticating will fail.
# **Note 2:** The frontend expects to be redirected after authentication by the third party
# to <frontend-url>/auth/openid/<auth key>. Please make sure to configure the redirect url with your third party
# to <frontend-url>/auth/openid/<auth key>. Please make sure to configure the redirect url in your third party
# auth service accordingly if you're using the default vikunja frontend.
# The frontend will automatically provide the api with the redirect url, composed from the current url where it's hosted.
# If you want to use the desktop client with openid, make sure to allow redirects to `127.0.0.1`.
# Take a look at the [default config file](https://kolaente.dev/vikunja/api/src/branch/main/config.yml.sample) for more information about how to configure openid authentication.
openid:
# Enable or disable OpenID Connect authentication
enabled: false
# The url to redirect clients to. Defaults to the configured frontend url. If you're using Vikunja with the official
# frontend, you don't need to change this value.
# **Note:** The redirect url must exactly match the configured redirect url with the third party provider.
# This includes all slashes at the end or protocols.
redirecturl: <frontend url>
# A list of enabled providers
providers:
# The name of the provider as it will appear in the frontend.

View File

@ -24,6 +24,7 @@ Not all steps are necessary for every release.
* API
* Desktop
* Once built: Prune the cloudflare cache so that the new versions show up at [dl.vikunja.io](https://dl.vikunja.io/)
* Update the [Flathub desktop package](https://github.com/flathub/io.vikunja.Vikunja)
* Release Highlights Blogpost
* Include a section about Vikunja in general (totally fine to copy one from the earlier blog posts)
* New Features & Improvements: Mention bigger features, potentially with screenshots. Things like refactoring are sometimes also worth mentioning.

24
go.mod
View File

@ -21,7 +21,7 @@ require (
dario.cat/mergo v1.0.0
github.com/ThreeDotsLabs/watermill v1.3.5
github.com/adlio/trello v1.10.0
github.com/arran4/golang-ical v0.2.3
github.com/arran4/golang-ical v0.2.4
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2
github.com/bbrks/go-blurhash v1.1.1
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500
@ -31,28 +31,28 @@ require (
github.com/disintegration/imaging v1.6.2
github.com/dustinkirkland/golang-petname v0.0.0-20231002161417-6a283f1aaaf2
github.com/gabriel-vasile/mimetype v1.4.3
github.com/getsentry/sentry-go v0.25.0
github.com/getsentry/sentry-go v0.26.0
github.com/go-sql-driver/mysql v1.7.1
github.com/go-testfixtures/testfixtures/v3 v3.9.0
github.com/gocarina/gocsv v0.0.0-20231116093920-b87c2d0e983a
github.com/golang-jwt/jwt/v5 v5.2.0
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/google/uuid v1.5.0
github.com/google/uuid v1.6.0
github.com/hashicorp/go-version v1.6.0
github.com/iancoleman/strcase v0.3.0
github.com/jinzhu/copier v0.4.0
github.com/jszwedko/go-datemath v0.1.1-0.20230526204004-640a500621d6
github.com/labstack/echo-jwt/v4 v4.2.0
github.com/labstack/echo/v4 v4.11.3
github.com/labstack/echo/v4 v4.11.4
github.com/labstack/gommon v0.4.2
github.com/lib/pq v1.10.9
github.com/magefile/mage v1.15.0
github.com/mattn/go-sqlite3 v1.14.19
github.com/mattn/go-sqlite3 v1.14.21
github.com/olekukonko/tablewriter v0.0.5
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/pquerna/otp v1.4.0
github.com/prometheus/client_golang v1.18.0
github.com/redis/go-redis/v9 v9.3.1
github.com/redis/go-redis/v9 v9.4.0
github.com/robfig/cron/v3 v3.0.1
github.com/samedi/caldav-go v3.0.0+incompatible
github.com/spf13/afero v1.11.0
@ -65,20 +65,20 @@ require (
github.com/ulule/limiter/v3 v3.11.2
github.com/wneessen/go-mail v0.4.0
github.com/yuin/goldmark v1.6.0
golang.org/x/crypto v0.17.0
golang.org/x/crypto v0.18.0
golang.org/x/image v0.15.0
golang.org/x/oauth2 v0.15.0
golang.org/x/sync v0.5.0
golang.org/x/oauth2 v0.16.0
golang.org/x/sync v0.6.0
golang.org/x/sys v0.16.0
golang.org/x/term v0.16.0
golang.org/x/text v0.14.0
gopkg.in/d4l3k/messagediff.v1 v1.2.1
gopkg.in/yaml.v3 v3.0.1
mvdan.cc/xurls/v2 v2.5.0
src.techknowlogick.com/xgo v1.7.1-0.20231205202227-c7ed78300ce9
src.techknowlogick.com/xgo v1.7.1-0.20240124202215-77ac23f331fe
src.techknowlogick.com/xormigrate v1.7.1
xorm.io/builder v0.3.13
xorm.io/xorm v1.3.6
xorm.io/xorm v1.3.7
)
require (
@ -173,7 +173,7 @@ require (
golang.org/x/arch v0.4.0 // indirect
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.13.0 // indirect
google.golang.org/appengine v1.6.8 // indirect

26
go.sum
View File

@ -31,6 +31,8 @@ github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7D
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
github.com/arran4/golang-ical v0.2.3 h1:C4Vj7+BjJBIrAJhHgi6Ku+XUkQVugRq4re5Cqj5QVdE=
github.com/arran4/golang-ical v0.2.3/go.mod h1:RqMuPGmwRRwjkb07hmm+JBqcWa1vF1LvVmPtSZN2OhQ=
github.com/arran4/golang-ical v0.2.4 h1:0/rTXn2qqEekLKec3SzRRy+z7pCLtniMb0KD/dPogUo=
github.com/arran4/golang-ical v0.2.4/go.mod h1:RqMuPGmwRRwjkb07hmm+JBqcWa1vF1LvVmPtSZN2OhQ=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
github.com/bbrks/go-blurhash v1.1.1 h1:uoXOxRPDca9zHYabUTwvS4KnY++KKUbwFo+Yxb8ME4M=
@ -109,6 +111,8 @@ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uq
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/getsentry/sentry-go v0.25.0 h1:q6Eo+hS+yoJlTO3uu/azhQadsD8V+jQn2D8VvX1eOyI=
github.com/getsentry/sentry-go v0.25.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/getsentry/sentry-go v0.26.0 h1:IX3++sF6/4B5JcevhdZfdKIHfyvMmAq/UnqcyT2H6mA=
github.com/getsentry/sentry-go v0.26.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
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=
@ -204,6 +208,8 @@ github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@ -309,6 +315,8 @@ github.com/labstack/echo-jwt/v4 v4.2.0/go.mod h1:MA2RqdXdEn4/uEglx0HcUOgQSyBaTh5
github.com/labstack/echo/v4 v4.1.16/go.mod h1:awO+5TzAjvL8XpibdsfXxPgHr+orhtXZJZIQCVjogKI=
github.com/labstack/echo/v4 v4.11.3 h1:Upyu3olaqSHkCjs1EJJwQ3WId8b8b1hxbogyommKktM=
github.com/labstack/echo/v4 v4.11.3/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws=
github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8=
github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/labstack/gommon v0.4.1 h1:gqEff0p/hTENGMABzezPoPSRtIh1Cvw0ueMOe0/dfOk=
github.com/labstack/gommon v0.4.1/go.mod h1:TyTrpPqxR5KMk8LKVtLmfMjeQ5FEkBYdxLYPw/WfrOM=
@ -361,6 +369,10 @@ github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI=
github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/mattn/go-sqlite3 v1.14.20 h1:BAZ50Ns0OFBNxdAqFhbZqdPcht1Xlb16pDCqkq1spr0=
github.com/mattn/go-sqlite3 v1.14.20/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.21 h1:IXocQLOykluc3xPE0Lvy8FtggMz1G+U3mEjg+0zGizc=
github.com/mattn/go-sqlite3 v1.14.21/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
@ -430,6 +442,8 @@ github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
github.com/redis/go-redis/v9 v9.3.1 h1:KqdY8U+3X6z+iACvumCNxnoluToB+9Me+TvyFa21Mds=
github.com/redis/go-redis/v9 v9.3.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/redis/go-redis/v9 v9.4.0 h1:Yzoz33UZw9I/mFhx4MNrB6Fk+XHO1VukNcCa1+lwyKk=
github.com/redis/go-redis/v9 v9.4.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@ -575,6 +589,8 @@ golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@ -611,8 +627,12 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -622,6 +642,8 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -785,6 +807,8 @@ sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
src.techknowlogick.com/xgo v1.7.1-0.20231205202227-c7ed78300ce9 h1:lcNlqzNPv7WBKVRqGXWjs+nt9r5WBf2FG+eBOCUcyLM=
src.techknowlogick.com/xgo v1.7.1-0.20231205202227-c7ed78300ce9/go.mod h1:31CE1YKtDOrKTk9PSnjTpe6YbO6W/0LTYZ1VskL09oU=
src.techknowlogick.com/xgo v1.7.1-0.20240124202215-77ac23f331fe h1:8t+5jXWFfMOxWi0OIBMpRSM5agX6xhwA5+em+P9nGTE=
src.techknowlogick.com/xgo v1.7.1-0.20240124202215-77ac23f331fe/go.mod h1:31CE1YKtDOrKTk9PSnjTpe6YbO6W/0LTYZ1VskL09oU=
src.techknowlogick.com/xormigrate v1.7.1 h1:RKGLLUAqJ+zO8iZ7eOc7oLH7f0cs2gfXSZSvBRBHnlY=
src.techknowlogick.com/xormigrate v1.7.1/go.mod h1:YGNBdj8prENlySwIKmfoEXp7ILGjAltyKFXD0qLgD7U=
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
@ -797,3 +821,5 @@ xorm.io/xorm v1.3.4 h1:vWFKzR3DhGUDl5b4srhUjhDwjxkZAc4C7BFszpu0swI=
xorm.io/xorm v1.3.4/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo=
xorm.io/xorm v1.3.6 h1:hfpWHkDIWWqUi8FRF2H2M9O8lO3Ov47rwFcS9gPzPkU=
xorm.io/xorm v1.3.6/go.mod h1:qFJGFoVYbbIdnz2vaL5OxSQ2raleMpyRRalnq3n9OJo=
xorm.io/xorm v1.3.7 h1:mLceAGu0b87r9pD4qXyxGHxifOXIIrAdVcA6k95/osw=
xorm.io/xorm v1.3.7/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw=

View File

@ -26,6 +26,7 @@ import (
func init() {
rootCmd.AddCommand(indexCmd)
rootCmd.AddCommand(partialReindexCmd)
}
var indexCmd = &cobra.Command{
@ -35,8 +36,8 @@ var indexCmd = &cobra.Command{
initialize.FullInitWithoutAsync()
},
Run: func(cmd *cobra.Command, args []string) {
if !config.TypesenseEnabled.GetBool() {
log.Error("Typesense not enabled")
if config.TypesenseURL.GetString() == "" {
log.Error("Typesense not configured")
return
}
@ -56,3 +57,32 @@ var indexCmd = &cobra.Command{
log.Infof("Done!")
},
}
var partialReindexCmd = &cobra.Command{
Use: "partial-index",
Short: "Reindex any tasks which were not indexed yet into Typesense. This will not remove any existing index.",
PreRun: func(cmd *cobra.Command, args []string) {
initialize.FullInitWithoutAsync()
},
Run: func(cmd *cobra.Command, args []string) {
if config.TypesenseURL.GetString() == "" {
log.Error("Typesense not configured")
return
}
log.Infof("Indexing… This may take a while.")
err := models.CreateTypesenseCollections()
if err != nil {
log.Criticalf("Could not create Typesense collections: %s", err.Error())
return
}
err = models.SyncUpdatedTasksIntoTypesense()
if err != nil {
log.Criticalf("Could not reindex all changed tasks into Typesense: %s", err.Error())
return
}
log.Infof("Done!")
},
}

View File

@ -68,8 +68,8 @@ func init() {
userResetPasswordCmd.Flags().StringVarP(&userFlagPassword, "password", "p", "", "The new password of the user. Only used in combination with --direct. You will be asked to enter it if not provided through the flag.")
// Change status flags
userChangeEnabledCmd.Flags().BoolVarP(&userFlagDisableUser, "disable", "d", false, "Disable the user.")
userChangeEnabledCmd.Flags().BoolVarP(&userFlagEnableUser, "enable", "e", false, "Enable the user.")
userChangeStatusCmd.Flags().BoolVarP(&userFlagDisableUser, "disable", "d", false, "Disable the user.")
userChangeStatusCmd.Flags().BoolVarP(&userFlagEnableUser, "enable", "e", false, "Enable the user.")
// User deletion flags
userDeleteCmd.Flags().BoolVarP(&userFlagDeleteNow, "now", "n", false, "If provided, deletes the user immediately instead of sending them an email first.")
@ -77,7 +77,7 @@ func init() {
// Bypass confirm prompt
userDeleteCmd.Flags().BoolVarP(&userFlagDeleteConfirm, "confirm", "c", false, "Bypasses any prompts confirming the deletion request, use with caution!")
userCmd.AddCommand(userListCmd, userCreateCmd, userUpdateCmd, userResetPasswordCmd, userChangeEnabledCmd, userDeleteCmd)
userCmd.AddCommand(userListCmd, userCreateCmd, userUpdateCmd, userResetPasswordCmd, userChangeStatusCmd, userDeleteCmd)
rootCmd.AddCommand(userCmd)
}
@ -283,7 +283,7 @@ var userResetPasswordCmd = &cobra.Command{
},
}
var userChangeEnabledCmd = &cobra.Command{
var userChangeStatusCmd = &cobra.Command{
Use: "change-status [user id]",
Short: "Enable or disable a user. Will toggle the current status if no flag (--enable or --disable) is provided.",
PreRun: func(cmd *cobra.Command, args []string) {
@ -296,18 +296,19 @@ var userChangeEnabledCmd = &cobra.Command{
u := getUserFromArg(s, args[0])
var status user.Status
if userFlagEnableUser {
u.Status = user.StatusActive
status = user.StatusActive
} else if userFlagDisableUser {
u.Status = user.StatusDisabled
status = user.StatusDisabled
} else {
if u.Status == user.StatusActive {
u.Status = user.StatusDisabled
status = user.StatusDisabled
} else {
u.Status = user.StatusActive
status = user.StatusActive
}
}
_, err := user.UpdateUser(s, u, false)
err := user.SetUserStatus(s, u, status)
if err != nil {
_ = s.Rollback()
log.Fatalf("Could not enable the user")
@ -317,7 +318,7 @@ var userChangeEnabledCmd = &cobra.Command{
log.Fatalf("Error saving everything: %s", err)
}
fmt.Printf("User status successfully changed, status is now \"%s\"\n", u.Status)
fmt.Printf("User status successfully changed, status is now \"%s\"\n", status)
},
}

View File

@ -65,10 +65,9 @@ const (
ServiceEnableUserDeletion Key = `service.enableuserdeletion`
ServiceMaxAvatarSize Key = `service.maxavatarsize`
AuthLocalEnabled Key = `auth.local.enabled`
AuthOpenIDEnabled Key = `auth.openid.enabled`
AuthOpenIDRedirectURL Key = `auth.openid.redirecturl`
AuthOpenIDProviders Key = `auth.openid.providers`
AuthLocalEnabled Key = `auth.local.enabled`
AuthOpenIDEnabled Key = `auth.openid.enabled`
AuthOpenIDProviders Key = `auth.openid.providers`
LegalImprintURL Key = `legal.imprinturl`
LegalPrivacyURL Key = `legal.privacyurl`
@ -412,7 +411,7 @@ func InitConfig() {
// Just load environment variables
_ = viper.ReadInConfig()
log.ConfigLogger(LogEnabled.GetBool(), LogStandard.GetString(), LogPath.GetString(), LogLevel.GetString())
log.ConfigureLogger(LogEnabled.GetBool(), LogStandard.GetString(), LogPath.GetString(), LogLevel.GetString())
// Load the config file
viper.AddConfigPath(ServiceRootpath.GetString())
@ -437,7 +436,7 @@ func InitConfig() {
log.Warning(err.Error())
log.Warning("Using default config.")
} else {
log.ConfigLogger(LogEnabled.GetBool(), LogStandard.GetString(), LogPath.GetString(), LogLevel.GetString())
log.ConfigureLogger(LogEnabled.GetBool(), LogStandard.GetString(), LogPath.GetString(), LogLevel.GetString())
}
} else {
log.Info("No config file found, using default or config from environment variables.")
@ -451,10 +450,6 @@ func InitConfig() {
ServiceFrontendurl.Set(ServiceFrontendurl.GetString() + "/")
}
if AuthOpenIDRedirectURL.GetString() == "" {
AuthOpenIDRedirectURL.Set(ServiceFrontendurl.GetString() + "auth/openid/")
}
if MigrationTodoistRedirectURL.GetString() == "" {
MigrationTodoistRedirectURL.Set(ServiceFrontendurl.GetString() + "migrate/todoist")
}

View File

@ -95,7 +95,6 @@ func FullInit() {
models.RegisterUserDeletionCron()
models.RegisterOldExportCleanupCron()
openid.CleanupSavedOpenIDProviders()
models.RegisterPeriodicTypesenseResyncCron()
// Start processing events
go func() {

View File

@ -40,7 +40,7 @@ const logModule = `vikunja`
var logInstance = logging.MustGetLogger(logModule)
// logpath is the path in which log files will be written.
// This value is a mere fallback for other modules that could but shouldn't be used before calling ConfigLogger
// This value is a mere fallback for other modules that could but shouldn't be used before calling ConfigureLogger
var logPath = "."
// InitLogger initializes the global log handler
@ -58,8 +58,8 @@ func InitLogger() {
logInstance.SetBackend(backendLeveled)
}
// ConfigLogger configures the global log handler
func ConfigLogger(configLogEnabled bool, configLogStandard string, configLogPath string, configLogLevel string) {
// ConfigureLogger configures the global log handler
func ConfigureLogger(configLogEnabled bool, configLogStandard string, configLogPath string, configLogLevel string) {
lvl := strings.ToUpper(configLogLevel)
level, err := logging.LogLevel(lvl)
if err != nil {

View File

@ -52,7 +52,6 @@ func RegisterListeners() {
events.RegisterListener((&TaskAssigneeCreatedEvent{}).Name(), &SendTaskAssignedNotification{})
events.RegisterListener((&TaskDeletedEvent{}).Name(), &SendTaskDeletedNotification{})
events.RegisterListener((&ProjectCreatedEvent{}).Name(), &SendProjectCreatedNotification{})
events.RegisterListener((&TaskAssigneeCreatedEvent{}).Name(), &SubscribeAssigneeToTask{})
events.RegisterListener((&TeamMemberAddedEvent{}).Name(), &SendTeamMemberAddedNotification{})
events.RegisterListener((&TaskCommentUpdatedEvent{}).Name(), &HandleTaskCommentEditMentions{})
events.RegisterListener((&TaskCreatedEvent{}).Name(), &HandleTaskCreateMentions{})
@ -70,6 +69,7 @@ func RegisterListeners() {
if config.TypesenseEnabled.GetBool() {
events.RegisterListener((&TaskDeletedEvent{}).Name(), &RemoveTaskFromTypesense{})
events.RegisterListener((&TaskCreatedEvent{}).Name(), &AddTaskToTypesense{})
events.RegisterListener((&TaskUpdatedEvent{}).Name(), &UpdateTaskInTypesense{})
}
if config.WebhooksEnabled.GetBool() {
RegisterEventForWebhook(&TaskCreatedEvent{})
@ -290,20 +290,30 @@ func (s *SendTaskAssignedNotification) Handle(msg *message.Message) (err error)
return err
}
notifiedUsers := make(map[int64]bool)
for _, subscriber := range subscribers {
if subscriber.UserID == event.Doer.ID {
continue
}
if notifiedUsers[subscriber.UserID] {
// Users may be subscribed to the task and the project itself, which leads to double notifications
continue
}
n := &TaskAssignedNotification{
Doer: event.Doer,
Task: &task,
Assignee: event.Assignee,
Target: subscriber.User,
}
err = notifications.Notify(subscriber.User, n)
if err != nil {
return
}
notifiedUsers[subscriber.UserID] = true
}
return nil
@ -360,39 +370,6 @@ func (s *SendTaskDeletedNotification) Handle(msg *message.Message) (err error) {
return nil
}
type SubscribeAssigneeToTask struct {
}
// Name defines the name for the SubscribeAssigneeToTask listener
func (s *SubscribeAssigneeToTask) Name() string {
return "task.assignee.subscribe"
}
// Handle is executed when the event SubscribeAssigneeToTask listens on is fired
func (s *SubscribeAssigneeToTask) Handle(msg *message.Message) (err error) {
event := &TaskAssigneeCreatedEvent{}
err = json.Unmarshal(msg.Payload, event)
if err != nil {
return err
}
sub := &Subscription{
UserID: event.Assignee.ID,
EntityType: SubscriptionEntityTask,
EntityID: event.Task.ID,
}
sess := db.NewSession()
defer sess.Close()
err = sub.Create(sess, event.Assignee)
if err != nil && !IsErrSubscriptionAlreadyExists(err) {
return err
}
return sess.Commit()
}
// HandleTaskCreateMentions represents a listener
type HandleTaskCreateMentions struct {
}
@ -470,9 +447,9 @@ func (s *HandleTaskUpdateLastUpdated) Handle(msg *message.Message) (err error) {
return err
}
task, is := event["Task"].(map[string]interface{})
task, is := event["task"].(map[string]interface{})
if !is {
log.Errorf("Event payload does not contain task ID")
log.Errorf("Event payload does not contain task")
return
}
@ -511,7 +488,7 @@ type RemoveTaskFromTypesense struct {
// Name defines the name for the RemoveTaskFromTypesense listener
func (s *RemoveTaskFromTypesense) Name() string {
return "remove.task.from.typesense"
return "typesense.task.remove"
}
// Handle is executed when the event RemoveTaskFromTypesense listens on is fired
@ -537,7 +514,7 @@ type AddTaskToTypesense struct {
// Name defines the name for the AddTaskToTypesense listener
func (l *AddTaskToTypesense) Name() string {
return "add.task.to.typesense"
return "typesense.task.add"
}
// Handle is executed when the event AddTaskToTypesense listens on is fired
@ -563,6 +540,32 @@ func (l *AddTaskToTypesense) Handle(msg *message.Message) (err error) {
return
}
// UpdateTaskInTypesense represents a listener
type UpdateTaskInTypesense struct {
}
// Name defines the name for the UpdateTaskInTypesense listener
func (l *UpdateTaskInTypesense) Name() string {
return "typesense.task.update"
}
// Handle is executed when the event UpdateTaskInTypesense listens on is fired
func (l *UpdateTaskInTypesense) Handle(msg *message.Message) (err error) {
event := &TaskUpdatedEvent{}
err = json.Unmarshal(msg.Payload, event)
if err != nil {
return err
}
s := db.NewSession()
defer s.Close()
task := make(map[int64]*Task, 1)
task[event.Task.ID] = event.Task // Will be filled with all data by the Typesense connector
return reindexTasksInTypesense(s, task)
}
// IncreaseAttachmentCounter represents a listener
type IncreaseAttachmentCounter struct {
}
@ -677,30 +680,28 @@ type WebhookPayload struct {
Data interface{} `json:"data"`
}
func getIDAsInt64(id interface{}) int64 {
switch v := id.(type) {
case int64:
return v
case float64:
return int64(v)
}
return id.(int64)
}
func getProjectIDFromAnyEvent(eventPayload map[string]interface{}) int64 {
if task, has := eventPayload["task"]; has {
t := task.(map[string]interface{})
if projectID, has := t["project_id"]; has {
switch v := projectID.(type) {
case int64:
return v
case float64:
return int64(v)
}
return projectID.(int64)
return getIDAsInt64(projectID)
}
}
if project, has := eventPayload["project"]; has {
t := project.(map[string]interface{})
if projectID, has := t["id"]; has {
switch v := projectID.(type) {
case int64:
return v
case float64:
return int64(v)
}
return projectID.(int64)
return getIDAsInt64(projectID)
}
}
@ -739,7 +740,6 @@ func (wl *WebhookListener) Handle(msg *message.Message) (err error) {
break
}
}
}
if webhook == nil {

View File

@ -111,10 +111,18 @@ type TaskAssignedNotification struct {
Doer *user.User `json:"doer"`
Task *Task `json:"task"`
Assignee *user.User `json:"assignee"`
Target *user.User `json:"-"`
}
// ToMail returns the mail notification for TaskAssignedNotification
func (n *TaskAssignedNotification) ToMail() *notifications.Mail {
if n.Target.ID == n.Assignee.ID {
return notifications.NewMail().
Subject("You have been assigned to "+n.Task.Title+"("+n.Task.GetFullIdentifier()+")").
Line(n.Doer.GetName()+" has assigned you to "+n.Task.Title+".").
Action("View Task", n.Task.GetFrontendURL())
}
return notifications.NewMail().
Subject(n.Task.Title+"("+n.Task.GetFullIdentifier()+")"+" has been assigned to "+n.Assignee.GetName()).
Line(n.Doer.GetName()+" has assigned this task to "+n.Assignee.GetName()+".").

View File

@ -453,6 +453,10 @@ func getAllProjectsForUser(s *xorm.Session, userID int64, parentProjectIDs []int
parentIDsMap[id] = true
}
for _, project := range currentProjects {
parentIDsMap[project.ID] = true
}
newParentIDs := []int64{}
for _, project := range currentProjects {
if project.IsArchived {

View File

@ -266,6 +266,11 @@ func getSubscriptionsForProjects(s *xorm.Session, projectIDs []int64, u *user.Us
continue
}
ps[eID], err = GetProjectSimpleByID(s, eID)
if err != nil && IsErrProjectDoesNotExist(err) {
// If the project does not exist, it might got deleted. There could still be subscribers though.
delete(ps, eID)
continue
}
if err != nil {
return nil, err
}
@ -314,6 +319,10 @@ func getSubscriptionsForProjects(s *xorm.Session, projectIDs []int64, u *user.Us
_, has := projectsToSubscriptions[eID]
_, hasProject := ps[eID]
if !has && hasProject {
_, exists := ps[eID]
if !exists {
continue
}
var parent = ps[eID].ParentProject
for parent != nil {
sub, has := projectsToSubscriptions[parent.ID]

View File

@ -184,8 +184,13 @@ func (la *TaskAssginee) Delete(s *xorm.Session, a web.Auth) (err error) {
}
doer, _ := user.GetFromAuth(a)
task, err := GetTaskByIDSimple(s, la.TaskID)
if err != nil {
return err
}
return events.Dispatch(&TaskAssigneeDeletedEvent{
Task: &Task{ID: la.TaskID},
Task: &task,
Assignee: &user.User{ID: la.UserID},
Doer: doer,
})
@ -251,9 +256,24 @@ func (t *Task) addNewAssigneeByID(s *xorm.Session, newAssigneeID int64, project
return err
}
sub := &Subscription{
UserID: newAssigneeID,
EntityType: SubscriptionEntityTask,
EntityID: t.ID,
}
err = sub.Create(s, newAssignee)
if err != nil && !IsErrSubscriptionAlreadyExists(err) {
return err
}
doer, _ := user.GetFromAuth(auth)
task, err := GetTaskSimple(s, &Task{ID: t.ID})
if err != nil {
return err
}
err = events.Dispatch(&TaskAssigneeCreatedEvent{
Task: t,
Task: &task,
Assignee: newAssignee,
Doer: doer,
})

View File

@ -86,8 +86,13 @@ func (ta *TaskAttachment) NewAttachment(s *xorm.Session, f io.ReadCloser, realna
return err
}
task, err := GetTaskByIDSimple(s, ta.TaskID)
if err != nil {
return err
}
return events.Dispatch(&TaskAttachmentCreatedEvent{
Task: &Task{ID: ta.TaskID},
Task: &task,
Attachment: ta,
Doer: ta.CreatedBy,
})
@ -220,8 +225,13 @@ func (ta *TaskAttachment) Delete(s *xorm.Session, a web.Auth) error {
}
doer, _ := user.GetFromAuth(a)
task, err := GetTaskByIDSimple(s, ta.TaskID)
if err != nil {
return err
}
return events.Dispatch(&TaskAttachmentDeletedEvent{
Task: &Task{ID: ta.TaskID},
Task: &task,
Attachment: ta,
Doer: doer,
})

View File

@ -208,7 +208,10 @@ func (tf *TaskCollection) ReadAll(s *xorm.Session, a web.Auth, search string, pa
return nil, 0, 0, err
}
if !canRead {
return nil, 0, 0, ErrUserDoesNotHaveAccessToProject{ProjectID: tf.ProjectID}
return nil, 0, 0, ErrUserDoesNotHaveAccessToProject{
ProjectID: tf.ProjectID,
UserID: a.GetID(),
}
}
projects = []*Project{{ID: tf.ProjectID}}
}

View File

@ -114,8 +114,13 @@ func (tc *TaskComment) Delete(s *xorm.Session, _ web.Auth) error {
return err
}
task, err := GetTaskByIDSimple(s, tc.TaskID)
if err != nil {
return err
}
return events.Dispatch(&TaskCommentDeletedEvent{
Task: &Task{ID: tc.TaskID},
Task: &task,
Comment: tc,
Doer: tc.Author,
})

View File

@ -102,7 +102,10 @@ func TestTaskComment_Delete(t *testing.T) {
s := db.NewSession()
defer s.Close()
tc := &TaskComment{ID: 1}
tc := &TaskComment{
ID: 1,
TaskID: 1,
}
err := tc.Delete(s, u)
require.NoError(t, err)
err = s.Commit()

View File

@ -165,7 +165,7 @@ func (rel *TaskRelation) Create(s *xorm.Session, a web.Auth) error {
exists, err := s.
Where("(task_id = ? AND other_task_id = ? AND relation_kind = ?) OR (task_id = ? AND other_task_id = ? AND relation_kind = ?)",
rel.TaskID, rel.OtherTaskID, rel.RelationKind, rel.TaskID, rel.OtherTaskID, rel.RelationKind).
Exist(rel)
Exist(&TaskRelation{})
if err != nil {
return err
}
@ -201,8 +201,13 @@ func (rel *TaskRelation) Create(s *xorm.Session, a web.Auth) error {
}
doer, _ := user.GetFromAuth(a)
task, err := GetTaskByIDSimple(s, rel.TaskID)
if err != nil {
return err
}
return events.Dispatch(&TaskRelationCreatedEvent{
Task: &Task{ID: rel.TaskID},
Task: &task,
Relation: rel,
Doer: doer,
})
@ -261,8 +266,13 @@ func (rel *TaskRelation) Delete(s *xorm.Session, a web.Auth) error {
}
doer, _ := user.GetFromAuth(a)
task, err := GetTaskByIDSimple(s, rel.TaskID)
if err != nil {
return err
}
return events.Dispatch(&TaskRelationDeletedEvent{
Task: &Task{ID: rel.TaskID},
Task: &task,
Relation: rel,
Doer: doer,
})

View File

@ -1432,10 +1432,6 @@ func (t *Task) Delete(s *xorm.Session, a web.Auth) (err error) {
return err
}
if _, err = s.ID(t.ID).Delete(Task{}); err != nil {
return err
}
// Delete assignees
if _, err = s.Where("task_id = ?", t.ID).Delete(TaskAssginee{}); err != nil {
return err
@ -1484,6 +1480,12 @@ func (t *Task) Delete(s *xorm.Session, a web.Auth) (err error) {
return
}
// Actually delete the task
_, err = s.ID(t.ID).Delete(Task{})
if err != nil {
return err
}
doer, _ := user.GetFromAuth(a)
err = events.Dispatch(&TaskDeletedEvent{
Task: fullTask,

View File

@ -22,7 +22,6 @@ import (
"time"
"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"
@ -232,7 +231,7 @@ func ReindexAllTasks() (err error) {
return fmt.Errorf("could not index dummy task: %w", err)
}
err = reindexTasks(s, tasks)
err = reindexTasksInTypesense(s, tasks)
if err != nil {
return fmt.Errorf("could not reindex all tasks: %s", err.Error())
}
@ -278,7 +277,7 @@ func getTypesenseTaskForTask(s *xorm.Session, task *Task, projectsCache map[int6
return
}
func reindexTasks(s *xorm.Session, tasks map[int64]*Task) (err error) {
func reindexTasksInTypesense(s *xorm.Session, tasks map[int64]*Task) (err error) {
if len(tasks) == 0 {
log.Infof("No tasks to index")
@ -314,6 +313,8 @@ func reindexTasks(s *xorm.Session, tasks map[int64]*Task) (err error) {
return err
}
log.Debugf("Indexed tasks %v into Typesense", tasks)
return nil
}
@ -475,6 +476,8 @@ func convertTaskToTypesenseTask(task *Task) *typesenseTask {
return tt
}
// This function is only used to catch up with the Typesense Sync when it didn't index for some reason
func SyncUpdatedTasksIntoTypesense() (err error) {
tasks := make(map[int64]*Task)
@ -517,7 +520,7 @@ func SyncUpdatedTasksIntoTypesense() (err error) {
if len(tasks) > 0 {
log.Debugf("[Typesense Sync] Updating %d tasks", len(tasks))
err = reindexTasks(s, tasks)
err = reindexTasksInTypesense(s, tasks)
if err != nil {
_ = s.Rollback()
return
@ -539,20 +542,3 @@ func SyncUpdatedTasksIntoTypesense() (err error) {
return s.Commit()
}
func RegisterPeriodicTypesenseResyncCron() {
if !config.TypesenseEnabled.GetBool() {
log.Debugf("[Typesense Sync] Typesense is disabled, not setting up sync cron")
return
}
err := cron.Schedule("* * * * *", func() {
err := SyncUpdatedTasksIntoTypesense()
if err != nil {
log.Fatalf("[Typesense Sync] Could not sync updated tasks into typesense: %s", err)
}
})
if err != nil {
log.Fatalf("[Typesense Sync] Could not register typesense resync cron: %s", err)
}
}

View File

@ -40,8 +40,9 @@ import (
// Callback contains the callback after an auth request was made and redirected
type Callback struct {
Code string `query:"code" json:"code"`
Scope string `query:"scop" json:"scope"`
Code string `query:"code" json:"code"`
Scope string `query:"scop" json:"scope"`
RedirectURL string `json:"redirect_url"`
}
// Provider is the structure of an OpenID Connect provider
@ -103,6 +104,8 @@ func HandleCallback(c echo.Context) error {
return c.JSON(http.StatusBadRequest, models.Message{Message: "Provider does not exist"})
}
provider.Oauth2Config.RedirectURL = cb.RedirectURL
// Parse the access & ID token
oauth2Token, err := provider.Oauth2Config.Exchange(context.Background(), cb.Code)
if err != nil {

View File

@ -149,7 +149,6 @@ func getProviderFromMap(pi map[string]interface{}) (provider *Provider, err erro
provider.Oauth2Config = &oauth2.Config{
ClientID: provider.ClientID,
ClientSecret: provider.ClientSecret,
RedirectURL: config.AuthOpenIDRedirectURL.GetString() + k,
// Discovery returns the OAuth2 endpoints.
Endpoint: provider.openIDProvider.Endpoint(),

View File

@ -205,6 +205,11 @@ func createProjectWithEverything(s *xorm.Session, project *models.ProjectWithTas
oldid := t.ID
t.ProjectID = project.ID
err = t.Create(s, user)
if err != nil && models.IsErrTaskCannotBeEmpty(err) {
continue
}
if err != nil {
return
}

View File

@ -63,9 +63,8 @@ type localAuthInfo struct {
}
type openIDAuthInfo struct {
Enabled bool `json:"enabled"`
RedirectURL string `json:"redirect_url"`
Providers []*openid.Provider `json:"providers"`
Enabled bool `json:"enabled"`
Providers []*openid.Provider `json:"providers"`
}
type legalInfo struct {
@ -109,8 +108,7 @@ func Info(c echo.Context) error {
Enabled: config.AuthLocalEnabled.GetBool(),
},
OpenIDConnect: openIDAuthInfo{
Enabled: config.AuthOpenIDEnabled.GetBool(),
RedirectURL: config.AuthOpenIDRedirectURL.GetString(),
Enabled: config.AuthOpenIDEnabled.GetBool(),
},
},
}

View File

@ -623,7 +623,7 @@ func (vcls *VikunjaCaldavProjectStorage) getProjectRessource(isCollection bool)
if !can {
_ = s.Rollback()
log.Errorf("User %v tried to access a caldav resource (Project %v) which they are not allowed to access", vcls.user.Username, vcls.project.ID)
return rr, models.ErrUserDoesNotHaveAccessToProject{ProjectID: vcls.project.ID}
return rr, models.ErrUserDoesNotHaveAccessToProject{ProjectID: vcls.project.ID, UserID: vcls.user.ID}
}
err = vcls.project.ReadOne(s, vcls.user)
if err != nil {

View File

@ -8548,6 +8548,9 @@ const docTemplate = `{
"code": {
"type": "string"
},
"redirect_url": {
"type": "string"
},
"scope": {
"type": "string"
}
@ -8883,9 +8886,6 @@ const docTemplate = `{
"items": {
"$ref": "#/definitions/openid.Provider"
}
},
"redirect_url": {
"type": "string"
}
}
},

View File

@ -8540,6 +8540,9 @@
"code": {
"type": "string"
},
"redirect_url": {
"type": "string"
},
"scope": {
"type": "string"
}
@ -8875,9 +8878,6 @@
"items": {
"$ref": "#/definitions/openid.Provider"
}
},
"redirect_url": {
"type": "string"
}
}
},

View File

@ -1099,6 +1099,8 @@ definitions:
properties:
code:
type: string
redirect_url:
type: string
scope:
type: string
type: object
@ -1345,8 +1347,6 @@ definitions:
items:
$ref: '#/definitions/openid.Provider'
type: array
redirect_url:
type: string
type: object
v1.vikunjaInfos:
properties:

View File

@ -65,7 +65,7 @@ func (s Status) String() string {
}
const (
StatusActive = iota
StatusActive Status = iota
StatusEmailConfirmationRequired
StatusDisabled
)
@ -543,6 +543,13 @@ func UpdateUser(s *xorm.Session, user *User, forceOverride bool) (updatedUser *U
return updatedUser, err
}
func SetUserStatus(s *xorm.Session, user *User, status Status) (err error) {
_, err = s.Where("id = ?", user.ID).
Cols("status").
Update(&User{Status: status})
return
}
// UpdateUserPassword updates the password of a user
func UpdateUserPassword(s *xorm.Session, user *User, newPassword string) (err error) {