Compare commits

...

236 Commits

Author SHA1 Message Date
branchmispredictor 93dee49b25 Fix golint errors 2021-05-17 15:03:12 -04:00
branchmispredictor 27891e4492 Docs and formatting 2021-05-17 15:02:42 -04:00
branchmispredictor 2fa6523cc1 Add support to login using identity from an identity-aware proxy 2021-05-17 15:02:40 -04:00
renovate 2351194547 Update module yuin/goldmark to v1.3.7 (#867)
Reviewed-on: vikunja/api#867
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-05-17 15:03:08 +00:00
kolaente b7ec24ff52
Fix old references to master in docs 2021-05-17 12:53:12 +02:00
renovate aaac4c6dfc Update module lib/pq to v1.10.2 (#865)
Co-authored-by: konrad <konrad@kola-entertainments.de>
Reviewed-on: vikunja/api#865
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-05-17 10:44:55 +00:00
kolaente 2e52cc1802
Fix lint 2021-05-17 12:15:15 +02:00
kolaente 20ede346b4
Only filter out failing openid providers if multiple are configured and one of them failed 2021-05-16 13:28:15 +02:00
kolaente b76ad8efe2
Add more logging and better error messages for openid authentication + clarify docs 2021-05-16 13:23:10 +02:00
renovate d695681a0e Update module yuin/goldmark to v1.3.6 (#863)
Reviewed-on: vikunja/api#863
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-05-15 13:17:27 +00:00
renovate 52c3075c3d Update golang.org/x/oauth2 commit hash to f6687ab (#862)
Reviewed-on: vikunja/api#862
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-05-14 22:10:40 +00:00
kolaente e837c2a003
Release preparations 2021-05-14 17:03:42 +02:00
renovate f670d394fa Update golang.org/x/crypto commit hash to c07d793 (#861)
Reviewed-on: vikunja/api#861
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-05-13 17:20:01 +00:00
renovate 71cc7334cc Update golang.org/x/crypto commit hash to cd7d49e (#860)
Reviewed-on: vikunja/api#860
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-05-13 13:20:53 +00:00
earnest ma fc1867ec70 Update README (#858)
Reviewed-on: vikunja/api#858
Reviewed-by: konrad <konrad@kola-entertainments.de>
Co-authored-by: earnest ma <me@earne.link>
Co-committed-by: earnest ma <me@earne.link>
2021-05-11 18:14:35 +00:00
renovate d69482cda9 Update module gabriel-vasile/mimetype to v1.3.0 (#857)
Reviewed-on: vikunja/api#857
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-05-10 10:16:25 +00:00
renovate 71d60e908a Update module labstack/echo/v4 to v4.3.0 (#856)
Reviewed-on: vikunja/api#856
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-05-08 22:17:06 +00:00
kompetenzbolzen 86b7d224ab Expose tls parameter of Go MySQL driver to config file (#855)
Co-authored-by: Jonas Gunz <himself@jonasgunz.de>
Reviewed-on: vikunja/api#855
Reviewed-by: konrad <konrad@kola-entertainments.de>
Co-authored-by: kompetenzbolzen <himself@jonasgunz.de>
Co-committed-by: kompetenzbolzen <himself@jonasgunz.de>
2021-05-08 14:54:55 +00:00
kolaente 9dc72c5c98
Use golang's tzdata package to handle time zones 2021-05-07 12:18:21 +02:00
renovate f052fc19fc Update golang.org/x/crypto commit hash to 38f3c27 (#854)
Reviewed-on: vikunja/api#854
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-05-06 16:16:53 +00:00
renovate 06cc0a06e4 Update golang.org/x/crypto commit hash to 3497b51 (#853)
Reviewed-on: vikunja/api#853
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-05-06 06:26:24 +00:00
renovate 02dd7ee571 Update golang.org/x/image commit hash to 7319ad4 (#852)
Reviewed-on: vikunja/api#852
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-05-04 15:28:30 +00:00
renovate abc1fa2fed Update golang.org/x/crypto commit hash to e9a3299 (#851)
Reviewed-on: vikunja/api#851
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-05-03 20:14:00 +00:00
renovate b5da7fc546 Update golang.org/x/term commit hash to a79de54 (#850)
Reviewed-on: vikunja/api#850
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-05-03 08:37:51 +00:00
renovate d715b02421 Update golang.org/x/term commit hash to c04ba85 (#849)
Reviewed-on: vikunja/api#849
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-29 16:15:27 +00:00
renovate b7b69afa0c Update golang.org/x/term commit hash to f5beecf (#845)
Reviewed-on: vikunja/api#845
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-27 20:37:13 +00:00
renovate ce15ade6b8 Update golang.org/x/oauth2 commit hash to 81ed05c (#848)
Reviewed-on: vikunja/api#848
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-27 19:36:51 +00:00
kolaente 0986ec6bdd
Update changelog 2021-04-22 17:20:04 +02:00
kolaente 8b56308a59
Update changelog 2021-04-22 17:20:04 +02:00
kolaente 0f5f85e687
Fix tests 2021-04-22 17:13:47 +02:00
kolaente 4ceeb877b1
Fix checking list rights when accessing a bucket 2021-04-22 16:44:42 +02:00
kolaente 4393320691
Add security information to readme 2021-04-22 15:07:28 +02:00
kolaente e4db9dfe6c
Cleanup old docs themes submodule 2021-04-22 11:33:15 +02:00
kolaente 4504499f60
Switch building the docs to download the theme instead of building 2021-04-22 11:25:19 +02:00
renovate 43cb7f1fc2 Update golang.org/x/term commit hash to b80969c (#843)
Reviewed-on: vikunja/api#843
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-22 08:54:44 +00:00
renovate 30919fd4da Update module lib/pq to v1.10.1 (#841)
Reviewed-on: vikunja/api#841
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-21 20:28:50 +00:00
renovate 5089049b17 Update golang.org/x/crypto commit hash to 83a5a9b (#840)
Reviewed-on: vikunja/api#840
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-21 19:45:25 +00:00
renovate 6fc4e35ac4 Update golang.org/x/crypto commit hash to 5bf0f12 (#839)
Reviewed-on: vikunja/api#839
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-21 17:57:35 +00:00
kolaente 6e263b6a91
Improve sending overdue task reminders by only sending one for all overdue tasks 2021-04-18 15:32:02 +02:00
kolaente 7ff7b0d743
Improve duration format of overdue tasks in reminders 2021-04-18 14:25:50 +02:00
renovate 410a7426cf Update module go-testfixtures/testfixtures/v3 to v3.6.0 (#838)
Reviewed-on: vikunja/api#838
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-18 10:31:13 +00:00
renovate 8d1cee4500 Update golang.org/x/crypto commit hash to 4f45737 (#836)
Reviewed-on: vikunja/api#836
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-15 19:08:11 +00:00
kolaente f429efc220
Add bucket limit validation 2021-04-15 16:55:21 +02:00
kolaente 6e5a9868f5
Fix moving repeating tasks to the done bucket 2021-04-15 16:36:24 +02:00
renovate 2547de59ae Update module mattn/go-sqlite3 to v1.14.7 (#835)
Reviewed-on: vikunja/api#835
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-14 16:20:09 +00:00
konrad b4d726f5a8 Add repeat monthly setting for tasks (#834)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#834
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
2021-04-14 09:04:58 +00:00
renovate ad9749e37d Update golang.org/x/oauth2 commit hash to 5e61552 (#833)
Reviewed-on: vikunja/api#833
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-13 14:19:32 +00:00
kolaente 967270b2c1
Fix docs 2021-04-11 18:38:06 +02:00
konrad d07b284ee3 Add reminders for overdue tasks (#832)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#832
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
2021-04-11 15:08:43 +00:00
konrad b3c604fd2f Add link share password authentication (#831)
Reviewed-on: vikunja/api#831
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
2021-04-11 13:17:50 +00:00
renovate 6a927c0703 Update module labstack/echo/v4 to v4.2.2 (#830)
Reviewed-on: vikunja/api#830
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-08 13:01:29 +00:00
kolaente 126f3acdc8
Enable searching users by full email or name 2021-04-07 18:28:58 +02:00
kolaente 8ddc00bd29
Fix getting user info from /user endpoint for link shares 2021-04-07 15:02:57 +02:00
kolaente cb0df3ebbc
Show empty avatar when the user was not found 2021-04-07 14:56:44 +02:00
kolaente 325dcc5795
Fix matrix notify room id 2021-04-07 14:46:40 +02:00
konrad 84291679cc Add names for link shares (#829)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#829
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
2021-04-07 12:44:39 +00:00
kolaente b7d832891a
Switch telegram notifications to matrix notifications 2021-04-07 12:27:51 +02:00
renovate b2bbb03e48 Update golang.org/x/term commit hash to 72f3dc4 (#828)
Reviewed-on: vikunja/api#828
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-07 09:15:09 +00:00
kolaente 0b8173c1c3
Fix not able to make saved filters favorite 2021-04-03 16:49:20 +02:00
renovate 9b7eef985e Update golang.org/x/oauth2 commit hash to 2e8d934 (#827)
Reviewed-on: vikunja/api#827
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-03 11:08:49 +00:00
renovate 8a7baaed19 Update module go-sql-driver/mysql to v1.6.0 (#826)
Reviewed-on: vikunja/api#826
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-04-01 16:31:27 +00:00
kolaente 73f2d4532d
Make sure all tables are properly pluralized 2021-03-28 20:17:35 +02:00
kolaente bc782e68ff
Add systemd service file to linux packages 2021-03-28 18:18:58 +02:00
kolaente 6c3488b8aa
Fix event error handler retrying infinitely 2021-03-28 17:55:19 +02:00
kolaente d7f3c653f9
Remove unused tools from tools.go 2021-03-28 17:24:56 +02:00
renovate e2aa916bdd Update module adlio/trello to v1.9.0 (#825)
Reviewed-on: vikunja/api#825
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-28 15:04:37 +00:00
renovate 398f05e9a0 Update golang.org/x/oauth2 commit hash to 22b0ada (#823)
Reviewed-on: vikunja/api#823
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-25 10:50:41 +00:00
kolaente be3184d49f
Add test for moving a task to another list 2021-03-24 22:47:03 +01:00
konrad 81d021e872 Improve loading labels performance (#824)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#824
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
2021-03-24 21:46:20 +00:00
konrad d1b87d2705 Add a "done" option to kanban buckets (#821)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#821
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
2021-03-24 20:16:35 +00:00
kolaente 7b29ac7128
Fix user uploaded avatars 2021-03-23 22:32:23 +01:00
renovate 7b7ccddf51 Update golang.org/x/crypto commit hash to 0c34fe9 (#822)
Reviewed-on: vikunja/api#822
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-23 19:28:10 +00:00
kolaente 532855d850
Fix filter for task index 2021-03-21 18:48:41 +01:00
kolaente ee436efba3
Add endpoint to remove a list background 2021-03-21 17:49:14 +01:00
renovate 9d0dcb8d7d Update module spf13/afero to v1.6.0 (#820)
Reviewed-on: vikunja/api#820
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-21 10:53:41 +00:00
kolaente 6fa95e6492
Fix getting lists for shared, favorite and saved lists namespace 2021-03-18 21:39:38 +01:00
renovate fc4eb8ceb9 Update module prometheus/client_golang to v1.10.0 (#819)
Reviewed-on: vikunja/api#819
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-18 18:25:48 +00:00
renovate 87f7cbfa73 Update golang.org/x/term commit hash to de623e6 (#818)
Reviewed-on: vikunja/api#818
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-17 21:11:45 +00:00
renovate f8683796e8 Update golang.org/x/crypto commit hash to 513c2a4 (#817)
Reviewed-on: vikunja/api#817
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-17 21:11:29 +00:00
renovate 5e048feedf Update golang.org/x/crypto commit hash to e6e6c4f (#816)
Reviewed-on: vikunja/api#816
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-15 21:17:14 +00:00
kolaente 67167d4abb
Fix shared lists showing up twice 2021-03-14 21:12:03 +01:00
renovate 156e50f371 Update golang.org/x/oauth2 commit hash to cd4f82c (#815)
Reviewed-on: vikunja/api#815
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-14 12:49:05 +00:00
renovate cf2cfde4fc Update module src.techknowlogick.com/xgo to v1.4.0+1.16.2 (#814)
Reviewed-on: vikunja/api#814
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-12 09:22:48 +00:00
renovate f78bb613e4 Update golang.org/x/oauth2 commit hash to 5366d9d (#813)
Reviewed-on: vikunja/api#813
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-11 17:19:53 +00:00
renovate 3a7678bfb9 Update module gabriel-vasile/mimetype to v1.2.0 (#812)
Reviewed-on: vikunja/api#812
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-11 14:45:51 +00:00
konrad 466b2b676c Pagingation for tasks in kanban buckets (#805)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#805
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
2021-03-10 10:59:10 +00:00
renovate 89d0fbcc7c Update module imdario/mergo to v0.3.12 (#811)
Reviewed-on: vikunja/api#811
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-10 10:01:42 +00:00
renovate 77e9a58a52 Update module labstack/echo/v4 to v4.2.1 (#810)
Reviewed-on: vikunja/api#810
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-09 12:12:37 +00:00
renovate 81665168bc Update module lib/pq to v1.10.0 (#809)
Reviewed-on: vikunja/api#809
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-03-09 09:49:47 +00:00
kolaente 6de3d8b3a1
Explicitly check if there are Ids before trying to get items by a list of Ids 2021-03-02 18:40:39 +01:00
kolaente 3999580fe6
Add basic auth for metrics endpoint 2021-02-28 11:29:53 +01:00
renovate c71a1fea82 Update module jgautheron/goconst to v1 (#804)
Reviewed-on: vikunja/api#804
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-27 14:52:00 +00:00
renovate 729cb3de38 Update github.com/gordonklaus/ineffassign commit hash to 2e10b26 (#803)
Reviewed-on: vikunja/api#803
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-25 22:24:22 +00:00
kolaente 4880a0265b
Fix notifications table not being created on initial setup 2021-02-22 21:20:13 +01:00
konrad 2178166ece Add crud endpoints for notifications (#801)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#801
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
2021-02-21 14:50:34 +00:00
kolaente 509f23c550
Fix build
go mod tidy did the trick.
2021-02-20 18:47:02 +01:00
renovate a22dd094c2 Update golang.org/x/image commit hash to ac19c3e (#798)
Reviewed-on: vikunja/api#798
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-20 17:36:03 +00:00
renovate b6accd7c67 Update golang.org/x/crypto commit hash to 5ea612d (#797)
Reviewed-on: vikunja/api#797
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-20 16:56:37 +00:00
renovate 393a3bc37a Update golang.org/x/sync commit hash to 036812b (#799)
Reviewed-on: vikunja/api#799
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-20 15:28:21 +00:00
renovate b98ac9f551 Update golang.org/x/term commit hash to 6a3ed07 (#800)
Reviewed-on: vikunja/api#800
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-20 14:36:49 +00:00
renovate 8ab5289c3d Update golang.org/x/oauth2 commit hash to 9bb9049 (#796)
Reviewed-on: vikunja/api#796
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-20 07:35:37 +00:00
renovate 32cf66e9d5 Update module go-redis/redis/v8 to v8.6.0 (#795)
Reviewed-on: vikunja/api#795
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-20 07:34:44 +00:00
kolaente eb3a945678
Fix deleting task relations
While the request body of a DELETE request *can* have data in it, it is not really supported and pretty much undocumented. As such, it doesn't work in all clients and probably broke with recent updates.
This fixes this by moving all parts of the task relation used to identify it in the url.

More Info: https://stackoverflow.com/a/299696/10924593
2021-02-18 23:35:33 +01:00
renovate 3afedc25f0 Update golang.org/x/oauth2 commit hash to ba52d33 (#794)
Reviewed-on: vikunja/api#794
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-18 21:36:56 +00:00
renovate 4fc7d1f64f Update golang.org/x/crypto commit hash to b8e89b7 (#793)
Reviewed-on: vikunja/api#793
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-18 20:58:49 +00:00
renovate 0c5c54a267 Update module getsentry/sentry-go to v0.10.0 (#792)
Reviewed-on: vikunja/api#792
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-18 20:58:27 +00:00
kolaente 86a9d2e9f3
Explicitly set darwin-10.15 when building binaries 2021-02-18 21:35:45 +01:00
renovate 8b2b996e7a Update module src.techknowlogick.com/xgo to v1.3.0+1.16.0 (#791)
Reviewed-on: vikunja/api#791
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-18 06:42:25 +00:00
kolaente d8623fe185
Cleanup listener names 2021-02-17 20:50:04 +01:00
kolaente c873c1ec32
Send a notification to the user when they are added to the list 2021-02-17 20:48:06 +01:00
kolaente 0bd27ddeb7
Subscribe a user to a task when they are assigned to it 2021-02-17 20:14:38 +01:00
kolaente aaeb89db4f
Refactor getting all namespaces 2021-02-16 22:36:06 +01:00
renovate 2f1a3fea88 Update golang.org/x/oauth2 commit hash to 16ff188 (#789)
Reviewed-on: vikunja/api#789
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-16 21:06:45 +00:00
renovate d9a57e7ef4 Update golang.org/x/image commit hash to 4410531 (#788)
Reviewed-on: vikunja/api#788
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-16 06:54:08 +00:00
renovate ddcf7624bd Update golang.org/x/image commit hash to 55ae14f (#787)
Reviewed-on: vikunja/api#787
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-15 07:27:20 +00:00
kolaente 911e5b22ee
Fix lint 2021-02-14 23:11:39 +01:00
kolaente bef22f5756
Fix tests 2021-02-14 23:03:44 +01:00
kolaente d8e10e1a58
Add separate docker manifest file for latest docker images 2021-02-14 22:46:46 +01:00
kolaente 83f003355d
Fix sending notifications to users if the user object didn't have an email 2021-02-14 22:44:01 +01:00
kolaente 58492fffce
Run all lint checks at once 2021-02-14 22:40:08 +01:00
kolaente 268e344128
Fix multiarch docker image building 2021-02-14 22:11:12 +01:00
kolaente 9cff4e33ca
Fix docs 2021-02-14 20:37:18 +01:00
konrad e7875ecb3b Subscriptions and notifications for namespaces, tasks and lists (#786)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#786
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
2021-02-14 19:18:14 +00:00
renovate 618b464ca3 Update module labstack/echo/v4 to v4.2.0 (#785)
Reviewed-on: vikunja/api#785
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-13 22:46:03 +00:00
renovate 448ac314b6 Update module spf13/cobra to v1.1.3 (#784)
Reviewed-on: vikunja/api#784
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-13 22:43:14 +00:00
renovate d6c6fcadc5 Update golang.org/x/oauth2 commit hash to 6667018 (#783)
Reviewed-on: vikunja/api#783
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-13 22:39:28 +00:00
kolaente 65f42b8bda
Re-Enable migration test steps in pipeline 2021-02-13 16:58:12 +01:00
kolaente ec7becd426
Check if we're on main and change the version name accordingly if that's the case 2021-02-13 16:32:26 +01:00
kolaente 59092afbc0
Explicitly add docker build step for latest 2021-02-13 16:01:20 +01:00
kolaente 480db6aa9b
Pipeline debugging 2021-02-10 20:49:20 +01:00
kolaente bb77df68f5
Temporarily disable migration step 2021-02-10 20:25:24 +01:00
kolaente 9ef17a6dbc
Change test file names to unstable 2021-02-10 19:59:53 +01:00
kolaente 37a4e1e658
Temporary build fix 2021-02-10 19:58:24 +01:00
kolaente 02b6dbd07d
Fix unstable version build file names 2021-02-10 19:56:51 +01:00
kolaente 61d76e6875
Change unstable versions in migration tests 2021-02-10 18:53:30 +01:00
kolaente 7debeaa9ff
Change main branch to main 2021-02-10 18:50:15 +01:00
renovate 5d698f2ff8 Update module olekukonko/tablewriter to v0.0.5 (#782)
Reviewed-on: vikunja/api#782
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-10 17:47:21 +00:00
renovate 7bb3f4c847 Update module spf13/cobra to v1.1.2 (#781)
Reviewed-on: vikunja/api#781
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-10 06:38:34 +00:00
kolaente 269e7dd5df
Don't keep old releases from os packages when releasing for master 2021-02-09 20:41:19 +01:00
renovate 8cfa2aa480 Update github.com/gordonklaus/ineffassign commit hash to d0e41b2 (#780)
Reviewed-on: vikunja/api#780
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-09 19:27:41 +00:00
konrad 015ca310e9 Add notifications package for easy sending of notifications (#779)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#779
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
2021-02-07 21:05:09 +00:00
kolaente 9fe46f9a61
Don't try to get users for tasks if no tasks were found when looking for reminders 2021-02-07 14:46:47 +01:00
kolaente 18b35e1119
Fix drone file 2021-02-04 22:40:38 +01:00
kolaente b8ccfbd190
Add arm64 builds 2021-02-04 22:32:37 +01:00
kolaente 490ba2ea50
Fix due dates with times when migrating from todoist 2021-02-04 21:06:01 +01:00
kolaente fb53322d40
Change the name of the newly created bucket from "New Bucket" to "Backlog" 2021-02-04 20:48:07 +01:00
renovate 55f9106c9e Update module go-redis/redis/v8 to v8.5.0 (#778)
Reviewed-on: vikunja/api#778
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-04 18:42:39 +00:00
kolaente d600d8b5a6
Fix IncrBy and DecrBy in memory keyvalue implementation if there was no value set previously 2021-02-03 21:59:45 +01:00
konrad 0ab9ce9ec4 Add events (#777)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#777
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
2021-02-02 22:48:37 +00:00
kolaente a71aa0c898
Disable deb repo in drone 2021-02-02 21:32:57 +01:00
kolaente c4a71016b8
Update copyright year 2021-02-02 20:19:13 +01:00
renovate 34ef1438d8 Update golang.org/x/oauth2 commit hash to 0101308 (#776)
Reviewed-on: vikunja/api#776
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-02-01 19:29:22 +00:00
kolaente 657dcc5313
Fix lint 2021-01-31 13:51:23 +01:00
kolaente 2d283b78c2
Fix the shared lists pseudo namespace containing owned lists 2021-01-31 13:09:14 +01:00
kolaente 6bdc1fdb0d
Only send reminders for undone tasks 2021-01-31 12:54:15 +01:00
kolaente d69c799197
Fix resetting the bucket limit 2021-01-31 12:40:02 +01:00
kolaente 2e88600c93
Change keyvalue.Get to return if a value exists or not instead of an error 2021-01-31 12:32:46 +01:00
renovate fe72f30b24 Update golang.org/x/oauth2 commit hash to f9ce19e (#775)
Reviewed-on: vikunja/api#775
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-28 14:39:28 +00:00
kolaente 6945d8ba69
Pin golang alpine builder image to 3.12 to fix builds on arm 2021-01-26 21:02:59 +01:00
renovate ef0035d4bd Update module go-redis/redis/v8 to v8.4.11 (#774)
Reviewed-on: vikunja/api#774
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-26 19:14:03 +00:00
renovate db77de3ae6 Update golang.org/x/oauth2 commit hash to af13f52 (#773)
Reviewed-on: vikunja/api#773
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-25 22:07:04 +00:00
renovate 1c98fecbd9 Update module go-redis/redis/v8 to v8.4.10 (#771)
Reviewed-on: vikunja/api#771
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-22 08:23:08 +00:00
kolaente 343fa6ca0d
Add github funding link 2021-01-20 21:53:38 +01:00
renovate aadfb8d8f2 Update module go-redis/redis/v8 to v8.4.9 (#770)
Reviewed-on: vikunja/api#770
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-20 20:29:36 +00:00
konrad 2447f84e2b Fix /dav/principals/*/ throwing a server error when accessed with GET instead of PROPFIND (#769)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#769
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
2021-01-16 14:37:35 +00:00
kolaente c1ad9d58f5
Revert "Update alpine Docker tag to v3.13 (#768)"
This reverts commit 32c021e2

The alpine image in version 3.13 has issues, therefore I'm reverting that commit until they are fixed.
2021-01-16 14:52:38 +01:00
kolaente e16c5f72ca
Fix setting the user in created_by when uploading an attachment 2021-01-15 22:50:55 +01:00
kolaente 20af034d78
Fix retrieving over openid providers if there are none
Fixes #767
2021-01-15 20:40:07 +01:00
renovate 32c021e2b3 Update alpine Docker tag to v3.13 (#768)
Reviewed-on: vikunja/api#768
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-15 06:49:08 +00:00
renovate e9263f92d5 Update module iancoleman/strcase to v0.1.3 (#766)
Reviewed-on: vikunja/api#766
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-15 06:48:43 +00:00
renovate 044a1a9161 Update golang.org/x/oauth2 commit hash to d3ed898 (#765)
Reviewed-on: vikunja/api#765
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-13 21:25:20 +00:00
renovate 10ba7b5b65 Update golang.org/x/oauth2 commit hash to 8b1d76f (#764)
Reviewed-on: vikunja/api#764
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-13 17:11:55 +00:00
renovate e9a340026d Update module stretchr/testify to v1.7.0 (#763)
Reviewed-on: vikunja/api#763
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-13 10:22:09 +00:00
renovate 64441701fd Update golang.org/x/oauth2 commit hash to 01de73c (#762)
Reviewed-on: vikunja/api#762
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-12 21:15:21 +00:00
renovate df79173b22 Update module go-testfixtures/testfixtures/v3 to v3.5.0 (#761)
Reviewed-on: vikunja/api#761
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-11 22:14:13 +00:00
renovate 4e137ed72d Update module coreos/go-oidc to v3 (#760)
Reviewed-on: vikunja/api#760
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-11 22:13:58 +00:00
kolaente 279c5f6b73
0.16.0 release preparations 2021-01-10 16:09:26 +01:00
renovate a840880692 Update module go-redis/redis/v8 to v8.4.8 (#759)
Reviewed-on: vikunja/api#759
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-10 09:39:21 +00:00
renovate 4bb6842fb3 Update module go-redis/redis/v8 to v8.4.7 (#758)
Reviewed-on: vikunja/api#758
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-09 16:17:01 +00:00
konrad adf1172c39 Add tests for sending task reminders (#757)
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#757
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-committed-by: konrad <konrad@kola-entertainments.de>
2021-01-09 13:59:54 +00:00
renovate f0af97e411 Update module go-redis/redis/v8 to v8.4.6 (#756)
Reviewed-on: vikunja/api#756
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-09 11:11:07 +00:00
renovate ea5dd87b12 Update github.com/gordonklaus/ineffassign commit hash to 8eed68e (#755)
Reviewed-on: vikunja/api#755
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
2021-01-04 20:13:00 +00:00
kolaente ac23536c36
Make sure a password reset token can be used only once 2020-12-30 21:51:45 +01:00
kolaente 787044628f
Fix password reset without a reseet token 2020-12-30 21:43:14 +01:00
renovate c842b70cb5 Update module magefile/mage to v1.11.0 (#754)
Update module magefile/mage to v1.11.0

Reviewed-on: vikunja/api#754
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-29 09:52:09 +00:00
kolaente 456af4d4a9
Fix go header lint 2020-12-29 02:04:20 +01:00
renovate 8c97f45cb7 Update module mattn/go-sqlite3 to v1.14.6 (#751)
Update module mattn/go-sqlite3 to v1.14.6

Reviewed-on: vikunja/api#751
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-27 14:06:16 +00:00
renovate b8312469d7 Update module cweill/gotests to v1.6.0 (#752)
Update module cweill/gotests to v1.6.0

Reviewed-on: vikunja/api#752
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-27 01:17:05 +00:00
kolaente be7b53b9bc
Update nfpm config for nfpm v2 2020-12-23 20:51:37 +01:00
kolaente d6cb4f94f6
Update code header template 2020-12-23 20:51:16 +01:00
kolaente 9baf6d39bd
Change license to AGPLv3 2020-12-23 16:41:52 +01:00
konrad 8d1a09b5a2 Use db sessions everywere (#750)
Fix lint

Fix lint

Fix loading tasks with search

Fix loading lists

Fix loading task

Fix loading lists and namespaces

Fix tests

Fix user commands

Fix upload

Fix migration handlers

Fix all manual root handlers

Fix session in avatar

Fix session in list duplication & routes

Use sessions in migration code

Make sure the openid stuff uses a session

Add alias for db type in db package

Use sessions for file

Use a session for everything in users

Use a session for everything in users

Make sure to use a session everywhere in models

Create new session from db

Add session handling for user list

Add session handling for unsplash

Add session handling for teams and related

Add session handling for tasks and related entities

Add session handling for task reminders

Add session handling for task relations

Add session handling for task comments

Add session handling for task collections

Add session handling for task attachments

Add session handling for task assignees

Add session handling for saved filters

Add session handling for namespace and related types

Add session handling for namespace and related types

Add session handling for list users

Add session handling for list tests

Add session handling to list teams and related entities

Add session handling for link shares and related entities

Add session handling for labels and related entities

Add session handling for kanban and related entities

Add session handling for bulk task and related entities

Add session handling for lists and related entities

Add session configuration for web handler

Update web handler

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#750
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-12-23 15:32:28 +00:00
kolaente fa68e89c04
Add task filters for kanban
Signed-off-by: kolaente <k@knt.li>
2020-12-22 12:38:05 +01:00
konrad 2d4e2e452c Add task filter for lists and namespaces (#748)
Add more tests for getting namespaces

Fix namespaces not found

Fix namespaces not found

Make like the default

Update docs & fix docs

Enable searching namespaces by their ids

Enable searching lists by their ids

Enable searching labels by their ids

Enable searching by user ids

Update docs

Add namespace filter

Add task filter for lists

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#748
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-12-21 23:13:15 +00:00
renovate 111efd5fae Update golang.org/x/crypto commit hash to eec23a3 (#749)
Update golang.org/x/crypto commit hash to eec23a3

Reviewed-on: vikunja/api#749
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-21 19:17:02 +00:00
konrad 03e4bf30c2 Add task filter for labels (#747)
Update docs

Add task filter for labels

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#747
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-12-20 12:41:36 +00:00
konrad 18325e964d Add task filter for assignees (#746)
Update docs

Add filter by assignee

Fix string values

Update docs

Update docs

Make "in" task filter actually work

Add "in" filter type

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#746
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-12-19 21:39:11 +00:00
konrad 92bcce3f7c Add task filter for reminders (#745)
Update swagger docs about reminders

Fix filter concat for reminders

Add task filter for reminders

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#745
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-12-19 15:14:20 +00:00
kolaente 9508d0faee
Fix missing auto increments from b0d4902406 on mysql
Fixes #744
2020-12-19 15:04:30 +01:00
kolaente 90817b6dae
Add "like" filter comparator 2020-12-19 13:56:55 +01:00
konrad b2e4fde63a Add email reminders (#743)
Fix tests

Expose email reminder setting through jwt

Set reminders on by default

Fix lint

Make user email configurable

Expose email reminder setting through /info

Don't try to send any reminders if none were found

More spacing for buttons

Fix db time format

Enable reminders by default

Make emails look more like the frontend

Add config to disable it

Add sending emaisl

Add getting all task users and reminding them

Add getting the next reminder in a cron

Move task reminder to separate file

Add cron

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#743
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-12-18 23:21:17 +00:00
kolaente 7dc2abb8e5
Make the debian repo structure for buster instead of strech 2020-12-18 23:33:23 +01:00
kolaente 27c44d6d5e
Change avatar endpoint 2020-12-18 23:11:11 +01:00
renovate 8a6f8922f8 Update module go-redis/redis/v8 to v8.4.4 (#742)
Update module go-redis/redis/v8 to v8.4.4

Reviewed-on: vikunja/api#742
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-18 16:51:46 +00:00
konrad b0d4902406 Make sure all int64 db fields are using bigint when actually storing the data (#741)
Fix lint

Fix migration query for postgres

Fix migration statements

Add migration to make all int(11) fields bigint by default

Make all int(11) fields bigint by default

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#741
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-12-18 16:51:22 +00:00
renovate f15a8baee3 Update module ulule/limiter/v3 to v3.8.0 (#699)
fmt

Upgrade redis client to v8 everywhere

Update module ulule/limiter/v3 to v3.8.0

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#699
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-18 15:21:21 +00:00
konrad 0bd2632d29 Add login via email (#740)
Add login via email

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#740
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-12-18 13:54:49 +00:00
konrad 8d739b2cf9 Refactor adding more details to tasks (#739)
Refactor adding more details to tasks

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#739
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-12-18 13:54:36 +00:00
kolaente ccfa019870
Don't create a list identifier by default 2020-12-18 13:07:34 +01:00
konrad 969e467f48 Add colors for caldav (#738)
Add colors for caldav

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#738
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-12-18 12:04:27 +00:00
kolaente 5281ca548b
Fix docs about caldav tasks.org 2020-12-18 12:48:42 +01:00
konrad f5b5204776 Add Microsoft Todo migration (#737)
Add more logs

Fix lint

Generate docs

Add swagger docs

Add microsoft todo parsing logic

go mod tidy

Add basic test structure

Add more fields to tasks

rename microsoft todo package

Add getting microsoft todo data

Add structs and helper methods

Add microsoft todo config and routes

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#737
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-12-18 11:12:05 +00:00
renovate 25deb24849 Update module prometheus/client_golang to v1.9.0 (#735)
Update module prometheus/client_golang to v1.9.0

Reviewed-on: vikunja/api#735
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-17 20:06:30 +00:00
renovate d91c2e10b0 Update golang.org/x/crypto commit hash to 9d13527 (#736)
Update golang.org/x/crypto commit hash to 9d13527

Reviewed-on: vikunja/api#736
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-17 16:29:18 +00:00
konrad 9f3d898150 Add trello migration (#734)
Fix tests for background images

Generate docs

Fix lint

Do the swag

Add more logging

Remove the default bucket if it was empty

Add launch.json

Make importing backgrounds work

Add comment

Fix getting task attachments

Fix getting trello token

Add trello migration routes and status

Add support for converting checklists

Add test for attachments

Add the actual conversion

Add Trello conversion test

Add migration function stubs

Add basic trello migration structure

Add trello migration config

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#734
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-12-17 13:44:04 +00:00
renovate a7c585e086 Update golang.org/x/crypto commit hash to 8b5274c (#733)
Update golang.org/x/crypto commit hash to 8b5274c

Reviewed-on: vikunja/api#733
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-16 23:48:56 +00:00
konrad 00ed5884b4 Add support for migrating todoist boards (#732)
Add migrating buckets to converting todoist to vikunja structure

Add buckets migration

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#732
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-12-16 14:19:09 +00:00
kolaente 90ae940a6b
Clarify docs about cors configuration 2020-12-16 13:23:26 +01:00
kolaente e4de700a10
Simplify updating task reminders 2020-12-16 13:05:58 +01:00
renovate 1e020c9c50 Update golang.org/x/crypto commit hash to 5f87f34 (#729)
Update golang.org/x/crypto commit hash to 5f87f34

Reviewed-on: vikunja/api#729
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-10 21:18:12 +00:00
renovate d1e7d5116a Update golang.org/x/term commit hash to 2321bbc (#731)
Update golang.org/x/term commit hash to 2321bbc

Reviewed-on: vikunja/api#731
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-10 15:37:42 +00:00
renovate da064e9429 Update golang.org/x/lint commit hash to 83fdc39 (#728)
Update golang.org/x/lint commit hash to 83fdc39

Reviewed-on: vikunja/api#728
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-10 15:37:22 +00:00
renovate 67faa26cbc Update golang.org/x/image commit hash to 35266b9 (#727)
Update golang.org/x/image commit hash to 35266b9

Reviewed-on: vikunja/api#727
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-10 13:13:57 +00:00
renovate b0b6d5926b Update golang.org/x/term commit hash to ee85cb9 (#726)
Update golang.org/x/term commit hash to ee85cb9

Reviewed-on: vikunja/api#726
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-10 12:05:59 +00:00
renovate 22b626c9e0 Update golang.org/x/sync commit hash to 09787c9 (#725)
Update golang.org/x/sync commit hash to 09787c9

Reviewed-on: vikunja/api#725
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-10 09:54:29 +00:00
renovate eeb0006531 Update golang.org/x/oauth2 commit hash to 08078c5 (#722)
Update golang.org/x/oauth2 commit hash to 08078c5

Reviewed-on: vikunja/api#722
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-09 22:10:52 +00:00
renovate 9db56f86ca Update module spf13/afero to v1.5.1 (#730)
Update module spf13/afero to v1.5.1

Reviewed-on: vikunja/api#730
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-09 18:27:42 +00:00
renovate c71265aafe Update module spf13/afero to v1.5.0 (#724)
Update module spf13/afero to v1.5.0

Reviewed-on: vikunja/api#724
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-08 17:21:55 +00:00
renovate 24c8792150 Update module getsentry/sentry-go to v0.9.0 (#723)
Update module getsentry/sentry-go to v0.9.0

Reviewed-on: vikunja/api#723
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-08 14:02:53 +00:00
renovate 2f69c6342a Update module src.techknowlogick.com/xgo to v1.2.0+1.15.6 (#720)
Update module src.techknowlogick.com/xgo to v1.2.0+1.15.6

Reviewed-on: vikunja/api#720
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-07 15:49:23 +00:00
renovate c99ed212da Update module swaggo/swag to v1.7.0 (#721)
Update module swaggo/swag to v1.7.0

Reviewed-on: vikunja/api#721
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-07 15:49:08 +00:00
renovate c8af41738c Update golang.org/x/crypto commit hash to be400ae (#719)
Update golang.org/x/crypto commit hash to be400ae

Reviewed-on: vikunja/api#719
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-03 18:39:55 +00:00
renovate f3801843a4 Update golang.org/x/oauth2 commit hash to 0b49973 (#718)
Update golang.org/x/oauth2 commit hash to 0b49973

Reviewed-on: vikunja/api#718
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-03 06:47:02 +00:00
renovate 08430f1951 Update golang.org/x/crypto commit hash to c8d3bf9 (#710)
Change terminal package

Update golang.org/x/crypto commit hash to c8d3bf9

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#710
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-02 21:33:03 +00:00
renovate 80ce8f80ba Update module lib/pq to v1.9.0 (#717)
Update module lib/pq to v1.9.0

Reviewed-on: vikunja/api#717
Co-Authored-By: renovate <renovatebot@kolaente.de>
Co-Committed-By: renovate <renovatebot@kolaente.de>
2020-12-02 07:04:04 +00:00
konrad 9334b29366 Add testing endpoint to reset db tables (#716)
Fix lint

Better error messages

Add docs

Add testing endpoint to reset db

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#716
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
2020-11-28 23:08:30 +00:00
357 changed files with 19135 additions and 5183 deletions

View File

@ -40,7 +40,7 @@ services:
trigger:
branch:
include:
- master
- main
event:
include:
- push
@ -61,6 +61,7 @@ steps:
GOPROXY: 'https://goproxy.kolaente.de'
commands:
- mage -compile ./mage-static
- env
when:
event: [ push, tag, pull_request ]
@ -82,10 +83,8 @@ steps:
GOPROXY: 'https://goproxy.kolaente.de'
depends_on: [ build ]
commands:
- ./mage-static build:generate
- ./mage-static check:got-swag
- wget -O - -q https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.31.0
- ./mage-static check:golangci
- ./mage-static check:all
when:
event: [ push, tag, pull_request ]
@ -94,8 +93,8 @@ steps:
pull: true
commands:
# Get the latest version
- wget https://dl.vikunja.io/api/master/vikunja-master-linux-amd64-full.zip -q -O vikunja-latest.zip
- unzip vikunja-latest.zip vikunja-master-linux-amd64
- wget https://dl.vikunja.io/api/unstable/vikunja-unstable-linux-amd64-full.zip -q -O vikunja-latest.zip
- unzip vikunja-latest.zip vikunja-unstable-linux-amd64
- name: test-migration-sqlite
image: kolaente/toolbox:latest
@ -107,7 +106,7 @@ steps:
VIKUNJA_LOG_DATABASE: stdout
VIKUNJA_LOG_DATABASELEVEL: debug
commands:
- ./vikunja-master-linux-amd64 migrate
- ./vikunja-unstable-linux-amd64 migrate
# Run the migrations from the binary build in the step before
- ./vikunja migrate
when:
@ -126,7 +125,7 @@ steps:
VIKUNJA_LOG_DATABASE: stdout
VIKUNJA_LOG_DATABASELEVEL: debug
commands:
- ./vikunja-master-linux-amd64 migrate
- ./vikunja-unstable-linux-amd64 migrate
# Run the migrations from the binary build in the step before
- ./vikunja migrate
when:
@ -146,7 +145,7 @@ steps:
VIKUNJA_LOG_DATABASE: stdout
VIKUNJA_LOG_DATABASELEVEL: debug
commands:
- ./vikunja-master-linux-amd64 migrate
- ./vikunja-unstable-linux-amd64 migrate
# Run the migrations from the binary build in the step before
- ./vikunja migrate
when:
@ -158,7 +157,6 @@ steps:
environment:
GOPROXY: 'https://goproxy.kolaente.de'
commands:
- ./mage-static build:generate
- ./mage-static test:unit
depends_on: [ fetch-tags, mage ]
when:
@ -172,7 +170,6 @@ steps:
VIKUNJA_TESTS_USE_CONFIG: 1
VIKUNJA_DATABASE_TYPE: sqlite
commands:
- ./mage-static build:generate
- ./mage-static test:unit
depends_on: [ fetch-tags, mage ]
when:
@ -190,7 +187,6 @@ steps:
VIKUNJA_DATABASE_PASSWORD: vikunjatest
VIKUNJA_DATABASE_DATABASE: vikunjatest
commands:
- ./mage-static build:generate
- ./mage-static test:unit
depends_on: [ fetch-tags, mage ]
when:
@ -209,7 +205,6 @@ steps:
VIKUNJA_DATABASE_DATABASE: vikunjatest
VIKUNJA_DATABASE_SSLMODE: disable
commands:
- ./mage-static build:generate
- ./mage-static test:unit
depends_on: [ fetch-tags, mage ]
when:
@ -221,7 +216,6 @@ steps:
environment:
GOPROXY: 'https://goproxy.kolaente.de'
commands:
- ./mage-static build:generate
- ./mage-static test:integration
depends_on: [ fetch-tags, mage ]
when:
@ -235,7 +229,6 @@ steps:
VIKUNJA_TESTS_USE_CONFIG: 1
VIKUNJA_DATABASE_TYPE: sqlite
commands:
- ./mage-static build:generate
- ./mage-static test:integration
depends_on: [ fetch-tags, mage ]
when:
@ -253,7 +246,6 @@ steps:
VIKUNJA_DATABASE_PASSWORD: vikunjatest
VIKUNJA_DATABASE_DATABASE: vikunjatest
commands:
- ./mage-static build:generate
- ./mage-static test:integration
depends_on: [ fetch-tags, mage ]
when:
@ -272,7 +264,6 @@ steps:
VIKUNJA_DATABASE_DATABASE: vikunjatest
VIKUNJA_DATABASE_SSLMODE: disable
commands:
- ./mage-static build:generate
- ./mage-static test:integration
depends_on: [ fetch-tags, mage ]
when:
@ -295,7 +286,7 @@ workspace:
trigger:
ref:
- refs/heads/master
- refs/heads/main
- "refs/tags/**"
steps:
@ -323,7 +314,6 @@ steps:
commands:
- export PATH=$PATH:$GOPATH/bin
- go install github.com/magefile/mage
- ./mage-static build:generate
- ./mage-static release:dirs
depends_on: [ fetch-tags, mage ]
@ -416,10 +406,10 @@ steps:
path_style: true
strip_prefix: dist/zip/
source: dist/zip/*
target: /api/master/
target: /api/unstable/
when:
branch:
- master
- main
event:
- push
depends_on: [ sign-release ]
@ -451,6 +441,9 @@ steps:
commands:
- apk add git go
- ./mage-static release:packages
- mv dist/os-packages/vikunja*.x86_64.rpm dist/os-packages/vikunja-unstable-x86_64.rpm
- mv dist/os-packages/vikunja*_amd64.deb dist/os-packages/vikunja-unstable-amd64.deb
- mv dist/os-packages/vikunja*_x86_64.apk dist/os-packages/vikunja-unstable-x86_64.apk
depends_on: [ static-build-linux ]
# Push the os releases to our pseudo-s3-bucket
@ -468,10 +461,10 @@ steps:
path_style: true
strip_prefix: dist/os-packages/
source: dist/os-packages/*
target: /api/master/
target: /api/unstable/
when:
branch:
- master
- main
event:
- push
depends_on: [ build-os-packages ]
@ -496,23 +489,24 @@ steps:
- tag
depends_on: [ build-os-packages ]
- name: deb-structure
image: kolaente/reprepro
pull: true
environment:
GPG_PRIVATE_KEY:
from_secret: gpg_privatekey
commands:
- export GPG_TTY=$(tty)
- gpg -qk
- echo "use-agent" >> ~/.gnupg/gpg.conf
- gpgconf --kill gpg-agent
- echo $GPG_PRIVATE_KEY > ~/frederik.gpg
- gpg --import ~/frederik.gpg
- mkdir debian/conf -p
- cp build/reprepro-dist-conf debian/conf/distributions
- ./mage-static release:reprepro
depends_on: [ build-os-packages ]
### Broken, disabled until we figure out how to fix it
# - name: deb-structure
# image: kolaente/reprepro
# pull: true
# environment:
# GPG_PRIVATE_KEY:
# from_secret: gpg_privatekey
# commands:
# - export GPG_TTY=$(tty)
# - gpg -qk
# - echo "use-agent" >> ~/.gnupg/gpg.conf
# - gpgconf --kill gpg-agent
# - echo $GPG_PRIVATE_KEY > ~/frederik.gpg
# - gpg --import ~/frederik.gpg
# - mkdir debian/conf -p
# - cp build/reprepro-dist-conf debian/conf/distributions
# - ./mage-static release:reprepro
# depends_on: [ build-os-packages ]
# Push the releases to our pseudo-s3-bucket
- name: release-deb
@ -530,7 +524,7 @@ steps:
strip_prefix: debian
source: debian/*/*/*/*/*
target: /deb/
depends_on: [ deb-structure ]
# depends_on: [ deb-structure ]
---
kind: pipeline
@ -547,23 +541,18 @@ trigger:
event:
- push
branch:
- master
- main
steps:
- name: submodules
image: docker:git
commands:
- git submodule update --init
- git submodule update --recursive --remote
- name: theme
image: kolaente/yarn
image: kolaente/toolbox
pull: true
group: build-static
commands:
- mkdir docs/themes/vikunja -p
- cd docs/themes/vikunja
- yarn --production=false
- ./node_modules/.bin/gulp prod
- wget https://dl.vikunja.io/theme/vikunja-theme.tar.gz
- tar -xzf vikunja-theme.tar.gz
- name: build
image: monachus/hugo:v0.54.0
@ -595,11 +584,11 @@ depends_on:
platform:
os: linux
arch: arm
arch: arm64
trigger:
ref:
- refs/heads/master
- refs/heads/main
- "refs/tags/**"
steps:
@ -607,7 +596,22 @@ steps:
image: docker:git
commands:
- git fetch --tags
- name: docker
- name: docker-arm-latest
image: plugins/docker:linux-arm
pull: true
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/api
tags: latest-linux-arm
depends_on: [ fetch-tags ]
when:
ref:
- refs/heads/main
- name: docker-arm
image: plugins/docker:linux-arm
pull: true
settings:
@ -619,6 +623,40 @@ steps:
auto_tag: true
auto_tag_suffix: linux-arm
depends_on: [ fetch-tags ]
when:
ref:
- "refs/tags/**"
- name: docker-arm64-latest
image: plugins/docker:linux-arm64
pull: true
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/api
tags: latest-linux-arm64
depends_on: [ fetch-tags ]
when:
ref:
- refs/heads/main
- name: docker-arm64
image: plugins/docker:linux-arm64
pull: true
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/api
auto_tag: true
auto_tag_suffix: linux-arm64
depends_on: [ fetch-tags ]
when:
ref:
- "refs/tags/**"
---
kind: pipeline
@ -634,7 +672,7 @@ platform:
trigger:
ref:
- refs/heads/master
- refs/heads/main
- "refs/tags/**"
steps:
@ -642,6 +680,21 @@ steps:
image: docker:git
commands:
- git fetch --tags
- name: docker-latest
image: plugins/docker:linux-amd64
pull: true
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/api
tags: latest-linux-amd64
depends_on: [ fetch-tags ]
when:
ref:
- refs/heads/main
- name: docker
image: plugins/docker:linux-amd64
pull: true
@ -654,6 +707,9 @@ steps:
auto_tag: true
auto_tag_suffix: linux-amd64
depends_on: [ fetch-tags ]
when:
ref:
- "refs/tags/**"
---
kind: pipeline
@ -662,7 +718,7 @@ name: docker-manifest
trigger:
ref:
- refs/heads/master
- refs/heads/main
- "refs/tags/**"
depends_on:
@ -670,6 +726,21 @@ depends_on:
- docker-arm-release
steps:
- name: manifest-latest
pull: always
image: plugins/manifest
settings:
tags: latest
ignore_missing: true
spec: docker-manifest-latest.tmpl
password:
from_secret: docker_password
username:
from_secret: docker_username
when:
ref:
- refs/heads/main
- name: manifest
pull: always
image: plugins/manifest
@ -681,6 +752,9 @@ steps:
from_secret: docker_password
username:
from_secret: docker_username
when:
ref:
- "refs/tags/**"
---
kind: pipeline
@ -689,25 +763,27 @@ name: notify
trigger:
ref:
- refs/heads/master
- refs/heads/main
- "refs/tags/**"
depends_on:
- testing
- release
- deploy-docs
- docker-arm-release
- docker-amd64-release
- docker-manifest
steps:
- name: telegram
image: appleboy/drone-telegram:1-linux-amd64
- name: notify
image: plugins/matrix
settings:
token:
from_secret: TELEGRAM_TOKEN
to:
from_secret: TELEGRAM_TO
message: >
{{repo.owner}}/{{repo.name}}: \[{{build.status}}] Build {{build.number}}
{{commit.author}} pushed to {{commit.branch}} {{commit.sha}}: `{{commit.message}}`
Build started at {{datetime build.started "2006-Jan-02T15:04:05Z" "GMT+2"}} finished at {{datetime build.finished "2006-Jan-02T15:04:05Z" "GMT+2"}}.
homeserver: https://matrix.org
roomid: WqBDCxzghKcNflkErL:matrix.org
username:
from_secret: matrix_username
password:
from_secret: matrix_password
when:
status:
- success

1
.github/FUNDING.yml vendored
View File

@ -1 +1,2 @@
github: kolaente
custom: https://www.buymeacoffee.com/kolaente

2
.gitignore vendored
View File

@ -4,6 +4,7 @@
config.yml
config.yaml
!docs/config.yml
docs/themes/
*.db
Run
dist/
@ -23,3 +24,4 @@ files/
vikunja-dump*
vendor/
os-packages/
mage_output_file.go

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "docs/themes/vikunja"]
path = docs/themes/vikunja
url = ../theme.git

View File

@ -1,5 +1,5 @@
run:
timeout: 5m
timeout: 15m
tests: true
linters:
@ -22,11 +22,11 @@ linters:
- unused
fast: false
linter-settings:
linters-settings:
nestif:
min-complexity: 6
goheader:
template-path: code-hesader-template.txt
template-path: code-header-template.txt
issues:
exclude-rules:
@ -74,3 +74,17 @@ issues:
- path: pkg/modules/migration
linters:
- gocyclo
- path: pkg/routes/api/v1/docs.go
linters:
- goheader
- text: "Missed string"
linters:
- goheader
- path: pkg/modules/auth/identityawareproxy/middleware_test.go
text: "G101:" # We don't care about hardcoded credentials in this test
linters:
- gosec
- path: pkg/modules/auth/auth.go
text: "stutters"
linters:
- golint

17
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,17 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceRoot}",
"env": {},
"args": []
}
]
}

View File

@ -7,6 +7,279 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
All releases can be found on https://code.vikunja.io/api/releases.
## [0.17.0] - 2021-05-14
### Added
* Add a "done" option to kanban buckets (#821)
* Add arm64 builds
* Add basic auth for metrics endpoint
* Add bucket limit validation
* Add crud endpoints for notifications (#801)
* Add endpoint to remove a list background
* Add events (#777)
* Add github funding link
* Add link share password authentication (#831)
* Add names for link shares (#829)
* Add notifications package for easy sending of notifications (#779)
* Add reminders for overdue tasks (#832)
* Add repeat monthly setting for tasks (#834)
* Add security information to readme
* Add separate docker manifest file for latest docker images
* Add systemd service file to linux packages
* Add test for moving a task to another list
* Enable searching users by full email or name
* Expose tls parameter of Go MySQL driver to config file (#855)
* Pagingation for tasks in kanban buckets (#805)
### Changed
* Change keyvalue.Get to return if a value exists or not instead of an error
* Change main branch to main
* Change test file names to unstable
* Change the name of the newly created bucket from "New Bucket" to "Backlog"
* Change unstable versions in migration tests
* Check if we're on main and change the version name accordingly if that's the case
* Cleanup listener names
* Cleanup old docs themes submodule
* Disable deb repo in drone
* Don't keep old releases from os packages when releasing for master
* Don't try to get users for tasks if no tasks were found when looking for reminders
* Explicitly add docker build step for latest
* Explicitly check if there are Ids before trying to get items by a list of Ids
* Improve duration format of overdue tasks in reminders
* Improve loading labels performance (#824)
* Improve sending overdue task reminders by only sending one for all overdue tasks
* Make sure all tables are properly pluralized
* Only send reminders for undone tasks
* Re-Enable migration test steps in pipeline
* Refactor getting all namespaces
* Remove unused tools from tools.go
* Run all lint checks at once
* Send a notification to the user when they are added to the list
* Show empty avatar when the user was not found
* Subscribe a user to a task when they are assigned to it
* Subscriptions and notifications for namespaces, tasks and lists (#786)
* Switch building the docs to download the theme instead of building
* Switch telegram notifications to matrix notifications
* Temporarily disable migration step
* Temporary build fix
* Update changelog
* Update copyright year
* Update README (#858)
* Use golang's tzdata package to handle time zones
### Fixed
* Explicitly set darwin-10.15 when building binaries
* Fix build
* Fix checking list rights when accessing a bucket
* Fix /dav/principals/*/ throwing a server error when accessed with GET instead of PROPFIND (#769)
* Fix deleting task relations
* Fix docs
* Fix drone file
* Fix due dates with times when migrating from todoist
* Fix event error handler retrying infinitely
* Fix filter for task index
* Fix getting lists for shared, favorite and saved lists namespace
* Fix getting user info from /user endpoint for link shares
* Fix IncrBy and DecrBy in memory keyvalue implementation if there was no value set previously
* Fix lint
* Fix matrix notify room id
* Fix moving repeating tasks to the done bucket
* Fix multiarch docker image building
* Fix not able to make saved filters favorite
* Fix notifications table not being created on initial setup
* Fix resetting the bucket limit
* Fix retrieving over openid providers if there are none
* Fix sending notifications to users if the user object didn't have an email
* Fix setting the user in created_by when uploading an attachment
* Fix shared lists showing up twice
* Fix tests
* Fix the shared lists pseudo namespace containing owned lists
* Fix unstable version build file names
* Fix user uploaded avatars
* Pin golang alpine builder image to 3.12 to fix builds on arm
* Revert "Update alpine Docker tag to v3.13 (#768)"
### Dependency Updates
* Update alpine Docker tag to v3.13 (#768)
* Update github.com/gordonklaus/ineffassign commit hash to 2e10b26 (#803)
* Update github.com/gordonklaus/ineffassign commit hash to d0e41b2 (#780)
* Update golang.org/x/crypto commit hash to 0c34fe9 (#822)
* Update golang.org/x/crypto commit hash to 3497b51 (#853)
* Update golang.org/x/crypto commit hash to 38f3c27 (#854)
* Update golang.org/x/crypto commit hash to 4f45737 (#836)
* Update golang.org/x/crypto commit hash to 513c2a4 (#817)
* Update golang.org/x/crypto commit hash to 5bf0f12 (#839)
* Update golang.org/x/crypto commit hash to 5ea612d (#797)
* Update golang.org/x/crypto commit hash to 83a5a9b (#840)
* Update golang.org/x/crypto commit hash to b8e89b7 (#793)
* Update golang.org/x/crypto commit hash to c07d793 (#861)
* Update golang.org/x/crypto commit hash to cd7d49e (#860)
* Update golang.org/x/crypto commit hash to e6e6c4f (#816)
* Update golang.org/x/crypto commit hash to e9a3299 (#851)
* Update golang.org/x/image commit hash to 4410531 (#788)
* Update golang.org/x/image commit hash to 55ae14f (#787)
* Update golang.org/x/image commit hash to 7319ad4 (#852)
* Update golang.org/x/image commit hash to ac19c3e (#798)
* Update golang.org/x/oauth2 commit hash to 0101308 (#776)
* Update golang.org/x/oauth2 commit hash to 01de73c (#762)
* Update golang.org/x/oauth2 commit hash to 16ff188 (#789)
* Update golang.org/x/oauth2 commit hash to 22b0ada (#823)
* Update golang.org/x/oauth2 commit hash to 2e8d934 (#827)
* Update golang.org/x/oauth2 commit hash to 5366d9d (#813)
* Update golang.org/x/oauth2 commit hash to 5e61552 (#833)
* Update golang.org/x/oauth2 commit hash to 6667018 (#783)
* Update golang.org/x/oauth2 commit hash to 81ed05c (#848)
* Update golang.org/x/oauth2 commit hash to 8b1d76f (#764)
* Update golang.org/x/oauth2 commit hash to 9bb9049 (#796)
* Update golang.org/x/oauth2 commit hash to af13f52 (#773)
* Update golang.org/x/oauth2 commit hash to ba52d33 (#794)
* Update golang.org/x/oauth2 commit hash to cd4f82c (#815)
* Update golang.org/x/oauth2 commit hash to d3ed898 (#765)
* Update golang.org/x/oauth2 commit hash to f9ce19e (#775)
* Update golang.org/x/sync commit hash to 036812b (#799)
* Update golang.org/x/term commit hash to 6a3ed07 (#800)
* Update golang.org/x/term commit hash to 72f3dc4 (#828)
* Update golang.org/x/term commit hash to a79de54 (#850)
* Update golang.org/x/term commit hash to b80969c (#843)
* Update golang.org/x/term commit hash to c04ba85 (#849)
* Update golang.org/x/term commit hash to de623e6 (#818)
* Update golang.org/x/term commit hash to f5beecf (#845)
* Update module adlio/trello to v1.9.0 (#825)
* Update module coreos/go-oidc to v3 (#760)
* Update module gabriel-vasile/mimetype to v1.2.0 (#812)
* Update module gabriel-vasile/mimetype to v1.3.0 (#857)
* Update module getsentry/sentry-go to v0.10.0 (#792)
* Update module go-redis/redis/v8 to v8.4.10 (#771)
* Update module go-redis/redis/v8 to v8.4.11 (#774)
* Update module go-redis/redis/v8 to v8.4.9 (#770)
* Update module go-redis/redis/v8 to v8.5.0 (#778)
* Update module go-redis/redis/v8 to v8.6.0 (#795)
* Update module go-sql-driver/mysql to v1.6.0 (#826)
* Update module go-testfixtures/testfixtures/v3 to v3.5.0 (#761)
* Update module go-testfixtures/testfixtures/v3 to v3.6.0 (#838)
* Update module iancoleman/strcase to v0.1.3 (#766)
* Update module imdario/mergo to v0.3.12 (#811)
* Update module jgautheron/goconst to v1 (#804)
* Update module labstack/echo/v4 to v4.2.0 (#785)
* Update module labstack/echo/v4 to v4.2.1 (#810)
* Update module labstack/echo/v4 to v4.2.2 (#830)
* Update module labstack/echo/v4 to v4.3.0 (#856)
* Update module lib/pq to v1.10.0 (#809)
* Update module lib/pq to v1.10.1 (#841)
* Update module mattn/go-sqlite3 to v1.14.7 (#835)
* Update module olekukonko/tablewriter to v0.0.5 (#782)
* Update module prometheus/client_golang to v1.10.0 (#819)
* Update module spf13/afero to v1.6.0 (#820)
* Update module spf13/cobra to v1.1.2 (#781)
* Update module spf13/cobra to v1.1.3 (#784)
* Update module src.techknowlogick.com/xgo to v1.3.0+1.16.0 (#791)
* Update module src.techknowlogick.com/xgo to v1.4.0+1.16.2 (#814)
* Update module stretchr/testify to v1.7.0 (#763)
## [0.16.1] - 2021-04-22
### Fixed
* Fix checking list rights when accessing a bucket
* Remove old deb-structure ci step
* Fix docker from
## [0.16.0] - 2021-01-10
### Added
* Add colors for caldav (#738)
* Add email reminders (#743)
* Add "like" filter comparator
* Add login via email (#740)
* Add Microsoft Todo migration (#737)
* Add name field to users
* Add support for migrating todoist boards (#732)
* Add task filter for assignees (#746)
* Add task filter for labels (#747)
* Add task filter for lists and namespaces (#748)
* Add task filter for reminders (#745)
* Add task filters for kanban
* Add testing endpoint to reset db tables (#716)
* Add tests for sending task reminders (#757)
* Add trello migration (#734)
* Authentication with OpenID Connect providers (#713)
### Fixed
* Fix completion status in DAV for OpenTasks and multiline descriptions (#697)
* Fix docs about caldav tasks.org
* Fix drone badge in README
* Fix getting current user when updating avatar or user name
* Fix go header lint
* Fix /info endpoint 500 error when no openid providers were configured
* Fix missing auto increments from b0d4902406 on mysql
* Fix not possible to create tasks if metrics were enabled
* Fix password reset without a reseet token
* Fix task updated timestamp not being updated in the response after updating a task
### Changed
* Change avatar endpoint
* Change license to AGPLv3
* Clarify docs about cors configuration
* Don't create a list identifier by default
* Make sure all int64 db fields are using bigint when actually storing the data (#741)
* Make sure a password reset token can be used only once
* Make the debian repo structure for buster instead of strech
* Refactor adding more details to tasks (#739)
* Simplify updating task reminders
* Update code header template
* Update github.com/gordonklaus/ineffassign commit hash to 3b93a88 (#701)
* Update github.com/gordonklaus/ineffassign commit hash to 8eed68e (#755)
* Update github.com/jgautheron/goconst commit hash to b58d7cf (#702)
* Update github.com/jgautheron/goconst commit hash to ccae5bf (#712)
* Update github.com/jgautheron/goconst commit hash to f8e4fe8 (#703)
* Update golang.org/x/crypto commit hash to 0c6587e (#706)
* Update golang.org/x/crypto commit hash to 5f87f34 (#729)
* Update golang.org/x/crypto commit hash to 8b5274c (#733)
* Update golang.org/x/crypto commit hash to 9d13527 (#736)
* Update golang.org/x/crypto commit hash to be400ae (#719)
* Update golang.org/x/crypto commit hash to c8d3bf9 (#710)
* Update golang.org/x/crypto commit hash to eec23a3 (#749)
* Update golang.org/x/image commit hash to 35266b9 (#727)
* Update golang.org/x/lint commit hash to 83fdc39 (#728)
* Update golang.org/x/oauth2 commit hash to 08078c5 (#722)
* Update golang.org/x/oauth2 commit hash to 0b49973 (#718)
* Update golang.org/x/oauth2 commit hash to 9fd6049 (#714)
* Update golang.org/x/sync commit hash to 09787c9 (#725)
* Update golang.org/x/sync commit hash to 67f06af (#695)
* Update golang.org/x/term commit hash to 2321bbc (#731)
* Update golang.org/x/term commit hash to ee85cb9 (#726)
* Update module cweill/gotests to v1.6.0 (#752)
* Update module fzipp/gocyclo to v0.3.1 (#696)
* Update module gabriel-vasile/mimetype to v1.1.2 (#708)
* Update module getsentry/sentry-go to v0.8.0 (#709)
* Update module getsentry/sentry-go to v0.9.0 (#723)
* Update module go-redis/redis/v8 to v8.4.4 (#742)
* Update module go-redis/redis/v8 to v8.4.6 (#756)
* Update module go-redis/redis/v8 to v8.4.7 (#758)
* Update module go-redis/redis/v8 to v8.4.8 (#759)
* Update module lib/pq to v1.9.0 (#717)
* Update module magefile/mage to v1.11.0 (#754)
* Update module mattn/go-sqlite3 to v1.14.5 (#711)
* Update module mattn/go-sqlite3 to v1.14.6 (#751)
* Update module pquerna/otp to v1.3.0 (#705)
* Update module prometheus/client_golang to v1.9.0 (#735)
* Update module spf13/afero to v1.5.0 (#724)
* Update module spf13/afero to v1.5.1 (#730)
* Update module src.techknowlogick.com/xgo to v1.2.0+1.15.6 (#720)
* Update module src.techknowlogick.com/xormigrate to v1.4.0 (#700)
* Update module swaggo/swag to v1.6.9 (#694)
* Update module swaggo/swag to v1.7.0 (#721)
* Update module ulule/limiter/v3 to v3.8.0 (#699)
* Update nfpm config for nfpm v2
* Use db sessions everywere (#750)
## [0.15.1] - 2020-10-20
### Fixed

View File

@ -1,7 +1,7 @@
##############
# Build stage
FROM golang:1-alpine AS build-env
FROM golang:1-alpine3.12 AS build-env
ARG VIKUNJA_VERSION
ENV TAGS "sqlite"
@ -17,7 +17,7 @@ WORKDIR ${GOPATH}/src/code.vikunja.io/api
# Checkout version if set
RUN if [ -n "${VIKUNJA_VERSION}" ]; then git checkout "${VIKUNJA_VERSION}"; fi \
&& go install github.com/magefile/mage \
&& mage build:clean build:build
&& mage build:clean build
###################
# The actual image

143
LICENSE
View File

@ -1,5 +1,5 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
@ -7,17 +7,15 @@
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
@ -26,44 +24,34 @@ them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
@ -72,7 +60,7 @@ modification follow.
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
@ -549,35 +537,45 @@ to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
@ -635,40 +633,29 @@ the "copyright" line and a pointer to where the full notice is found.
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
it under the terms of the GNU Affero General Public License 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 General Public License for more details.
GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
For more information on this, and how to apply and follow the GNU AGPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View File

@ -1,11 +1,11 @@
<img src="https://vikunja.io/images/vikunja-logo.svg" alt="" style="display: block;width: 50%;margin: 0 auto;" width="50%"/>
[![Build Status](https://drone.kolaente.de/api/badges/vikunja/api/status.svg)](https://drone.kolaente.de/vikunja/api)
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](LICENSE)
[![Download](https://img.shields.io/badge/download-v0.15.1-brightgreen.svg)](https://dl.vikunja.io)
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](LICENSE)
[![Download](https://img.shields.io/badge/download-v0.17.0-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/git.kolaente.de/vikunja/api)](https://goreportcard.com/report/git.kolaente.de/vikunja/api)
[![Go Report Card](https://goreportcard.com/badge/kolaente.dev/vikunja/api)](https://goreportcard.com/report/kolaente.dev/vikunja/api)
# Vikunja API
@ -13,17 +13,22 @@
# Table of contents
* [Security Reports](#security-reports)
* [Features](#features)
* [Docs](#docs)
* [Roadmap](#roadmap)
* [Contributing](#contributing)
* [License](#license)
## Security Reports
If you find any security-related issues you don't want to disclose publicly, please use [the contact information on our website](https://vikunja.io/contact/#security).
## Features
* Create TODO lists with tasks
* Reminder for tasks
* Namespaces: A "group" which bundels multiple lists
* Namespaces: A "group" which bundles multiple lists
* Share lists and namespaces with teams and users with granular permissions
* Plenty of details for tasks
@ -35,46 +40,22 @@ try it on [try.vikunja.io](https://try.vikunja.io)!
* [Installing](https://vikunja.io/docs/installing/)
* [Build from source](https://vikunja.io/docs/build-from-sources/)
* [Development setup](https://vikunja.io/docs/development/)
* [Magefile](https://vikunja.io/docs/mage/)
* [Magefile](https://vikunja.io/docs/magefile/)
* [Testing](https://vikunja.io/docs/testing/)
All docs can be found on [the vikunja home page](https://vikunja.io/docs/).
All docs can be found on [the Vikunja home page](https://vikunja.io/docs/).
### Roadmap
> I know, it's still a long way to go. I'm currently working on a lot of "basic" features, the exiting things will come later. Don't worry, they'll come.
See [the roadmap](https://my.vikunja.cloud/share/QFyzYEmEYfSyQfTOmIRSwLUpkFjboaBqQCnaPmWd/auth) (hosted on Vikunja!) for more!
* [x] Prioritize tasks
* [x] Subtasks
* [x] Repeating tasks
* [x] Get tasks via caldav
* [x] Get all your tasks for an interval (day/month/period)
* [x] Labels for tasks
* [x] Assign users to tasks
* [x] Attachments on tasks
* [x] More sharing features
* [x] Share with individual users
* [x] Share via a world-readable link with or without password, like Nextcloud
* [x] Disable registration, making an instance "invite-only"
* [ ] SSE to notify multiple clients of updates when something was changed
* [ ] "Smart Lists" - Create lists based on filters
* [ ] IMAP-Integration - Send an email to Vikunja to create a new task
* [ ] Webhooks - Trigger other events when an action is done (like completing a task)
* [ ] Performace statistics - Get an overview and beautiful charts about what you got done this month
* [ ] Activity feeds - Get a quick overview about who did what
* [ ] Bulk-edit multiple tasks at once
* [ ] Team-efforts - Requiring a task to be marked as done by multiple members until it's done
* [ ] Global limits for namespaces/lists/tasks
See [our roadmap](https://my.vikunja.cloud/share/QFyzYEmEYfSyQfTOmIRSwLUpkFjboaBqQCnaPmWd/auth) (hosted on Vikunja!) for even more!
* [ ] [Mobile apps](https://code.vikunja.io/app) (seperate repo) *In Progress*
* [ ] [Webapp](https://code.vikunja.io/frontend) (seperate repo) *In Progress*
* [ ] [Mobile apps](https://code.vikunja.io/app) (separate repo) *In Progress*
* [ ] [Webapp](https://code.vikunja.io/frontend) (separate repo) *In Progress*
## Contributing
Fork -> Push -> Pull-Request. Also see the [dev docs](https://vikunja.io/docs/development/) for more infos.
Fork -> Push -> Pull-Request. Also see the [dev docs](https://vikunja.io/docs/development/) for more info.
## License
This project is licensed under the GPLv3 License. See the [LICENSE](LICENSE) file for the full license text.
This project is licensed under the AGPLv3 License. See the [LICENSE](LICENSE) file for the full license text.

View File

@ -1,5 +1,7 @@
#!/bin/bash
systemctl enable vikunja.service
# Fix the config to contain proper values
NEW_SECRET=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)
sed -i "s/<jwt-secret>/$NEW_SECRET/g" /etc/vikunja/config.yml

View File

@ -1,8 +1,8 @@
Origin: dl.vikunja.io
Label: Vikunja
Codename: strech
Codename: buster
Architectures: amd64
Components: main
Description: The debian repo for Vikunja builds.
SignWith: yes
Pull: strech
Pull: buster

View File

@ -1,15 +1,15 @@
Vikunja is a to-do list application to facilitate your life.
Copyright 2018-2020 Vikunja and contributors. All rights reserved.
Copyright 2018-2021 Vikunja and contributors. All rights reserved.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
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 General Public License for more details.
GNU Affero General Public Licensee for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
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/>.

View File

@ -13,9 +13,6 @@ service:
rootpath: <rootpath>
# The max number of items which can be returned per page
maxitemsperpage: 50
# If set to true, enables a /metrics endpoint for prometheus to collect metrics about the system
# You'll need to use redis for this in order to enable common metrics over multiple nodes
enablemetrics: false
# Enable the caldav endpoint, see the docs for more details
enablecaldav: true
# Set the motd message, available from the /info endpoint
@ -26,7 +23,7 @@ service:
enableregistration: true
# Whether to enable task attachments or not
enabletaskattachments: true
# The time zone all timestamps are in
# The time zone all timestamps are in. Please note that time zones have to use [the official tz database names](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). UTC or GMT offsets won't work.
timezone: GMT
# Whether task comments should be enabled or not
enabletaskcomments: true
@ -34,6 +31,14 @@ service:
enabletotp: true
# If not empty, enables logging of crashes and unhandled errors in sentry.
sentrydsn: ''
# If not empty, this will enable `/test/{table}` endpoints which allow to put any content in the database.
# Used to reset the db before frontend tests. Because this is quite a dangerous feature allowing for lots of harm,
# each request made to this endpoint neefs to provide an `Authorization: <token>` header with the token from below. <br/>
# **You should never use this unless you know exactly what you're doing**
testingtoken: ''
# If enabled, vikunja will send an email to everyone who is either assigned to a task or created it when a task reminder
# is due.
enableemailreminders: true
database:
# Database type to use. Supported types are mysql, postgres and sqlite.
@ -57,6 +62,8 @@ database:
# Secure connection mode. Only used with postgres.
# (see https://pkg.go.dev/github.com/lib/pq?tab=doc#hdr-Connection_String_Parameters)
sslmode: disable
# Enable SSL/TLS for mysql connections. Options: false, true, skip-verify, preferred
tls: false
cache:
# If cache is enabled or not
@ -83,7 +90,7 @@ cors:
# Note: If you want to put the frontend and the api on seperate domains or ports, you will need to enable this.
# Otherwise the frontend won't be able to make requests to the api through the browser.
enable: true
# A list of origins which may access the api.
# A list of origins which may access the api. These need to include the protocol (`http://` or `https://`) and port, if any.
origins:
- "*"
# How long (in seconds) the results of a preflight request can be cached.
@ -128,6 +135,10 @@ log:
http: "stdout"
# Echo has its own logging which usually is unnessecary, which is why it is disabled by default. Possible values are stdout, stderr, file or off to disable standard logging.
echo: "off"
# Whether or not to log events. Useful for debugging. Possible values are stdout, stderr, file or off to disable events logging.
events: "stdout"
# The log level for event log messages. Possible values (case-insensitive) are ERROR, INFO, DEBUG.
eventslevel: "info"
ratelimit:
# whether or not to enable the rate limit
@ -169,7 +180,7 @@ migration:
todoist:
# Wheter to enable the todoist migrator or not
enable: false
# The client id, required for making requests to the wunderlist api
# The client id, required for making requests to the todoist api
# You need to register your vikunja instance at https://developer.todoist.com/appconsole.html to get this
clientid:
# The client secret, also required for making requests to the todoist api
@ -180,6 +191,33 @@ migration:
# with the code obtained from the todoist api.
# Note that the vikunja frontend expects this to be /migrate/todoist
redirecturl:
trello:
# Wheter to enable the trello migrator or not
enable: false
# The client id, required for making requests to the trello api
# You need to register your vikunja instance at https://trello.com/app-key (log in before you visit that link) to get this
key:
# The url where clients are redirected after they authorized Vikunja to access their trello cards.
# This needs to match the url you entered when registering your Vikunja instance at trello.
# This is usually the frontend url where the frontend then makes a request to /migration/trello/migrate
# with the code obtained from the trello api.
# Note that the vikunja frontend expects this to end on /migrate/trello.
redirecturl: <frontend url>/migrate/trello
microsofttodo:
# Wheter to enable the microsoft todo migrator or not
enable: false
# The client id, required for making requests to the microsoft graph api
# See https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#register-an-application
# for information about how to register your vikuinja instance.
clientid:
# The client secret, also required for making requests to the microsoft graph api
clientsecret:
# The url where clients are redirected after they authorized Vikunja to access their microsoft todo tasks.
# This needs to match the url you entered when registering your Vikunja instance at microsoft.
# This is usually the frontend url where the frontend then makes a request to /migration/microsoft-todo/migrate
# with the code obtained from the microsoft graph api.
# Note that the vikunja frontend expects this to be /migrate/microsoft-todo
redirecturl: <frontend url>/migrate/microsoft-todo
avatar:
# When using gravatar, this is the duration in seconds until a cached gravatar user avatar expires
@ -224,10 +262,12 @@ auth:
enabled: true
# OpenID configuration will allow users to authenticate through a third-party OpenID Connect compatible provider.<br/>
# The provider needs to support the `openid`, `profile` and `email` scopes.<br/>
# **Note:** The frontend expects to be redirected after authentication by the third party
# **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
# auth service accordingy if you're using the default vikunja frontend.
# Take a look at the [default config file](https://kolaente.dev/vikunja/api/src/branch/master/config.yml.sample) for more information about how to configure openid authentication.
# 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
@ -244,3 +284,23 @@ auth:
clientid:
# The client secret used to authenticate Vikunja at the OpenID Connect provider.
clientsecret:
# Identity-Aware Proxy configuration will allow users to authenticate through an identity-aware proxy in front of Vikunja.<br/>
# The proxy needs to supply a signed JWT over HTTP headers with claims for `sub`, `iss`, and `email`.
# It must also serve the public keys for that signed JWT in the JWKS format.
identityawareproxy:
# Enable or disable Identity-Aware Proxy authentication
enabled: false
# The URL of the proxy's JWKS endpoint
jwksuri: <proxy's JWKS url>
# The HTTP header containing the signed JWT from the proxy
jwtheader:
# Prometheus metrics endpoint
metrics:
# If set to true, enables a /metrics endpoint for prometheus to collect metrics about Vikunja.
enabled: false
# If set to a non-empty value the /metrics endpoint will require this as a username via basic auth in combination with the password below.
username:
# If set to a non-empty value the /metrics endpoint will require this as a password via basic auth in combination with the username below.
password:

View File

@ -0,0 +1,17 @@
image: vikunja/api:latest
manifests:
-
image: vikunja/api:latest-linux-amd64
platform:
architecture: amd64
os: linux
-
image: vikunja/api:latest-linux-arm64
platform:
architecture: arm64
os: linux
-
image: vikunja/api:latest-linux-arm
platform:
architecture: arm
os: linux

View File

@ -11,6 +11,11 @@ manifests:
platform:
architecture: amd64
os: linux
-
image: vikunja/api:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm64
platform:
architecture: arm64
os: linux
-
image: vikunja/api:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-arm
platform:

View File

@ -15,7 +15,7 @@ menu:
We use go modules to vendor libraries for Vikunja, so you'll need at least go `1.11` to use these.
If you don't intend to add new dependencies, go `1.9` and above should be fine.
To contribute to Vikunja, fork the project and work on the master branch.
To contribute to Vikunja, fork the project and work on the main branch.
A lot of developing tasks are automated using a Magefile, so make sure to [take a look at it]({{< ref "mage.md">}}).

View File

@ -0,0 +1,195 @@
---
date: 2018-10-13T19:26:34+02:00
title: "Events and Listeners"
draft: false
menu:
sidebar:
parent: "development"
---
# Events and Listeners
Vikunja provides a simple observer pattern mechanism through events and listeners.
The basic principle of events is always the same: Something happens (=An event is fired) and something reacts to it (=A listener is called).
Vikunja supports this principle through the `events` package.
It is built upon the excellent [watermill](https://watermill.io) library.
Currently, it only supports dispatching events through Go Channels which makes it configuration-less.
More methods of dispatching events (like kafka or rabbitmq) are available in watermill and could be enabled with a PR.
This document explains how events and listeners work in Vikunja, how to use them and how to create new ones.
{{< table_of_contents >}}
## Events
### Definition
Each event has to implement this interface:
```golang
type Event interface {
Name() string
}
```
An event can contain whatever data you need.
When an event is dispatched, all of the data it contains will be marshaled into json for dispatching.
You then get the event with all its data back in the listener, see below.
#### Naming Convention
Event names should roughly have the entity they're dealing with on the left and the action on the right of the name, separated by `.`.
There's no limit to how "deep" or specifig an event name can be.
The name should have the most general concept it's describing at the left, getting more specific on the right of it.
#### Location
All events for a package should be declared in the `events.go` file of that package.
### Creating a New Event
The easiest way to create a new event is to generate it with mage:
```
mage dev:make-event <event-name> <package>
```
The function takes the name of the event as the first argument and the package where the event should be created as the second argument.
Events will be appended to the `pkg/<module>/events.go` file.
Both parameters are mandatory.
The event type name is automatically camel-cased and gets the `Event` suffix if the provided name does not already have one.
The event name is derived from the type name and stripped of the `.event` suffix.
The generated event will look something like the example below.
### Dispatching events
To dispatch an event, simply call the `events.Dispatch` method and pass in the event as parameter.
### Example
The `TaskCreatedEvent` is declared in the `pkg/models/events.go` file as follows:
```golang
// TaskCreatedEvent represents an event where a task has been created
type TaskCreatedEvent struct {
Task *Task
Doer web.Auth
}
// Name defines the name for TaskCreatedEvent
func (t *TaskCreatedEvent) Name() string {
return "task.created"
}
```
It is dispatched in the `createTask` function of the `models` package:
```golang
func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err error) {
// ...
err = events.Dispatch(&TaskCreatedEvent{
Task: t,
Doer: a,
})
// ...
}
```
As you can see, the curent task and doer are injected into it.
### Special Events
#### `BootedEvent`
Once Vikunja is fully initialized, right before the api web server is started, this event is fired.
## Listeners
A listener is a piece of code that gets executed asynchronously when an event is dispatched.
A single event can have multiple listeners who are independent of each other.
### Definition
All listeners must implement this interface:
```golang
// Listener represents something that listens to events
type Listener interface {
Handle(msg *message.Message) error
Name() string
}
```
The `Handle` method is executed when the event this listener listens on is dispatched.
* As the single parameter, it gets the payload of the event, which is the event struct when it was dispatched decoded as json object and passed as a slice of bytes.
To use it you'll need to unmarshal it. Unfortunately there's no way to pass an already populated event object to the function because we would not know what type it has when parsing it.
* If the handler returns an error, the listener is retried 5 times, with an exponentional back-off period in between retries.
If it still fails after the fifth retry, the event is nack'd and it's up to the event dispatcher to resend it.
You can learn more about this mechanism in the [watermill documentation](https://watermill.io/docs/middlewares/#retry).
The `Name` method needs to return a unique listener name for this listener.
It should follow the same convention as event names, see above.
### Creating a New Listener
The easiest way to create a new listener for an event is with mage:
```
mage dev:make-listener <listener-name> <event-name> <package>
```
This will create a new listener type in the `pkg/<package>/listners.go` file and implement the `Handle` and `Name` methods.
It will also pre-generate some boilerplate code to unmarshal the event from the payload.
Furthermore, it will register the listener for its event in the `RegisterListeners()` method of the same file.
This function is called at startup and has to contain all events you want to listen for.
### Listening for Events
To listen for an event, you need to register the listener for the event it should be called for.
This usually happens in the `RegisterListeners()` method in `pkg/<package>/listners.go` which is called at start up.
The listener will never be executed if it hasn't been registered.
See the example below.
### Example
```golang
// RegisterListeners registers all event listeners
func RegisterListeners() {
events.RegisterListener((&ListCreatedEvent{}).Name(), &IncreaseListCounter{})
}
// IncreaseTaskCounter represents a listener
type IncreaseTaskCounter struct {}
// Name defines the name for the IncreaseTaskCounter listener
func (s *IncreaseTaskCounter) Name() string {
return "task.counter.increase"
}
// Hanlde is executed when the event IncreaseTaskCounter listens on is fired
func (s *IncreaseTaskCounter) Handle(payload message.Payload) (err error) {
return keyvalue.IncrBy(metrics.TaskCountKey, 1)
}
```
## Testing
When testing, you should call the `events.Fake()` method in the `TestMain` function of the package you want to test.
This prevents any events from being fired and lets you assert an event has been dispatched like so:
```golang
events.AssertDispatched(t, &TaskCreatedEvent{})
```

View File

@ -39,7 +39,7 @@ There are multiple categories of subcommands in the magefile:
## CI
These tasks are automatically run in our CI every time someone pushes to master or you update a pull request:
These tasks are automatically run in our CI every time someone pushes to main or you update a pull request:
* `mage check:lint`
* `mage check:fmt`

View File

@ -0,0 +1,113 @@
---
date: 2021-02-07T19:26:34+02:00
title: "Notifications"
toc: true
draft: false
menu:
sidebar:
parent: "development"
---
# Notifications
Vikunjs provides a simple abstraction to send notifications per mail and in the database.
{{< table_of_contents >}}
## Definition
Each notification has to implement this interface:
```golang
type Notification interface {
ToMail() *Mail
ToDB() interface{}
Name() string
}
```
Both functions return the formatted messages for mail and database.
A notification will only be sent or recorded for those of the two methods which don't return `nil`.
For example, if your notification should not be recorded in the database but only sent out per mail, it is enough to let the `ToDB` function return `nil`.
### Mail notifications
A list of chainable functions is available to compose a mail:
```golang
mail := NewMail().
// The optional sender of the mail message.
From("test@example.com").
// The optional receipient of the mail message. Uses the mail address of the notifiable if omitted.
To("test@otherdomain.com").
// The subject of the mail to send.
Subject("Testmail").
// The greeting, or "intro" line of the mail.
Greeting("Hi there,").
// A line of text
Line("This is a line of text").
// An action can contain a title and a url. It gets rendered as a big button in the mail.
// Note that you can have only one action per mail.
// All lines added before an action will appearr in the mail before the button, all lines
// added afterwards will appear after it.
Action("The Action", "https://example.com").
// Another line of text.
Line("This should be an outro line").
```
If not provided, the `from` field of the mail contains the value configured in [`mailer.fromemail`](https://vikunja.io/docs/config-options/#fromemail).
### Database notifications
All data returned from the `ToDB()` method is serialized to json and saved into the database, along with the id of the
notifiable, the name of the notification and a time stamp.
If you don't use the database notification, the `Name()` function can return an empty string.
## Creating a new notification
The easiest way to generate a mail is by using the `mage dev:make-notification` command.
It takes the name of the notification and the package where the notification will be created.
## Notifiables
Notifiables can receive a notification.
A notifiable is defined with this interface:
```golang
type Notifiable interface {
// Should return the email address this notifiable has.
RouteForMail() string
// Should return the id of the notifiable entity
RouteForDB() int64
}
```
The `User` type from the `user` package implements this interface.
## Sending a notification
Sending a notification is done with the `Notify` method from the `notifications` package.
It takes a notifiable and a notification as input.
For example, the email confirm notification when a new user registers is sent like this:
```golang
n := &EmailConfirmNotification{
User: update.User,
IsNew: false,
}
err = notifications.Notify(update.User, n)
return
```
## Testing
The `mail` package provides a `Fake()` method which you should call in the `MainTest` functions of your package.
If it was called, no mails are being sent and you can instead assert they have been sent with the `AssertSent` method.
## Example
Take a look at the [pkg/user/notifications.go](https://code.vikunja.io/api/src/branch/main/pkg/user/notifications.go) file for a good example.

View File

@ -23,13 +23,13 @@ As an example, this is the definition of a list with all comments:
// List represents a list of tasks
type List struct {
// The unique, numeric id of this list.
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id" param:"list"`
ID int64 `xorm:"bigint autoincr not null unique pk" json:"id" param:"list"`
// The title of the list. You'll see this in the namespace overview.
Title string `xorm:"varchar(250)" json:"title" valid:"required,runelength(3|250)" minLength:"3" maxLength:"250"`
// The description of the list.
Description string `xorm:"varchar(1000)" json:"description" valid:"runelength(0|1000)" maxLength:"1000"`
OwnerID int64 `xorm:"int(11) INDEX" json:"-"`
NamespaceID int64 `xorm:"int(11) INDEX" json:"-" param:"namespace"`
OwnerID int64 `xorm:"bigint INDEX" json:"-"`
NamespaceID int64 `xorm:"bigint INDEX" json:"-" param:"namespace"`
// The user who created this list.
Owner User `xorm:"-" json:"owner" valid:"-"`

View File

@ -32,7 +32,7 @@ first:
Vikunja supports using `toml`, `yaml`, `hcl`, `ini`, `json`, envfile, env variables and Java Properties files.
We reccomend yaml or toml, but you're free to use whatever you want.
Vikunja provides a default [`config.yml`](https://kolaente.dev/vikunja/api/src/branch/master/config.yml.sample) file which you can use as a starting point.
Vikunja provides a default [`config.yml`](https://kolaente.dev/vikunja/api/src/branch/main/config.yml.sample) file which you can use as a starting point.
# Config file locations
@ -46,7 +46,7 @@ Vikunja will search on various places for a config file:
# Default configuration with explanations
The following explains all possible config variables and their defaults.
You can find a full example configuration file in [here](https://code.vikunja.io/api/src/branch/master/config.yml.sample).
You can find a full example configuration file in [here](https://code.vikunja.io/api/src/branch/main/config.yml.sample).
If you don't provide a value in your config file, their default will be used.
@ -55,7 +55,7 @@ If you don't provide a value in your config file, their default will be used.
Most config variables are nested under some "higher-level" key.
For example, the `interface` config variable is a child of the `service` key.
The docs below aim to reflect that leveling, but please also have a lookt at [the default config](https://code.vikunja.io/api/src/branch/master/config.yml.sample) file
The docs below aim to reflect that leveling, but please also have a lookt at [the default config](https://code.vikunja.io/api/src/branch/main/config.yml.sample) file
to better grasp how the nesting looks like.
<!-- Generated config will be injected here -->
@ -100,13 +100,6 @@ The max number of items which can be returned per page
Default: `50`
### enablemetrics
If set to true, enables a /metrics endpoint for prometheus to collect metrics about the system
You'll need to use redis for this in order to enable common metrics over multiple nodes
Default: `false`
### enablecaldav
Enable the caldav endpoint, see the docs for more details
@ -139,7 +132,7 @@ Default: `true`
### timezone
The time zone all timestamps are in
The time zone all timestamps are in. Please note that time zones have to use [the official tz database names](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). UTC or GMT offsets won't work.
Default: `GMT`
@ -161,6 +154,22 @@ If not empty, enables logging of crashes and unhandled errors in sentry.
Default: `<empty>`
### testingtoken
If not empty, this will enable `/test/{table}` endpoints which allow to put any content in the database.
Used to reset the db before frontend tests. Because this is quite a dangerous feature allowing for lots of harm,
each request made to this endpoint neefs to provide an `Authorization: <token>` header with the token from below. <br/>
**You should never use this unless you know exactly what you're doing**
Default: `<empty>`
### enableemailreminders
If enabled, vikunja will send an email to everyone who is either assigned to a task or created it when a task reminder
is due.
Default: `true`
---
## database
@ -228,6 +237,12 @@ Secure connection mode. Only used with postgres.
Default: `disable`
### tls
Enable SSL/TLS for mysql connections. Options: false, true, skip-verify, preferred
Default: `false`
---
## cache
@ -300,7 +315,7 @@ Default: `true`
### origins
A list of origins which may access the api.
A list of origins which may access the api. These need to include the protocol (`http://` or `https://`) and port, if any.
Default: `<empty>`
@ -430,6 +445,18 @@ Echo has its own logging which usually is unnessecary, which is why it is disabl
Default: `off`
### events
Whether or not to log events. Useful for debugging. Possible values are stdout, stderr, file or off to disable events logging.
Default: `stdout`
### eventslevel
The log level for event log messages. Possible values (case-insensitive) are ERROR, INFO, DEBUG.
Default: `info`
---
## ratelimit
@ -503,6 +530,14 @@ Default: `<empty>`
Default: `<empty>`
### trello
Default: `<empty>`
### microsofttodo
Default: `<empty>`
---
## avatar
@ -580,10 +615,46 @@ Default: `<empty>`
OpenID configuration will allow users to authenticate through a third-party OpenID Connect compatible provider.<br/>
The provider needs to support the `openid`, `profile` and `email` scopes.<br/>
**Note:** The frontend expects to be redirected after authentication by the third party
**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
auth service accordingy if you're using the default vikunja frontend.
Take a look at the [default config file](https://kolaente.dev/vikunja/api/src/branch/master/config.yml.sample) for more information about how to configure openid authentication.
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.
Default: `<empty>`
---
## metrics
Prometheus metrics endpoint
### enabled
If set to true, enables a /metrics endpoint for prometheus to collect metrics about Vikunja.
Default: `false`
### username
If set to a non-empty value the /metrics endpoint will require this as a username via basic auth in combination with the password below.
Default: `<empty>`
### password
If set to a non-empty value the /metrics endpoint will require this as a password via basic auth in combination with the username below.
Default: `<empty>`
### identityawareproxy
Identity-Aware Proxy configuration will allow users to authenticate through an identity-aware proxy in front of Vikunja.<br/>
The proxy needs to supply a signed JWT over HTTP headers with claims for `sub`, `iss`, and `email`.
It must also serve the public keys for that signed JWT in the JWKS format.
Default: `<empty>`

View File

@ -28,7 +28,7 @@ wget <download-url>
### Verify the GPG signature
Starting with version `0.7`, all releases are signed using pgp.
Releases from `master` will always be signed.
Releases from `main` will always be signed.
To validate the downloaded zip file use the signiture file `.asc` and the key `FF054DACD908493A`:

View File

@ -70,10 +70,10 @@ Vikunja **currently does not** support these properties:
* [Evolution](https://wiki.gnome.org/Apps/Evolution/)
* [OpenTasks](https://opentasks.app/) + [DAVx⁵](https://www.davx5.com/)
* [Tasks (Android)](https://tasks.org/)
### Not working
* [Tasks (Android)](https://tasks.org/)
* [Thunderbird (68)](https://www.thunderbird.net/)
## Dev logs

View File

@ -131,10 +131,11 @@ This document describes the different errors Vikunja can return.
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 10001 | 404 | The bucket does not exist. |
| 10002 | 400 | The bucket does not belong to that list. |
| 10003 | 412 | You cannot remove the last bucket on a list. |
| 10004 | 412 | You cannot add the task to this bucket as it already exceeded the limit of tasks it can hold. |
| 10001 | 404 | The bucket does not exist. |
| 10002 | 400 | The bucket does not belong to that list. |
| 10003 | 412 | You cannot remove the last bucket on a list. |
| 10004 | 412 | You cannot add the task to this bucket as it already exceeded the limit of tasks it can hold. |
| 10005 | 412 | There can be only one done bucket per list. |
## Saved Filters
@ -142,3 +143,17 @@ This document describes the different errors Vikunja can return.
|-----------|------------------|-------------|
| 11001 | 404 | The saved filter does not exist. |
| 11002 | 412 | Saved filters are not available for link shares. |
## Subscriptions
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 12001 | 412 | The subscription entity type is invalid. |
| 12002 | 412 | The user is already subscribed to the entity itself or a parent entity. |
## Link Shares
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 13001 | 412 | This link share requires a password for authentication, but none was provided. |
| 13002 | 403 | The provided link share password was invalid. |

1
docs/themes/vikunja vendored

@ -1 +0,0 @@
Subproject commit 958219fc84db455ed58d7a4380bbffc8d04fd5cf

87
go.mod
View File

@ -17,70 +17,65 @@
module code.vikunja.io/api
require (
4d63.com/tz v1.2.0
code.vikunja.io/web v0.0.0-20200809154828-8767618f181f
dmitri.shuralyov.com/go/generated v0.0.0-20170818220700-b1254a446363 // indirect
code.vikunja.io/web v0.0.0-20210131201003-26386be9a9ae
gitea.com/xorm/xorm-redis-cache v0.2.0
github.com/ThreeDotsLabs/watermill v1.1.1
github.com/adlio/trello v1.9.0
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef
github.com/beevik/etree v1.1.0 // indirect
github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2
github.com/client9/misspell v0.3.4
github.com/coreos/go-oidc v2.2.1+incompatible
github.com/cweill/gotests v1.5.3
github.com/d4l3k/messagediff v1.2.1 // indirect
github.com/cweill/gotests v1.6.0
github.com/d4l3k/messagediff v1.2.1
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/disintegration/imaging v1.6.2
github.com/dustinkirkland/golang-petname v0.0.0-20191129215211-8e5a1ed0cff0
github.com/fzipp/gocyclo v0.3.1
github.com/gabriel-vasile/mimetype v1.1.2
github.com/getsentry/sentry-go v0.8.0
github.com/go-errors/errors v1.1.1
github.com/go-openapi/swag v0.19.9 // indirect
github.com/go-redis/redis/v7 v7.4.0
github.com/go-sql-driver/mysql v1.5.0
github.com/go-testfixtures/testfixtures/v3 v3.4.1
github.com/gabriel-vasile/mimetype v1.3.0
github.com/getsentry/sentry-go v0.10.0
github.com/go-errors/errors v1.1.1 // indirect
github.com/go-redis/redis/v8 v8.6.0
github.com/go-sql-driver/mysql v1.6.0
github.com/go-testfixtures/testfixtures/v3 v3.6.0
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0
github.com/google/go-cmp v0.5.2 // indirect
github.com/gordonklaus/ineffassign v0.0.0-20201107091007-3b93a8888063
github.com/iancoleman/strcase v0.1.2
github.com/imdario/mergo v0.3.11
github.com/jgautheron/goconst v0.0.0-20201117150253-ccae5bf973f3
github.com/golang/snappy v0.0.2 // indirect
github.com/iancoleman/strcase v0.1.3
github.com/imdario/mergo v0.3.12
github.com/kr/text v0.2.0 // indirect
github.com/labstack/echo/v4 v4.1.17
github.com/labstack/echo/v4 v4.3.0
github.com/labstack/gommon v0.3.0
github.com/laurent22/ical-go v0.1.1-0.20181107184520-7e5d6ade8eef
github.com/lib/pq v1.8.0
github.com/magefile/mage v1.10.0
github.com/lestrrat-go/jwx v1.0.6
github.com/lib/pq v1.10.2
github.com/magefile/mage v1.11.0
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-sqlite3 v1.14.5
github.com/mattn/go-colorable v0.1.8 // indirect
github.com/mattn/go-sqlite3 v1.14.7
github.com/mitchellh/mapstructure v1.3.2 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/olekukonko/tablewriter v0.0.4
github.com/onsi/ginkgo v1.13.0 // indirect
github.com/olekukonko/tablewriter v0.0.5
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/pelletier/go-toml v1.8.0 // indirect
github.com/pquerna/otp v1.3.0
github.com/pquerna/cachecontrol v0.0.0-20200921180117-858c6e7e6b7e // indirect
github.com/prometheus/client_golang v1.8.0
github.com/pquerna/otp v1.3.0
github.com/prometheus/client_golang v1.10.0
github.com/robfig/cron/v3 v3.0.1
github.com/samedi/caldav-go v3.0.0+incompatible
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546
github.com/spf13/afero v1.4.1
github.com/spf13/afero v1.6.0
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/cobra v1.1.1
github.com/spf13/cobra v1.1.3
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/viper v1.7.1
github.com/stretchr/testify v1.6.1
github.com/swaggo/swag v1.6.9
github.com/ulule/limiter/v3 v3.5.0
golang.org/x/crypto v0.0.0-20201112155050-0c6587e931a9
golang.org/x/image v0.0.0-20200927104501-e162460cd6b5
golang.org/x/lint v0.0.0-20200302205851-738671d3881b
golang.org/x/net v0.0.0-20201016165138-7b1cca2348c0 // indirect
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9
golang.org/x/tools v0.0.0-20201017001424-6003fad69a88 // indirect
github.com/stretchr/testify v1.7.0
github.com/swaggo/swag v1.7.0
github.com/ulule/limiter/v3 v3.8.0
github.com/yuin/goldmark v1.3.7
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
golang.org/x/image v0.0.0-20210504121937-7319ad40d33e
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/term v0.0.0-20210503060354-a79de5458b56
golang.org/x/tools v0.1.0 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/d4l3k/messagediff.v1 v1.2.1
@ -88,15 +83,15 @@ require (
gopkg.in/ini.v1 v1.57.0 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c
honnef.co/go/tools v0.0.1-2020.1.5
src.techknowlogick.com/xgo v1.1.1-0.20200811225412-bff6512e7c9c
src.techknowlogick.com/xgo v1.4.1-0.20210311222705-d25c33fcd864
src.techknowlogick.com/xormigrate v1.4.0
xorm.io/builder v0.3.7
xorm.io/builder v0.3.8
xorm.io/core v0.7.3
xorm.io/xorm v1.0.2
xorm.io/xorm v1.0.7
)
replace (
github.com/adlio/trello => github.com/kolaente/trello v1.7.1-0.20201216234312-5c4ef79b531e
github.com/coreos/bbolt => go.etcd.io/bbolt v1.3.4
github.com/coreos/go-systemd => github.com/coreos/go-systemd/v22 v22.0.0
github.com/hpcloud/tail => github.com/jeffbean/tail v1.0.1 // See https://github.com/hpcloud/tail/pull/159
@ -104,4 +99,4 @@ replace (
gopkg.in/fsnotify.v1 => github.com/kolaente/fsnotify v1.4.10-0.20200411160148-1bc3c8ff4048 // See https://github.com/fsnotify/fsnotify/issues/328 and https://github.com/golang/go/issues/26904
)
go 1.13
go 1.15

506
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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/>.
// +build mage
@ -24,9 +24,7 @@ import (
"context"
"crypto/sha256"
"fmt"
"github.com/magefile/mage/mg"
"golang.org/x/sync/errgroup"
"gopkg.in/yaml.v3"
"github.com/iancoleman/strcase"
"io"
"io/ioutil"
"os"
@ -35,6 +33,10 @@ import (
"runtime"
"strings"
"time"
"github.com/magefile/mage/mg"
"golang.org/x/sync/errgroup"
"gopkg.in/yaml.v3"
)
const (
@ -50,21 +52,25 @@ var (
Ldflags = ""
Tags = ""
VersionNumber = "dev"
Version = "master" // This holds the built version, master by default, when building from a tag or release branch, their name
Version = "unstable" // This holds the built version, unstable by default, when building from a tag or release branch, their name
BinLocation = ""
PkgVersion = "master"
PkgVersion = "unstable"
ApiPackages = []string{}
RootPath = ""
GoFiles = []string{}
// Aliases are mage aliases of targets
Aliases = map[string]interface{}{
"build": Build.Build,
"do-the-swag": DoTheSwag,
"check:got-swag": Check.GotSwag,
"release:os-package": Release.OsPackage,
"dev:create-migration": Dev.CreateMigration,
"generate-docs": GenerateDocs,
"build": Build.Build,
"do-the-swag": DoTheSwag,
"check:got-swag": Check.GotSwag,
"release:os-package": Release.OsPackage,
"dev:make-migration": Dev.MakeMigration,
"dev:make-event": Dev.MakeEvent,
"dev:make-listener": Dev.MakeListener,
"dev:make-notification": Dev.MakeNotification,
"generate-docs": GenerateDocs,
"check:golangci-fix": Check.GolangciFix,
}
)
@ -84,6 +90,10 @@ func setVersion() {
} else if os.Getenv("DRONE_BRANCH") != "" {
Version = strings.Replace(os.Getenv("DRONE_BRANCH"), "release/v", "", 1)
}
if Version == "main" {
Version = "unstable"
}
}
func setBinLocation() {
@ -95,7 +105,7 @@ func setBinLocation() {
}
func setPkgVersion() {
if Version == "master" {
if Version == "unstable" {
PkgVersion = VersionNumber
}
}
@ -292,6 +302,25 @@ func moveFile(src, dst string) error {
return nil
}
func appendToFile(filename, content string) error {
f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString(content)
return err
}
const InfoColor = "\033[1;32m%s\033[0m"
func printSuccess(text string, args ...interface{}) {
text = fmt.Sprintf(text, args...)
fmt.Printf(InfoColor+"\n", text)
}
// Formats the code using go fmt
func Fmt() {
mg.Deps(initVars)
@ -381,7 +410,7 @@ func (Check) GolangciFix() {
runAndStreamOutput("golangci-lint", "run", "--fix")
}
// Runs fmt-check, lint, got-swag, misspell-check, ineffasign-check, gocyclo-check, static-check, gosec-check, goconst-check all in parallel
// Runs golangci and the swagger test in parralel
func (Check) All() {
mg.Deps(initVars)
mg.Deps(
@ -410,16 +439,9 @@ func (Build) Clean() error {
return nil
}
// Generates static content into the final binary
func (Build) Generate() {
mg.Deps(initVars)
runAndStreamOutput("go", "generate", PACKAGE+"/pkg/static")
}
// Builds a vikunja binary, ready to run
func (Build) Build() {
mg.Deps(initVars)
mg.Deps(Build.Generate)
runAndStreamOutput("go", "build", Goflags[0], "-tags", Tags, "-ldflags", "-s -w "+Ldflags, "-o", Executable)
}
@ -428,8 +450,7 @@ type Release mg.Namespace
// Runs all steps in the right order to create release packages for various platforms
func (Release) Release(ctx context.Context) error {
mg.Deps(initVars)
mg.Deps(Build.Generate, Release.Dirs)
mg.Deps(Release.Windows, Release.Linux, Release.Darwin)
mg.Deps(Release.Dirs)
// Run compiling in parallel to speed it up
errs, _ := errgroup.WithContext(ctx)
@ -512,7 +533,7 @@ func (Release) Linux() error {
// Builds binaries for darwin
func (Release) Darwin() error {
return runXgo("darwin/*")
return runXgo("darwin-10.15/*")
}
// Compresses the built binaries in dist/binaries/ to reduce their filesize
@ -646,7 +667,7 @@ func (Release) Zip() error {
// Creates a debian repo structure
func (Release) Reprepro() {
mg.Deps(setVersion, setBinLocation)
runAndStreamOutput("reprepro_expect", "debian", "includedeb", "strech", RootPath+"/"+DIST+"/os-packages/"+Executable+"_"+strings.ReplaceAll(VersionNumber, "v0", "0")+"_amd64.deb")
runAndStreamOutput("reprepro_expect", "debian", "includedeb", "buster", RootPath+"/"+DIST+"/os-packages/"+Executable+"_"+strings.ReplaceAll(VersionNumber, "v0", "0")+"_amd64.deb")
}
// Creates deb, rpm and apk packages
@ -693,7 +714,7 @@ func (Release) Packages() error {
type Dev mg.Namespace
// Creates a new bare db migration skeleton in pkg/migration with the current date
func (Dev) CreateMigration() error {
func (Dev) MakeMigration() error {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Enter the name of the struct: ")
@ -703,19 +724,19 @@ func (Dev) CreateMigration() error {
date := time.Now().Format("20060102150405")
migration := `// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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
@ -745,14 +766,175 @@ func init() {
})
}
`
f, err := os.Create(RootPath + "/pkg/migration/" + date + ".go")
filename := "/pkg/migration/" + date + ".go"
f, err := os.Create(RootPath + filename)
defer f.Close()
if err != nil {
return err
}
_, err = f.WriteString(migration)
return err
if _, err := f.WriteString(migration); err != nil {
return err
}
printSuccess("Migration has been created at %s!", filename)
return nil
}
// Create a new event. Takes the name of the event as the first argument and the module where the event should be created as the second argument. Events will be appended to the pkg/<module>/events.go file.
func (Dev) MakeEvent(name, module string) error {
name = strcase.ToCamel(name)
if !strings.HasSuffix(name, "Event") {
name += "Event"
}
eventName := strings.ReplaceAll(strcase.ToDelimited(name, '.'), ".event", "")
newEventCode := `
// ` + name + ` represents a ` + name + ` event
type ` + name + ` struct {
}
// Name defines the name for ` + name + `
func (t *` + name + `) Name() string {
return "` + eventName + `"
}
`
filename := "./pkg/" + module + "/events.go"
if err := appendToFile(filename, newEventCode); err != nil {
return err
}
printSuccess("The new event has been created successfully! Head over to %s and adjust its content.", filename)
return nil
}
// Create a new listener for an event. Takes the name of the listener, the name of the event to listen to and the module where everything should be placed as parameters.
func (Dev) MakeListener(name, event, module string) error {
name = strcase.ToCamel(name)
listenerName := strcase.ToDelimited(name, '.')
listenerCode := `
// ` + name + ` represents a listener
type ` + name + ` struct {
}
// Name defines the name for the ` + name + ` listener
func (s *` + name + `) Name() string {
return "` + listenerName + `"
}
// Handle is executed when the event ` + name + ` listens on is fired
func (s *` + name + `) Handle(msg *message.Message) (err error) {
event := &` + event + `{}
err = json.Unmarshal(msg.Payload, event)
if err != nil {
return err
}
return nil
}
`
filename := "./pkg/" + module + "/listeners.go"
//////
// Register the listener
file, err := os.Open(filename)
if err != nil {
return err
}
scanner := bufio.NewScanner(file)
var idx int64 = 0
for scanner.Scan() {
if scanner.Text() == "}" {
//idx -= int64(len(scanner.Text()))
break
}
idx += int64(len(scanner.Bytes()) + 1)
}
file.Close()
registerListenerCode := ` events.RegisterListener((&` + event + `{}).Name(), &` + name + `{})
`
f, err := os.OpenFile(filename, os.O_RDWR, 0600)
if err != nil {
return err
}
defer f.Close()
if _, err := f.Seek(idx, 0); err != nil {
return err
}
remainder, err := ioutil.ReadAll(f)
if err != nil {
return err
}
f.Seek(idx, 0)
f.Write([]byte(registerListenerCode))
f.Write(remainder)
///////
// Append the listener code
if err := appendToFile(filename, listenerCode); err != nil {
return err
}
printSuccess("The new listener has been created successfully! Head over to %s and adjust its content.", filename)
return nil
}
// Create a new notification. Takes the name of the notification as the first argument and the module where the notification should be created as the second argument. Notifications will be appended to the pkg/<module>/notifications.go file.
func (Dev) MakeNotification(name, module string) error {
name = strcase.ToCamel(name)
if !strings.HasSuffix(name, "Notification") {
name += "Notification"
}
notficationName := strings.ReplaceAll(strcase.ToDelimited(name, '.'), ".notification", "")
newNotificationCode := `
// ` + name + ` represents a ` + name + ` notification
type ` + name + ` struct {
}
// ToMail returns the mail notification for ` + name + `
func (n *` + name + `) ToMail() *notifications.Mail {
return notifications.NewMail().
Subject("").
Greeting("Hi ").
Line("").
Action("", "")
}
// ToDB returns the ` + name + ` notification in a format which can be saved in the db
func (n *` + name + `) ToDB() interface{} {
return nil
}
// Name returns the name of the notification
func (n *` + name + `) Name() string {
return "` + notficationName + `"
}
`
filename := "./pkg/" + module + "/notifications.go"
if err := appendToFile(filename, newNotificationCode); err != nil {
return err
}
printSuccess("The new notification has been created successfully! Head over to %s and adjust its content.", filename)
return nil
}
type configOption struct {
@ -864,7 +1046,7 @@ const (
configInjectComment = `<!-- Generated config will be injected here -->`
)
// Generates the error docs from a commented config.yml.sample file in the repo root.
// Generates the config docs from a commented config.yml.sample file in the repo root.
func GenerateDocs() error {
config, err := ioutil.ReadFile("config.yml.sample")

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 main

View File

@ -7,12 +7,19 @@ maintainer: "Vikunja Maintainers <maintainers@vikunja.io>"
homepage: "https://vikunja.io"
section: "default"
priority: "extra"
license: "GPLv3"
files:
<binlocation>: /opt/vikunja/vikunja
config_files:
./config.yml.sample: /etc/vikunja/config.yml
symlinks:
/opt/vikunja/vikunja: /usr/local/bin/vikunja
license: "AGPLv3"
depends:
- systemd
contents:
- src: <binlocation>
dst: /opt/vikunja/vikunja
- src: ./config.yml.sample
dst: /etc/vikunja/config.yml
type: "config"
- src: /opt/vikunja/vikunja
dst: /usr/local/bin/vikunja
type: "symlink"
- src: vikunja.service
dst: /usr/lib/systemd/system/vikunja.service
scripts:
postinstall: ./build/after-install.sh

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 caldav
@ -37,6 +37,7 @@ type Event struct {
Description string
UID string
Alarms []Alarm
Color string
Timestamp time.Time
Start time.Time
@ -56,6 +57,7 @@ type Todo struct {
Organizer *user.User
Priority int64 // 0-9, 1 is highest
RelatedToUID string
Color string
Start time.Time
End time.Time
@ -76,6 +78,24 @@ type Alarm struct {
type Config struct {
Name string
ProdID string
Color string
}
func getCaldavColor(color string) (caldavcolor string) {
if color == "" {
return ""
}
if !strings.HasPrefix(color, "#") {
color = "#" + color
}
color += "FF"
return `
X-APPLE-CALENDAR-COLOR:` + color + `
X-OUTLOOK-COLOR:` + color + `
X-FUNAMBOL-COLOR:` + color
}
// ParseEvents parses an array of caldav events and gives them back as string
@ -85,7 +105,7 @@ VERSION:2.0
METHOD:PUBLISH
X-PUBLISHED-TTL:PT4H
X-WR-CALNAME:` + config.Name + `
PRODID:-//` + config.ProdID + `//EN`
PRODID:-//` + config.ProdID + `//EN` + getCaldavColor(config.Color)
for _, e := range events {
@ -102,7 +122,7 @@ PRODID:-//` + config.ProdID + `//EN`
caldavevents += `
BEGIN:VEVENT
UID:` + e.UID + `
SUMMARY:` + e.Summary + `
SUMMARY:` + e.Summary + getCaldavColor(e.Color) + `
DESCRIPTION:` + formattedDescription + `
DTSTAMP:` + makeCalDavTimeFromTimeStamp(e.Timestamp) + `
DTSTART:` + makeCalDavTimeFromTimeStamp(e.Start) + `
@ -137,7 +157,7 @@ VERSION:2.0
METHOD:PUBLISH
X-PUBLISHED-TTL:PT4H
X-WR-CALNAME:` + config.Name + `
PRODID:-//` + config.ProdID + `//EN`
PRODID:-//` + config.ProdID + `//EN` + getCaldavColor(config.Color)
for _, t := range todos {
if t.UID == "" {
@ -148,7 +168,7 @@ PRODID:-//` + config.ProdID + `//EN`
BEGIN:VTODO
UID:` + t.UID + `
DTSTAMP:` + makeCalDavTimeFromTimeStamp(t.Timestamp) + `
SUMMARY:` + t.Summary
SUMMARY:` + t.Summary + getCaldavColor(t.Color)
if t.Start.Unix() > 0 {
caldavtodos += `

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 caldav
@ -40,6 +40,7 @@ func TestParseEvents(t *testing.T) {
config: &Config{
Name: "test",
ProdID: "RandomProdID which is not random",
Color: "ffffff",
},
events: []*Event{
{
@ -49,6 +50,7 @@ func TestParseEvents(t *testing.T) {
Timestamp: time.Unix(1543626724, 0).In(config.GetTimeZone()),
Start: time.Unix(1543626724, 0).In(config.GetTimeZone()),
End: time.Unix(1543627824, 0).In(config.GetTimeZone()),
Color: "affffe",
},
{
Summary: "Event #2",
@ -72,9 +74,15 @@ METHOD:PUBLISH
X-PUBLISHED-TTL:PT4H
X-WR-CALNAME:test
PRODID:-//RandomProdID which is not random//EN
X-APPLE-CALENDAR-COLOR:#ffffffFF
X-OUTLOOK-COLOR:#ffffffFF
X-FUNAMBOL-COLOR:#ffffffFF
BEGIN:VEVENT
UID:randommduid
SUMMARY:Event #1
X-APPLE-CALENDAR-COLOR:#affffeFF
X-OUTLOOK-COLOR:#affffeFF
X-FUNAMBOL-COLOR:#affffeFF
DESCRIPTION:Lorem Ipsum
DTSTAMP:20181201T011204
DTSTART:20181201T011204
@ -301,6 +309,7 @@ func TestParseTodos(t *testing.T) {
config: &Config{
Name: "test",
ProdID: "RandomProdID which is not random",
Color: "ffffff",
},
todos: []*Todo{
{
@ -309,6 +318,7 @@ func TestParseTodos(t *testing.T) {
Dolor sit amet`,
UID: "randommduid",
Timestamp: time.Unix(1543626724, 0).In(config.GetTimeZone()),
Color: "affffe",
},
},
},
@ -318,10 +328,16 @@ METHOD:PUBLISH
X-PUBLISHED-TTL:PT4H
X-WR-CALNAME:test
PRODID:-//RandomProdID which is not random//EN
X-APPLE-CALENDAR-COLOR:#ffffffFF
X-OUTLOOK-COLOR:#ffffffFF
X-FUNAMBOL-COLOR:#ffffffFF
BEGIN:VTODO
UID:randommduid
DTSTAMP:20181201T011204
SUMMARY:Todo #1
X-APPLE-CALENDAR-COLOR:#affffeFF
X-OUTLOOK-COLOR:#affffeFF
X-FUNAMBOL-COLOR:#affffeFF
DESCRIPTION:Lorem Ipsum\nDolor sit amet
LAST-MODIFIED:00010101T000000
END:VTODO

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 cmd

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 cmd

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 cmd

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 cmd

View File

@ -1,25 +1,27 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 cmd
import (
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/initialize"
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/mail"
"code.vikunja.io/api/pkg/notifications"
"github.com/spf13/cobra"
)
@ -39,8 +41,20 @@ var testmailCmd = &cobra.Command{
},
Run: func(cmd *cobra.Command, args []string) {
log.Info("Sending testmail...")
email := args[0]
if err := mail.SendTestMail(email); err != nil {
message := notifications.NewMail().
From(config.MailerFromEmail.GetString()).
To(args[0]).
Subject("Test from Vikunja").
Line("This is a test mail!").
Line("If you received this, Vikunja is correctly set up to send emails.").
Action("Go to your instance", config.ServiceFrontendurl.GetString())
opts, err := notifications.RenderMail(message)
if err != nil {
log.Errorf("Error sending test mail: %s", err.Error())
return
}
if err := mail.SendTestMail(opts); err != nil {
log.Errorf("Error sending test mail: %s", err.Error())
return
}

View File

@ -1,19 +1,18 @@
// Copyright 2020 Vikunja and contriubtors. All rights reserved.
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This file is part of Vikunja.
//
// Vikunja is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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.
//
// Vikunja is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
// 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 cmd
@ -24,13 +23,15 @@ import (
"strings"
"time"
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/api/pkg/initialize"
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/models"
"code.vikunja.io/api/pkg/user"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
"golang.org/x/crypto/ssh/terminal"
"golang.org/x/term"
"xorm.io/xorm"
)
var (
@ -73,12 +74,12 @@ func getPasswordFromFlagOrInput() (pw string) {
pw = userFlagPassword
if userFlagPassword == "" {
fmt.Print("Enter Password: ")
bytePW, err := terminal.ReadPassword(int(os.Stdin.Fd()))
bytePW, err := term.ReadPassword(int(os.Stdin.Fd()))
if err != nil {
log.Fatalf("Error reading password: %s", err)
}
fmt.Printf("\nConfirm Password: ")
byteConfirmPW, err := terminal.ReadPassword(int(os.Stdin.Fd()))
byteConfirmPW, err := term.ReadPassword(int(os.Stdin.Fd()))
if err != nil {
log.Fatalf("Error reading password: %s", err)
}
@ -91,13 +92,13 @@ func getPasswordFromFlagOrInput() (pw string) {
return
}
func getUserFromArg(arg string) *user.User {
func getUserFromArg(s *xorm.Session, arg string) *user.User {
id, err := strconv.ParseInt(arg, 10, 64)
if err != nil {
log.Fatalf("Invalid user id: %s", err)
}
u, err := user.GetUserByID(id)
u, err := user.GetUserByID(s, id)
if err != nil {
log.Fatalf("Could not get user: %s", err)
}
@ -116,8 +117,16 @@ var userListCmd = &cobra.Command{
initialize.FullInit()
},
Run: func(cmd *cobra.Command, args []string) {
users, err := user.ListUsers("")
s := db.NewSession()
defer s.Close()
users, err := user.ListAllUsers(s)
if err != nil {
_ = s.Rollback()
log.Fatalf("Error getting users: %s", err)
}
if err := s.Commit(); err != nil {
log.Fatalf("Error getting users: %s", err)
}
@ -153,21 +162,30 @@ var userCreateCmd = &cobra.Command{
initialize.FullInit()
},
Run: func(cmd *cobra.Command, args []string) {
s := db.NewSession()
defer s.Close()
u := &user.User{
Username: userFlagUsername,
Email: userFlagEmail,
Password: getPasswordFromFlagOrInput(),
}
newUser, err := user.CreateUser(u)
newUser, err := user.CreateUser(s, u)
if err != nil {
_ = s.Rollback()
log.Fatalf("Error creating new user: %s", err)
}
err = models.CreateNewNamespaceForUser(newUser)
err = models.CreateNewNamespaceForUser(s, newUser)
if err != nil {
_ = s.Rollback()
log.Fatalf("Error creating new namespace for user: %s", err)
}
if err := s.Commit(); err != nil {
log.Fatalf("Error saving everything: %s", err)
}
fmt.Printf("\nUser was created successfully.\n")
},
}
@ -180,7 +198,10 @@ var userUpdateCmd = &cobra.Command{
initialize.FullInit()
},
Run: func(cmd *cobra.Command, args []string) {
u := getUserFromArg(args[0])
s := db.NewSession()
defer s.Close()
u := getUserFromArg(s, args[0])
if userFlagUsername != "" {
u.Username = userFlagUsername
@ -192,11 +213,16 @@ var userUpdateCmd = &cobra.Command{
u.AvatarProvider = userFlagAvatar
}
_, err := user.UpdateUser(u)
_, err := user.UpdateUser(s, u)
if err != nil {
_ = s.Rollback()
log.Fatalf("Error updating the user: %s", err)
}
if err := s.Commit(); err != nil {
log.Fatalf("Error saving everything: %s", err)
}
fmt.Println("User updated successfully.")
},
}
@ -209,22 +235,31 @@ var userResetPasswordCmd = &cobra.Command{
},
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
u := getUserFromArg(args[0])
s := db.NewSession()
defer s.Close()
u := getUserFromArg(s, args[0])
// By default we reset as usual, only with specific flag directly.
if userFlagResetPasswordDirectly {
err := user.UpdateUserPassword(u, getPasswordFromFlagOrInput())
err := user.UpdateUserPassword(s, u, getPasswordFromFlagOrInput())
if err != nil {
_ = s.Rollback()
log.Fatalf("Could not update user password: %s", err)
}
fmt.Println("Password updated successfully.")
} else {
err := user.RequestUserPasswordResetToken(u)
err := user.RequestUserPasswordResetToken(s, u)
if err != nil {
_ = s.Rollback()
log.Fatalf("Could not send password reset email: %s", err)
}
fmt.Println("Password reset email sent successfully.")
}
if err := s.Commit(); err != nil {
log.Fatalf("Could not send password reset email: %s", err)
}
},
}
@ -236,7 +271,10 @@ var userChangeEnabledCmd = &cobra.Command{
},
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
u := getUserFromArg(args[0])
s := db.NewSession()
defer s.Close()
u := getUserFromArg(s, args[0])
if userFlagEnableUser {
u.IsActive = true
@ -245,11 +283,16 @@ var userChangeEnabledCmd = &cobra.Command{
} else {
u.IsActive = !u.IsActive
}
_, err := user.UpdateUser(u)
_, err := user.UpdateUser(s, u)
if err != nil {
_ = s.Rollback()
log.Fatalf("Could not enable the user")
}
if err := s.Commit(); err != nil {
log.Fatalf("Error saving everything: %s", err)
}
fmt.Printf("User status successfully changed, user is now active: %t.\n", u.IsActive)
},
}

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 cmd

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 cmd
@ -22,6 +22,8 @@ import (
"os/signal"
"time"
"code.vikunja.io/api/pkg/cron"
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/initialize"
"code.vikunja.io/api/pkg/log"
@ -70,5 +72,6 @@ var webCmd = &cobra.Command{
if err := e.Shutdown(ctx); err != nil {
e.Logger.Fatal(err)
}
cron.Stop()
},
}

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 config
@ -25,8 +25,8 @@ import (
"path/filepath"
"strings"
"time"
_ "time/tzdata" // Imports time zone data instead of relying on the os
"4d63.com/tz"
"github.com/spf13/viper"
)
@ -36,12 +36,13 @@ type Key string
// These constants hold all config value keys
const (
// #nosec
ServiceJWTSecret Key = `service.JWTSecret`
ServiceInterface Key = `service.interface`
ServiceFrontendurl Key = `service.frontendurl`
ServiceEnableCaldav Key = `service.enablecaldav`
ServiceRootpath Key = `service.rootpath`
ServiceMaxItemsPerPage Key = `service.maxitemsperpage`
ServiceJWTSecret Key = `service.JWTSecret`
ServiceInterface Key = `service.interface`
ServiceFrontendurl Key = `service.frontendurl`
ServiceEnableCaldav Key = `service.enablecaldav`
ServiceRootpath Key = `service.rootpath`
ServiceMaxItemsPerPage Key = `service.maxitemsperpage`
// Deprecated. Use metrics.enabled
ServiceEnableMetrics Key = `service.enablemetrics`
ServiceMotd Key = `service.motd`
ServiceEnableLinkSharing Key = `service.enablelinksharing`
@ -51,11 +52,16 @@ const (
ServiceEnableTaskComments Key = `service.enabletaskcomments`
ServiceEnableTotp Key = `service.enabletotp`
ServiceSentryDsn Key = `service.sentrydsn`
ServiceTestingtoken Key = `service.testingtoken`
ServiceEnableEmailReminders Key = `service.enableemailreminders`
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`
AuthOpenIDRedirectURL Key = `auth.openid.redirecturl`
AuthOpenIDProviders Key = `auth.openid.providers`
AuthIdentityAwareProxyEnabled Key = `auth.identityawareproxy.enabled`
AuthIdentityAwareProxyJwksURI Key = `auth.identityawareproxy.jwksuri`
AuthIdentityAwareProxyJwtHeader Key = `auth.identityawareproxy.jwtheader`
LegalImprintURL Key = `legal.imprinturl`
LegalPrivacyURL Key = `legal.privacyurl`
@ -70,6 +76,7 @@ const (
DatabaseMaxIdleConnections Key = `database.maxidleconnections`
DatabaseMaxConnectionLifetime Key = `database.maxconnectionlifetime`
DatabaseSslMode Key = `database.sslmode`
DatabaseTLS Key = `database.tls`
CacheEnabled Key = `cache.enabled`
CacheType Key = `cache.type`
@ -99,6 +106,8 @@ const (
LogHTTP Key = `log.http`
LogEcho Key = `log.echo`
LogPath Key = `log.path`
LogEvents Key = `log.events`
LogEventsLevel Key = `log.eventslevel`
RateLimitEnabled Key = `ratelimit.enabled`
RateLimitKind Key = `ratelimit.kind`
@ -109,14 +118,21 @@ const (
FilesBasePath Key = `files.basepath`
FilesMaxSize Key = `files.maxsize`
MigrationWunderlistEnable Key = `migration.wunderlist.enable`
MigrationWunderlistClientID Key = `migration.wunderlist.clientid`
MigrationWunderlistClientSecret Key = `migration.wunderlist.clientsecret`
MigrationWunderlistRedirectURL Key = `migration.wunderlist.redirecturl`
MigrationTodoistEnable Key = `migration.todoist.enable`
MigrationTodoistClientID Key = `migration.todoist.clientid`
MigrationTodoistClientSecret Key = `migration.todoist.clientsecret`
MigrationTodoistRedirectURL Key = `migration.todoist.redirecturl`
MigrationWunderlistEnable Key = `migration.wunderlist.enable`
MigrationWunderlistClientID Key = `migration.wunderlist.clientid`
MigrationWunderlistClientSecret Key = `migration.wunderlist.clientsecret`
MigrationWunderlistRedirectURL Key = `migration.wunderlist.redirecturl`
MigrationTodoistEnable Key = `migration.todoist.enable`
MigrationTodoistClientID Key = `migration.todoist.clientid`
MigrationTodoistClientSecret Key = `migration.todoist.clientsecret`
MigrationTodoistRedirectURL Key = `migration.todoist.redirecturl`
MigrationTrelloEnable Key = `migration.trello.enable`
MigrationTrelloKey Key = `migration.trello.key`
MigrationTrelloRedirectURL Key = `migration.trello.redirecturl`
MigrationMicrosoftTodoEnable Key = `migration.microsofttodo.enable`
MigrationMicrosoftTodoClientID Key = `migration.microsofttodo.clientid`
MigrationMicrosoftTodoClientSecret Key = `migration.microsofttodo.clientsecret`
MigrationMicrosoftTodoRedirectURL Key = `migration.microsofttodo.redirecturl`
CorsEnable Key = `cors.enable`
CorsOrigins Key = `cors.origins`
@ -131,6 +147,10 @@ const (
BackgroundsUnsplashApplicationID Key = `backgrounds.providers.unsplash.applicationid`
KeyvalueType Key = `keyvalue.type`
MetricsEnabled Key = `metrics.enabled`
MetricsUsername Key = `metrics.username`
MetricsPassword Key = `metrics.password`
)
// GetString returns a string config value
@ -175,7 +195,7 @@ var timezone *time.Location
// it way easier, especially when testing.
func GetTimeZone() *time.Location {
if timezone == nil {
loc, err := tz.LoadLocation(ServiceTimeZone.GetString())
loc, err := time.LoadLocation(ServiceTimeZone.GetString())
if err != nil {
fmt.Printf("Error parsing time zone: %s", err)
os.Exit(1)
@ -225,10 +245,12 @@ func InitDefaultConfig() {
ServiceTimeZone.setDefault("GMT")
ServiceEnableTaskComments.setDefault(true)
ServiceEnableTotp.setDefault(true)
ServiceEnableEmailReminders.setDefault(true)
// Auth
AuthLocalEnabled.setDefault(true)
AuthOpenIDEnabled.setDefault(false)
AuthIdentityAwareProxyEnabled.setDefault(false)
// Database
DatabaseType.setDefault("sqlite")
@ -241,6 +263,7 @@ func InitDefaultConfig() {
DatabaseMaxIdleConnections.setDefault(50)
DatabaseMaxConnectionLifetime.setDefault(10000)
DatabaseSslMode.setDefault("disable")
DatabaseTLS.setDefault("false")
// Cacher
CacheEnabled.setDefault(false)
@ -271,6 +294,8 @@ func InitDefaultConfig() {
LogHTTP.setDefault("stdout")
LogEcho.setDefault("off")
LogPath.setDefault(ServiceRootpath.GetString() + "/logs")
LogEvents.setDefault("stdout")
LogEventsLevel.setDefault("INFO")
// Rate Limit
RateLimitEnabled.setDefault(false)
RateLimitKind.setDefault("user")
@ -287,6 +312,8 @@ func InitDefaultConfig() {
// Migration
MigrationWunderlistEnable.setDefault(false)
MigrationTodoistEnable.setDefault(false)
MigrationTrelloEnable.setDefault(false)
MigrationMicrosoftTodoEnable.setDefault(false)
// Avatar
AvatarGravaterExpiration.setDefault(3600)
// List Backgrounds
@ -295,6 +322,8 @@ func InitDefaultConfig() {
BackgroundsUnsplashEnabled.setDefault(false)
// Key Value
KeyvalueType.setDefault("memory")
// Metrics
MetricsEnabled.setDefault(false)
}
// InitConfig initializes the config, sets defaults etc.
@ -340,6 +369,19 @@ func InitConfig() {
AuthOpenIDRedirectURL.Set(ServiceFrontendurl.GetString() + "auth/openid/")
}
if MigrationTrelloRedirectURL.GetString() == "" {
MigrationTrelloRedirectURL.Set(ServiceFrontendurl.GetString() + "migrate/trello")
}
if MigrationMicrosoftTodoRedirectURL.GetString() == "" {
MigrationMicrosoftTodoRedirectURL.Set(ServiceFrontendurl.GetString() + "migrate/microsoft-todo")
}
if ServiceEnableMetrics.GetBool() {
log.Println("WARNING: service.enablemetrics is deprecated and will be removed in a future release. Please use metrics.enable.")
MetricsEnabled.Set(true)
}
log.Printf("Using config file: %s", viper.ConfigFileUsed())
}

40
pkg/cron/cron.go Normal file
View File

@ -0,0 +1,40 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package cron
import (
"github.com/robfig/cron/v3"
)
var c *cron.Cron
// Init starts the cron
func Init() {
c = cron.New()
c.Start()
}
// Schedule schedules a job as a cron job
func Schedule(schedule string, f func()) (err error) {
_, err = c.AddFunc(schedule, f)
return
}
// Stop stops the cron scheduler
func Stop() {
c.Stop()
}

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 db
@ -31,6 +31,7 @@ import (
"xorm.io/core"
"xorm.io/xorm"
"xorm.io/xorm/caches"
"xorm.io/xorm/schemas"
_ "github.com/go-sql-driver/mysql" // Because.
_ "github.com/lib/pq" // Because.
@ -112,11 +113,12 @@ func initMysqlEngine() (engine *xorm.Engine, err error) {
// We're using utf8mb here instead of just utf8 because we want to use non-BMP characters.
// See https://stackoverflow.com/a/30074553/10924593 for more info.
connStr := fmt.Sprintf(
"%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true",
"%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=true&tls=%s",
config.DatabaseUser.GetString(),
config.DatabasePassword.GetString(),
config.DatabaseHost.GetString(),
config.DatabaseDatabase.GetString())
config.DatabaseDatabase.GetString(),
config.DatabaseTLS.GetString())
engine, err = xorm.NewEngine("mysql", connStr)
if err != nil {
return
@ -211,3 +213,13 @@ func WipeEverything() error {
return nil
}
// NewSession creates a new xorm session
func NewSession() *xorm.Session {
return x.NewSession()
}
// Type returns the db type of the currently configured db
func Type() schemas.DBType {
return x.Dialect().URI().DBType
}

View File

@ -1,22 +1,26 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 db
import "encoding/json"
import (
"encoding/json"
"xorm.io/xorm/schemas"
)
// Dump dumps all database tables
func Dump() (data map[string][]byte, err error) {
@ -52,3 +56,22 @@ func Restore(table string, contents []map[string]interface{}) (err error) {
return
}
// RestoreAndTruncate removes all content from the table before restoring it from the contents map
func RestoreAndTruncate(table string, contents []map[string]interface{}) (err error) {
if _, err := x.IsTableExist(table); err != nil {
return err
}
if x.Dialect().URI().DBType == schemas.SQLITE {
if _, err := x.Query("DELETE FROM " + table); err != nil {
return err
}
} else {
if _, err := x.Query("TRUNCATE TABLE ?", table); err != nil {
return err
}
}
return Restore(table, contents)
}

View File

@ -16,12 +16,14 @@
title: testbucket3
list_id: 1
created_by_id: 1
is_done_bucket: 1
created: 2020-04-18 21:13:52
updated: 2020-04-18 21:13:52
- id: 4
title: testbucket4 - other list
list_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
@ -207,3 +209,9 @@
created_by_id: 1
created: 2020-04-18 21:13:52
updated: 2020-04-18 21:13:52
- id: 35
title: testbucket35
list_id: 23
created_by_id: -2
created: 2020-04-18 21:13:52
updated: 2020-04-18 21:13:52

View File

@ -22,3 +22,12 @@
shared_by_id: 1
created: 2018-12-01 15:13:12
updated: 2018-12-02 15:13:12
- id: 4
hash: testWithPassword
list_id: 1
right: 0
password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.' # 1234
sharing_type: 2
shared_by_id: 1
created: 2018-12-01 15:13:12
updated: 2018-12-02 15:13:12

View File

@ -171,6 +171,7 @@
namespace_id: 14
updated: 2018-12-02 15:13:12
created: 2018-12-01 15:13:12
# User 1 does not have access to this list
-
id: 20
title: Test20

View File

@ -0,0 +1,35 @@
- id: 1
entity_type: 3 # Task
entity_id: 2
user_id: 1
created: 2021-02-01 15:13:12
- id: 2
entity_type: 1 # Namespace
entity_id: 6
user_id: 6
created: 2021-02-01 15:13:12
- id: 3
entity_type: 2 # List
entity_id: 12 # belongs to namespace 7
user_id: 6
created: 2021-02-01 15:13:12
- id: 4
entity_type: 3 # Task
entity_id: 22 # belongs to list 13 which belongs to namespace 8
user_id: 6
created: 2021-02-01 15:13:12
- id: 5
entity_type: 1 # Namespace
entity_id: 8
user_id: 6
created: 2021-02-01 15:13:12
- id: 6
entity_type: 2 # List
entity_id: 13
user_id: 6
created: 2021-02-01 15:13:12
- id: 7
entity_type: 3 # Task
entity_id: 26
user_id: 6
created: 2021-02-01 15:13:12

View File

@ -9,3 +9,8 @@
file_id: 9999
created_by_id: 1
created: 2018-12-01 15:13:12
- id: 3
task_id: 1
file_id: 1
created_by_id: -2
created: 2018-12-01 15:13:12

View File

@ -94,3 +94,9 @@
task_id: 36
created: 2020-02-19 18:07:06
updated: 2020-02-19 18:07:06
- id: 17
comment: comment 17
author_id: -2
task_id: 35
created: 2020-02-19 18:07:06
updated: 2020-02-19 18:07:06

View File

@ -6,3 +6,7 @@
task_id: 27
reminder: 2018-12-01 01:13:44
created: 2018-12-01 01:12:04
- id: 3
task_id: 2
reminder: 2018-12-01 01:13:44
created: 2018-12-01 01:12:04

View File

@ -338,5 +338,20 @@
bucket_id: 20
created: 2018-12-01 01:12:04
updated: 2018-12-01 01:12:04
- id: 37
title: 'task #37'
done: false
created_by_id: -2
list_id: 2
index: 2
created: 2018-12-01 01:12:04
updated: 2018-12-01 01:12:04
- id: 38
title: 'task #37 done with due date'
done: true
created_by_id: 1
list_id: 22
index: 2
created: 2018-12-01 01:12:04
updated: 2018-12-01 01:12:04
due_date: 2018-10-30 22:25:24

View File

@ -45,4 +45,10 @@
list_id: 19
right: 2
updated: 2018-12-02 15:13:12
created: 2018-12-01 15:13:12
created: 2018-12-01 15:13:12
- id: 8
team_id: 1
list_id: 21
right: 0
updated: 2018-12-02 15:13:12
created: 2018-12-01 15:13:12

View File

@ -58,6 +58,7 @@
email: 'user7@example.com'
is_active: true
issuer: local
discoverable_by_email: true
updated: 2018-12-02 15:13:12
created: 2018-12-01 15:13:12
- id: 8
@ -86,6 +87,7 @@
created: 2018-12-01 15:13:12
- id: 11
username: 'user11'
name: 'Some one else'
password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.' # 1234
email: 'user11@example.com'
is_active: true
@ -94,10 +96,12 @@
created: 2018-12-01 15:13:12
- id: 12
username: 'user12'
name: 'Name with spaces'
password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.' # 1234
email: 'user12@example.com'
is_active: true
issuer: local
discoverable_by_name: true
updated: 2018-12-02 15:13:12
created: 2018-12-01 15:13:12
- id: 13

View File

@ -1,19 +1,18 @@
// Copyright2018-2020 Vikunja and contriubtors. All rights reserved.
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This file is part of Vikunja.
//
// Vikunja is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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.
//
// Vikunja is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
// 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 db

View File

@ -1,19 +1,18 @@
// Copyright 2018-2020 Vikunja and contriubtors. All rights reserved.
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This file is part of Vikunja.
//
// Vikunja is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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.
//
// Vikunja is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
// 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 db

112
pkg/events/events.go Normal file
View File

@ -0,0 +1,112 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package events
import (
"context"
"encoding/json"
"time"
"code.vikunja.io/api/pkg/log"
vmetrics "code.vikunja.io/api/pkg/metrics"
"github.com/ThreeDotsLabs/watermill"
"github.com/ThreeDotsLabs/watermill/components/metrics"
"github.com/ThreeDotsLabs/watermill/message"
"github.com/ThreeDotsLabs/watermill/message/router/middleware"
"github.com/ThreeDotsLabs/watermill/pubsub/gochannel"
)
var pubsub *gochannel.GoChannel
// Event represents the event interface used by all events
type Event interface {
Name() string
}
// InitEvents sets up everything needed to work with events
func InitEvents() (err error) {
logger := log.NewWatermillLogger()
router, err := message.NewRouter(
message.RouterConfig{},
logger,
)
if err != nil {
return err
}
metricsBuilder := metrics.NewPrometheusMetricsBuilder(vmetrics.GetRegistry(), "", "")
metricsBuilder.AddPrometheusRouterMetrics(router)
pubsub = gochannel.NewGoChannel(
gochannel.Config{
OutputChannelBuffer: 1024,
},
logger,
)
poison, err := middleware.PoisonQueue(pubsub, "poison")
if err != nil {
return err
}
router.AddNoPublisherHandler("poison.logger", "poison", pubsub, func(msg *message.Message) error {
meta := ""
for s, m := range msg.Metadata {
meta += s + "=" + m + ", "
}
log.Errorf("Error while handling message %s, %s payload=%s", msg.UUID, meta, string(msg.Payload))
return nil
})
router.AddMiddleware(
poison,
middleware.Retry{
MaxRetries: 5,
InitialInterval: time.Millisecond * 100,
MaxInterval: time.Hour,
Multiplier: 2,
MaxElapsedTime: 0,
RandomizationFactor: 1,
Logger: logger,
}.Middleware,
middleware.Recoverer,
)
for topic, funcs := range listeners {
for _, handler := range funcs {
router.AddNoPublisherHandler(topic+"."+handler.Name(), topic, pubsub, handler.Handle)
}
}
return router.Run(context.Background())
}
// Dispatch dispatches an event
func Dispatch(event Event) error {
if isUnderTest {
dispatchedTestEvents = append(dispatchedTestEvents, event)
return nil
}
content, err := json.Marshal(event)
if err != nil {
return err
}
msg := message.NewMessage(watermill.NewUUID(), content)
return pubsub.Publish(event.Name(), msg)
}

36
pkg/events/listeners.go Normal file
View File

@ -0,0 +1,36 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package events
import "github.com/ThreeDotsLabs/watermill/message"
// Listener represents something that listens to events
type Listener interface {
Handle(msg *message.Message) error
Name() string
}
var listeners map[string][]Listener
func init() {
listeners = make(map[string][]Listener)
}
// RegisterListener is used to register a listener when a specific event happens
func RegisterListener(name string, listener Listener) {
listeners[name] = append(listeners[name], listener)
}

49
pkg/events/testing.go Normal file
View File

@ -0,0 +1,49 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package events
import (
"testing"
"github.com/stretchr/testify/assert"
)
var (
isUnderTest bool
dispatchedTestEvents []Event
)
// Fake sets up the "test mode" of the events package. Typically you'd call this function in the TestMain function
// in the package you're testing. It will prevent any events from being fired, instead they will be recorded and be
// available for assertions.
func Fake() {
isUnderTest = true
dispatchedTestEvents = nil
}
// AssertDispatched asserts an event has been dispatched.
func AssertDispatched(t *testing.T, event Event) {
var found bool
for _, testEvent := range dispatchedTestEvents {
if event.Name() == testEvent.Name() {
found = true
break
}
}
assert.True(t, found, "Failed to assert "+event.Name()+" has been dispatched.")
}

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 files

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 files

View File

@ -1,19 +1,18 @@
// Copyright 2018-2020 Vikunja and contriubtors. All rights reserved.
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This file is part of Vikunja.
//
// Vikunja is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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.
//
// Vikunja is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
// 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 files

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 files

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 files
@ -22,6 +22,7 @@ import (
"time"
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/web"
"github.com/c2h5oh/datasize"
"github.com/spf13/afero"
@ -29,13 +30,13 @@ import (
// File holds all information about a file
type File struct {
ID int64 `xorm:"int(11) autoincr not null unique pk" json:"id"`
ID int64 `xorm:"bigint autoincr not null unique pk" json:"id"`
Name string `xorm:"text not null" json:"name"`
Mime string `xorm:"text null" json:"mime"`
Size uint64 `xorm:"int(11) not null" json:"size"`
Size uint64 `xorm:"bigint not null" json:"size"`
Created time.Time `xorm:"created" json:"created"`
CreatedByID int64 `xorm:"int(11) not null" json:"-"`
CreatedByID int64 `xorm:"bigint not null" json:"-"`
File afero.File `xorm:"-" json:"-"`
// This ReadCloser is only used for migration purposes. Use with care!
@ -93,27 +94,44 @@ func CreateWithMime(f io.Reader, realname string, realsize uint64, a web.Auth, m
Mime: mime,
}
_, err = x.Insert(file)
s := db.NewSession()
defer s.Close()
_, err = s.Insert(file)
if err != nil {
_ = s.Rollback()
return
}
// Save the file to storage with its new ID as path
err = file.Save(f)
if err != nil {
_ = s.Rollback()
return
}
return
}
// Delete removes a file from the DB and the file system
func (f *File) Delete() (err error) {
deleted, err := x.Where("id = ?", f.ID).Delete(f)
s := db.NewSession()
defer s.Close()
deleted, err := s.Where("id = ?", f.ID).Delete(f)
if err != nil {
_ = s.Rollback()
return err
}
if deleted == 0 {
_ = s.Rollback()
return ErrFileDoesNotExist{FileID: f.ID}
}
err = afs.Remove(f.getFileName())
if err != nil {
_ = s.Rollback()
return err
}
return
}

View File

@ -1,19 +1,18 @@
// Copyright 2018-2020 Vikunja and contriubtors. All rights reserved.
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This file is part of Vikunja.
//
// Vikunja is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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.
//
// Vikunja is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
// 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 files

View File

@ -1,19 +1,18 @@
// Copyright 2018-2020 Vikunja and contriubtors. All rights reserved.
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This file is part of Vikunja.
//
// Vikunja is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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.
//
// Vikunja is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
// 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 files

29
pkg/initialize/events.go Normal file
View File

@ -0,0 +1,29 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package initialize
import "time"
// BootedEvent represents a BootedEvent event
type BootedEvent struct {
BootedAt time.Time
}
// TopicName defines the name for BootedEvent
func (t *BootedEvent) Name() string {
return "booted"
}

View File

@ -1,23 +1,27 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 initialize
import (
"time"
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/cron"
"code.vikunja.io/api/pkg/events"
"code.vikunja.io/api/pkg/files"
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/mail"
@ -25,6 +29,7 @@ import (
"code.vikunja.io/api/pkg/models"
"code.vikunja.io/api/pkg/modules/keyvalue"
migrator "code.vikunja.io/api/pkg/modules/migration"
"code.vikunja.io/api/pkg/notifications"
"code.vikunja.io/api/pkg/red"
"code.vikunja.io/api/pkg/user"
)
@ -62,6 +67,10 @@ func InitEngines() {
if err != nil {
log.Fatal(err.Error())
}
err = notifications.InitDB()
if err != nil {
log.Fatal(err.Error())
}
}
// FullInit initializes all kinds of things in the right order
@ -80,4 +89,26 @@ func FullInit() {
// Start the mail daemon
mail.StartMailDaemon()
// Start the cron
cron.Init()
models.RegisterReminderCron()
models.RegisterOverdueReminderCron()
// Start processing events
go func() {
models.RegisterListeners()
user.RegisterListeners()
err := events.InitEvents()
if err != nil {
log.Fatal(err.Error())
}
err = events.Dispatch(&BootedEvent{
BootedAt: time.Now(),
})
if err != nil {
log.Fatal(err)
}
}()
}

View File

@ -1,5 +1,5 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by

View File

@ -1,19 +1,18 @@
// Copyright 2020 Vikunja and contriubtors. All rights reserved.
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This file is part of Vikunja.
//
// Vikunja is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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.
//
// Vikunja is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
// 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 integrations

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations
@ -24,6 +24,8 @@ import (
"strings"
"testing"
"code.vikunja.io/api/pkg/events"
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/api/pkg/files"
@ -85,6 +87,7 @@ func setupTestEnv() (e *echo.Echo, err error) {
files.InitTests()
user.InitTests()
models.SetupTests()
events.Fake()
err = db.LoadFixtures()
if err != nil {
@ -111,34 +114,38 @@ func bootstrapTestRequest(t *testing.T, method string, payload string, queryPara
return
}
func newTestRequest(t *testing.T, method string, handler func(ctx echo.Context) error, payload string) (rec *httptest.ResponseRecorder, err error) {
c, rec := bootstrapTestRequest(t, method, payload, nil)
func newTestRequest(t *testing.T, method string, handler func(ctx echo.Context) error, payload string, queryParams url.Values, urlParams map[string]string) (rec *httptest.ResponseRecorder, err error) {
rec, c := testRequestSetup(t, method, payload, queryParams, urlParams)
err = handler(c)
return
}
func addUserTokenToContext(t *testing.T, user *user.User, c echo.Context) {
jwtConfig := auth.GetJWTConfig()
// Get the token as a string
token, err := auth.NewUserJWTAuthtoken(user)
assert.NoError(t, err)
// We send the string token through the parsing function to get a valid jwt.Token
tken, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
tken, err := jwt.ParseWithClaims(token, jwtConfig.Claims, func(t *jwt.Token) (interface{}, error) {
return []byte(config.ServiceJWTSecret.GetString()), nil
})
assert.NoError(t, err)
c.Set("user", tken)
c.Set(jwtConfig.ContextKey, tken)
}
func addLinkShareTokenToContext(t *testing.T, share *models.LinkSharing, c echo.Context) {
jwtConfig := auth.GetJWTConfig()
// Get the token as a string
token, err := auth.NewLinkShareJWTAuthtoken(share)
assert.NoError(t, err)
// We send the string token through the parsing function to get a valid jwt.Token
tken, err := jwt.Parse(token, func(t *jwt.Token) (interface{}, error) {
tken, err := jwt.ParseWithClaims(token, jwtConfig.Claims, func(t *jwt.Token) (interface{}, error) {
return []byte(config.ServiceJWTSecret.GetString()), nil
})
assert.NoError(t, err)
c.Set("user", tken)
c.Set(jwtConfig.ContextKey, tken)
}
func testRequestSetup(t *testing.T, method string, payload string, queryParams url.Values, urlParams map[string]string) (rec *httptest.ResponseRecorder, c echo.Context) {

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations
@ -19,6 +19,8 @@ package integrations
import (
"testing"
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/api/pkg/models"
"code.vikunja.io/web/handler"
"github.com/labstack/echo/v4"
@ -33,6 +35,20 @@ func TestBucket(t *testing.T) {
},
t: t,
}
testHandlerLinkShareWrite := webHandlerTest{
linkShare: &models.LinkSharing{
ID: 2,
Hash: "test2",
ListID: 2,
Right: models.RightWrite,
SharingType: models.SharingTypeWithoutPassword,
SharedByID: 1,
},
strFunc: func() handler.CObject {
return &models.Bucket{}
},
t: t,
}
t.Run("ReadAll", func(t *testing.T) {
t.Run("Normal", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(nil, map[string]string{"list": "1"})
@ -297,5 +313,15 @@ func TestBucket(t *testing.T) {
assert.Contains(t, rec.Body.String(), `"title":"Lorem Ipsum"`)
})
})
t.Run("Link Share", func(t *testing.T) {
rec, err := testHandlerLinkShareWrite.testCreateWithLinkShare(nil, map[string]string{"list": "2"}, `{"title":"Lorem Ipsum"}`)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `"title":"Lorem Ipsum"`)
db.AssertExists(t, "buckets", map[string]interface{}{
"list_id": 2,
"created_by_id": -2,
"title": "Lorem Ipsum",
}, false)
})
})
}

View File

@ -0,0 +1,60 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package integrations
import (
"net/http"
"testing"
"code.vikunja.io/api/pkg/models"
apiv1 "code.vikunja.io/api/pkg/routes/api/v1"
"github.com/stretchr/testify/assert"
)
func TestLinkSharingAuth(t *testing.T) {
t.Run("Without Password", func(t *testing.T) {
rec, err := newTestRequest(t, http.MethodPost, apiv1.AuthenticateLinkShare, ``, nil, map[string]string{"share": "test"})
assert.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
assert.Contains(t, rec.Body.String(), `"token":"`)
assert.Contains(t, rec.Body.String(), `"list_id":1`)
})
t.Run("Without Password, Password Provided", func(t *testing.T) {
rec, err := newTestRequest(t, http.MethodPost, apiv1.AuthenticateLinkShare, `{"password":"somethingsomething"}`, nil, map[string]string{"share": "test"})
assert.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
assert.Contains(t, rec.Body.String(), `"token":"`)
assert.Contains(t, rec.Body.String(), `"list_id":1`)
})
t.Run("With Password, No Password Provided", func(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.AuthenticateLinkShare, ``, nil, map[string]string{"share": "testWithPassword"})
assert.Error(t, err)
assertHandlerErrorCode(t, err, models.ErrCodeLinkSharePasswordRequired)
})
t.Run("With Password, Password Provided", func(t *testing.T) {
rec, err := newTestRequest(t, http.MethodPost, apiv1.AuthenticateLinkShare, `{"password":"1234"}`, nil, map[string]string{"share": "testWithPassword"})
assert.NoError(t, err)
assert.Equal(t, http.StatusOK, rec.Code)
assert.Contains(t, rec.Body.String(), `"token":"`)
assert.Contains(t, rec.Body.String(), `"list_id":1`)
})
t.Run("With Wrong Password", func(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.AuthenticateLinkShare, `{"password":"someWrongPassword"}`, nil, map[string]string{"share": "testWithPassword"})
assert.Error(t, err)
assertHandlerErrorCode(t, err, models.ErrCodeLinkSharePasswordInvalid)
})
}

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations
@ -553,7 +553,7 @@ func TestLinkSharing(t *testing.T) {
rec, err := testHandlerTaskWriteCollection.testReadAllWithLinkShare(nil, nil)
assert.NoError(t, err)
assert.NotContains(t, rec.Body.String(), `task #2`)
assert.NotContains(t, rec.Body.String(), `task #3`)
assert.NotContains(t, rec.Body.String(), `task #3"`)
assert.NotContains(t, rec.Body.String(), `task #4`)
assert.NotContains(t, rec.Body.String(), `task #5`)
assert.NotContains(t, rec.Body.String(), `task #6`)

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations
@ -30,12 +30,12 @@ func TestLogin(t *testing.T) {
rec, err := newTestRequest(t, http.MethodPost, apiv1.Login, `{
"username": "user1",
"password": "1234"
}`)
}`, nil, nil)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), "token")
})
t.Run("Empty payload", func(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.Login, `{}`)
_, err := newTestRequest(t, http.MethodPost, apiv1.Login, `{}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
})
@ -43,7 +43,7 @@ func TestLogin(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.Login, `{
"username": "userWichDoesNotExist",
"password": "1234"
}`)
}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeWrongUsernameOrPassword)
})
@ -51,7 +51,7 @@ func TestLogin(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.Login, `{
"username": "user1",
"password": "wrong"
}`)
}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeWrongUsernameOrPassword)
})
@ -59,7 +59,7 @@ func TestLogin(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.Login, `{
"username": "user5",
"password": "1234"
}`)
}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeEmailNotConfirmed)
})

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations
@ -31,12 +31,12 @@ func TestRegister(t *testing.T) {
"username": "newUser",
"password": "1234",
"email": "email@example.com"
}`)
}`, nil, nil)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `"username":"newUser"`)
})
t.Run("Empty payload", func(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.RegisterUser, `{}`)
_, err := newTestRequest(t, http.MethodPost, apiv1.RegisterUser, `{}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
})
@ -45,7 +45,7 @@ func TestRegister(t *testing.T) {
"username": "",
"password": "1234",
"email": "email@example.com"
}`)
}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
})
@ -54,7 +54,7 @@ func TestRegister(t *testing.T) {
"username": "newUser",
"password": "",
"email": "email@example.com"
}`)
}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
})
@ -63,7 +63,7 @@ func TestRegister(t *testing.T) {
"username": "newUser",
"password": "1234",
"email": ""
}`)
}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
})
@ -72,7 +72,7 @@ func TestRegister(t *testing.T) {
"username": "user1",
"password": "1234",
"email": "email@example.com"
}`)
}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrorCodeUsernameExists)
})
@ -81,7 +81,7 @@ func TestRegister(t *testing.T) {
"username": "newUser",
"password": "1234",
"email": "user1@example.com"
}`)
}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrorCodeUserEmailExists)
})

View File

@ -1,19 +1,18 @@
// Copyright 2018-2020 Vikunja and contriubtors. All rights reserved.
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This file is part of Vikunja.
//
// Vikunja is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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.
//
// Vikunja is distributed in the hope that it will be useful,
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// along with Vikunja. If not, see <https://www.gnu.org/licenses/>.
// 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 integrations
@ -114,49 +113,49 @@ func TestTaskCollection(t *testing.T) {
t.Run("by priority", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}}, urlParams)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
})
t.Run("by priority desc", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"desc"}}, urlParams)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `[{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":1`)
assert.Contains(t, rec.Body.String(), `[{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1`)
})
t.Run("by priority asc", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"asc"}}, urlParams)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
})
// should equal duedate asc
t.Run("by due_date", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}}, urlParams)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
})
t.Run("by duedate desc", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"desc"}}, urlParams)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
})
// Due date without unix suffix
t.Run("by duedate asc without suffix", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"asc"}}, urlParams)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
})
t.Run("by due_date without suffix", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}}, urlParams)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
})
t.Run("by duedate desc without suffix", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"desc"}}, urlParams)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
})
t.Run("by duedate asc", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"asc"}}, urlParams)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
})
t.Run("invalid sort parameter", func(t *testing.T) {
_, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"loremipsum"}}, urlParams)
@ -172,10 +171,10 @@ func TestTaskCollection(t *testing.T) {
// Invalid parameter should not sort at all
rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"loremipsum"}}, urlParams)
assert.NoError(t, err)
assert.NotContains(t, rec.Body.String(), `[{"id":3,"title":"task #3 high prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":100,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":4,"title":"task #4 low prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":1`)
assert.NotContains(t, rec.Body.String(), `{"id":4,"title":"task #4 low prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":1,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":3,"title":"task #3 high prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":100,"start_date":0,"end_date":0,"assignees":null,"labels":null,"created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}}]`)
assert.NotContains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"due_date":1543636724,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":6,"title":"task #6 lower due date"`)
assert.NotContains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"due_date":1543616724,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"due_date":1543636724,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":0,"end_date":0,"assignees":null,"labels":null,"created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}}]`)
assert.NotContains(t, rec.Body.String(), `[{"id":3,"title":"task #3 high prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":4,"title":"task #4 low prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":1`)
assert.NotContains(t, rec.Body.String(), `{"id":4,"title":"task #4 low prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":3,"title":"task #3 high prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":0,"end_date":0,"assignees":null,"labels":null,"created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}}]`)
assert.NotContains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"due_date":1543636724,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":6,"title":"task #6 lower due date"`)
assert.NotContains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"due_date":1543616724,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"due_date":1543636724,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":0,"end_date":0,"assignees":null,"labels":null,"created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}}]`)
})
})
t.Run("Filter", func(t *testing.T) {
@ -342,42 +341,42 @@ func TestTaskCollection(t *testing.T) {
t.Run("by priority", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}}, nil)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
})
t.Run("by priority desc", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"desc"}}, nil)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `[{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":1`)
assert.Contains(t, rec.Body.String(), `[{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1`)
})
t.Run("by priority asc", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"priority"}, "order_by": []string{"asc"}}, nil)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
assert.Contains(t, rec.Body.String(), `{"id":33,"title":"task #33 with percent done","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0.5,"identifier":"test1-17","index":17,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":1,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":4,"title":"task #4 low prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-4","index":4,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":3,"title":"task #3 high prio","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"0001-01-01T00:00:00Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-3","index":3,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
})
// should equal duedate asc
t.Run("by due_date", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}}, nil)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
})
t.Run("by duedate desc", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"desc"}}, nil)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
assert.Contains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":6,"title":"task #6 lower due date`)
})
t.Run("by duedate asc", func(t *testing.T) {
rec, err := testHandler.testReadAllWithUser(url.Values{"sort_by": []string{"due_date"}, "order_by": []string{"asc"}}, nil)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
assert.Contains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-11-30T22:25:24Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-6","index":6,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":3,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"done_at":"0001-01-01T00:00:00Z","due_date":"2018-12-01T03:58:44Z","reminder_dates":null,"list_id":1,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":"0001-01-01T00:00:00Z","end_date":"0001-01-01T00:00:00Z","assignees":null,"labels":null,"hex_color":"","percent_done":0,"identifier":"test1-5","index":5,"related_tasks":{},"attachments":null,"is_favorite":false,"created":"2018-12-01T01:12:04Z","updated":"2018-12-01T01:12:04Z","bucket_id":2,"position":0,"created_by":{"id":1,"name":"","username":"user1","created":"2018-12-01T15:13:12Z","updated":"2018-12-02T15:13:12Z"}}]`)
})
t.Run("invalid parameter", func(t *testing.T) {
// Invalid parameter should not sort at all
rec, err := testHandler.testReadAllWithUser(url.Values{"sort": []string{"loremipsum"}}, nil)
assert.NoError(t, err)
assert.NotContains(t, rec.Body.String(), `[{"id":3,"title":"task #3 high prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":100,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":4,"title":"task #4 low prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":1`)
assert.NotContains(t, rec.Body.String(), `{"id":4,"title":"task #4 low prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":1,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":3,"title":"task #3 high prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":100,"start_date":0,"end_date":0,"assignees":null,"labels":null,"created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}}]`)
assert.NotContains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"due_date":1543636724,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":6,"title":"task #6 lower due date"`)
assert.NotContains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"due_date":1543616724,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"due_date":1543636724,"reminder_dates":null,"repeat_after":0,"repeat_from_current_date":false,"priority":0,"start_date":0,"end_date":0,"assignees":null,"labels":null,"created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}}]`)
assert.NotContains(t, rec.Body.String(), `[{"id":3,"title":"task #3 high prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":4,"title":"task #4 low prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":1`)
assert.NotContains(t, rec.Body.String(), `{"id":4,"title":"task #4 low prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":1,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":3,"title":"task #3 high prio","description":"","done":false,"due_date":0,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":100,"start_date":0,"end_date":0,"assignees":null,"labels":null,"created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}}]`)
assert.NotContains(t, rec.Body.String(), `[{"id":5,"title":"task #5 higher due date","description":"","done":false,"due_date":1543636724,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":6,"title":"task #6 lower due date"`)
assert.NotContains(t, rec.Body.String(), `{"id":6,"title":"task #6 lower due date","description":"","done":false,"due_date":1543616724,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":0,"end_date":0,"assignees":null,"labels":null,"hex_color":"","created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}},{"id":5,"title":"task #5 higher due date","description":"","done":false,"due_date":1543636724,"reminder_dates":null,"repeat_after":0,"repeat_mode":0,"priority":0,"start_date":0,"end_date":0,"assignees":null,"labels":null,"created":1543626724,"updated":1543626724,"created_by":{"id":0,"name":"","username":"","email":"","created":0,"updated":0}}]`)
})
})
t.Run("Filter", func(t *testing.T) {

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations
@ -19,6 +19,8 @@ package integrations
import (
"testing"
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/api/pkg/models"
"code.vikunja.io/web/handler"
"github.com/labstack/echo/v4"
@ -33,6 +35,20 @@ func TestTaskComments(t *testing.T) {
},
t: t,
}
testHandlerLinkShareWrite := webHandlerTest{
linkShare: &models.LinkSharing{
ID: 2,
Hash: "test2",
ListID: 2,
Right: models.RightWrite,
SharingType: models.SharingTypeWithoutPassword,
SharedByID: 1,
},
strFunc: func() handler.CObject {
return &models.TaskComment{}
},
t: t,
}
// Only run specific nested tests:
// ^TestTaskComments$/^Update$/^Update_task_items$/^Removing_Assignees_null$
t.Run("Update", func(t *testing.T) {
@ -281,5 +297,15 @@ func TestTaskComments(t *testing.T) {
assert.Contains(t, rec.Body.String(), `"comment":"Lorem Ipsum"`)
})
})
t.Run("Link Share", func(t *testing.T) {
rec, err := testHandlerLinkShareWrite.testCreateWithLinkShare(nil, map[string]string{"task": "13"}, `{"comment":"Lorem Ipsum"}`)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `"comment":"Lorem Ipsum"`)
db.AssertExists(t, "task_comments", map[string]interface{}{
"task_id": 13,
"comment": "Lorem Ipsum",
"author_id": -2,
}, false)
})
})
}

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations
@ -19,6 +19,8 @@ package integrations
import (
"testing"
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/api/pkg/models"
"code.vikunja.io/web/handler"
"github.com/labstack/echo/v4"
@ -33,6 +35,20 @@ func TestTask(t *testing.T) {
},
t: t,
}
testHandlerLinkShareWrite := webHandlerTest{
linkShare: &models.LinkSharing{
ID: 2,
Hash: "test2",
ListID: 2,
Right: models.RightWrite,
SharingType: models.SharingTypeWithoutPassword,
SharedByID: 1,
},
strFunc: func() handler.CObject {
return &models.Task{}
},
t: t,
}
// Only run specific nested tests:
// ^TestTask$/^Update$/^Update_task_items$/^Removing_Assignees_null$
t.Run("Update", func(t *testing.T) {
@ -489,5 +505,15 @@ func TestTask(t *testing.T) {
assertHandlerErrorCode(t, err, models.ErrCodeBucketDoesNotExist)
})
})
t.Run("Link Share", func(t *testing.T) {
rec, err := testHandlerLinkShareWrite.testCreateWithLinkShare(nil, map[string]string{"list": "2"}, `{"title":"Lorem Ipsum"}`)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `"title":"Lorem Ipsum"`)
db.AssertExists(t, "tasks", map[string]interface{}{
"list_id": 2,
"title": "Lorem Ipsum",
"created_by_id": -2,
}, false)
})
})
}

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations
@ -28,23 +28,23 @@ import (
func TestUserConfirmEmail(t *testing.T) {
t.Run("Normal test", func(t *testing.T) {
rec, err := newTestRequest(t, http.MethodPost, apiv1.UserConfirmEmail, `{"token": "tiepiQueed8ahc7zeeFe1eveiy4Ein8osooxegiephauph2Ael"}`)
rec, err := newTestRequest(t, http.MethodPost, apiv1.UserConfirmEmail, `{"token": "tiepiQueed8ahc7zeeFe1eveiy4Ein8osooxegiephauph2Ael"}`, nil, nil)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `The email was confirmed successfully.`)
})
t.Run("Empty payload", func(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.UserConfirmEmail, `{}`)
_, err := newTestRequest(t, http.MethodPost, apiv1.UserConfirmEmail, `{}`, nil, nil)
assert.Error(t, err)
assert.Equal(t, http.StatusPreconditionFailed, err.(*echo.HTTPError).Code)
assertHandlerErrorCode(t, err, user.ErrCodeInvalidEmailConfirmToken)
})
t.Run("Empty token", func(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.UserConfirmEmail, `{"token": ""}`)
_, err := newTestRequest(t, http.MethodPost, apiv1.UserConfirmEmail, `{"token": ""}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeInvalidEmailConfirmToken)
})
t.Run("Invalid token", func(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.UserConfirmEmail, `{"token": "invalidToken"}`)
_, err := newTestRequest(t, http.MethodPost, apiv1.UserConfirmEmail, `{"token": "invalidToken"}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeInvalidEmailConfirmToken)
})

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations
@ -28,11 +28,7 @@ func TestUserList(t *testing.T) {
t.Run("Normal test", func(t *testing.T) {
rec, err := newTestRequestWithUser(t, http.MethodPost, apiv1.UserList, &testuser1, "", nil, nil)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `user1`)
assert.Contains(t, rec.Body.String(), `user2`)
assert.Contains(t, rec.Body.String(), `user3`)
assert.Contains(t, rec.Body.String(), `user4`)
assert.Contains(t, rec.Body.String(), `user5`)
assert.Equal(t, "null\n", rec.Body.String())
})
t.Run("Search for user3", func(t *testing.T) {
rec, err := newTestRequestWithUser(t, http.MethodPost, apiv1.UserList, &testuser1, "", map[string][]string{"s": {"user3"}}, nil)

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations
@ -28,22 +28,22 @@ import (
func TestUserRequestResetPasswordToken(t *testing.T) {
t.Run("Normal requesting a password reset token", func(t *testing.T) {
rec, err := newTestRequest(t, http.MethodPost, apiv1.UserRequestResetPasswordToken, `{"email": "user1@example.com"}`)
rec, err := newTestRequest(t, http.MethodPost, apiv1.UserRequestResetPasswordToken, `{"email": "user1@example.com"}`, nil, nil)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `Token was sent.`)
})
t.Run("Empty payload", func(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.UserRequestResetPasswordToken, `{}`)
_, err := newTestRequest(t, http.MethodPost, apiv1.UserRequestResetPasswordToken, `{}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
})
t.Run("Invalid email address", func(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.UserRequestResetPasswordToken, `{"email": "user1example.com"}`)
_, err := newTestRequest(t, http.MethodPost, apiv1.UserRequestResetPasswordToken, `{"email": "user1example.com"}`, nil, nil)
assert.Error(t, err)
assert.Equal(t, http.StatusBadRequest, err.(*echo.HTTPError).Code)
})
t.Run("No user with that email address", func(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.UserRequestResetPasswordToken, `{"email": "user1000@example.com"}`)
_, err := newTestRequest(t, http.MethodPost, apiv1.UserRequestResetPasswordToken, `{"email": "user1000@example.com"}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeUserDoesNotExist)
})

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations
@ -31,12 +31,12 @@ func TestUserPasswordReset(t *testing.T) {
rec, err := newTestRequest(t, http.MethodPost, apiv1.UserResetPassword, `{
"new_password": "1234",
"token": "passwordresettesttoken"
}`)
}`, nil, nil)
assert.NoError(t, err)
assert.Contains(t, rec.Body.String(), `The password was updated successfully.`)
})
t.Run("Empty payload", func(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.UserResetPassword, `{}`)
_, err := newTestRequest(t, http.MethodPost, apiv1.UserResetPassword, `{}`, nil, nil)
assert.Error(t, err)
assert.Equal(t, http.StatusBadRequest, err.(*echo.HTTPError).Code)
})
@ -44,7 +44,7 @@ func TestUserPasswordReset(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.UserResetPassword, `{
"new_password": "",
"token": "passwordresettesttoken"
}`)
}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeNoUsernamePassword)
})
@ -52,7 +52,7 @@ func TestUserPasswordReset(t *testing.T) {
_, err := newTestRequest(t, http.MethodPost, apiv1.UserResetPassword, `{
"new_password": "1234",
"token": "invalidtoken"
}`)
}`, nil, nil)
assert.Error(t, err)
assertHandlerErrorCode(t, err, user.ErrCodeInvalidPasswordResetToken)
})

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 integrations

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 log
@ -49,6 +49,7 @@ func InitLogger() {
config.LogDatabase.Set("off")
config.LogHTTP.Set("off")
config.LogEcho.Set("off")
config.LogEvents.Set("off")
return
}

View File

@ -0,0 +1,91 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package log
import (
"fmt"
"strings"
"time"
"code.vikunja.io/api/pkg/config"
"github.com/ThreeDotsLabs/watermill"
"github.com/op/go-logging"
)
const watermillFmt = `%{color}%{time:` + time.RFC3339Nano + `}: %{level}` + "\t" + `▶ [EVENTS] %{id:03x}%{color:reset} %{message}`
const watermillLogModule = `vikunja_events`
type WatermillLogger struct {
logger *logging.Logger
}
func NewWatermillLogger() *WatermillLogger {
lvl := strings.ToUpper(config.LogEventsLevel.GetString())
level, err := logging.LogLevel(lvl)
if err != nil {
Criticalf("Error setting events log level %s: %s", lvl, err.Error())
}
watermillLogger := &WatermillLogger{
logger: logging.MustGetLogger(watermillLogModule),
}
logBackend := logging.NewLogBackend(GetLogWriter("events"), "", 0)
backend := logging.NewBackendFormatter(logBackend, logging.MustStringFormatter(watermillFmt+"\n"))
backendLeveled := logging.AddModuleLevel(backend)
backendLeveled.SetLevel(level, watermillLogModule)
watermillLogger.logger.SetBackend(backendLeveled)
return watermillLogger
}
func concatFields(fields watermill.LogFields) string {
full := ""
for key, val := range fields {
full += fmt.Sprintf("%s=%v, ", key, val)
}
if full != "" {
full = full[:len(full)-2]
}
return full
}
func (w *WatermillLogger) Error(msg string, err error, fields watermill.LogFields) {
w.logger.Errorf("%s: %s, %s", msg, err, concatFields(fields))
}
func (w *WatermillLogger) Info(msg string, fields watermill.LogFields) {
w.logger.Infof("%s, %s", msg, concatFields(fields))
}
func (w *WatermillLogger) Debug(msg string, fields watermill.LogFields) {
w.logger.Debugf("%s, %s", msg, concatFields(fields))
}
func (w *WatermillLogger) Trace(msg string, fields watermill.LogFields) {
w.logger.Debugf("%s, %s", msg, concatFields(fields))
}
func (w *WatermillLogger) With(fields watermill.LogFields) watermill.LoggerAdapter {
return w
}

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 log
@ -44,7 +44,7 @@ func NewXormLogger(lvl string) *XormLogger {
}
level, err := logging.LogLevel(lvl)
if err != nil {
Critical("Error setting database log level: %s", err.Error())
Criticalf("Error setting database log level: %s", err.Error())
}
xormLogger := &XormLogger{

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 mail

View File

@ -1,35 +1,30 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 mail
import (
"bytes"
"html/template"
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/static"
"code.vikunja.io/api/pkg/utils"
"github.com/shurcooL/httpfs/html/vfstemplate"
"gopkg.in/gomail.v2"
)
// Opts holds infos for a mail
type Opts struct {
From string
To string
Subject string
Message string
@ -56,7 +51,7 @@ type header struct {
// SendTestMail sends a test mail to a receipient.
// It works without a queue.
func SendTestMail(to string) error {
func SendTestMail(opts *Opts) error {
if config.MailerHost.GetString() == "" {
log.Warning("Mailer seems to be not configured! Please see the config docs for more details.")
return nil
@ -69,19 +64,17 @@ func SendTestMail(to string) error {
}
defer s.Close()
m := gomail.NewMessage()
m.SetHeader("From", config.MailerFromEmail.GetString())
m.SetHeader("To", to)
m.SetHeader("Subject", "Test from Vikunja")
m.SetBody("text/plain", "This is a test mail! If you got this, Vikunja is correctly set up to send emails.")
m := sendMail(opts)
return gomail.Send(s, m)
}
// SendMail puts a mail in the queue
func SendMail(opts *Opts) {
func sendMail(opts *Opts) *gomail.Message {
m := gomail.NewMessage()
m.SetHeader("From", config.MailerFromEmail.GetString())
if opts.From == "" {
opts.From = config.MailerFromEmail.GetString()
}
m.SetHeader("From", opts.From)
m.SetHeader("To", opts.To)
m.SetHeader("Subject", opts.Subject)
for _, h := range opts.Headers {
@ -97,49 +90,16 @@ func SendMail(opts *Opts) {
m.SetBody("text/plain", opts.Message)
m.AddAlternative("text/html", opts.HTMLMessage)
}
return m
}
// SendMail puts a mail in the queue
func SendMail(opts *Opts) {
if isUnderTest {
sentMails = append(sentMails, opts)
return
}
m := sendMail(opts)
Queue <- m
}
// Template holds a pointer about a template
type Template struct {
Templates *template.Template
}
// SendMailWithTemplate parses a template and sends it via mail
func SendMailWithTemplate(to, subject, tpl string, data map[string]interface{}) {
var htmlContent bytes.Buffer
var plainContent bytes.Buffer
t, err := vfstemplate.ParseGlob(static.Templates, nil, "*.tmpl")
if err != nil {
log.Errorf("SendMailWithTemplate: ParseGlob: %v", err)
return
}
boundary := "np" + utils.MakeRandomString(13)
data["Boundary"] = boundary
data["FrontendURL"] = config.ServiceFrontendurl.GetString()
if err := t.ExecuteTemplate(&htmlContent, tpl+".html.tmpl", data); err != nil {
log.Errorf("ExecuteTemplate: %v", err)
return
}
if err := t.ExecuteTemplate(&plainContent, tpl+".plain.tmpl", data); err != nil {
log.Errorf("ExecuteTemplate: %v", err)
return
}
opts := &Opts{
To: to,
Subject: subject,
Message: plainContent.String(),
HTMLMessage: htmlContent.String(),
ContentType: ContentTypeMultipart,
Boundary: boundary,
}
SendMail(opts)
}

48
pkg/mail/testing.go Normal file
View File

@ -0,0 +1,48 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package mail
import (
"reflect"
"testing"
"github.com/stretchr/testify/assert"
)
var (
isUnderTest bool
sentMails []*Opts
)
// Fake stops any mails from being sent and instead allows for recording and querying them.
func Fake() {
isUnderTest = true
sentMails = nil
}
// AssertSent asserts if a mail has been sent
func AssertSent(t *testing.T, opts *Opts) {
var found bool
for _, testMail := range sentMails {
if reflect.DeepEqual(testMail, opts) {
found = true
break
}
}
assert.True(t, found, "Failed to assert mail '%v' has been sent.", opts)
}

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 metrics
@ -91,7 +91,7 @@ func SetUserActive(a web.Auth) (err error) {
// getActiveUsers returns the active users from redis
func getActiveUsers() (users activeUsersMap, err error) {
u, err := keyvalue.Get(ActiveUsersKey)
u, _, err := keyvalue.Get(ActiveUsersKey)
if err != nil {
return nil, err
}

View File

@ -1,26 +1,24 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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 metrics
import (
"code.vikunja.io/api/pkg/config"
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/modules/keyvalue"
e "code.vikunja.io/api/pkg/modules/keyvalue/error"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
@ -42,6 +40,18 @@ const (
TeamCountKey = `teamcount`
)
var registry *prometheus.Registry
func GetRegistry() *prometheus.Registry {
if registry == nil {
registry = prometheus.NewRegistry()
registry.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}))
registry.MustRegister(prometheus.NewGoCollector())
}
return registry
}
// InitMetrics Initializes the metrics
func InitMetrics() {
// init active users, sometimes we'll have garbage from previous runs in redis instead
@ -49,61 +59,79 @@ func InitMetrics() {
log.Fatalf("Could not set initial count for active users, error was %s", err)
}
GetRegistry()
// Register total list count metric
promauto.NewGaugeFunc(prometheus.GaugeOpts{
err := registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{
Name: "vikunja_list_count",
Help: "The number of lists on this instance",
}, func() float64 {
count, _ := GetCount(ListCountKey)
return float64(count)
})
}))
if err != nil {
log.Criticalf("Could not register metrics for %s: %s", ListCountKey, err)
}
// Register total user count metric
promauto.NewGaugeFunc(prometheus.GaugeOpts{
err = registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{
Name: "vikunja_user_count",
Help: "The total number of users on this instance",
}, func() float64 {
count, _ := GetCount(UserCountKey)
return float64(count)
})
}))
if err != nil {
log.Criticalf("Could not register metrics for %s: %s", UserCountKey, err)
}
// Register total Namespaces count metric
promauto.NewGaugeFunc(prometheus.GaugeOpts{
Name: "vikunja_namespcae_count",
err = registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{
Name: "vikunja_namespace_count",
Help: "The total number of namespaces on this instance",
}, func() float64 {
count, _ := GetCount(NamespaceCountKey)
return float64(count)
})
}))
if err != nil {
log.Criticalf("Could not register metrics for %s: %s", NamespaceCountKey, err)
}
// Register total Tasks count metric
promauto.NewGaugeFunc(prometheus.GaugeOpts{
err = registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{
Name: "vikunja_task_count",
Help: "The total number of tasks on this instance",
}, func() float64 {
count, _ := GetCount(TaskCountKey)
return float64(count)
})
}))
if err != nil {
log.Criticalf("Could not register metrics for %s: %s", TaskCountKey, err)
}
// Register total user count metric
promauto.NewGaugeFunc(prometheus.GaugeOpts{
err = registry.Register(promauto.NewGaugeFunc(prometheus.GaugeOpts{
Name: "vikunja_team_count",
Help: "The total number of teams on this instance",
}, func() float64 {
count, _ := GetCount(TeamCountKey)
return float64(count)
})
}))
if err != nil {
log.Criticalf("Could not register metrics for %s: %s", TeamCountKey, err)
}
}
// GetCount returns the current count from redis
func GetCount(key string) (count int64, err error) {
cnt, err := keyvalue.Get(key)
cnt, exists, err := keyvalue.Get(key)
if err != nil {
if e.IsErrValueNotFoundForKey(err) {
return 0, nil
}
return 0, err
}
if !exists {
return 0, nil
}
count = cnt.(int64)
return
@ -113,22 +141,3 @@ func GetCount(key string) (count int64, err error) {
func SetCount(count int64, key string) error {
return keyvalue.Put(key, count)
}
// UpdateCount updates a count with a given amount
func UpdateCount(update int64, key string) {
if !config.ServiceEnableMetrics.GetBool() {
return
}
if update > 0 {
err := keyvalue.IncrBy(key, update)
if err != nil {
log.Error(err.Error())
}
}
if update < 0 {
err := keyvalue.DecrBy(key, update)
if err != nil {
log.Error(err.Error())
}
}
}

View File

@ -1,17 +1,17 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2020 Vikunja and contributors. All rights reserved.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// 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 General Public License for more details.
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU General Public License
// 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

Some files were not shown because too many files have changed in this diff Show More