forked from vikunja/vikunja
Compare commits
236 Commits
master
...
93dee49b25
Author | SHA1 | Date | |
---|---|---|---|
93dee49b25 | |||
27891e4492 | |||
2fa6523cc1 | |||
2351194547 | |||
b7ec24ff52 | |||
aaac4c6dfc | |||
2e52cc1802 | |||
20ede346b4 | |||
b76ad8efe2 | |||
d695681a0e | |||
52c3075c3d | |||
e837c2a003 | |||
f670d394fa | |||
71cc7334cc | |||
fc1867ec70 | |||
d69482cda9 | |||
71d60e908a | |||
86b7d224ab | |||
9dc72c5c98 | |||
f052fc19fc | |||
06cc0a06e4 | |||
02dd7ee571 | |||
abc1fa2fed | |||
b5da7fc546 | |||
d715b02421 | |||
b7b69afa0c | |||
ce15ade6b8 | |||
0986ec6bdd | |||
8b56308a59 | |||
0f5f85e687 | |||
4ceeb877b1 | |||
4393320691 | |||
e4db9dfe6c | |||
4504499f60 | |||
43cb7f1fc2 | |||
30919fd4da | |||
5089049b17 | |||
6fc4e35ac4 | |||
6e263b6a91 | |||
7ff7b0d743 | |||
410a7426cf | |||
8d1cee4500 | |||
f429efc220 | |||
6e5a9868f5 | |||
2547de59ae | |||
b4d726f5a8 | |||
ad9749e37d | |||
967270b2c1 | |||
d07b284ee3 | |||
b3c604fd2f | |||
6a927c0703 | |||
126f3acdc8 | |||
8ddc00bd29 | |||
cb0df3ebbc | |||
325dcc5795 | |||
84291679cc | |||
b7d832891a | |||
b2bbb03e48 | |||
0b8173c1c3 | |||
9b7eef985e | |||
8a7baaed19 | |||
73f2d4532d | |||
bc782e68ff | |||
6c3488b8aa | |||
d7f3c653f9 | |||
e2aa916bdd | |||
398f05e9a0 | |||
be3184d49f | |||
81d021e872 | |||
d1b87d2705 | |||
7b29ac7128 | |||
7b7ccddf51 | |||
532855d850 | |||
ee436efba3 | |||
9d0dcb8d7d | |||
6fa95e6492 | |||
fc4eb8ceb9 | |||
87f7cbfa73 | |||
f8683796e8 | |||
5e048feedf | |||
67167d4abb | |||
156e50f371 | |||
cf2cfde4fc | |||
f78bb613e4 | |||
3a7678bfb9 | |||
466b2b676c | |||
89d0fbcc7c | |||
77e9a58a52 | |||
81665168bc | |||
6de3d8b3a1 | |||
3999580fe6 | |||
c71a1fea82 | |||
729cb3de38 | |||
4880a0265b | |||
2178166ece | |||
509f23c550 | |||
a22dd094c2 | |||
b6accd7c67 | |||
393a3bc37a | |||
b98ac9f551 | |||
8ab5289c3d | |||
32cf66e9d5 | |||
eb3a945678 | |||
3afedc25f0 | |||
4fc7d1f64f | |||
0c5c54a267 | |||
86a9d2e9f3 | |||
8b2b996e7a | |||
d8623fe185 | |||
c873c1ec32 | |||
0bd27ddeb7 | |||
aaeb89db4f | |||
2f1a3fea88 | |||
d9a57e7ef4 | |||
ddcf7624bd | |||
911e5b22ee | |||
bef22f5756 | |||
d8e10e1a58 | |||
83f003355d | |||
58492fffce | |||
268e344128 | |||
9cff4e33ca | |||
e7875ecb3b | |||
618b464ca3 | |||
448ac314b6 | |||
d6c6fcadc5 | |||
65f42b8bda | |||
ec7becd426 | |||
59092afbc0 | |||
480db6aa9b | |||
bb77df68f5 | |||
9ef17a6dbc | |||
37a4e1e658 | |||
02b6dbd07d | |||
61d76e6875 | |||
7debeaa9ff | |||
5d698f2ff8 | |||
7bb3f4c847 | |||
269e7dd5df | |||
8cfa2aa480 | |||
015ca310e9 | |||
9fe46f9a61 | |||
18b35e1119 | |||
b8ccfbd190 | |||
490ba2ea50 | |||
fb53322d40 | |||
55f9106c9e | |||
d600d8b5a6 | |||
0ab9ce9ec4 | |||
a71aa0c898 | |||
c4a71016b8 | |||
34ef1438d8 | |||
657dcc5313 | |||
2d283b78c2 | |||
6bdc1fdb0d | |||
d69c799197 | |||
2e88600c93 | |||
fe72f30b24 | |||
6945d8ba69 | |||
ef0035d4bd | |||
db77de3ae6 | |||
1c98fecbd9 | |||
343fa6ca0d | |||
aadfb8d8f2 | |||
2447f84e2b | |||
c1ad9d58f5 | |||
e16c5f72ca | |||
20af034d78 | |||
32c021e2b3 | |||
e9263f92d5 | |||
044a1a9161 | |||
10ba7b5b65 | |||
e9a340026d | |||
64441701fd | |||
df79173b22 | |||
4e137ed72d | |||
279c5f6b73 | |||
a840880692 | |||
4bb6842fb3 | |||
adf1172c39 | |||
f0af97e411 | |||
ea5dd87b12 | |||
ac23536c36 | |||
787044628f | |||
c842b70cb5 | |||
456af4d4a9 | |||
8c97f45cb7 | |||
b8312469d7 | |||
be7b53b9bc | |||
d6cb4f94f6 | |||
9baf6d39bd | |||
8d1a09b5a2 | |||
fa68e89c04 | |||
2d4e2e452c | |||
111efd5fae | |||
03e4bf30c2 | |||
18325e964d | |||
92bcce3f7c | |||
9508d0faee | |||
90817b6dae | |||
b2e4fde63a | |||
7dc2abb8e5 | |||
27c44d6d5e | |||
8a6f8922f8 | |||
b0d4902406 | |||
f15a8baee3 | |||
0bd2632d29 | |||
8d739b2cf9 | |||
ccfa019870 | |||
969e467f48 | |||
5281ca548b | |||
f5b5204776 | |||
25deb24849 | |||
d91c2e10b0 | |||
9f3d898150 | |||
a7c585e086 | |||
00ed5884b4 | |||
90ae940a6b | |||
e4de700a10 | |||
1e020c9c50 | |||
d1e7d5116a | |||
da064e9429 | |||
67faa26cbc | |||
b0b6d5926b | |||
22b626c9e0 | |||
eeb0006531 | |||
9db56f86ca | |||
c71265aafe | |||
24c8792150 | |||
2f69c6342a | |||
c99ed212da | |||
c8af41738c | |||
f3801843a4 | |||
08430f1951 | |||
80ce8f80ba | |||
9334b29366 |
210
.drone1.yml
210
.drone1.yml
|
@ -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
1
.github/FUNDING.yml
vendored
|
@ -1 +1,2 @@
|
|||
github: kolaente
|
||||
custom: https://www.buymeacoffee.com/kolaente
|
||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -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
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
|||
[submodule "docs/themes/vikunja"]
|
||||
path = docs/themes/vikunja
|
||||
url = ../theme.git
|
|
@ -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
17
.vscode/launch.json
vendored
Normal 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": []
|
||||
}
|
||||
]
|
||||
}
|
273
CHANGELOG.md
273
CHANGELOG.md
|
@ -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
|
||||
|
|
|
@ -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
143
LICENSE
|
@ -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>.
|
51
README.md
51
README.md
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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/>.
|
|
@ -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:
|
17
docker-manifest-latest.tmpl
Normal file
17
docker-manifest-latest.tmpl
Normal 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
|
|
@ -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:
|
||||
|
|
|
@ -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">}}).
|
||||
|
||||
|
|
195
docs/content/doc/development/events-and-listeners.md
Normal file
195
docs/content/doc/development/events-and-listeners.md
Normal 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{})
|
||||
```
|
|
@ -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`
|
||||
|
|
113
docs/content/doc/development/notifications.md
Normal file
113
docs/content/doc/development/notifications.md
Normal 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.
|
|
@ -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:"-"`
|
||||
|
|
|
@ -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>`
|
||||
|
||||
|
|
|
@ -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`:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
docs/themes/vikunja
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit 958219fc84db455ed58d7a4380bbffc8d04fd5cf
|
87
go.mod
87
go.mod
|
@ -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
|
||||
|
|
256
magefile.go
256
magefile.go
|
@ -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")
|
||||
|
|
8
main.go
8
main.go
|
@ -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
|
||||
|
|
21
nfpm.yaml
21
nfpm.yaml
|
@ -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
|
||||
|
|
|
@ -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 += `
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
},
|
||||
}
|
||||
|
|
|
@ -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
40
pkg/cron/cron.go
Normal 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()
|
||||
}
|
24
pkg/db/db.go
24
pkg/db/db.go
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
35
pkg/db/fixtures/subscriptions.yml
Normal file
35
pkg/db/fixtures/subscriptions.yml
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
112
pkg/events/events.go
Normal 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
36
pkg/events/listeners.go
Normal 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
49
pkg/events/testing.go
Normal 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.")
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
29
pkg/initialize/events.go
Normal 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"
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
60
pkg/integrations/link_sharing_auth_test.go
Normal file
60
pkg/integrations/link_sharing_auth_test.go
Normal 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)
|
||||
})
|
||||
}
|
|
@ -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`)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
91
pkg/log/watermill_logger.go
Normal file
91
pkg/log/watermill_logger.go
Normal 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
|
||||
}
|
|
@ -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{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
48
pkg/mail/testing.go
Normal 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)
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue
Block a user