Compare commits

..
724 Commits
Author SHA1 Message Date
kolaente 16ed5fd982 Release preparations 2020-05-19 17:27:37 +02:00
kolaente 24aa68f090 Don't return all tasks when a user has no lists 2020-05-19 17:23:49 +02:00
kolaente 91a3b7aba2 0.13 release preperations 2020-05-12 22:11:46 +02:00
kolaente 4137d4aed2 Fix creating new things with a link share auth 2020-05-12 15:51:48 +02:00
kolaente cb095d70df Add explanation to docs about cors 2020-05-12 11:10:07 +02:00
kolaente e43e601912 Add traefik 2 example configuration 2020-05-11 22:02:15 +02:00
kolaente 55cd40d175 Fix team rights not updating for namespace rights 2020-05-11 18:39:30 +02:00
renovateandkonrad 55cd74efca Update module go-testfixtures/testfixtures/v3 to v3.2.0 (#505)
Update module go-testfixtures/testfixtures/v3 to v3.2.0

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/505
2020-05-11 10:10:15 +00:00
renovateandkonrad a9d0079bf3 Update golang.org/x/crypto commit hash to 06a226f (#504)
Update golang.org/x/crypto commit hash to 06a226f

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/504
2020-05-11 09:02:23 +00:00
konradandkolaente 8ac158cdb4 Task Filter Fixes (#495)
Fix gocyclo

Fix misspell

Error codes docs

Filter fixes

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/495
2020-05-09 15:48:56 +00:00
renovateandkonrad def2362682 Update module spf13/viper to v1.7.0 (#494)
Update module spf13/viper to v1.7.0

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/494
2020-05-09 13:44:17 +00:00
kolaente 18f6e31b54 Fix parsing array style comparators by query param 2020-05-09 15:08:58 +02:00
kolaente 7e1d0a81bf Change totp secret datatype from varchar to text 2020-05-09 14:45:57 +02:00
renovateandkonrad f30e405229 Update module lib/pq to v1.5.2 (#491)
Update module lib/pq to v1.5.2

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/491
2020-05-08 13:23:26 +00:00
kolaente 563fe16bd4 Add checking and logging when trying to put a task into a nonexisting bucket 2020-05-07 10:20:10 +02:00
kolaente a30a358b73 Update theme 2020-05-06 21:03:15 +02:00
kolaente 497499e221 Fix reference to reverse proxies in docs 2020-05-06 21:02:58 +02:00
kolaente 1fdc51078e Add docs for changing frontend url 2020-05-06 20:44:48 +02:00
renovateandkonrad 60f343a926 Update module lib/pq to v1.5.1 (#485)
Update module lib/pq to v1.5.1

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/485
2020-05-05 08:59:08 +00:00
konradandkolaente fd3ccd6130 Fix total label count when getting all labels (#477)
Fix total label count when getting all labels

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/477
2020-05-03 21:28:36 +00:00
kolaente a97ce76f1f Fix bucket ID being reset with no need to do so 2020-05-03 22:25:48 +02:00
kolaente 83cf6e191c Fix not moving its bucket when moving a task between lists 2020-05-03 21:33:59 +02:00
kolaente f0ac6e89be Remove setting task bucket to 0 2020-05-03 21:24:28 +02:00
renovateandkonrad 23950c0602 Update module lib/pq to v1.5.0 (#476)
Update module lib/pq to v1.5.0

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/476
2020-05-03 18:14:57 +00:00
renovateandkonrad 19a05a7c2c Update golang.org/x/crypto commit hash to 4b2356b (#475)
Update golang.org/x/crypto commit hash to 4b2356b

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/475
2020-05-01 10:06:00 +00:00
renovateandkonrad 299e856736 Update module prometheus/client_golang to v1.6.0 (#463)
Update module prometheus/client_golang to v1.6.0

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/463
2020-04-28 18:50:58 +00:00
renovateandkonrad 6d95dc16c2 Update golang.org/x/crypto commit hash to 729f1e8 (#458)
Update golang.org/x/crypto commit hash to 729f1e8

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/458
2020-04-27 18:56:31 +00:00
kolaente fa28ddc2f7 Fix pagination count for task collection 2020-04-27 19:28:19 +02:00
kolaente 56dbb564ea Fix link share creation & creating admin link shares without admin rights 2020-04-27 12:51:09 +02:00
renovateandkonrad 711124f5c0 Update module go-testfixtures/testfixtures/v3 to v3.1.2 (#457)
Update module go-testfixtures/testfixtures/v3 to v3.1.2

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/457
2020-04-27 09:10:08 +00:00
kolaente 5606f987fa Add creating a new first bucket when creating a new list 2020-04-26 15:51:59 +02:00
kolaente f0cb3b5e36 Fix removing the last bucket 2020-04-26 00:57:47 +02:00
konradandkolaente 231dc3913f Add real buckets for tasks which don't have one (#446)
Add docs for error code

Add moving new tasks into the default bucket when none was provided

Add moving tasks in default bucket when deleting one

Fix tests again

Add test for removing a bucket

Fix tests

Prevent removing the last bucket

Remove the empty pseudo bucket

Add migration to create a new bucket for each list (and put all tasks in it

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/446
2020-04-25 20:32:02 +00:00
renovateandkonrad 2b1fc441e6 Update golang.org/x/crypto commit hash to 4bdfaf4 (#438)
Update golang.org/x/crypto commit hash to 4bdfaf4

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/438
2020-04-24 15:23:22 +00:00
e433289832 Task Position (#412)
Fix misspell

Fix sorting tasks with null values

Fix sorting by priority for postgres

Merge branch 'master' into feature/position

Add community link

Update golang.org/x/crypto commit hash to 44a6062 (#429)

Update golang.org/x/crypto commit hash to 44a6062

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/429

Update module lib/pq to v1.4.0 (#428)

Update module lib/pq to v1.4.0

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/428

Fix updating position

Add ordering tasks in buckets by position

Make task sort by string

Merge branch 'master' into feature/position

Update golang.org/x/crypto commit hash to 3c4aac8 (#419)

Update golang.org/x/crypto commit hash to 3c4aac8

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/419

Merge branch 'master' into feature/position

Fix moving tasks back into the empty (ID: 0) bucket

Add adding a default position when creating new tasks

Update golang.org/x/crypto commit hash to a76a400 (#411)

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

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/411

Remove unused code

Fix tests

Add migration for position attribute

Add position attribute

Co-authored-by: kolaente <k@knt.li>
Co-authored-by: renovate <renovatebot@kolaente.de>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/412
2020-04-24 15:23:03 +00:00
kolaente 86bdd1e386 Add community link 2020-04-24 13:00:29 +02:00
renovateandkonrad 4f1c0d99ea Update golang.org/x/crypto commit hash to 44a6062 (#429)
Update golang.org/x/crypto commit hash to 44a6062

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/429
2020-04-22 22:49:56 +00:00
renovateandkonrad f0792cfb0b Update module lib/pq to v1.4.0 (#428)
Update module lib/pq to v1.4.0

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/428
2020-04-22 10:16:38 +00:00
renovateandkonrad dece744685 Update golang.org/x/crypto commit hash to 3c4aac8 (#419)
Update golang.org/x/crypto commit hash to 3c4aac8

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/419
2020-04-21 07:41:16 +00:00
kolaente 68ab6d2e75 Fix moving tasks back into the empty (ID: 0) bucket 2020-04-20 23:08:38 +02:00
renovateandkonrad c69f0bf3cb Update golang.org/x/crypto commit hash to a76a400 (#411)
Update golang.org/x/crypto commit hash to a76a400

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/411
2020-04-20 20:58:32 +00:00
kolaente 59037e4eee Fix moving tasks in buckets 2020-04-20 18:08:20 +02:00
kolaente 1bd8348be7 Add categories to error docs 2020-04-19 14:33:51 +02:00
konradandkolaente ecdecdd94e Kanban (#393)
Fix tests

Add error docs

Add swagger docs for bucket endpoints

Add integration tests

Fix tests

Fix err shadow

Make sure a bucket and a task belong to the same list when adding or updating a task

Add tests

Add getting users of a bucket

Fix log level when testing

Fix lint

Add migration for buckets

Cleanup/Comments/Reorganization

Add Kanban bucket handling

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/393
2020-04-19 07:27:28 +00:00
konradandkolaente 28ec44c91f Add moving tasks between lists (#389)
Fix misspell

Add moving tasks between lists

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/389
2020-04-18 12:35:37 +00:00
kolaente 895d9613b5 Add endpoint to disable totp auth 2020-04-18 01:38:49 +02:00
kolaente 87d0c9088d Add endpoint to get the current users totp status 2020-04-18 00:22:59 +02:00
konradandkolaente 24904585a2 Add 2fa for authentification (#383)
Fix user tests

Add swagger docs

Fix lint

Add totp check when logging in

Make totp enrollment work

Add migration for totp table

go mod vendor

Add routes for totp routes

Add route handler for totp routes

Add basic implementation to enroll a user in totp

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/383
2020-04-17 19:25:35 +00:00
kolaente 1dca8e96a7 Add changing email for users 2020-04-17 16:01:45 +02:00
kolaente e1ab2095fa Update docs theme 2020-04-16 23:31:36 +02:00
renovateandkonrad 12e18de8ad Update golang.org/x/crypto commit hash to 0848c95 (#371)
Update golang.org/x/crypto commit hash to 0848c95

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/371
2020-04-15 06:48:46 +00:00
kolaente 025b00247d Fix replace statements for tail 2020-04-14 21:37:00 +02:00
kolaente 5832991c4d Fix tests after renaming json fields to snake_case 2020-04-13 23:27:55 +02:00
kolaente 81990f3f80 Update xorm redis cacher to use the xorm logger instead of a special seperate one 2020-04-13 23:18:33 +02:00
kolaente 368cbdf979 Fix gosec in drone 2020-04-13 23:04:59 +02:00
kolaente b8d7c97eb7 Add gosec static analysis 2020-04-13 22:30:09 +02:00
kolaente fb8ac92abf Change all json fields to snake_case 2020-04-12 22:48:46 +02:00
kolaente 0bfb3a4709 Add configuration options for log level 2020-04-12 22:32:21 +02:00
kolaente 9559a68416 Update module prometheus/client_golang to v1 2020-04-12 22:06:24 +02:00
konradandkolaente d28f005552 Update xorm to v1 (#323)
Fix limit for databases other than sqlite

go mod tidy && go mod vendor

Remove unneeded break statements

Make everything work with the new xorm version

Fix xorm logging

Fix lint

Fix redis init

Fix using id field

Fix database init for testing

Change default database log level

Add xorm logger

Use const for postgres

go mod tidy

Merge branch 'master' into update/xorm

# Conflicts:
#	go.mod
#	go.sum
#	vendor/modules.txt

go mod vendor

Fix loading fixtures for postgres

Go mod vendor1

Update xorm to version 1

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/323
2020-04-12 17:29:24 +00:00
renovateandkonrad 713560702b Update module go-redis/redis to v7 (#309)
Update module go-redis/redis to v7

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/309
2020-04-11 21:43:04 +00:00
konradandkolaente 0ba121fdfb Task filters (#243)
Fix not returning errors

Fix integration tests

Add more tests

Make task filtering actually work

Change tests

Fix using filter conditions

Fix test

Remove unused fields

Fix static check

Remove start and end date fields on task collection

Fix misspell

add filter logic when getting tasks

Add parsing filter query parameters into task filters

Start adding support for filters

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/243
2020-04-11 14:20:33 +00:00
kolaente 0e2449482f Fix dependencies 2020-04-09 23:06:57 +02:00
renovateandkonrad 8d1a3f4fd7 Update module spf13/viper to v1.6.3 (#291)
Update module spf13/viper to v1.6.3

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/291
2020-04-09 20:29:11 +00:00
renovateandkonrad 1e0f2dde6a Update module go-redis/redis to v6.15.7 (#290)
Update module go-redis/redis to v6.15.7

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/290
2020-04-09 20:28:58 +00:00
renovateandkonrad 7abac07837 Update src.techknowlogick.com/xgo commit hash to bb0faa3 (#279)
Update src.techknowlogick.com/xgo commit hash to bb0faa3

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/279
2020-04-09 04:36:03 +00:00
renovateandkonrad 15d718fb1a Update module go-redis/redis to v7 (#277)
Update module go-redis/redis to v7

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/277
2020-04-09 04:35:36 +00:00
renovateandkonrad 4ca3f714ea Update module stretchr/testify to v1.5.1 (#274)
Update module stretchr/testify to v1.5.1

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/274
2020-04-08 20:30:48 +00:00
renovateandkonrad 6d1b123a25 Update module spf13/cobra to v0.0.7 (#271)
Update module spf13/cobra to v0.0.7

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/271
2020-04-08 19:44:10 +00:00
renovateandkonrad 13ebb98644 Update module spf13/viper to v1.6.2 (#272)
Update module spf13/viper to v1.6.2

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/272
2020-04-08 18:43:35 +00:00
renovateandkonrad dda558fe1c Update module prometheus/client_golang to v0.9.4 (#245)
Update module prometheus/client_golang to v0.9.4

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/245
2020-04-07 20:42:06 +00:00
renovateandkonrad 76f19db6e7 Update module labstack/echo/v4 to v4.1.16 (#241)
Update module labstack/echo/v4 to v4.1.16

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/241
2020-04-07 18:59:53 +00:00
renovateandkonrad f776b799b8 Update module olekukonko/tablewriter to v0.0.4 (#240)
Update module olekukonko/tablewriter to v0.0.4

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/240
2020-04-07 16:58:27 +00:00
renovateandkonrad 746a443660 Update module imdario/mergo to v0.3.9 (#238)
Update module imdario/mergo to v0.3.9

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/238
2020-04-07 16:05:10 +00:00
renovateandkonrad 026d3dc80d Update module go-redis/redis to v6.15.7 (#234)
Update module go-redis/redis to v6.15.7

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/234
2020-04-07 12:31:33 +00:00
renovateandkonrad fd7dd47d5e Update github.com/gordonklaus/ineffassign commit hash to 7953dde (#233)
Update github.com/gordonklaus/ineffassign commit hash to 7953dde

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/233
2020-04-07 12:30:57 +00:00
renovateandkonrad 1e5a1b4892 Update github.com/shurcooL/httpfs commit hash to 8d4bc4b (#229)
Update github.com/shurcooL/httpfs commit hash to 8d4bc4b

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/229
2020-04-07 08:39:00 +00:00
renovateandkonrad c7f6748761 Update github.com/jgautheron/goconst commit hash to cda7ea3 (#228)
Update github.com/jgautheron/goconst commit hash to cda7ea3

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/228
2020-04-07 08:38:00 +00:00
renovateandkonrad 7efa0069cb Update golang.org/x/crypto commit hash to 056763e (#222)
Update golang.org/x/crypto commit hash to 056763e

Update golang.org/x/lint commit hash to 738671d (#223)

Update golang.org/x/lint commit hash to 738671d

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/223

Update src.techknowlogick.com/xgo commit hash to c43d4c4 (#224)

Update src.techknowlogick.com/xgo commit hash to c43d4c4

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/224

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/222
2020-04-07 08:37:20 +00:00
renovateandkonrad 424cf80e5c Update golang.org/x/lint commit hash to 738671d (#223)
Update golang.org/x/lint commit hash to 738671d

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/223
2020-04-07 07:29:05 +00:00
renovateandkonrad 1448d9de98 Update src.techknowlogick.com/xgo commit hash to c43d4c4 (#224)
Update src.techknowlogick.com/xgo commit hash to c43d4c4

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/224
2020-04-07 07:28:48 +00:00
renovateandkonrad cbf01e118a Update github.com/c2h5oh/datasize commit hash to 28bbd47 (#212)
Update github.com/c2h5oh/datasize commit hash to 28bbd47

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/212
2020-04-06 20:28:57 +00:00
renovateandkonrad 191942fcd1 Update alpine Docker tag to v3.11 (#160)
Update alpine Docker tag to v3.11

Add github token for renovate (#164)

Add github token for renovate

Add github token for renovate

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/164

Update Renovate Configuration (#161)

Add labels to renovate

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/161

Co-authored-by: konrad <konrad@kola-entertainments.de>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/160
2020-04-06 06:40:42 +00:00
konradandkolaente d5c8f2541d Add github token for renovate (#164)
Add github token for renovate

Add github token for renovate

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/164
2020-04-05 19:16:21 +00:00
konradandkolaente 6e9ad3d808 Update Renovate Configuration (#161)
Add labels to renovate

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/161
2020-04-05 17:24:06 +00:00
renovateandkonrad 36fdff5b8b Configure Renovate (#159)
Add renovate.json

Reviewed-on: https://kolaente.dev/vikunja/api/pulls/159
2020-04-05 15:11:27 +00:00
kolaente 8f4139f44a 0.12 Release Preparations 2020-04-04 22:29:32 +02:00
kolaente e7706a20dd Fix call to println
Signed-off-by: kolaente <k@knt.li>
2020-04-02 21:38:16 +02:00
kolaente 6d1018e647 Fix searching for config in home directories
Signed-off-by: kolaente <k@knt.li>
2020-04-02 21:13:42 +02:00
kolaente 11246b948f Fix getting the authenticated user with caldav
Signed-off-by: kolaente <k@knt.li>
2020-04-01 22:51:57 +02:00
konradandkolaente 7b619bd084 Colors for lists and namespaces (#155)
Add Hex Color properties migration

Add Hex Color properties

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/155
2020-03-22 21:09:32 +00:00
kolaente 35f05cbbec Show lists as archived if their namespace is archived
Signed-off-by: kolaente <k@knt.li>
2020-03-22 21:39:57 +01:00
kolaente 0a1887d6e7 Fix archiving namespaces
Signed-off-by: kolaente <k@knt.li>
2020-03-22 19:02:53 +01:00
kolaente c6d22bb1f8 Fix updating lists with an identifier
Signed-off-by: kolaente <k@knt.li>
2020-03-22 18:45:10 +01:00
kolaente 6132863f4a Fix getting archived lists and namespaces
Signed-off-by: kolaente <k@knt.li>
2020-03-22 18:24:54 +01:00
kolaente 26ffd2fd22 Fix getting one namespace
Signed-off-by: kolaente <k@knt.li>
2020-03-21 13:55:42 +01:00
51c74de1de expand relative path ~/.config/vikunja to $HOME/.config/vikunja **WINDOWS** (#147)
apply correct formatting

add quotes to make the yaml gods happy

log path of config file used by viper

resolve merge conflicts: windows compatible $HOME path

Prepare changelog & readme for 0.11 release

expand relative path ~/.config/vikunja to $HOME/.config/vikunja (#146)

update dependencies

expand relative path ~/.config/vikunja

Co-authored-by: Julian <juliangaal@protonmail.com>
Co-authored-by: konrad <konrad@kola-entertainments.de>

Co-authored-by: Julian Gaal <gjulian@uos.de>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/147
Reviewed-by: konrad <konrad@kola-entertainments.de>
2020-03-20 21:21:44 +00:00
konradandkolaente 5126330a10 Add support for archiving lists and namespaces (#152)
Add query param to get all lists including archived ones

Add query param to get all namespaces including archived ones

Fix getting lists by namespace only not archived lists

Fix misspell

Fix lint

Merge branch 'master' into feature/archive-lists-namespaces

Add docs for error codes

Fix archive error codes

Don't let archived lists show up in general lists

Fix updating description

Fix updating lists with link shares

More comments

Fix un-archiving lists

Move check for archiving a list to canWrite Check

Add more tests

Add more checks

Add checks for namespaces and lists

Add namespace edit

Add tests

Add migrations and filter

Add basic tests

Add is archived property to lists and namespaces

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/152
2020-03-15 21:50:39 +00:00
konradandkolaente 4472020ee9 Add workaround for timezones on windows (#151)
Add workaround for timezones on windows

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/151
2020-03-09 22:41:08 +00:00
kolaente 7de26a462f Add build time to compile flags 2020-03-02 20:24:26 +01:00
kolaente f2f17b11e8 Change release bucket 2020-03-01 22:51:50 +01:00
konradandkolaente cdd068cdb6 Add empty avatar provider (#149)
Fix lint

Add docs for avatar configuration

Add default avatar provider

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/149
2020-03-01 21:10:25 +00:00
konradandkolaente 584e3af237 Add proxying gravatar requests for user avatars (#148)
Fix getting avatar based on email

Remove avatarUrl from user struct

Fix staticcheck

Add default avatar size

Add config option for caching avatars

go mod vendor

Add swagger docs

Add proxying gravatar requests for user avatars

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/148
2020-03-01 20:30:37 +00:00
kolaente 7ddfa76a84 Prepare changelog & readme for 0.11 release 2020-03-01 17:32:38 +01:00
funkythingsandkonrad 1e03c39141 expand relative path ~/.config/vikunja to $HOME/.config/vikunja (#146)
update dependencies

expand relative path ~/.config/vikunja

Authored-by: Julian Gaal <gjulian@uos.de>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/146
Reviewed-by: konrad <konrad@kola-entertainments.de>
2020-02-29 19:51:47 +00:00
konradandkolaente 88bf8f3df0 Fix updating dates when marking a task as done (#145)
Fix lint

Fix reminders not being updated

Fix updating dates when marking a task as done

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/145
2020-02-26 21:09:45 +00:00
kolaente c551706b52 Make sure the author is returned when creating a new comment 2020-02-25 21:18:42 +01:00
konradandkolaente 1f039c4cda Task Comments (#138)
Add swagger docs

Add integration tests

Add tests

Add task comment test fixtures

Add config option to enable/disable task comments

Add custom error if a task comment does not exist

Fix lint

Add getting author when getting a single comment

Fix getting comments/comments author

Add rights check to ReadAll

+ actually get the comment author

Add migration and table definitions

Add routes

Add ReadOne method

Add basic crud rights

Signed-off-by: kolaente <k@knt.li>

Implement basic crudable functions for task comments

Signed-off-by: kolaente <k@knt.li>

Start adding task comments

Signed-off-by: kolaente <k@knt.li>
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/138
2020-02-19 21:57:56 +00:00
konradandkolaente 5901cf64b4 Fix inserting task structure with related tasks (#142)
Fix typo

Fix creating related tasks

Add better logging

Fix inserting task structure with related tasks

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/142
2020-02-18 22:00:54 +00:00
kolaente f87bb6d8ef Update theme 2020-02-18 18:47:19 +01:00
kolaente 021a715aff Fix frontend url for wunderlist migration in docs 2020-02-17 19:52:26 +01:00
konradandkolaente e95a6eeb11 Explicitly disable wunderlist migration by default (#141)
Fix wunderlist callback link in docs

Explicitly disable wunderlist migration by default

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/141
2020-02-17 17:29:17 +00:00
Dpvhandkonrad f46e9cb64e Fixed typo in docker-compose example (#140)
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/140
Reviewed-by: konrad <konrad@kola-entertainments.de>
2020-02-17 16:47:55 +00:00
ce5be947b4 Add postgres support (#135)
Revert fixture fixes for postgres

Use postgres connection string with spaces instead of url

Fix label order

Make postgres tests in ci less verbose

Add sequence update script

Skip resets in postgres

Remove option to skip resets in postgres

Make postgres tests in ci verboseq

Update test fixtures database

Fix file tests on postgres

Add postgres options to sample config

Make sure tests init test fixtures before running the actual tests

Fix issues with IDs too big to fit in an int

Fix duplicate auto incremented IDs

Refactor / Fix team tests

Refactor team member tests

Fix team member create

Fix label test

Fix getting labels

Fix test fixtures for postgresql

Fix connection string params

Disable ssl mode on postgres integration tests

Disable ssl mode on postgres tests

Use sprintf to create the connection string for postgresql

fixup! Add postgres support

Add postgres support

Added generate as a make dependency for make build

Clarify docs on building

Co-authored-by: kolaente <k@knt.li>
Co-authored-by: Jan Tojnar <jtojnar@gmail.com>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/135
2020-02-16 21:42:04 +00:00
kolaente 7e42724439 Added generate as a make dependency for make build
Clarify docs on building

Signed-off-by: kolaente <k@knt.li>
2020-02-15 11:35:24 +01:00
konradandkolaente caf91d1904 Update xorm to use the new import path (#133)
Fix ineffassign

Fix getting all labels including the ones not associated to a task

Signed-off-by: kolaente <k@knt.li>

Fix logging sql queries

Signed-off-by: kolaente <k@knt.li>

Start fixing getting all labels

Update xormigrate

Update xorm to use the new import path

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/133
2020-02-14 16:34:25 +00:00
shilchandkonrad 014ec2be69 Use relative url in .gitmodules (#132)
Use relative url in .gitmodules

Co-authored-by: Simon Hilchenbach <simon@hilchenba.ch>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/132
Reviewed-by: konrad <konrad@kola-entertainments.de>
2020-02-13 21:18:49 +00:00
kolaente 5d96c62a47 Fix time zone settings not working in Docker 2020-02-08 23:18:41 +01:00
kolaente 1c3b35fa6f Add more logging to web handler methods 2020-02-08 22:45:38 +01:00
kolaente d84a160054 Remove double user field 2020-02-08 22:12:06 +01:00
konradandkolaente db2d868eed Return iso dates for everything date related from the api (#130)
Remove traces of unix timestamp

Revert renaming reminder table column

Fix staticcheck

Remove unused table call

Add migration for renaming reminders table

Fix issues with using TimeStamp

Fix lint

Updated all created / updated fields to use TimeStamps

Add comments

Convert all created / updated fields to datetime

Add time util package

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/130
2020-02-08 12:48:49 +00:00
kolaente 1f99238019 Update copyright header 2020-02-07 17:27:45 +01:00
konradandkolaente f603b41d99 Better efficency for loading teams (#128)
Fix staticcheck

Better performance for getting teams on a namespace

Better performance for getting teams on a list

Fix lint

Fix swagger

Signed-off-by: kolaente <k@knt.li>

Make loading a single full team more efficent

Signed-off-by: kolaente <k@knt.li>

Make loading teams more efficent

Signed-off-by: kolaente <k@knt.li>

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/128
2020-01-27 17:28:17 +00:00
konradandkolaente 2abb858859 Add rate limit by ip for non-authenticated routes (#127)
Add rate limit by ip for non-authenticated routes

Signed-off-by: kolaente <k@knt.li>

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/127
2020-01-26 19:53:47 +00:00
konradandkolaente a464d1760c Add logging for invalid model errors (#126)
Add logging for invalid model errors

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/126
2020-01-26 19:40:23 +00:00
konradandkolaente fc65052ba0 Add config options for task attachments (#125)
Add config options for task attachments

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/125
2020-01-26 19:10:31 +00:00
konradandkolaente b2b1546a8f Add config options for cors handling (#124)
Add config options for cors handling

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/124
2020-01-26 19:09:54 +00:00
konradandkolaente 7e9446ea07 Refactor User and DB handling (#123)
fix copyright date

Add more user tests

More user tests

More user tests

Start refactoring user tests

Docs

Fix lint

Fix db fixtures init in tests

Fix models test

Fix loading fixtures

Fix ineffasign

Fix lint

Fix integration tests

Fix init of test engine creation

Fix user related tests

Better handling of creating test enging

Moved all fixtures to db package

Moved all fixtures to db package

Moved user related stuff to seperate package

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/123
2020-01-26 17:08:06 +00:00
konradandkolaente 8c33e24e92 Migration Improvements (#122)
Update swagger docs

Update docs

Let the wunderlist migrator use the registerRoutes function

Add migration status table

Add migration status

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/122
2020-01-20 19:48:46 +00:00
kolaente 0654ead831 Update version link in README 2020-01-19 22:27:19 +01:00
kolaente 2b80025cc0 Update changelog for v0.10 2020-01-19 22:25:38 +01:00
konradandkolaente 3081338a37 Use redis INCRBY and DECRBY when updating metrics values (#121)
Move test coverage processing to a seperate command

Use redis INCRBY and DECRBY when updating metrics values

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/121
2020-01-19 17:26:26 +00:00
konradandkolaente 9e39399689 Migration (#120)
Go mod tidy

[skip ci] Add modules/migration to docs

[skip ci] update date

fmt

Merge branch 'master' into feature/migration

# Conflicts:
#	pkg/routes/api/v1/info.go

Add docs on how to create a migrator

Add available migrators to /info endpoint

Return a message once everything was migrated successfully

Add swagger docs for wunderlist migration

Docs for migration [skip ci]

Fix due date fixture in migration test

Fix staticcheck

Fix lint

Logging and cleanup

Make the migrator work with real data

Add routes for migration

Fix misspell

Add method to store a full vikunja structure into vikunja

Add getting all data from wunderlist

Add attachment migration from wunderlist

Add done and done at to wunderlist migrator

Add todo

Add wunderlist auth url implementation

Fix lint

Finish wunderlist migration

Added all structs for the wunderlist migratior

Fix owner field being null for user shared namespaces (#119)

Update copyright year (#118)

Add option to disable registration (#117)

Added migrator interface

Co-authored-by: kolaente <k@knt.li>
Reviewed-on: https://kolaente.dev/vikunja/api/pulls/120
2020-01-19 16:52:16 +00:00
konrad 1d2cdf0fb8 Fix owner field being null for user shared namespaces (#119) 2020-01-09 19:24:08 +00:00
konrad a0c5e4e985 Update copyright year (#118) 2020-01-09 17:33:22 +00:00
konrad 402cef3c15 Add option to disable registration (#117) 2019-12-30 23:27:02 +00:00
kolaente b9f0ba84ab Add motd config option to docs 2019-12-25 17:27:10 +01:00
konrad 7cdc997191 Fix new tasks not getting a new task index (#116) 2019-12-08 15:10:34 +00:00
konrad 720df3cbed Add task identifier (#115) 2019-12-07 22:28:45 +00:00
konrad 1a47d7d80d Use utf8mb4 instead of plain utf8 (#114) 2019-12-07 20:14:13 +00:00
konrad 62e550bf35 Add user token renew (#113) 2019-12-07 19:52:04 +00:00
kolaente 10ab8ef4d9 Fix task collection tests 2019-12-07 17:21:37 +01:00
kolaente d483fe8beb Fix passing sort_by and order_by as query path arrays 2019-12-07 16:57:19 +01:00
kolaente 1555f04bd2 Fix sorting tasks by bool values
There was a bug where it would return all tasks with a true value before the ones with a false value. This is the exact opposite of what the db does, leading to wrongly sorted values
2019-12-07 16:56:18 +01:00
konrad d8399e374c Sort Order for tasks (#110) 2019-12-07 14:30:51 +00:00
shilchandkonrad e890001ee1 Consistent copyright text in file headers (#112) 2019-12-04 19:39:56 +00:00
shilchandkonrad 38653b49c7 Add tests for md5 generation (#111) 2019-12-04 19:19:38 +00:00
konrad 7e4deab8f7 Task collection improvements (#109) 2019-12-01 13:38:11 +00:00
konrad d96831fe3a Endpoint to get tasks on a list (#108) 2019-11-29 22:59:20 +00:00
kolaente 4c55b4455c update theme 2019-11-25 19:12:42 +01:00
kolaente b6308f783b Add files volume to docker compose docs 2019-11-25 19:08:24 +01:00
kolaente 843c1e5193 Update docs with a traefik configuration 2019-11-25 19:07:11 +01:00
kolaente 6045f4a426 Prepare changelog & readme for 0.9 release 2019-11-24 19:38:23 +01:00
kolaente 7be14239a3 [skip ci] Add changelog in repo 2019-11-24 19:33:16 +01:00
konrad 27ba31366c Fix default logging settings (#107) 2019-11-24 18:17:59 +00:00
kolaente 9dc419e854 Add file volume to the docker image 2019-11-24 18:36:43 +01:00
kolaente 37efd5cb49 Fixed removing reminders 2019-11-24 16:13:16 +01:00
kolaente dcec9511dc Fixed a bug where deleting an attachment would cause a nil panic 2019-11-19 23:07:48 +01:00
kolaente c203d73b33 Fixed a bug where adding assignees or reminders via an update would re-create them and not respect already inserted ones, leaving a lot of garbage 2019-11-03 23:08:26 +01:00
konrad 9be5ab248c Add endpoint to get a single task (#106) 2019-11-02 20:33:18 +00:00
kolaente ed4c17892e Fixed building docs theme 2019-10-30 21:53:57 +01:00
kolaente 886110a20a update docs theme 2019-10-30 21:47:16 +01:00
konrad 8948a5f219 Improve pagination (#105) 2019-10-23 21:11:40 +00:00
kolaente 89f385a53d Move from markdown lists to Vikunja for roadmap [skip ci] 2019-10-20 20:52:41 +02:00
kolaente 82f11c4ec2 Fixed not getting all labels when retrieving a list with all tasks 2019-10-20 17:56:53 +02:00
kolaente eb279fdba3 Refactored getting task IDs for labels 2019-10-20 17:55:54 +02:00
kolaente 48e422b379 [skip ci] Prepare the roadmap for migration 2019-10-20 17:54:32 +02:00
kolaente 854fde1e4c Fixed panic when using link share and metrics 2019-10-19 22:34:33 +02:00
kolaente b653278e42 Reverted telegram notification in CI "fix" 2019-10-19 18:18:39 +02:00
kolaente 35e4ab198f Fixed telegram notification in CI 2019-10-19 16:57:39 +02:00
kolaente b81cd6128a Fixed error when setting max file size on 32-Bit systems 2019-10-18 17:30:25 +02:00
konradandGitea 2169464983 Task Attachments (#104) 2019-10-16 20:52:29 +00:00
kolaente e2f481a6e5 Fixed migration for task relations 2019-10-13 11:44:56 +02:00
kolaente af1d1e1921 [skip ci] updated todo 2019-09-25 20:45:20 +02:00
konradandGitea 8fe33fd616 Task Relations (#103) 2019-09-25 18:44:41 +00:00
konradandGitea 1272255975 Added percent done to tasks (#102) 2019-09-21 10:52:10 +00:00
kolaente 1e2ec17343 [skip ci] update todo 2019-09-20 18:45:28 +02:00
konradandGitea 2f267f3f68 Moved teams_{namespace|list}_* to {namespace|list}_teams_* for better consistency (#101) 2019-09-20 16:39:02 +00:00
konradandGitea 694fc62495 Refactored getting all lists for a namespace (#100) 2019-09-20 16:16:31 +00:00
konradandGitea 8d5a2685c4 Fixed labels being displayed multiple times if they were associated with more than one task (#99) 2019-09-20 15:52:09 +00:00
konradandGitea 71ef86e0df Added more infos to a link share auth (#98) 2019-09-08 19:22:54 +00:00
konradandGitea 6140920cb8 Fixed rate limit panic when authenticatin with a link share auth token (#97) 2019-09-08 19:11:42 +00:00
konradandGitea fdd1624121 Small link share fixes (#96) 2019-09-07 13:19:23 +00:00
kolaente 158ad631e1 [skip ci] update todo 2019-09-05 22:48:51 +02:00
kolaente c126d2f55c [skip ci] update todo 2019-09-05 22:00:21 +02:00
kolaente 1d98e4cabe Fixed metrics on/off setting 2019-09-01 18:39:03 +02:00
kolaente 43676f045c Switched default logger to stdout instead of stderr 2019-09-01 18:23:35 +02:00
kolaente ba7db545fe Added extra depth to logging to correctly show the functions calling the logger in logs 2019-09-01 17:56:22 +02:00
kolaente 021ee48ec3 Made sure all tags are checked out when building in docker 2019-09-01 11:43:01 +02:00
kolaente a324921dce Updated Readme [skip ci] 2019-09-01 11:01:36 +02:00
konradandGitea 8d57923a7d Sharing of lists via public links (#94) 2019-08-31 20:56:41 +00:00
kolaente 88ea66798b [skip ci] updated todo 2019-08-27 22:51:27 +02:00
konradandGitea 66cdd79666 Refactor ListTask to Task (#92) 2019-08-14 20:19:04 +00:00
konradandGitea be14634e1e GetUser now returns a pointer (#93) 2019-08-14 19:59:31 +00:00
kolaente 8fbe721453 [skip ci] updated todo 2019-08-13 22:31:05 +02:00
kolaente 5d3e169883 [skip ci] update todo 2019-08-11 14:56:50 +02:00
kolaente 208eb4e68c Fixed swaggerdocs of description fields 2019-07-21 23:57:19 +02:00
kolaente 8d76280811 [skip ci] updated todo 2019-07-21 23:53:04 +02:00
kolaente 10fbbe1db6 Moved metrics init to seperate methods 2019-07-21 23:44:12 +02:00
konradandGitea 4327a559e5 feature/rate-limit (#91) 2019-07-21 21:27:30 +00:00
kolaente 2e599e792e [skip ci] update todo 2019-07-20 20:46:06 +02:00
konradandGitea 48826a6ed7 Logger refactoring (#90) 2019-07-20 18:12:10 +00:00
kolaente 15a0963bd1 [skip ci] update todo 2019-07-18 22:54:55 +02:00
konradandGitea 9a7d470ce2 Limit the test pipeline to run only on pull requests (#89) 2019-07-18 20:28:56 +00:00
konradandGitea ef0e7c9769 Use longtext instead of varchar(1000) on description fields (#88) 2019-07-18 19:56:34 +00:00
konradandGitea 12eaddc8ee Added http endpoint to list all users on a list (#87) 2019-07-18 16:38:21 +00:00
konradandGitea b63928850a Simplify structure by having less files (#86) 2019-07-16 14:15:40 +00:00
kolaente 4005cd2f32 [skip ci] Updated todo 2019-07-16 01:04:19 +02:00
kolaente 5cc89fd474 [skip ci] Updated todo 2019-07-16 00:56:25 +02:00
konradandGitea e2d9de191d /info endpoint (#85) 2019-07-15 22:54:38 +00:00
kolaente c3ea45d900 Removed rancher from drone config 2019-07-13 19:23:09 +02:00
konradandGitea 50ca8bd28e Statically compile templates in the final binary (#84) 2019-07-11 19:10:42 +00:00
konradandGitea 1f1a079fd3 Better config handling with constants (#83) 2019-07-06 20:12:26 +00:00
kolaente f1d21ea52b Use the auth methods to get IDs to avoid unneeded casts 2019-06-28 10:21:48 +02:00
kolaente fc3c5f2187 Updated the web handler with updated param binder 2019-06-28 09:13:17 +02:00
kolaente 5d3b6573ca Updated echo to use the latest version 2019-06-28 09:01:50 +02:00
konradandGitea 9930f98f8e Compress binaries after building them (#81) 2019-06-22 22:07:58 +00:00
konradandGitea 16825ba7c6 Update echo (#82) 2019-06-22 21:51:58 +00:00
kolaente 4e8c2a7bf6 Fixed avatar url when logging in 2019-06-06 12:28:08 +02:00
kolaente 7f5a6e338c [skip ci] updated todo 2019-06-06 12:13:15 +02:00
konrad 2763df20c9 [skip ci] updated todo 2019-06-05 22:25:55 +02:00
kolaente 9bc09ebbe5 Fixed user sharing not working 2019-06-04 19:45:09 +02:00
konradandGitea 6746984c97 Simplified the docker image (#80) 2019-06-02 14:37:10 +00:00
konradandGitea 7acf318b28 Fixed duedate spelling issue (#79) 2019-05-31 08:10:56 +00:00
konradandGitea f638fae4fd Add the md5-hashed user email to user objects for use with gravatar (#78) 2019-05-31 07:24:59 +00:00
konrad bd930bf654 [skip ci] rearrange todo 2019-05-30 22:32:24 +02:00
kolaente 2cdb0eed3e [skip ci] updated todo 2019-05-27 18:30:08 +02:00
konradandGitea 85d08e5697 Fixed check if the user really exists before updating/deleting its rights (#77) 2019-05-25 10:16:55 +00:00
kolaente 4c4eb76fed [skip ci] updated todo 2019-05-25 11:53:16 +02:00
konradandGitea 50d1f29125 Use the username instead of a user when adding a user to a team or giving it rights (#76) 2019-05-25 09:47:16 +00:00
kolaente 3fffcbd986 [skip ci] updated todo 2019-05-25 10:09:47 +02:00
konradandGitea 24ce940885 Put reminders in an extra table (#75) 2019-05-25 07:33:57 +00:00
konradandGitea 802a13cffd Added settings for max open/idle connections and max connection lifetime (#74) 2019-05-25 05:49:52 +00:00
kolaente 6b348fad04 Used one branch for both fixes in caldav-go 2019-05-24 20:01:59 +02:00
kolaente 951d92b2f0 Fixed ical-go package include 2019-05-24 19:45:58 +02:00
kolaente 24f06b2da5 Fixed ical-go package include 2019-05-24 19:45:33 +02:00
kolaente a7bbaf7c5f Fixed replace directive 2019-05-24 11:57:18 +02:00
konrad 3356a691f7 Removed drone debug env variables 2019-05-22 22:55:32 +02:00
konrad 7d46c88285 Fixed build 2019-05-22 20:36:11 +02:00
konradandGitea 7107d030fc Better caldav support (#73) 2019-05-22 17:48:48 +00:00
konrad de24fcc2f8 Fixed metrics endpoint not working 2019-05-12 16:49:16 +02:00
konrad 3d7fd9ca20 Updated libraries 2019-05-07 21:42:24 +02:00
konradandGitea 2b160b73c3 Fix tests (#72) 2019-04-30 18:36:39 +00:00
kolaente 24704bd4ed Added color field to tasks 2019-04-30 11:26:37 +02:00
konrad 733d0be753 [skip ci] Updated todo 2019-04-28 23:50:38 +02:00
konrad e40ab8652d [skip ci] Updated todo 2019-04-28 23:49:13 +02:00
konrad b854112704 [skip ci] Updated todo 2019-04-28 23:47:25 +02:00
konrad e2820e6806 Merge remote-tracking branch 'origin/master' 2019-04-27 11:41:40 +02:00
konrad a6e70f1b29 Fixed enabling go modules for cross-platform 2019-04-27 11:41:28 +02:00
konrad 44223bde77 Fixed enabling go modules for cross-platform 2019-04-27 11:24:47 +02:00
kolaente d404716342 Fixed integration tests 2019-04-24 22:58:20 +02:00
konrad 7e38937efc Fixed lint 2019-04-23 21:58:42 +02:00
konrad ed671baf8f Fixed listID not being returned in tasks 2019-04-23 21:53:37 +02:00
kolaente d4ff1eca80 Added dependencies 2019-04-23 10:34:28 +02:00
kolaente 6bab8fb769 Updated and re-enabled statickcheck 2019-04-23 10:34:06 +02:00
kolaente 07bdb08f9c Fixed darwin build 2019-04-22 14:31:46 +02:00
kolaente 1117b6eb47 Change path in drone 2019-04-22 14:20:25 +02:00
kolaente 10f80c190b Switched to techknowlogick/xgo 2019-04-22 14:02:18 +02:00
kolaente c8858f6cfb Fixed xgo docker image 2019-04-22 13:27:26 +02:00
kolaente dd1749f11f Disabled staticcheck until their memory leak is resolved 2019-04-22 13:04:16 +02:00
kolaente 99f83542f6 Updated staticcheck 2019-04-22 12:59:42 +02:00
kolaente 5dc1fd0f86 Switched to use src.techknowlogick.com/xgo 2019-04-21 23:07:33 +02:00
kolaente b1701ca769 Removed debugging 2019-04-21 23:04:46 +02:00
kolaente 5cfaa0f322 Debugging 2019-04-21 22:43:18 +02:00
kolaente 7b332808f9 Always fetch tags in drone when building 2019-04-21 22:39:35 +02:00
kolaente 228c47d79e removed unneded drone configs 2019-04-21 22:36:01 +02:00
kolaente 27339a7cf0 Debugging 2019-04-21 21:55:31 +02:00
kolaente 3adfb81d5e Debugging 2019-04-21 21:54:47 +02:00
konradandGitea 3872d1d8a7 Integration tests (#71) 2019-04-21 18:18:17 +00:00
kolaente 46efcb1005 updated version in readme 2019-04-05 17:00:02 +02:00
kolaente 0ed6c6cc0d updated version in readme 2019-04-05 16:54:41 +02:00
kolaente 93dbaea303 Fixed priority not updating when set to 0 2019-04-05 12:40:40 +02:00
kolaente 55e33c1694 [skip ci] updated todo 2019-04-05 12:16:57 +02:00
kolaente 2d9d27f63c Fixed getting lists by namespace 2019-04-02 10:53:16 +02:00
konradandGitea 87873e53c5 Fix rights checks (#70) 2019-04-01 19:48:48 +00:00
konradandGitea 19faee0102 Hide a users email everywhere (#69) 2019-04-01 18:19:55 +00:00
kolaente ac5446e4f5 [skip ci] update todo 2019-03-31 22:33:28 +02:00
kolaente a799527a3c [skip ci] update todo 2019-03-31 22:31:03 +02:00
konradandGitea 2b28ab12f1 Added docs for cli usage and adding new commands (#68) 2019-03-31 19:54:17 +00:00
konradandGitea be5a17e993 DB Migrations (#67) 2019-03-29 17:54:35 +00:00
kolaente e21471a193 Update web handler (fixed) 2019-03-29 18:29:44 +01:00
konrad 81f76f09ce Added docs redirect
Updated docs theme
2019-03-24 19:38:12 +01:00
konrad c27e8fe2f1 updated docs theme 2019-03-24 18:33:42 +01:00
konradandGitea 8d78e473f5 Added cli for general usage of Vikunja (#66) 2019-03-24 17:15:44 +00:00
konradandGitea 5525ee0328 Refactored canRead method to get the list before checking the right (#65) 2019-03-24 13:17:36 +00:00
konradandGitea 47352d3ed4 Let rights methods return errors (#64) 2019-03-24 12:35:50 +00:00
konradandGitea 11e7c071ce Updated handler config (#63) 2019-03-24 09:13:40 +00:00
konrad 1dc14d5ddf Fixed labels not being queried correctly on tasks 2019-03-22 22:03:41 +01:00
kolaente c42e22f352 Fixed bulk update label tasks 2019-03-21 19:26:04 +01:00
kolaente 72e64f7203 Fixed swagger docs for bulk label tasks 2019-03-21 18:42:21 +01:00
kolaente 25999d9b69 Fixed swagger docs for task labels 2019-03-21 07:40:56 +01:00
konradandGitea eb4d38b5b8 Fixed rights check on lists and namespaces (#62) 2019-03-08 21:31:37 +00:00
kolaente 65f428fe78 Updated swagger docs 2019-03-08 15:41:46 +01:00
konrad 2cc968ec61 [skip ci] updated todo 2019-03-07 21:25:54 +01:00
kolaente 073aa9940f [skip ci] update todo 2019-03-03 18:18:47 +01:00
kolaente 5506dd1ceb [skip ci] update todo 2019-03-03 17:43:25 +01:00
kolaente e47313b17e [skip ci] update todo 2019-03-03 15:33:14 +01:00
konrad 7cc172cc0c [skip ci] updated todo 2019-02-24 22:18:20 +01:00
konrad 2bcd6e9cb6 [skip ci] updated todo 2019-02-24 18:35:25 +01:00
konrad afd55d8cf8 [skip ci] updated todo 2019-02-24 12:06:20 +01:00
konrad caed219d39 [skip ci] Update todo 2019-02-23 21:05:10 +01:00
konradandGitea 1b84292332 Fix lint errs (#59) 2019-02-18 19:32:41 +00:00
konradandGitea 15ef6deabc Use query params to sort tasks instead of url params (#61) 2019-02-18 18:06:15 +00:00
konrad a06a5fc4f4 Updated readme and todo 2019-02-17 20:57:28 +01:00
konradandGitea 2d88fad5b1 Huge improvements for docs (#58) 2019-02-17 19:53:04 +00:00
konrad 5e7c9b9eb9 Added possible fix for logging when nothing is set 2019-01-25 21:09:24 +01:00
konradandGitea 9e635ea54e Improve logging handling (#57) 2019-01-25 11:40:54 +00:00
kolaente d0fa9ddaec Remove debugging 2019-01-23 14:33:44 +01:00
konrad add491d1e0 moar debugging 2019-01-22 22:35:00 +01:00
konrad e735378caf added debug + possible fix 2019-01-22 22:15:56 +01:00
konrad f95aa431b8 added debug + possible fix 2019-01-22 21:50:15 +01:00
kolaente 01e7540530 Fix makefile 2019-01-22 13:13:11 +01:00
konradandGitea 75431e1ca5 Rights performance improvements for lists and namespaces (#54) 2019-01-21 22:08:04 +00:00
konrad f6c7c764d1 Fix drone move step 2019-01-21 23:03:11 +01:00
konradandGitea eedc19a49e Build debian packages (#56) 2019-01-21 21:52:26 +00:00
konrad c07e2b6cd4 remove unused makefile variable 2019-01-20 18:43:38 +01:00
konradandGitea 08cbd18bc5 Added more config paths (#55) 2019-01-20 17:13:21 +00:00
konrad 8362799a93 Merge remote-tracking branch 'origin/master' 2019-01-20 00:56:42 +01:00
konrad 3edc728094 [skip ci] updated todo 2019-01-20 00:56:36 +01:00
konradandGitea d3975193fe Fix build building infinitly (#53) 2019-01-18 09:24:07 +00:00
konrad 6b00ccc942 updated todo with a shit ton of new features 2019-01-17 00:57:13 +01:00
konrad 7e8c2bb53b Fixed depend_on 2019-01-16 23:09:18 +01:00
konrad 20c4b249a4 Pipeline now uses two seperate configs to handle tags and pushes to master 2019-01-16 23:07:43 +01:00
konrad 0db5292f9f clone depth now uses the "good" format for drone 1 2019-01-15 23:07:39 +01:00
konrad 08e84f4e8d re-add automatic deploy 2019-01-14 23:53:53 +01:00
konrad a791fe0fa7 updated todo 2019-01-14 23:35:54 +01:00
konradandGitea 19218b28a2 Refactor {List|Namespace}{User|Team} to not expose unneded values via json (#52) 2019-01-14 22:32:56 +00:00
konrad cf0b0a2853 updated todo 2019-01-14 22:51:25 +01:00
konradandGitea 17fefae8bb Simplify list rights check (#50) 2019-01-14 21:49:50 +00:00
konrad 3d05d0aa45 fix dronefile lint 2019-01-14 20:51:30 +01:00
konrad cbcd12b5e5 remove debbugging 2019-01-14 20:48:02 +01:00
konrad 8fdb8b7840 fix debugging 2019-01-14 20:36:40 +01:00
konrad ed44478b20 remove debug step 2019-01-14 20:35:54 +01:00
konrad 0a092214c8 fix section 2019-01-14 18:47:00 +01:00
konrad 3ebf0da1b9 Added debugging for ci 2019-01-14 18:05:09 +01:00
konrad 07bc4f3f01 Added debugging for ci 2019-01-14 17:40:42 +01:00
kolaente cb58f55923 modify signing to sign zip and detach the signature 2019-01-13 01:07:10 +01:00
kolaente 7cc078aaec Fix sequence of drone builds 2019-01-13 00:25:02 +01:00
kolaente d20a899f92 fix sign step 2019-01-13 00:17:45 +01:00
kolaente 3cfe8c238a Add gpg sign step 2019-01-12 23:58:17 +01:00
kolaente 22495a66e0 Fixed minio folder definition 2019-01-12 00:03:41 +01:00
konradandGitea d5e68ee037 Update drone to version 1 (#49) 2019-01-11 22:46:51 +00:00
konradandGitea 318920fe29 Improve label handling (#48) 2019-01-09 23:08:12 +00:00
konradandGitea 364a172876 Assignees optimizations (#47) 2019-01-08 19:13:07 +00:00
kolaente 31c39388f1 Fixed the generated version by the makefile to be more verbose 2019-01-03 23:51:16 +01:00
kolaente 056e37331e [skip ci] Update todo 2019-01-03 23:35:53 +01:00
kolaente 09787fb29b [skip ci] Update todo 2019-01-03 23:31:29 +01:00
konradandGitea 607dbd6ae8 API Docs improvements (#46) 2019-01-03 22:22:06 +00:00
kolaente 3183d10dbe [skip ci] update readme and todo 2018-12-31 02:21:44 +01:00
konradandGitea 6b40df50d3 Add labels to tasks (#45) 2018-12-31 01:18:41 +00:00
konradandGitea d39007baa0 Task assignees (#44) 2018-12-29 14:29:50 +00:00
kolaente 37345e6bd3 update todo
update gitignore
2018-12-28 23:38:43 +01:00
konradandGitea 018dd8164c [CI] Add more checks (#43) 2018-12-28 22:15:05 +00:00
konradandGitea 3814b8a504 Add bulk edit for tasks (#42) 2018-12-28 21:49:46 +00:00
kolaente b050132f4f Update todo 2018-12-27 23:37:25 +01:00
kolaente 36eb580c8a Updated swagger docs 2018-12-25 21:45:26 +01:00
kolaente 067bb695b1 Updated todo 2018-12-25 21:29:55 +01:00
kolaente fd80094eca Updated todo 2018-12-25 21:29:16 +01:00
kolaente ce0bff8d9c Fixed a bug where updating a list would update it with the same values it had before 2018-12-25 15:30:11 +01:00
konradandGitea 5a93475be9 Get tasks between a date range (#41) 2018-12-22 18:06:14 +00:00
konradandGitea 784b890f70 Start end end dates for tasks (#40) 2018-12-22 15:45:16 +00:00
konradandGitea 7322bfafb3 Fix swaggerdocs generation to produce actually valid output (#39) 2018-12-21 21:30:43 +00:00
konrad 0edc5fd315 go mod tidy 2018-12-19 22:07:23 +01:00
konradandGitea cbc5995ad3 Various user fixes (#38) 2018-12-19 21:05:25 +00:00
konradandGitea 3e4f7fb2f4 Fix sorting of tasks in lists (#37) 2018-12-19 19:14:48 +00:00
kolaente 79b463d0af updated todo 2018-12-19 16:50:22 +01:00
konradandGitea 97febdb397 Tests can now use config files (#36) 2018-12-18 16:01:46 +00:00
kolaente 67e94f95b0 update todo 2018-12-18 15:35:20 +01:00
kolaente 34af627b66 updated todo 2018-12-18 10:38:00 +01:00
konradandGitea ec347a71bc Fix "unexpected EOF" error when using metrics (#35) 2018-12-17 12:22:06 +00:00
konradandGitea 777d63dff1 More unit tests (#34) 2018-12-16 13:21:32 +00:00
konrad 424dfe19af Only make all platform builds when pushing to master 2018-12-16 11:53:26 +01:00
kolaente 7b439cc568 Properly init tables for redis 2018-12-14 17:45:31 +01:00
konrad 553055f073 Fixed build 2018-12-13 16:09:00 +01:00
konrad 70f7f630a3 Update todo 2018-12-12 23:56:00 +01:00
konrad 82340cb70b cleanup 2018-12-12 23:53:20 +01:00
konrad 94fd2d758a cleanup 2018-12-12 23:51:40 +01:00
konradandGitea e047673c6b Add prometheus endpoint for getting metrics (#33) 2018-12-12 22:50:35 +00:00
konrad ee398b5272 Updated todo 2018-12-12 16:25:39 +01:00
konrad 3e8fd1e619 updated todo 2018-12-04 23:32:35 +01:00
konradandGitea 0c1d786ade Exlicitly get the pseudonamespace with all shared lists (#32) 2018-12-04 10:16:42 +00:00
kolaente f1fca3346b Merge branch 'master' of ssh://git.kolaente.de:9022/vikunja/api 2018-12-03 15:13:26 +01:00
kolaente 07d6e1219b updated todo 2018-12-03 15:13:21 +01:00
konrad 8e5ff72c4a fixed path to get all tasks (echo bug) 2018-12-02 19:31:03 +01:00
konrad fc17232819 Updated vendor 2018-12-02 19:30:42 +01:00
konrad 8aed78b296 update version in readme 2018-12-02 02:18:31 +01:00
konradandGitea cc6b35e314 Priorites for tasks (#31) 2018-12-02 00:49:30 +00:00
konradandGitea f2f881f505 Fixed generation of swagger docs (#30) 2018-12-01 02:04:10 +00:00
konradandGitea 6c5885747b Subtasks (#28) 2018-12-01 02:00:57 +00:00
konradandGitea 007d8ec375 Fixed generation of swagger docs (#29) 2018-12-01 01:59:17 +00:00
konrad 1b24cdf164 updated todo 2018-12-01 00:28:01 +01:00
konradandGitea ce2cae9430 Move the crudhandler to own repo (#27) 2018-11-30 23:26:56 +00:00
konrad d9304f6996 remove drone github update step 2018-11-28 22:53:55 +01:00
konrad d5e4195ee7 added drone config to update github mirror 2018-11-28 21:04:17 +01:00
konrad 136adb69c8 tidied mod 2018-11-28 20:50:06 +01:00
konradandGitea 06fc9f7886 Repeating tasks (#25) 2018-11-26 20:24:00 +00:00
konradandGitea 3f44e3b83e Change License to GPLv3 (#26) 2018-11-26 20:17:33 +00:00
konradandGitea b73786f7fe Make validation less verbose (#24) 2018-11-25 21:38:50 +00:00
kolaente e5c1588576 Fix docker build 2018-11-25 22:00:43 +01:00
konradandGitea d51ed8defd make validation less verbose (#23) 2018-11-24 12:44:40 +00:00
konradandGitea fded3c23d0 Multiple Reminders (#22) 2018-11-21 15:03:47 +00:00
konradandGitea af0ce5bb96 Added Shared lists overview in namespaces (#21) 2018-11-19 11:37:59 +00:00
konradandGitea 0c112a0ca3 Fixed Validation being to verbose (#20) 2018-11-17 00:12:26 +00:00
konrad 196b6728b8 updated readme 2018-11-17 00:29:10 +01:00
konrad 5bc23458de updated todo 2018-11-17 00:20:48 +01:00
konradandGitea 0c544fe355 Added validation for structs (#19) 2018-11-16 23:17:37 +00:00
konradandGitea 373bbd2202 Migrate to new swagger docs generation (#18) 2018-11-12 15:46:35 +00:00
konradandGitea d3de658882 Implemented search for everything (#17) 2018-11-09 17:33:06 +00:00
konrad ad74d24ee2 updated docs for pagination 2018-11-09 17:28:59 +01:00
konradandGitea d232836423 Added pagination (#16) 2018-11-09 10:30:17 +00:00
konrad 0e7e1b7e38 updated todo 2018-11-06 22:28:56 +00:00
konrad f976fd9f54 updated todo 2018-11-06 22:09:54 +00:00
konradandGitea d03fca801b CalDAV support (#15) 2018-11-03 15:05:45 +00:00
konradandGitea 31a4a1dd00 Added a route to get all tasks sorted desc by their due dates (#14) 2018-11-02 16:59:49 +00:00
konradandGitea 14207a0fa8 Fix tests in drone (#13) 2018-11-02 14:37:11 +00:00
konrad e906184bf7 updated version in readme 2018-11-02 15:29:01 +01:00
kolaente 1f41db9239 Hotfix: fix duplicate header in html mails with templates 2018-11-02 11:23:41 +01:00
konradandGitea 4f8a0f8739 Fixed no root path for templates and static assets (#12) 2018-11-02 10:01:28 +00:00
konradandGitea c51ca4dd26 Fixed dockerfile (#11) 2018-11-02 09:18:38 +00:00
konradandGitea 9e539b8c40 Fix checking for an email verification token (#10) 2018-11-01 22:59:20 +00:00
konradandGitea 9a5eb577b8 Fix not checking for user credentials upon login (#9) 2018-11-01 22:51:05 +00:00
konradandGitea 4713023a97 Prevent login from inactive (aka non-verified) users (#8) 2018-11-01 22:47:41 +00:00
konradandGitea 301a4eedda New structure (#7) 2018-10-31 12:42:38 +00:00
kolaente 3f9fad0e2a use go modules from vendor when building the docker image 2018-10-28 18:38:40 +01:00
kolaente 990740fc19 fixed fmt 2018-10-28 17:35:48 +01:00
kolaente 960d72aa1b Fixed tests 2018-10-28 17:30:10 +01:00
kolaente f94bbf023c Merge branch 'master' of ssh://git.kolaente.de:9022/vikunja/api 2018-10-28 17:24:13 +01:00
kolaente 2556ef7624 added vendor 2018-10-28 17:24:10 +01:00
konradandGitea 321c0f2404 Fix build when using go modules (#6) 2018-10-28 16:11:13 +00:00
konradandGitea 738c22b5f9 Add user email verification when registering (#5) 2018-10-27 13:14:55 +00:00
konradandGitea d0c30cb089 Password reset with token only (#4) 2018-10-27 13:12:15 +00:00
konradandGitea 0cfea682ea Add password reset (#3) 2018-10-27 09:33:28 +00:00
konrad 95197ec6ed moar featurecreep 2018-10-22 22:20:45 +02:00
konrad eecace511d updated todo 2018-10-21 22:22:56 +02:00
konrad 6793e13e6d updated todo 2018-10-21 22:21:37 +02:00
konrad 85da2d72aa updated todo 2018-10-21 22:19:51 +02:00
kolaente 206705d2e9 updated makefile to use new golint url 2018-10-15 12:54:39 +02:00
kolaente 522e647db0 Added config for database max connections 2018-10-11 18:39:53 +02:00
kolaente bbd90eb976 Fixed not setting http code on error 2018-10-11 18:18:44 +02:00
kolaente d8f6a628db Replaced CObject with a function returning an object 2018-10-11 17:53:59 +02:00
kolaente a612037ee1 added go mod 2018-10-11 13:28:41 +02:00
kolaente 224cebfd10 Fixed tests failing 2018-10-06 22:26:17 +02:00
kolaente f4ac036f27 removed unused errors 2018-10-06 18:55:14 +02:00
kolaente c626b05af6 Improved log error messages 2018-10-06 18:44:04 +02:00
kolaente 56dc781594 added docs for error codes 2018-10-06 18:32:33 +02:00
kolaente 1ddb819c31 updated docs 2018-10-06 15:47:26 +02:00
kolaente 75b611de48 updated docs 2018-10-06 15:41:57 +02:00
konrad c5100aad42 updated todo 2018-10-06 15:08:38 +02:00
konrad f969593c0a Improved error handling 2018-10-06 15:04:14 +02:00
konrad a4137b3d6f Added more checks to not leave an error unpassed when checking for rights 2018-10-06 13:25:37 +02:00
konrad 06638fccc8 Fixed lint & misspell 2018-10-06 13:07:42 +02:00
konrad a108ed689d Added extra function to get a list without tasks or user objects 2018-10-06 13:05:29 +02:00
kolaente 53a7f2e6a7 cleanup 2018-10-05 19:17:39 +02:00
kolaente 3819927dd2 updated todo 2018-10-05 19:16:31 +02:00
kolaente cca677878d Optimized used sql queries when getting lists or namespaces with lists 2018-10-05 19:16:14 +02:00
kolaente a1a77a9b75 improved logging format 2018-10-05 18:49:56 +02:00
kolaente 6ea4f0598c fmt 2018-10-05 18:46:05 +02:00
kolaente 358b569bf1 Addded indecies everywhere 2018-10-05 18:46:01 +02:00
kolaente 1139eee2ad Improved update password method to ask the current password 2018-10-04 07:53:45 +02:00
konrad a6d49a5e70 Fixed lint 2018-10-03 19:32:05 +02:00
kolaente cd4fca19fd updated swagger spec 2018-10-03 19:30:43 +02:00
konrad 85c9fba808 Added the ability to update a users password 2018-10-03 19:28:17 +02:00
konrad 17368dea9a Cleanup 2018-10-03 19:00:09 +02:00
konrad 43c67d8c29 added go report badge 2018-09-23 21:16:56 +02:00
konradandGitea e724aeb206 Added new checks (#2)
* added gocyclo-check
* Added new tests to drone
* Added new checks to makefile
2018-09-23 19:15:14 +00:00
konrad b912ff4176 updated drone config 2018-09-22 23:52:19 +02:00
konrad 849b64fc0c updated drone 2018-09-22 22:55:06 +02:00
konrad ce661f1c6e updated drone 2018-09-22 22:38:25 +02:00
konrad 06a4ede4a8 fmt 2018-09-22 11:06:39 +02:00
kolaente 6519c62ade fixed a bug where xorm treid to insert something with an id wich already exist 2018-09-21 08:41:28 +02:00
kolaente bfc783d1d0 updated swagger docs 2018-09-20 22:06:19 +02:00
kolaente e7d43567aa updated readme 2018-09-20 21:59:43 +02:00
kolaente 6c35db57c7 updated todo 2018-09-20 19:44:43 +02:00
kolaente 64d290bcae Added endpoint to search for users 2018-09-20 19:42:01 +02:00
kolaente 3401d7ab2c Fixed makefile 2018-09-20 07:36:58 +02:00
kolaente 8d27daccc6 Fixed lint & fmt 2018-09-20 07:31:36 +02:00
kolaente 0f60c607ee updated todo 2018-09-19 20:52:22 +02:00
kolaente 036a5fcefd updated todo 2018-09-19 08:45:45 +02:00
kolaente 5bb78a749e Fixed list update not working 2018-09-19 08:45:23 +02:00
kolaente aeff343a31 Fixed namespace update not working 2018-09-19 08:44:00 +02:00
kolaente e93cba7108 Added logging 2018-09-19 08:35:53 +02:00
kolaente 091711f4c5 Updated todo 2018-09-19 08:25:24 +02:00
kolaente 477db9ea1c Added swaggercheck to drone build 2018-09-19 08:24:50 +02:00
kolaente cbfb7eafa8 Updated swaggerdocs 2018-09-19 08:23:54 +02:00
kolaente 067672dcb4 Added an endpoint to update a team <-> namespace relation 2018-09-19 08:16:04 +02:00
kolaente aa40ab8eed Added an endpoint to update a team <-> list relation 2018-09-19 08:08:41 +02:00
kolaente 5e8597699d Added endpoint to update a user <-> namespace relation 2018-09-19 08:03:39 +02:00
kolaente 1e993f1e5c Fixed a bug where it was not possible to give a user access to a namespace 2018-09-19 08:03:05 +02:00
kolaente 4f538abc83 Added endpoint to update a users right for a list 2018-09-19 07:54:47 +02:00
kolaente 3a338f54f9 added try link to readme 2018-09-18 18:20:39 +02:00
kolaente 5fbf63bddc /namespaces/{namespaceID}/teams now also returns the team right 2018-09-18 08:17:18 +02:00
kolaente db54309df4 updated todo 2018-09-17 19:51:01 +02:00
kolaente f93a27d67d fmt 2018-09-17 19:46:31 +02:00
kolaente 30ce67c38f updated todo 2018-09-17 19:45:52 +02:00
kolaente 0a06e5a246 /lists/{listID}/teams now also returns the user right 2018-09-17 19:45:18 +02:00
kolaente cf6577445d /namepspaces/{namespacesID}/users now also returns the user right 2018-09-17 19:39:14 +02:00
kolaente b1564659c4 /lists/{listID}/users now also returns the user right 2018-09-17 19:36:44 +02:00
kolaente 59361df9b2 updated todo 2018-09-17 19:32:34 +02:00
kolaente dffb6dab7f updated todo 2018-09-17 19:26:34 +02:00
kolaente 1ea2f0a8c1 updated todo 2018-09-17 19:19:56 +02:00
kolaente 45c5d4fb82 updated todo 2018-09-17 18:45:54 +02:00
kolaente 96cafe0ad9 Moved swaggerdocs to /api/v1/swagger 2018-09-17 18:38:15 +02:00
kolaente 1d62b09792 Moved swaggerdocs to /api/v1/swagger 2018-09-17 18:34:46 +02:00
kolaente 24382f2dc0 Merge remote-tracking branch 'origin/master' 2018-09-17 18:25:17 +02:00
JonasFranzandGitea 26d37bbedf Add /user endpoint (#1) 2018-09-17 16:25:05 +00:00
kolaente 8ca8803404 Updated swaggerdocs 2018-09-17 08:22:31 +02:00
kolaente 42bd69321a Merge remote-tracking branch 'origin/master' 2018-09-17 07:48:03 +02:00
kolaente 382407e07f updated todo 2018-09-17 07:30:23 +02:00
kolaente 5a83ce1216 /namespaces now also gets lists 2018-09-17 07:27:49 +02:00
konrad 4c96ee4263 updated makefile 2018-09-15 16:11:28 +02:00
kolaente 3707f4d3c5 fmt 2018-09-13 22:14:53 +02:00
kolaente 382daac0dd when ID = 0 is passed to a 'GetSthByID'-function, it now returns a 'not exist' error 2018-09-13 20:07:11 +02:00
kolaente 716b06feff added new cache libraries 2018-09-13 19:53:39 +02:00
kolaente 416745ddab added options to configure cache 2018-09-13 19:53:03 +02:00
kolaente 23dc9f777e updated gitignore 2018-09-13 19:30:22 +02:00
kolaente 8cb85dc151 updated gitignore 2018-09-13 19:28:46 +02:00
kolaente fc136948d6 updated gitignore 2018-09-13 19:28:38 +02:00
kolaente 836b5812c0 Merge branch 'master' of ssh://git.kolaente.de:9022/vikunja/api 2018-09-13 19:27:29 +02:00
kolaente 7d8e3f1bae Updated tests 2018-09-13 19:24:40 +02:00
konrad 13145962a4 updated todo 2018-09-12 23:05:13 +02:00
konrad b47c19d46c Merge branch 'master' of ssh://git.kolaente.de:9022/vikunja/api 2018-09-12 22:59:53 +02:00
konrad 7c9818440a updated todo 2018-09-12 22:59:45 +02:00
kolaente c018589749 fixed lint + fmt 2018-09-12 21:45:30 +02:00
kolaente 1f3f8afa85 Fixed a bug where it was not possible for a user to see a namespace which could be access by a team the user was in 2018-09-12 20:13:00 +02:00
kolaente e85d3c4f36 Fixed a bug where a user didn't had access to lists which are not his own, but part of a namespace he owns 2018-09-12 19:56:07 +02:00
kolaente 65818d6f9e Added libs 2018-09-10 22:25:37 +02:00
kolaente 31a850c28e Fixed un-setting a task as done not working 2018-09-10 19:38:35 +02:00
kolaente 431564d63c When updating a list task, all relevant values are now updated. 2018-09-10 19:34:34 +02:00
kolaente 5b8cd30736 Added rancher deploy to drone 2018-09-10 19:24:17 +02:00
kolaente 0da1bb74e0 Fixed lint 2018-09-10 19:22:00 +02:00
kolaente 8ed1fb304e Fixed task update function not updating when marking a task as done 2018-09-10 07:59:45 +02:00
kolaente b91d9eb712 Fixed task update function to be able to update a task with minimal informaton 2018-09-10 07:41:39 +02:00
konrad b16c88a6f3 Added swaggerfiles do dockerfile 2018-09-08 16:54:21 +02:00
kolaente d48f3f9737 fixed crashing when no config was found 2018-09-08 16:43:37 +02:00
konrad 82c098aa0d Updated config to not hard fail when no config file is found. 2018-09-08 16:10:46 +02:00
kolaente 371dd52fa9 updated dockerimage 2018-09-08 16:10:06 +02:00
konrad f0b0319f54 [skip-ci] added s6config 2018-09-08 15:51:49 +02:00
konrad f920e336f0 [skip-ci] added s6config 2018-09-08 15:44:04 +02:00
konrad c834bc14d5 Moved dockerfile 2018-09-08 15:23:53 +02:00
konrad 8245c90bc1 Fixed dockerfile 2018-09-08 15:18:57 +02:00
konrad 9d83293590 Updated makefile 2018-09-08 15:18:15 +02:00
konrad e882fbe6ad Added dockerfile 2018-09-08 15:08:33 +02:00
konrad 6c7f8fd89a updated deps 2018-09-08 13:50:18 +02:00
konrad f47d4586c4 [skip-ci] updated docs 2018-09-08 13:50:05 +02:00
konrad 4d81a13ba5 Updated deps 2018-09-08 13:36:22 +02:00
konrad de10754cb8 Added missing viper dependencies 2018-09-08 13:33:04 +02:00
konrad f45c8aa0ce Fixed lint 2018-09-08 13:31:13 +02:00
konrad 427f752990 Vikunja now uses viper to handle config 2018-09-08 13:29:35 +02:00
kolaente 4f3e016751 Fixed CORS once and for all 2018-09-07 22:49:16 +02:00
kolaente 4749352bbd Fixed cors (Again...) 2018-09-07 08:43:23 +02:00
kolaente 21774fd447 updated todo 2018-09-07 08:24:15 +02:00
konrad 64639ab832 Added cors headers for /namespaces 2018-09-07 08:20:19 +02:00
konrad fc8c6c97fd Updated todo 2018-09-06 19:01:13 +02:00
konrad fb746714d0 Updated return status when creating 2018-09-06 18:57:28 +02:00
konrad c1767d219a Fixed getting all lists of a namespace not working 2018-09-06 18:55:58 +02:00
kolaente 37de3ef232 Fixed user_namespace relation not working 2018-09-06 18:52:10 +02:00
kolaente 6d971c5fe1 fmt 2018-09-06 08:46:47 +02:00
kolaente c43db9929b Namespaces now respect user rights 2018-09-06 08:46:34 +02:00
konrad 521e7c3bef List rights are now respected 2018-09-06 08:42:18 +02:00
konrad 92174aac08 Fixed a bug where a user could see every namespace 2018-09-06 08:39:05 +02:00
konrad f2758e239c Added namespace user rights 2018-09-04 20:15:24 +02:00
konrad 422662e3e1 updated featurecreep 2018-09-04 19:54:15 +02:00
konrad 245259216f Fixed creating of new users 2018-09-04 19:39:31 +02:00
konrad 906aee8b7d Updated featurecreep 2018-08-30 19:18:36 +02:00
konrad 76f3357a0c fmt 2018-08-30 19:14:16 +02:00
konrad 478c98fb8d Refactor GetUser & GetUserByID 2018-08-30 19:14:02 +02:00
konrad aeb1521cc4 Cleanup/fixing methods 2018-08-30 19:00:27 +02:00
konrad efaa277751 Added methods to revoke a users access to a list 2018-08-30 18:52:12 +02:00
konrad b1c3e92f66 Added methods to give users access to a list 2018-08-30 08:58:09 +02:00
konrad d31f16aff1 Renamed list items to tasks 2018-08-30 08:09:17 +02:00
konrad d5758e0444 fmt 2018-08-29 15:22:17 +02:00
konrad c17dec7954 Updated swagger docs 2018-08-29 15:13:54 +02:00
konrad 4e70486a9b Cleanup 2018-08-29 14:40:03 +02:00
konrad bdff353e78 Added tests for team <-> list relations 2018-08-29 14:33:04 +02:00
konrad 98e3d3e884 Added tests for team <-> list relations 2018-08-29 08:50:52 +02:00
konrad 950533df21 Added tests for team namespace relationsk 2018-08-29 08:26:59 +02:00
kolaente f71f98b8f4 updated featurecreep 2018-08-29 08:02:12 +02:00
kolaente 5db306bacc fmt 2018-07-27 19:28:12 +02:00
kolaente 261136c2bc Added tests for team members 2018-07-27 19:20:49 +02:00
kolaente d556162591 fmt 2018-07-27 16:28:28 +02:00
kolaente 51064f3d8f Added tests for teams 2018-07-27 16:28:09 +02:00
kolaente a55e28df76 updated todo 2018-07-27 15:57:47 +02:00
kolaente 62ac4c2a74 fmt 2018-07-27 15:53:01 +02:00
kolaente 628f3eee64 Added tests for namespaces 2018-07-27 15:52:50 +02:00
kolaente ba606515d1 Improved tests for lists 2018-07-27 15:11:47 +02:00
kolaente f7bc88c825 Added tests for listitems 2018-07-27 14:47:52 +02:00
kolaente 2c12797111 fmt 2018-07-26 10:50:03 +02:00
kolaente c97a4d74cb Added check if the namespace exists when creating a list 2018-07-26 10:49:33 +02:00
kolaente 6eeab7fe10 improved tests 2018-07-26 10:49:17 +02:00
kolaente a78b333e3f Added tests for list creation 2018-07-26 10:29:19 +02:00
kolaente 935aef8a38 Added check for list title when creating a new list 2018-07-26 10:29:09 +02:00
kolaente a9094506fa cleanup 2018-07-26 10:10:39 +02:00
kolaente 7b07137b67 fmt 2018-07-26 10:08:01 +02:00
kolaente fba505130d updated gitignore 2018-07-26 10:07:18 +02:00
kolaente 80e9021ba6 Fixed a bug where it was possible to add the same user multiple times to a team 2018-07-26 10:06:41 +02:00
konrad 9c451daf30 Added method to delete a user from a team 2018-07-26 09:58:48 +02:00
konrad bc580e0115 Added method to add a user to a team 2018-07-26 09:53:32 +02:00
kolaente 0b2f66965a [skip-ci] updated todo 2018-07-25 23:03:53 +02:00
kolaente 4baf74a999 Added http test files 2018-07-25 22:26:53 +02:00
kolaente 29e3afdd08 Added roadmap 2018-07-25 21:47:26 +02:00
kolaente 5b0788ed1e renamed build steps 2018-07-25 17:43:38 +02:00
kolaente 8f2a24298d fixed makefile
+ lint & fmt
2018-07-25 17:30:29 +02:00
kolaente 32b369e2e4 Added drone 2018-07-25 17:28:54 +02:00
kolaente 01aa1910ef Renamed all packages 2018-07-25 16:26:32 +02:00
kolaente 0df8881028 Renamed all packages 2018-07-25 16:24:46 +02:00
kolaente d18570574a updated todo 2018-07-25 00:51:23 +02:00
kolaente e602914659 Implemented proper check for team rights on namespaces 2018-07-25 00:49:44 +02:00
kolaente f36eeb662a Implemented proper check for team rights on lists 2018-07-25 00:40:24 +02:00
konrad 7dc8699cbd updated todo
+ fmt
2018-07-24 17:47:08 +02:00
kolaente 26c2ad078f Fixed a bug where it was possible to add a team multiple times to a list/namespace 2018-07-24 17:46:32 +02:00
kolaente 9638f36788 implemented deletomg a team from a list 2018-07-24 17:32:08 +02:00
kolaente 227a2afd37 implemented viewing all teams of a list 2018-07-24 17:29:46 +02:00
kolaente edf9b6f2c7 Implemented creating a team <-> list relation 2018-07-24 17:29:13 +02:00
konrad 6ff10e6353 added missing libraries 2018-07-24 14:06:03 +02:00
kolaente 9de26f6547 cleanup 2018-07-24 13:56:57 +02:00
kolaente 9c0c9474e8 Migrated to dep instead of govendor 2018-07-24 13:49:45 +02:00
konrad 0a2eae120e More docs 2018-07-24 00:48:02 +02:00
konrad 7e0965ed91 docs 2018-07-21 15:45:46 +02:00
konrad 0487889963 fmt + lint + docs 2018-07-21 15:28:09 +02:00
konrad 9979b7e321 implemented update method via param binder 2018-07-21 15:17:02 +02:00
konrad 9e75e9b73b implemented readone with parambinder 2018-07-21 15:08:46 +02:00
konrad d06ed68125 cleanup 2018-07-18 22:19:51 +02:00
konrad 935c99be45 implemented read all method for namespace teams 2018-07-18 22:06:29 +02:00
konrad 6618874441 Fixed parambinder 2018-07-18 21:54:04 +02:00
konrad de95ff40bf implemented creation of thing via parambinder 2018-07-18 08:56:19 +02:00
konrad ebb5b332b6 implemented delete team <-> namespace relation 2018-07-18 08:16:15 +02:00
konrad 249128a46e implemented binding url params directly to struct instead of passing them to the method for deleting items 2018-07-18 08:15:38 +02:00
konrad f0c003d069 implemented custom param binder
This is currently more a workaround, until the echo pr gets merged
2018-07-17 23:10:54 +02:00
kolaente 1a7779a229 Merge branch 'master' of ssh://git.kolaente.de:9022/vikunja/api 2018-07-17 09:10:45 +02:00
konrad 7feb82702d implemented create team <-> namespace relation 2018-07-17 08:44:21 +02:00
konrad 2e3c10be13 updated todo + cleanup 2018-07-17 08:16:04 +02:00
konrad 0439bade41 updated todo 2018-07-16 22:17:35 +02:00
kolaente a46901397b Merge remote-tracking branch 'real-origin/master' 2018-07-16 09:16:21 +02:00
konrad f6a816941b implemented get all teams the user is part of 2018-07-16 08:52:16 +02:00
konrad b11bd9f0b1 fixed lint 2018-07-16 08:45:38 +02:00
konrad 7dc4cd2173 Implemented Get one team method 2018-07-16 08:43:47 +02:00
konrad 8a06db5351 Implemented team delete method 2018-07-16 08:18:15 +02:00
kolaente 90da51ad7e Updated sample config 2018-07-15 18:31:43 +02:00
konrad 4cf0cd233c Implemented team update method 2018-07-14 18:29:24 +02:00
konrad bcbd415529 Fixed a bug where a struct would have old values in it 2018-07-14 17:46:01 +02:00
konrad a5552b8f9d fixed lint + fmt 2018-07-14 17:37:46 +02:00
konrad bc0e6da602 cleanup 2018-07-14 17:36:17 +02:00
konrad e1c58843e9 implemented team create method 2018-07-14 17:34:59 +02:00
konrad 376c649a12 cleanup 2018-07-12 23:47:50 +02:00
konrad bb44b2f98c fmt 2018-07-12 23:37:14 +02:00
konrad 7f7b243cbe cleanup 2018-07-12 23:36:55 +02:00
konrad c5888093fe Implemented deletion of namespaces 2018-07-12 23:33:37 +02:00
konrad 55c02bc973 Fixed CanDelete 2018-07-12 23:33:21 +02:00
konrad b24b245f4d Fixed creation of new namespaces 2018-07-12 23:22:02 +02:00
konrad e5493965ff Fixed creation of new lists 2018-07-12 23:18:50 +02:00
konrad ddcc063b0b Implemented CanCreate method 2018-07-12 23:16:32 +02:00
konrad 6fd2a97574 Implemented CanUpdate method 2018-07-12 23:07:03 +02:00
konrad e3b996c383 Cleanup 2018-07-12 22:42:41 +02:00
konrad 4e503072a8 Implemented CanDelete method for lists and listitems 2018-07-12 21:20:24 +02:00
konrad 217208274e cleanup 2018-07-12 21:10:58 +02:00
konrad 32fde286db Optimized right checking
+ list.ReadAll now really gets all lists
2018-07-12 21:07:59 +02:00
konrad bae9c7f35e Added right check for namespaces 2018-07-12 13:43:42 +02:00
konrad fb4fa25f2f fmt 2018-07-12 11:55:07 +02:00
konrad 868b93dbbc implemented get one namespace via interface mthod 2018-07-12 11:54:55 +02:00
konrad 6f5cf55e42 fmt + lint 2018-07-12 00:37:31 +02:00
konrad 4ae95c1333 Updated featurecreep 2018-07-12 00:36:38 +02:00
konrad 261aaba315 implemented namespace update via interface method 2018-07-12 00:30:31 +02:00
konrad 0aa84e653f implemented namespace creation via interface method 2018-07-12 00:09:16 +02:00
konrad 4734a0a6a6 use echo.NewHTTPError 2018-07-11 14:27:16 +02:00
konrad 4213f3b08c implemented get all namespaces via interface 2018-07-11 13:00:00 +02:00
konrad 5c4fb7ed73 implemented delete list item via CRUD 2018-07-11 11:44:17 +02:00
konrad 281e9c1cd0 fmt 2018-07-11 02:40:29 +02:00
konrad ee4a904e35 Implemented create and update methods for items 2018-07-11 02:39:55 +02:00
konrad 592dc20af4 List item creation is now done via handler 2018-07-11 02:13:53 +02:00
konrad b067425dc3 more optimization 2018-07-11 01:45:11 +02:00
konrad e97fa30202 more optimization 2018-07-11 00:28:53 +02:00
konrad 237874eda6 Fixed lint + fmt 2018-07-10 14:02:23 +02:00
konrad c8622b0029 Implemented Delete methods on list 2018-07-10 13:27:25 +02:00
kolaente b1de837c4f Implemented Create and Update methods on list 2018-07-09 23:17:19 +02:00
kolaente 9e8f13edf6 Getting all lists or one works now 2018-07-09 19:49:27 +02:00
kolaente d5eb2f08e3 Implemented CRUD Helper, every struct needs its own methods 2018-07-08 22:50:01 +02:00
kolaente 0c5ed914e0 CRUD helper now returns directly the target struct filled with data instead of a sub objectq 2018-07-08 13:26:43 +02:00
kolaente 490f32d46b Added CRUD helper method 2018-07-07 14:19:34 +02:00
kolaente 2d0d074f89 small optimizations 2018-07-06 08:40:35 +02:00
kolaente 31eb916af2 updated featurecreep 2018-07-05 08:55:34 +02:00
kolaente 462dfc8868 Implemented method to add a list to a namespace 2018-07-05 08:52:05 +02:00
kolaente 93efaa95f8 Implemented method to delete a namespace 2018-07-04 19:21:04 +02:00
kolaente 2d81330b27 Removed debugging 2018-07-04 18:44:13 +02:00
kolaente f59917e721 Fixed getting all lists of one namespace 2018-07-04 08:56:52 +02:00
kolaente b57ca9375a Fixed namespace updates not working 2018-07-04 08:15:47 +02:00
kolaente ac134fb16b Small fixes to manage namespaces 2018-07-03 09:09:44 +02:00
kolaente 064e1cd3b7 Small fixes to manage namespaces 2018-07-03 08:48:28 +02:00
kolaente e0244e28d7 Added method to show all lists in a namespace 2018-07-03 08:26:28 +02:00
kolaente 06cae09f77 Added method to show one namespace 2018-07-02 09:09:32 +02:00
kolaente 124e4f4a5b Added method to show all namespaces a user has access to 2018-07-02 08:54:44 +02:00
kolaente 6dfdcb9571 Added basic functions + endpoints to add/update namespaces 2018-07-02 08:40:24 +02:00
kolaente bd2bf24813 Started working on namespaces 2018-06-14 17:43:00 +02:00
kolaente ac0a50663d Added basic definitions for namespaces and teams 2018-06-14 16:14:49 +02:00
kolaente 6398134eef More Featurecreep. Or call it a plan. Whatever you want. 2018-06-14 14:58:00 +02:00
kolaente 6141956847 Added swagger UI 2018-06-14 14:19:19 +02:00
kolaente 33c5f91491 Updated Roadmap 2018-06-13 13:49:19 +02:00
kolaente 8500659aec added generated swagger spec 2018-06-13 13:45:53 +02:00
kolaente 4589f3b4bb Added docs via swagger 2018-06-13 13:45:22 +02:00
kolaente 0652125c25 Fixed returning of user infos when updating a todo item 2018-06-13 12:18:55 +02:00
konrad b11a6b912e More Featurecreep 2018-06-12 19:57:48 +02:00
konrad f0f92ad1a1 Improved creation of list items 2018-06-12 19:57:38 +02:00
konrad fc974fd87f Added endpoint to be able to edit list items 2018-06-12 19:44:47 +02:00
konrad 1b3b2ccb59 Improved item deletion rights check 2018-06-12 18:49:56 +02:00
konrad 1bb7187285 Added check to only let a user delete his own list 2018-06-12 18:46:59 +02:00
konrad be18247682 Added check to only let a user delete his own list 2018-06-12 18:35:36 +02:00
konrad 5ba9d76328 Added method to delete a list 2018-06-12 18:17:52 +02:00
konrad dcb046665f Added method to delete a list 2018-06-12 18:17:21 +02:00
kolaente 853fb2a2b7 Added method to delete a todo item from a list 2018-06-12 18:07:47 +02:00
konrad 91f67dc364 Added functions for adding items to a todolist 2018-06-10 19:49:40 +02:00
konrad 7bac9f490e Started adding listitems 2018-06-10 15:55:56 +02:00
konrad abd21f0c14 Plan. 2018-06-10 15:32:25 +02:00
konrad cf4871af59 cleanup 2018-06-10 14:43:35 +02:00
konrad 125f0ba230 Added lists view 2018-06-10 14:41:42 +02:00
konrad b841ec121b unit tests improvments 2018-06-10 14:24:33 +02:00
konrad 2cf20fe1c4 fixed lint + fmt 2018-06-10 14:22:37 +02:00
konrad f372128784 Added list create and update methods 2018-06-10 14:14:10 +02:00
konrad fb4c9d580c Update gitignore 2018-06-10 11:41:29 +02:00
konrad db6c2bfd8f made tests work again 2018-06-10 11:41:10 +02:00
konrad 5510249813 updated fixtures 2018-06-10 11:37:24 +02:00
konrad d840651a24 removed unused errors 2018-06-10 11:35:53 +02:00
konrad 1bee67cac7 Made registration work 2018-06-10 11:34:59 +02:00
kolaente 2ca4c521aa deleted old binary 2018-06-10 11:13:23 +02:00
konrad 986059d719 updated makefile 2018-06-10 11:13:01 +02:00
konrad 479cf54ada initial commit 2018-06-10 11:11:42 +02:00
3081 changed files with 920413 additions and 85112 deletions
-526
View File
@@ -1,526 +0,0 @@
---
kind: pipeline
type: docker
name: build
trigger:
branch:
include:
- main
event:
include:
- push
- pull_request
services:
- name: api
image: vikunja/api:unstable
environment:
VIKUNJA_SERVICE_TESTINGTOKEN: averyLongSecretToSe33dtheDB
VIKUNJA_LOG_LEVEL: DEBUG
steps:
# Disabled until we figure out why it is so slow
# - name: restore-cache
# image: meltwater/drone-cache:dev
# pull: always
# environment:
# AWS_ACCESS_KEY_ID:
# from_secret: cache_aws_access_key_id
# AWS_SECRET_ACCESS_KEY:
# from_secret: cache_aws_secret_access_key
# settings:
# debug: true
# restore: true
# bucket: kolaente.dev-drone-dependency-cache
# endpoint: https://s3.fr-par.scw.cloud
# region: fr-par
# path_style: true
# cache_key: '{{ .Repo.Name }}_{{ checksum "pnpm-lock.yaml" }}_{{ arch }}_{{ os }}'
# mount:
# - .cache
- name: dependencies
image: node:18-alpine
pull: always
environment:
PNPM_CACHE_FOLDER: .cache/pnpm
CYPRESS_CACHE_FOLDER: .cache/cypress
commands:
- corepack enable && pnpm config set store-dir .cache/pnpm
- pnpm install --fetch-timeout 100000
# depends_on:
# - restore-cache
- name: lint
image: node:18-alpine
pull: always
environment:
PNPM_CACHE_FOLDER: .cache/pnpm
commands:
- corepack enable && pnpm config set store-dir .cache/pnpm
- pnpm run lint
depends_on:
- dependencies
- name: build-prod
image: node:18-alpine
pull: always
environment:
PNPM_CACHE_FOLDER: .cache/pnpm
commands:
- corepack enable && pnpm config set store-dir .cache/pnpm
- pnpm run build
depends_on:
- dependencies
- name: test-unit
image: node:18-alpine
pull: always
commands:
- corepack enable && pnpm config set store-dir .cache/pnpm
- pnpm run test:unit
depends_on:
- dependencies
- name: typecheck
failure: ignore
image: node:18-alpine
pull: always
environment:
PNPM_CACHE_FOLDER: .cache/pnpm
commands:
- corepack enable && pnpm config set store-dir .cache/pnpm
- pnpm run typecheck
depends_on:
- dependencies
- name: test-frontend
image: cypress/browsers:node18.12.0-chrome107
pull: always
environment:
CYPRESS_API_URL: http://api:3456/api/v1
CYPRESS_TEST_SECRET: averyLongSecretToSe33dtheDB
PNPM_CACHE_FOLDER: .cache/pnpm
CYPRESS_CACHE_FOLDER: .cache/cypress
CYPRESS_DEFAULT_COMMAND_TIMEOUT: 60000
CYPRESS_RECORD_KEY:
from_secret: cypress_project_key
commands:
- sed -i 's/localhost/api/g' dist/index.html
- corepack enable && pnpm config set store-dir .cache/pnpm
- pnpm cypress install
- pnpm run test:e2e-record
depends_on:
- build-prod
# - name: rebuild-cache
# image: meltwater/drone-cache:dev
# pull: always
# environment:
# AWS_ACCESS_KEY_ID:
# from_secret: cache_aws_access_key_id
# AWS_SECRET_ACCESS_KEY:
# from_secret: cache_aws_secret_access_key
# settings:
# rebuild: true
# bucket: kolaente.dev-drone-dependency-cache
# endpoint: https://s3.fr-par.scw.cloud
# region: fr-par
# path_style: true
# cache_key: '{{ .Repo.Name }}_{{ checksum "pnpm-lock.yaml" }}_{{ arch }}_{{ os }}'
# mount:
# - .cache
# depends_on:
# - dependencies
- name: deploy-preview
image: node:18-alpine
pull: always
environment:
NETLIFY_AUTH_TOKEN:
from_secret: netlify_auth_token
NETLIFY_SITE_ID:
from_secret: netlify_site_id
GITEA_TOKEN:
from_secret: gitea_token
commands:
- cp -r dist dist-preview
# Override the default api url used for preview
- sed -i 's|http://localhost:3456|https://try.vikunja.io|g' dist-preview/index.html
- apk add --no-cache perl-utils
# create via:
# `shasum -a 384 ./scripts/deploy-preview-netlify.mjs > ./scripts/deploy-preview-netlify.mjs.sha384`
- shasum -a 384 -c ./scripts/deploy-preview-netlify.mjs.sha384
- node ./scripts/deploy-preview-netlify.mjs
depends_on:
- build-prod
when:
event:
include:
- pull_request
---
kind: pipeline
type: docker
name: release-latest
depends_on:
- build
trigger:
branch:
- main
event:
- push
steps:
- name: fetch-tags
image: docker:git
commands:
- git fetch --tags
# - name: restore-cache
# image: meltwater/drone-cache:dev
# pull: always
# environment:
# AWS_ACCESS_KEY_ID:
# from_secret: cache_aws_access_key_id
# AWS_SECRET_ACCESS_KEY:
# from_secret: cache_aws_secret_access_key
# settings:
# restore: true
# bucket: kolaente.dev-drone-dependency-cache
# endpoint: https://s3.fr-par.scw.cloud
# region: fr-par
# path_style: true
# cache_key: '{{ .Repo.Name }}_{{ checksum "pnpm-lock.yaml" }}_{{ arch }}_{{ os }}'
# mount:
# - .cache
- name: build
image: node:18-alpine
pull: always
environment:
PNPM_CACHE_FOLDER: .cache/pnpm
commands:
- apk add git
- corepack enable && pnpm config set store-dir .cache/pnpm
- pnpm install --fetch-timeout 100000 --frozen-lockfile
- pnpm run lint
- "echo '{\"VERSION\": \"'$(git describe --tags --always --abbrev=10 | sed 's/-/+/' | sed 's/^v//' | sed 's/-g/-/')'\"}' > src/version.json"
- pnpm run build
- sed -i 's/http\:\\/\\/localhost\\:3456\\/api\\/v1/\\/api\\/v1/g' dist/index.html # Override the default api url used for developing
# depends_on:
# - restore-cache
- name: static
image: kolaente/zip
pull: always
commands:
- cd dist
- zip -r ../vikunja-frontend-unstable.zip *
- cd ..
depends_on: [ build ]
- name: release
image: plugins/s3
pull: always
settings:
bucket: vikunja-releases
access_key:
from_secret: aws_access_key_id
secret_key:
from_secret: aws_secret_access_key
endpoint: https://s3.fr-par.scw.cloud
region: fr-par
path_style: true
source: vikunja-frontend-unstable.zip
target: /frontend/
depends_on: [ static ]
---
kind: pipeline
type: docker
name: release-version
depends_on:
- build
trigger:
event:
- tag
steps:
- name: fetch-tags
image: docker:git
commands:
- git fetch --tags
# - name: restore-cache
# image: meltwater/drone-cache:dev
# pull: always
# environment:
# AWS_ACCESS_KEY_ID:
# from_secret: cache_aws_access_key_id
# AWS_SECRET_ACCESS_KEY:
# from_secret: cache_aws_secret_access_key
# settings:
# restore: true
# bucket: kolaente.dev-drone-dependency-cache
# endpoint: https://s3.fr-par.scw.cloud
# region: fr-par
# path_style: true
# cache_key: '{{ .Repo.Name }}_{{ checksum "pnpm-lock.yaml" }}_{{ arch }}_{{ os }}'
# mount:
# - .cache
- name: build
image: node:18-alpine
pull: always
environment:
PNPM_CACHE_FOLDER: .cache/pnpm
commands:
- apk add git
- corepack enable && pnpm config set store-dir .cache/pnpm
- pnpm install --fetch-timeout 100000 --frozen-lockfile
- pnpm run lint
- "echo '{\"VERSION\": \"'$(git describe --tags --always --abbrev=10 | sed 's/-/+/' | sed 's/^v//' | sed 's/-g/-/')'\"}' > src/version.json"
- pnpm run build
- sed -i 's/http\:\\/\\/localhost\\:3456\\/api\\/v1/\\/api\\/v1/g' dist/index.html # Override the default api url used for developing
# depends_on:
# - restore-cache
- name: static
image: kolaente/zip
pull: always
commands:
- cd dist
- zip -r ../vikunja-frontend-${DRONE_TAG##v}.zip *
- cd ..
depends_on: [ build ]
- name: release
image: plugins/s3
pull: always
settings:
bucket: vikunja-releases
access_key:
from_secret: aws_access_key_id
secret_key:
from_secret: aws_secret_access_key
endpoint: https://s3.fr-par.scw.cloud
region: fr-par
path_style: true
source: vikunja-frontend-${DRONE_TAG##v}.zip
target: /frontend/
depends_on: [ static ]
---
kind: pipeline
type: docker
name: trigger-desktop-update
trigger:
branch:
- main
event:
- push
depends_on:
- release-latest
steps:
- name: trigger
image: plugins/downstream
settings:
server: https://drone.kolaente.de
token:
from_secret: drone_token
repositories:
- vikunja/desktop@main
---
kind: pipeline
type: docker
name: docker-release
depends_on:
- release-latest
- release-version
trigger:
ref:
- refs/heads/main
- "refs/tags/**"
event:
exclude:
- cron
steps:
- name: fetch-tags
image: docker:git
commands:
- git fetch --tags
- name: docker-unstable
image: thegeeklab/drone-docker-buildx
privileged: true
pull: always
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/frontend
tags: unstable
build_args:
- USE_RELEASE=true
- RELEASE_VERSION=unstable
platforms:
- linux/386
- linux/amd64
- linux/arm/v6
- linux/arm/v7
- linux/arm64/v8
depends_on: [ fetch-tags ]
when:
ref:
- refs/heads/main
- name: generate-tags
image: thegeeklab/docker-autotag
environment:
DOCKER_AUTOTAG_VERSION: ${DRONE_TAG}
DOCKER_AUTOTAG_EXTRA_TAGS: latest
DOCKER_AUTOTAG_OUTPUT_FILE: .tags
depends_on: [ fetch-tags ]
when:
ref:
- "refs/tags/**"
- name: docker-release
image: thegeeklab/drone-docker-buildx
privileged: true
pull: always
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/frontend
build_args:
- USE_RELEASE=true
- RELEASE_VERSION=${DRONE_TAG##v}
platforms:
- linux/386
- linux/amd64
- linux/arm/v6
- linux/arm/v7
- linux/arm64/v8
depends_on: [ generate-tags ]
when:
ref:
- "refs/tags/**"
---
kind: pipeline
type: docker
name: notify
trigger:
ref:
- refs/heads/main
- "refs/tags/**"
event:
exclude:
- cron
depends_on:
- build
- release-version
- release-latest
- trigger-desktop-update
- docker-release
steps:
- name: notify
image: plugins/matrix
settings:
homeserver: https://matrix.org
roomid: WqBDCxzghKcNflkErL:matrix.org
username:
from_secret: matrix_username
password:
from_secret: matrix_password
when:
status:
- success
- failure
---
kind: pipeline
type: docker
name: update-translations
trigger:
branch:
- main
event:
- cron
cron:
- update_translations
steps:
- name: download
pull: always
image: jonasfranz/crowdin
settings:
download: true
export_dir: src/i18n/lang/
ignore_branch: true
project_identifier: vikunja
environment:
CROWDIN_KEY:
from_secret: crowdin_key
- name: move-files
pull: always
image: bash
depends_on:
- download
commands:
- mv src/i18n/lang/*/*.json src/i18n/lang
- name: push
pull: always
image: appleboy/drone-git-push
depends_on:
- move-files
settings:
author_email: "frederik@vikunja.io"
author_name: Frederick [Bot]
branch: main
commit: true
commit_message: "[skip ci] Updated translations via Crowdin"
remote: "ssh://git@kolaente.dev:9022/vikunja/frontend.git"
ssh_key:
from_secret: translation_git_push_ssh_key
- name: upload
pull: always
image: jonasfranz/crowdin
depends_on:
- clone
settings:
files:
en.json: src/i18n/lang/en.json
ignore_branch: true
project_identifier: vikunja
environment:
CROWDIN_KEY:
from_secret: crowdin_key
---
kind: signature
hmac: 971875b90c7bb1649d1b00d022d0b594ba9b68f927bf8f0dbe840190816d676b
...
+617
View File
@@ -0,0 +1,617 @@
kind: pipeline
name: testing
workspace:
base: /go
path: src/code.vikunja.io/api
services:
- name: test-mysql-unit
image: mariadb:10
environment:
MYSQL_ROOT_PASSWORD: vikunjatest
MYSQL_DATABASE: vikunjatest
- name: test-mysql-integration
image: mariadb:10
environment:
MYSQL_ROOT_PASSWORD: vikunjatest
MYSQL_DATABASE: vikunjatest
- name: test-postgres-unit
image: postgres:12
environment:
POSTGRES_PASSWORD: vikunjatest
POSTGRES_DB: vikunjatest
- name: test-postgres-integration
image: postgres:12
environment:
POSTGRES_PASSWORD: vikunjatest
POSTGRES_DB: vikunjatest
trigger:
branch:
include:
- master
event:
include:
- push
- pull_request
steps:
- name: fetch-tags
image: docker:git
commands:
- git fetch --tags
- name: build
image: vikunja/golang-build:latest
pull: true
environment:
GOFLAGS: '-mod=vendor'
commands:
- make generate
- make lint
- make fmt-check
# - make got-swag # Commented out until we figured out how to get this working on drone
- make ineffassign-check
- make misspell-check
- make goconst-check
- make gocyclo-check
- make static-check
- wget -O - -q https://raw.githubusercontent.com/securego/gosec/master/install.sh | sh -s -- -b $GOPATH/bin v2.2.0 # Need to manually install as it does not support being installed via go modules like the rest.
- make gosec-check
- make build
when:
event: [ push, tag, pull_request ]
- name: test
image: vikunja/golang-build:latest
pull: true
commands:
- make test
depends_on: [ build ]
when:
event: [ push, tag, pull_request ]
- name: test-sqlite
image: vikunja/golang-build:latest
pull: true
environment:
VIKUNJA_TESTS_USE_CONFIG: 1
VIKUNJA_DATABASE_TYPE: sqlite
commands:
- make test
depends_on: [ build ]
when:
event: [ push, tag, pull_request ]
- name: test-mysql
image: vikunja/golang-build:latest
pull: true
environment:
VIKUNJA_TESTS_USE_CONFIG: 1
VIKUNJA_DATABASE_TYPE: mysql
VIKUNJA_DATABASE_HOST: test-mysql-unit
VIKUNJA_DATABASE_USER: root
VIKUNJA_DATABASE_PASSWORD: vikunjatest
VIKUNJA_DATABASE_DATABASE: vikunjatest
commands:
- make test
depends_on: [ build ]
when:
event: [ push, tag, pull_request ]
- name: test-postgres
image: vikunja/golang-build:latest
pull: true
environment:
VIKUNJA_TESTS_USE_CONFIG: 1
VIKUNJA_DATABASE_TYPE: postgres
VIKUNJA_DATABASE_HOST: test-postgres-unit
VIKUNJA_DATABASE_USER: postgres
VIKUNJA_DATABASE_PASSWORD: vikunjatest
VIKUNJA_DATABASE_DATABASE: vikunjatest
VIKUNJA_DATABASE_SSLMODE: disable
commands:
- make test
depends_on: [ build ]
when:
event: [ push, tag, pull_request ]
- name: integration-test
image: vikunja/golang-build:latest
pull: true
commands:
- make integration-test
depends_on: [ build ]
when:
event: [ push, tag, pull_request ]
- name: integration-test-sqlite
image: vikunja/golang-build:latest
pull: true
environment:
VIKUNJA_TESTS_USE_CONFIG: 1
VIKUNJA_DATABASE_TYPE: sqlite
commands:
- make integration-test
depends_on: [ build ]
when:
event: [ push, tag, pull_request ]
- name: integration-test-mysql
image: vikunja/golang-build:latest
pull: true
environment:
VIKUNJA_TESTS_USE_CONFIG: 1
VIKUNJA_DATABASE_TYPE: mysql
VIKUNJA_DATABASE_HOST: test-mysql-integration
VIKUNJA_DATABASE_USER: root
VIKUNJA_DATABASE_PASSWORD: vikunjatest
VIKUNJA_DATABASE_DATABASE: vikunjatest
commands:
- make integration-test
depends_on: [ build ]
when:
event: [ push, tag, pull_request ]
- name: integration-test-postgres
image: vikunja/golang-build:latest
pull: true
environment:
VIKUNJA_TESTS_USE_CONFIG: 1
VIKUNJA_DATABASE_TYPE: postgres
VIKUNJA_DATABASE_HOST: test-postgres-integration
VIKUNJA_DATABASE_USER: postgres
VIKUNJA_DATABASE_PASSWORD: vikunjatest
VIKUNJA_DATABASE_DATABASE: vikunjatest
VIKUNJA_DATABASE_SSLMODE: disable
commands:
- make integration-test
depends_on: [ build ]
when:
event: [ push, tag, pull_request ]
---
########
# Build a release when pushing to master
# We need to copy this because drone currently can't run a pipeline on either a push to master or a tag.
########
kind: pipeline
name: deploy-master
depends_on:
- testing
workspace:
base: /go
path: src/code.vikunja.io/api
trigger:
branch:
- master
event:
- push
steps:
# Needed to get the versions right as they depend on tags
- name: fetch-tags
image: docker:git
commands:
- git fetch --tags
- name: before-static-build
image: techknowlogick/xgo:latest
pull: true
commands:
- export PATH=$PATH:$GOPATH/bin
- make generate
- make release-dirs
depends_on: [ fetch-tags ]
- name: static-build-windows
image: techknowlogick/xgo:latest
pull: true
environment:
# This path does not exist. However, when we set the gopath to /go, the build fails. Not sure why.
# Leaving this here until we know how to resolve this properly.
GOPATH: /srv/app
commands:
- export PATH=$PATH:$GOPATH/bin
- make release-windows
depends_on: [ before-static-build ]
- name: static-build-linux
image: techknowlogick/xgo:latest
pull: true
environment:
# This path does not exist. However, when we set the gopath to /go, the build fails. Not sure why.
# Leaving this here until we know how to resolve this properly.
GOPATH: /srv/app
commands:
- export PATH=$PATH:$GOPATH/bin
- make release-linux
depends_on: [ before-static-build ]
- name: static-build-darwin
image: techknowlogick/xgo:latest
pull: true
environment:
# This path does not exist. However, when we set the gopath to /go, the build fails. Not sure why.
# Leaving this here until we know how to resolve this properly.
GOPATH: /srv/app
commands:
- export PATH=$PATH:$GOPATH/bin
- make release-darwin
depends_on: [ before-static-build ]
- name: after-build-compress
image: kolaente/upx
pull: true
depends_on:
- static-build-windows
- static-build-linux
- static-build-darwin
commands:
- make release-compress
- name: after-build-static
image: techknowlogick/xgo:latest
pull: true
depends_on:
- after-build-compress
commands:
- make release-copy
- make release-check
- make release-os-package
- make release-zip
- name: sign-release
image: plugins/gpgsign:1
pull: true
depends_on: [ after-build-static ]
settings:
key:
from_secret: gpg_privkey
passphrase:
from_secret: gpg_password
files:
- dist/zip/*
detach_sign: true
# Push the releases to our pseudo-s3-bucket
- name: release-latest
image: plugins/s3:1
pull: true
settings:
bucket: vikunja
access_key:
from_secret: aws_access_key_id
secret_key:
from_secret: aws_secret_access_key
endpoint: https://storage.kolaente.de
path_style: true
strip_prefix: dist/zip/
source: dist/zip/*
target: /api/master/
depends_on: [ sign-release ]
# Build a debian package and push it to our bucket
- name: build-deb
image: kolaente/fpm
pull: true
commands:
- make build-deb
depends_on: [ static-build-linux ]
- 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
- make reprepro
depends_on: [ build-deb ]
# Push the releases to our pseudo-s3-bucket
- name: release-deb
image: plugins/s3:1
pull: true
settings:
bucket: vikunja
access_key:
from_secret: aws_access_key_id
secret_key:
from_secret: aws_secret_access_key
endpoint: https://storage.kolaente.de
path_style: true
strip_prefix: debian
source: debian/*/*/*/*/*
target: /deb/
depends_on: [ deb-structure ]
# Build the docker image and push it to docker hub
- name: docker
image: plugins/docker
pull: true
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/api
auto_tag: true
depends_on: [ fetch-tags ]
- name: telegram
image: appleboy/drone-telegram
depends_on:
- release-latest
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"}}.
when:
status:
- success
- failure
---
########
# Build a release when tagging
# We need to copy this because drone currently can't run a pipeline on either a push to master or a tag.
########
kind: pipeline
name: deploy-version
depends_on:
- testing
workspace:
base: /go
path: src/code.vikunja.io/api
trigger:
event:
- tag
steps:
- name: fetch-tags
image: docker:git
commands:
- git fetch --tags
- name: before-static-build
image: techknowlogick/xgo:latest
pull: true
commands:
- make generate
- make release-dirs
depends_on: [ fetch-tags ]
- name: static-build-windows
image: techknowlogick/xgo:latest
pull: true
environment:
# This path does not exist. However, when we set the gopath to /go, the build fails. Not sure why.
# Leaving this here until we know how to resolve this properly.
GOPATH: /srv/app
commands:
- export PATH=$PATH:$GOPATH/bin
- make release-windows
depends_on: [ before-static-build ]
- name: static-build-linux
image: techknowlogick/xgo:latest
pull: true
environment:
# This path does not exist. However, when we set the gopath to /go, the build fails. Not sure why.
# Leaving this here until we know how to resolve this properly.
GOPATH: /srv/app
commands:
- export PATH=$PATH:$GOPATH/bin
- make release-linux
depends_on: [ before-static-build ]
- name: static-build-darwin
image: techknowlogick/xgo:latest
pull: true
environment:
# This path does not exist. However, when we set the gopath to /go, the build fails. Not sure why.
# Leaving this here until we know how to resolve this properly.
GOPATH: /srv/app
commands:
- export PATH=$PATH:$GOPATH/bin
- make release-darwin
depends_on: [ before-static-build ]
- name: after-build-compress
image: kolaente/upx
pull: true
depends_on:
- static-build-windows
- static-build-linux
- static-build-darwin
commands:
- make release-compress
- name: after-build-static
image: techknowlogick/xgo:latest
pull: true
depends_on:
- after-build-compress
commands:
- make release-copy
- make release-check
- make release-os-package
- make release-zip
- name: sign-release
image: plugins/gpgsign:1
pull: true
depends_on: [ after-build-static ]
settings:
key:
from_secret: gpg_privkey
passphrase:
from_secret: gpg_password
files:
- dist/zip/*
detach_sign: true
# Push the releases to our pseudo-s3-bucket
- name: release-version
image: plugins/s3:1
pull: true
settings:
bucket: vikunja
access_key:
from_secret: aws_access_key_id
secret_key:
from_secret: aws_secret_access_key
endpoint: https://storage.kolaente.de
path_style: true
strip_prefix: dist/zip/
source: dist/zip/*
target: /api/${DRONE_TAG##v}/
depends_on: [ sign-release ]
# Build a debian package and push it to our bucket
- name: build-deb
image: kolaente/fpm
pull: true
commands:
- make build-deb
depends_on: [ static-build-linux ]
- 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
- make reprepro
depends_on: [ build-deb ]
# Push the releases to our pseudo-s3-bucket
- name: release-deb
image: plugins/s3:1
pull: true
settings:
bucket: vikunja
access_key:
from_secret: aws_access_key_id
secret_key:
from_secret: aws_secret_access_key
endpoint: https://storage.kolaente.de
path_style: true
strip_prefix: debian
source: debian/*/*/*/*/*
target: /deb/
depends_on: [ deb-structure ]
# Build the docker image and push it to docker hub
- name: docker
image: plugins/docker
pull: true
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/api
auto_tag: true
depends_on: [ fetch-tags ]
- name: telegram
image: appleboy/drone-telegram
depends_on:
- docker
- release-version
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"}}.
when:
status:
- success
- failure
---
kind: pipeline
name: deploy-docs
workspace:
base: /go
path: src/code.vikunja.io/api
clone:
depth: 50
trigger:
event:
- push
branch:
- master
steps:
- name: submodules
image: docker:git
commands:
- git submodule update --init
- git submodule update --recursive --remote
- name: theme
image: kolaente/yarn
pull: true
group: build-static
commands:
- cd docs/themes/vikunja
- yarn --production=false
- ./node_modules/.bin/gulp
- name: build
image: monachus/hugo:v0.54.0
pull: true
commands:
- cd docs
- hugo
- mv public/docs/* public # Hugo seems to be not capable of setting a different theme for a home page, so we do this ugly hack to fix it.
- name: docker
image: plugins/docker
pull: true
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: vikunja/docs
context: docs/
dockerfile: docs/Dockerfile
-29
View File
@@ -1,29 +0,0 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = false
insert_final_newline = false
[*.vue]
indent_style = tab
[*.{yaml,yml}]
indent_style = space
indent_size = 2
[*.json]
indent_style = space
indent_size = 2
[*.{scss,css}]
indent_style = space
indent_size = 2
[.nvmrc]
insert_final_newline = false
-13
View File
@@ -1,13 +0,0 @@
# (1) Duplicate this file and remove the '.example' suffix.
# Naming this file '.env.local' is a Vite convention to prevent accidentally
# submitting to git.
# For more info see: https://vitejs.dev/guide/env-and-mode.html#env-files
# (2) Comment in and adjust the values as needed.
# VITE_IS_ONLINE=true
# VITE_WORKBOX_DEBUG=false
# SENTRY_AUTH_TOKEN=YOUR_TOKEN
# SENTRY_ORG=vikunja
# SENTRY_PROJECT=frontend-oss
# VIKUNJA_FRONTEND_BASE=/custom-subpath
-1
View File
@@ -1 +0,0 @@
use flake
-58
View File
@@ -1,58 +0,0 @@
/* eslint-env node */
require("@rushstack/eslint-patch/modern-module-resolution")
module.exports = {
'root': true,
'env': {
'browser': true,
'es2022': true,
'node': true,
'vue/setup-compiler-macros': true,
},
'extends': [
'eslint:recommended',
'plugin:vue/vue3-essential',
'@vue/eslint-config-typescript/recommended',
],
'rules': {
'vue/html-quotes': [
'error',
'double',
],
'quotes': [
'error',
'single',
],
'comma-dangle': [
'error',
'always-multiline',
],
'semi': [
'error',
'never',
],
// see https://segmentfault.com/q/1010000040813116/a-1020000041134455 (original in chinese)
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': ['error', { vars: 'all', args: 'after-used', ignoreRestSiblings: true }],
'vue/multi-word-component-names': 0,
// disabled until we have support for reactivityTransform
// See https://github.com/vuejs/eslint-plugin-vue/issues/1948
// see also setting in `vite.config`
'vue/no-setup-props-destructure': 0,
},
'parser': 'vue-eslint-parser',
'parserOptions': {
'parser': '@typescript-eslint/parser',
'ecmaVersion': 2022,
'sourceType': 'module',
},
'ignorePatterns': [
'*.test.*',
'cypress/*',
],
'globals': {
'defineProps': 'readonly',
},
}
-44
View File
@@ -1,44 +0,0 @@
<!--
Please fill out this issue template to report a bug.
If you want to propose a new feature, please open a discussion thread in the forum: https://community.vikunja.io
-->
**Version information:**
Frontend Version:
API Version:
Browser and OS Version:
**Steps to reproduce:**
<!--
Add clear steps to reproduce the bug. Provide screenshots where applicable.
-->
1.
2.
...
**Expected behavior:**
<!--
Describe what happened.
-->
**Actual behavior:**
<!--
Describe what happened instead.
-->
**Checklist:**
* [ ] I have provided all required information
* [ ] I am using the latest release or the latest unstable build
* [ ] I was able to reproduce the bug on [try](https://try.vikunja.io)
+12
View File
@@ -0,0 +1,12 @@
# Description
# Checklist
* [ ] I added or improved tests
* [ ] I pushed new or updated dependencies to the repo using `go mod vendor`
* [ ] I added or improved docs for my feature
* [ ] Swagger (including `make do-the-swag`)
* [ ] Error codes
* [ ] New config options
-3
View File
@@ -1,3 +0,0 @@
github: kolaente
open_collective: vikunja
custom: ["https://vikunja.cloud", "https://www.buymeacoffee.com/kolaente"]
-59
View File
@@ -1,59 +0,0 @@
name: Bug Report
description: Found something you weren't expecting? Report it here!
labels:
- kind/bug
body:
- type: markdown
attributes:
value: |
NOTE: If your issue is a security concern, please send an email to security@vikunja.io instead of opening a public issue.
- type: markdown
attributes:
value: |
Please fill out this issue template to report a bug.
1. If you want to propose a new feature, please open a discussion thread in the forum: https://community.vikunja.io
2. Please ask questions or configuration/deploy problems on our [Matrix Room](https://matrix.to/#/#vikunja:matrix.org) or forum (https://community.vikunja.io).
3. Make sure you are using the latest release and
take a moment to check that your issue hasn't been reported before.
4. Please give all relevant information below for bug reports, because
incomplete details will be handled as an invalid report and closed.
- type: textarea
id: description
attributes:
label: Description
description: |
Please provide a description of your issue here, with a URL if you were able to reproduce the issue (see below).
- type: input
id: frontend-version
attributes:
label: Vikunja Frontend Version
description: Vikunja frontend version (or commit reference) of your instance
validations:
required: true
- type: input
id: api-version
attributes:
label: Vikunja API Version
description: Vikunja API version (or commit reference) of your instance
validations:
required: true
- type: input
id: browser-version
attributes:
label: Browser and version
description: If your issue is related to a frontend problem, please provide the browser and version you used to reproduce it.
- type: dropdown
id: can-reproduce
attributes:
label: Can you reproduce the bug on the Vikunja demo site?
options:
- "Yes"
- "No"
validations:
required: true
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: If this issue involves the Web Interface, please provide one or more screenshots
-17
View File
@@ -1,17 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: API issues
url: https://code.vikunja.io/api/issues
about: This is the frontend repo. Please open api-related bug reports and discussions in the api 0repo. Not sure if your issue is frontend or api? Ask in Matrix or the forum first.
- name: Forum
url: https://community.vikunja.io/
about: Feature Requests, Questions, configuration or deployment problems should be discussed in the forum.
- name: Security-related issues
url: https://vikunja.io/contact/#security
about: For security concerns, please send a mail to security@vikunja.io instead of opening a public issue.
- name: Chat on Matrix
url: https://matrix.to/#/#vikunja:matrix.org
about: Please ask any quick questions here.
- name: Translations
url: https://crowdin.com/project/vikunja
about: Any problems or requests for new languages about translations should be handled in crowdin.
+22 -41
View File
@@ -1,41 +1,22 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
stats.html
node_modules
.DS_Store
/dist*
coverage
*.zip
.direnv/
# Test files
cypress/screenshots
cypress/videos
# local env files
.env.local
.env.*.local
# Editor directories and files
.vscode
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*
!rollup.sw.js
# Local Netlify folder
.netlify
# histoire
.histoire
.idea/
.idea/*/*
.idea/httpRequests
config.yml
config.yaml
!docs/config.yml
*.db
Run
dist/
cover.*
/vikunja
Test_*
bin/
secrets
*.deb
debian/
logs/
docs/public/
docs/resources/
pkg/static/templates_vfsdata.go
files/
!pkg/files/
+3
View File
@@ -0,0 +1,3 @@
[submodule "docs/themes/vikunja"]
path = docs/themes/vikunja
url = ../theme.git
-2
View File
@@ -1,2 +0,0 @@
auto-install-peers=true
fetch-timeout=100000
-1
View File
@@ -1 +0,0 @@
18.15.0
-13
View File
@@ -1,13 +0,0 @@
{
"recommendations": [
"codezombiech.gitignore",
"dbaeumer.vscode-eslint",
"editorconfig.editorconfig",
"vue.volar",
"vue.vscode-typescript-vue-plugin",
"lokalise.i18n-ally",
"mgmcdermott.vscode-language-babel",
"mikestead.dotenv",
"Syler.sass-indented"
]
}
-34
View File
@@ -1,34 +0,0 @@
{
"eslint.packageManager": "pnpm",
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll": true
},
"eslint.format.enable": true,
"[javascript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
"[typescript]": {
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
},
// https://eslint.vuejs.org/user-guide/#editor-integrations
"eslint.validate": [
"javascript",
"javascriptreact",
"vue"
],
"volar.completion.preferredTagNameCase": "pascal",
// disable vetur in case it is installed
"vetur.validation.template": false,
// i18n ally
"i18n-ally.localesPaths": [
"src/i18n/lang"
],
"i18n-ally.sortKeys": true,
"i18n-ally.keepFulfilled": true,
"i18n-ally.keystyle": "nested"
}
+326 -4729
View File
File diff suppressed because it is too large Load Diff
+36 -59
View File
@@ -1,68 +1,45 @@
# syntax=docker/dockerfile:1
# ┬─┐┬ ┐o┬ ┬─┐
# │─││ │││ │ │
# ┘─┘┘─┘┘┘─┘┘─┘
FROM --platform=$BUILDPLATFORM node:18-alpine AS builder
##############
# Build stage
FROM golang:1-alpine AS build-env
WORKDIR /build
ARG VIKUNJA_VERSION
ENV TAGS "sqlite"
ENV GO111MODULE=on
ENV GOFLAGS=-mod=vendor
ARG USE_RELEASE=false
ARG RELEASE_VERSION=main
ENV PNPM_CACHE_FOLDER .cache/pnpm/
# Build deps
RUN apk --no-cache add build-base git
COPY package.json ./
COPY pnpm-lock.yaml ./
# Setup repo
COPY . ${GOPATH}/src/code.vikunja.io/api
WORKDIR ${GOPATH}/src/code.vikunja.io/api
RUN if [ "$USE_RELEASE" != true ]; then \
# https://pnpm.io/installation#using-corepack
corepack enable && \
pnpm install; \
fi
# Checkout version if set
RUN if [ -n "${VIKUNJA_VERSION}" ]; then git checkout "${VIKUNJA_VERSION}"; fi \
&& make clean generate build
COPY . ./
RUN if [ "$USE_RELEASE" != true ]; then \
apk add --no-cache --virtual .build-deps git jq && \
git describe --tags --always --abbrev=10 | sed 's/-/+/; s/^v//; s/-g/-/' | \
xargs -0 -I{} jq -Mcnr --arg version {} '{VERSION:$version}' | \
tee src/version.json && \
apk del .build-deps; \
fi
RUN if [ "$USE_RELEASE" = true ]; then \
wget "https://dl.vikunja.io/frontend/vikunja-frontend-${RELEASE_VERSION}.zip" -O frontend-release.zip && \
unzip frontend-release.zip -d dist/; \
else \
# we don't use corepack prepare here by intend since
# we have renovate to keep our dependencies up to date
# Build the frontend
pnpm run build; \
fi
# ┌┐┐┌─┐o┌┐┐┐ │
# ││││ ┬││││┌┼┘
# ┘└┘┘─┘┘┘└┘┘ └
FROM nginx:stable-alpine AS runner
WORKDIR /usr/share/nginx/html
###################
# The actual image
# Note: I wanted to use the scratch image here, but unfortunatly the go-sqlite bindings require cgo and
# because of this, the container would not start when I compiled the image without cgo.
FROM alpine:3.11
LABEL maintainer="maintainers@vikunja.io"
ENV VIKUNJA_HTTP_PORT 80
ENV VIKUNJA_HTTP2_PORT 81
ENV VIKUNJA_LOG_FORMAT main
ENV VIKUNJA_API_URL /api/v1
ENV VIKUNJA_SENTRY_ENABLED false
ENV VIKUNJA_SENTRY_DSN https://85694a2d757547cbbc90cd4b55c5a18d@o1047380.ingest.sentry.io/6024480
WORKDIR /app/vikunja/
COPY --from=build-env /go/src/code.vikunja.io/api/vikunja .
RUN adduser -S -D vikunja -h /app/vikunja -H \
&& chown vikunja -R /app/vikunja
ENV VIKUNJA_SERVICE_ROOTPATH=/app/vikunja/
COPY docker/injector.sh /docker-entrypoint.d/50-injector.sh
COPY docker/ipv6-disable.sh /docker-entrypoint.d/60-ipv6-disable.sh
COPY docker/nginx.conf /etc/nginx/nginx.conf
COPY docker/templates/. /etc/nginx/templates/
# copy compiled files from stage 1
COPY --from=builder /build/dist ./
# manage permissions
RUN chmod 0755 /docker-entrypoint.d/*.sh /etc/nginx/templates && \
chmod -R 0644 /etc/nginx/nginx.conf && \
chown -R nginx:nginx ./ /etc/nginx/conf.d /etc/nginx/templates && \
rm -f /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
# Fix time zone settings not working
RUN apk --no-cache add tzdata
# Files permissions
RUN mkdir /app/vikunja/files && \
chown -R vikunja /app/vikunja/files
VOLUME /app/vikunja/files
USER vikunja
CMD ["/app/vikunja/vikunja"]
EXPOSE 3456
+78 -65
View File
@@ -1,5 +1,5 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
@@ -7,15 +7,17 @@
Preamble
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 GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
the GNU General Public License is 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.
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.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
@@ -24,34 +26,44 @@ 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.
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.
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.
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.
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.
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.
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.
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.
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.
The precise terms and conditions for copying, distribution and
modification follow.
@@ -60,7 +72,7 @@ modification follow.
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
@@ -537,45 +549,35 @@ 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. 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.
13. Use with the GNU Affero General Public License.
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 General Public License into a single
under version 3 of the GNU Affero 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 work with which it is combined will remain governed by version
3 of the GNU General Public License.
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.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
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
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
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 Affero General
Program specifies that a certain numbered version of the GNU 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 Affero General Public License, you may choose any version ever published
GNU 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 Affero General Public License can be used, that proxy's
versions of the GNU 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.
@@ -633,29 +635,40 @@ 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 Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
it under the terms of the GNU 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 Affero General Public License for more details.
GNU General Public License for more details.
You should have received a copy of the GNU Affero General Public License
You should have received a copy of the GNU 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 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.
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".
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 AGPL, see
For more information on this, and how to apply and follow the GNU GPL, 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>.
+247
View File
@@ -0,0 +1,247 @@
DIST := dist
IMPORT := code.vikunja.io/api
SED_INPLACE := sed -i
ifeq ($(OS), Windows_NT)
EXECUTABLE := vikunja.exe
else
EXECUTABLE := vikunja
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
SED_INPLACE := sed -i ''
endif
endif
GOFILES := $(shell find . -name "*.go" -type f ! -path "./vendor/*" ! -path "*/bindata.go")
GOFMT ?= gofmt -s
GOFLAGS := -v -mod=vendor
EXTRA_GOFLAGS ?=
LDFLAGS := -X "code.vikunja.io/api/pkg/version.Version=$(shell git describe --tags --always --abbrev=10 | sed 's/-/+/' | sed 's/^v//' | sed 's/-g/-/')" -X "main.Tags=$(TAGS)" -X "code.vikunja.io/api/pkg/version.BuildTime=$(shell date -R)"
PACKAGES ?= $(filter-out code.vikunja.io/api/pkg/integrations,$(shell go list -mod=vendor ./... | grep -v /vendor/))
SOURCES ?= $(shell find . -name "*.go" -type f)
TAGS ?=
ifeq ($(OS), Windows_NT)
EXECUTABLE := vikunja.exe
else
EXECUTABLE := vikunja
endif
ifneq ($(DRONE_TAG),)
VERSION ?= $(subst v,,$(DRONE_TAG))
else
ifneq ($(DRONE_BRANCH),)
VERSION ?= $(subst release/v,,$(DRONE_BRANCH))
else
VERSION ?= master
endif
endif
ifeq ($(DRONE_WORKSPACE),'')
BINLOCATION := $(EXECUTABLE)
else
BINLOCATION := $(DIST)/binaries/$(EXECUTABLE)-$(VERSION)-linux-amd64
endif
ifeq ($(VERSION),master)
PKGVERSION := $(shell git describe --tags --always --abbrev=10 | sed 's/-/+/' | sed 's/^v//' | sed 's/-g/-/')
else
PKGVERSION := $(VERSION)
endif
.PHONY: all
all: build
.PHONY: clean
clean:
go clean ./...
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA)
.PHONY: test
test:
# We run everything sequentially and not in parallel to prevent issues with real test databases
VIKUNJA_SERVICE_ROOTPATH=$(shell pwd) go test $(GOFLAGS) -p 1 -cover -coverprofile cover.out $(PACKAGES)
.PHONY: test-coverage
test-coverage: test
go tool cover -html=cover.out -o cover.html
.PHONY: integration-test
integration-test:
# We run everything sequentially and not in parallel to prevent issues with real test databases
VIKUNJA_SERVICE_ROOTPATH=$(shell pwd) go test $(GOFLAGS) -p 1 code.vikunja.io/api/pkg/integrations
.PHONY: lint
lint:
@hash golint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
go install $(GOFLAGS) golang.org/x/lint/golint; \
fi
for PKG in $(PACKAGES); do golint -set_exit_status $$PKG || exit 1; done;
.PHONY: fmt
fmt:
$(GOFMT) -w $(GOFILES)
.PHONY: fmt-check
fmt-check:
# get all go files and run go fmt on them
@diff=$$($(GOFMT) -d $(GOFILES)); \
if [ -n "$$diff" ]; then \
echo "Please run 'make fmt' and commit the result:"; \
echo "$${diff}"; \
exit 1; \
fi;
.PHONY: build
build: generate $(EXECUTABLE)
.PHONY: generate
generate:
go generate code.vikunja.io/api/pkg/static
$(EXECUTABLE): $(SOURCES)
go build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@
.PHONY: compress-build
compress-build:
upx -9 $(EXECUTABLE)
.PHONY: release
release: release-dirs release-windows release-linux release-darwin release-copy release-check release-os-package release-zip
.PHONY: release-dirs
release-dirs:
mkdir -p $(DIST)/binaries $(DIST)/release $(DIST)/zip
.PHONY: release-windows
release-windows:
@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
go install $(GOFLAGS) src.techknowlogick.com/xgo; \
fi
xgo -dest $(DIST)/binaries -tags 'netgo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out vikunja-$(VERSION) .
ifneq ($(DRONE_WORKSPACE),'')
mv /build/* $(DIST)/binaries
endif
.PHONY: release-linux
release-linux:
@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
go install $(GOFLAGS) src.techknowlogick.com/xgo; \
fi
xgo -dest $(DIST)/binaries -tags 'netgo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'linux/*' -out vikunja-$(VERSION) .
ifneq ($(DRONE_WORKSPACE),'')
mv /build/* $(DIST)/binaries
endif
.PHONY: release-darwin
release-darwin:
@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
go install $(GOFLAGS) src.techknowlogick.com/xgo; \
fi
xgo -dest $(DIST)/binaries -tags 'netgo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin/*' -out vikunja-$(VERSION) .
ifneq ($(DRONE_WORKSPACE),'')
mv /build/* $(DIST)/binaries
endif
# Compresses all releases made by make release-* but not mips* releases since upx can't handle these.
.PHONY: release-compress
release-compress:
$(foreach file,$(filter-out $(wildcard $(wildcard $(DIST)/binaries/$(EXECUTABLE)-*mips*)),$(wildcard $(DIST)/binaries/$(EXECUTABLE)-*)), upx -9 $(file);)
.PHONY: release-copy
release-copy:
$(foreach file,$(wildcard $(DIST)/binaries/$(EXECUTABLE)-*),cp $(file) $(DIST)/release/$(notdir $(file));)
.PHONY: release-check
release-check:
cd $(DIST)/release; $(foreach file,$(wildcard $(DIST)/release/$(EXECUTABLE)-*),sha256sum $(notdir $(file)) > $(notdir $(file)).sha256;)
.PHONY: release-os-package
release-os-package:
$(foreach file,$(filter-out %.sha256,$(wildcard $(DIST)/release/$(EXECUTABLE)-*)),mkdir $(file)-full;mv $(file) $(file)-full/; mv $(file).sha256 $(file)-full/; cp config.yml.sample $(file)-full/config.yml; cp LICENSE $(file)-full/; )
.PHONY: release-zip
release-zip:
$(foreach file,$(wildcard $(DIST)/release/$(EXECUTABLE)-*),cd $(file); zip -r ../../zip/$(shell basename $(file)).zip *; cd ../../../; )
# Builds a deb package using fpm from a previously created binary (using make build)
.PHONY: build-deb
build-deb:
fpm -s dir -t deb --url https://vikunja.io -n vikunja -v $(PKGVERSION) --license GPLv3 --directories /opt/vikunja --after-install ./build/after-install.sh --description 'Vikunja is an open-source todo application, written in Go. It lets you create lists,tasks and share them via teams or directly between users.' -m maintainers@vikunja.io ./$(BINLOCATION)=/opt/vikunja/vikunja ./config.yml.sample=/etc/vikunja/config.yml;
.PHONY: reprepro
reprepro:
reprepro_expect debian includedeb strech ./$(EXECUTABLE)_$(PKGVERSION)_amd64.deb
.PHONY: got-swag
got-swag: do-the-swag
@diff=$$(git diff docs/swagger/swagger.json); \
if [ -n "$$diff" ]; then \
echo "Please run 'make do-the-swag' and commit the result:"; \
echo "$${diff}"; \
exit 1; \
fi;
.PHONY: do-the-swag
do-the-swag:
@hash swag > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
go install $(GOFLAGS) github.com/swaggo/swag/cmd/swag; \
fi
swag init -g pkg/routes/routes.go -o ./pkg/swagger;
# Fix the generated swagger file, currently a workaround until swaggo can properly use go mod
sed -i '/"definitions": {/a "code.vikunja.io.web.HTTPError": {"type": "object","properties": {"code": {"type": "integer"},"message": {"type": "string"}}},' pkg/swagger/docs.go;
sed -i 's/code.vikunja.io\/web.HTTPError/code.vikunja.io.web.HTTPError/g' pkg/swagger/docs.go;
sed -i 's/package\ docs/package\ swagger/g' pkg/swagger/docs.go;
sed -i 's/` + \\"`\\" + `/` + "`" + `/g' pkg/swagger/docs.go;
.PHONY: misspell-check
misspell-check:
@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
go install $(GOFLAGS) github.com/client9/misspell/cmd/misspell; \
fi
for S in $(GOFILES); do misspell -error $$S || exit 1; done;
.PHONY: ineffassign-check
ineffassign-check:
@hash ineffassign > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
go install $(GOFLAGS) github.com/gordonklaus/ineffassign; \
fi
for S in $(GOFILES); do ineffassign $$S || exit 1; done;
.PHONY: gocyclo-check
gocyclo-check:
@hash gocyclo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
go get -u github.com/fzipp/gocyclo; \
go install $(GOFLAGS) github.com/fzipp/gocyclo; \
fi
for S in $(GOFILES); do gocyclo -over 27 $$S || exit 1; done;
.PHONY: static-check
static-check:
@hash staticcheck > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
go get -u honnef.co/go/tools; \
go install $(GOFLAGS) honnef.co/go/tools/cmd/staticcheck; \
fi
staticcheck $(PACKAGES);
.PHONY: gosec-check
gosec-check:
@hash gosec > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
echo "Please manually install gosec by running"; \
echo "curl -sfL https://raw.githubusercontent.com/securego/gosec/master/install.sh | bash -s -- -b $GOPATH/bin v2.2.0"; \
exit 1; \
fi
gosec ./...
.PHONY: goconst-check
goconst-check:
@hash goconst > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
go get -u github.com/jgautheron/goconst/cmd/goconst; \
go install $(GOFLAGS) github.com/jgautheron/goconst/cmd/goconst; \
fi;
for S in $(PACKAGES); do goconst $$S || exit 1; done;
+61 -34
View File
@@ -1,53 +1,80 @@
# Web frontend for Vikunja
<img src="https://vikunja.io/images/vikunja-logo.svg" alt="" style="display: block;width: 50%;margin: 0 auto;" width="50%"/>
> The todo app to organize your life.
[![Build Status](https://drone1.kolaente.de/api/badges/vikunja/api/status.svg)](https://drone1.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.13.1-brightgreen.svg)](https://dl.vikunja.io)
[![Docker Pulls](https://img.shields.io/docker/pulls/vikunja/api.svg)](https://hub.docker.com/r/vikunja/api/)
[![Swagger Docs](https://img.shields.io/badge/swagger-docs-brightgreen.svg)](https://try.vikunja.io/api/v1/docs)
[![Go Report Card](https://goreportcard.com/badge/git.kolaente.de/vikunja/api)](https://goreportcard.com/report/git.kolaente.de/vikunja/api)
[![Build Status](https://drone.kolaente.de/api/badges/vikunja/frontend/status.svg)](https://drone.kolaente.de/vikunja/frontend)
[![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-blue.svg)](LICENSE)
[![Download](https://img.shields.io/badge/download-v0.20.5-brightgreen.svg)](https://dl.vikunja.io)
[![Translation](https://badges.crowdin.net/vikunja/localized.svg)](https://crowdin.com/project/vikunja)
# Vikunja API
This is the web frontend for Vikunja, written in Vue.js.
> The Todo-app to organize your life.
Take a look at [our roadmap](https://my.vikunja.cloud/share/UrdhKPqumxDXUbYpEGJLSIyNTwAnbBzVlwdDpRbv/auth) (hosted on Vikunja!) for a list of things we're currently working on!
# Table of contents
## Security Reports
* [Features](#features)
* [Docs](#docs)
* [Roadmap](#roadmap)
* [Contributing](#contributing)
* [License](#license)
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
## Docker
* Create TODO lists with tasks
* Reminder for tasks
* Namespaces: A "group" which bundels multiple lists
* Share lists and namespaces with teams and users with granular permissions
* Plenty of details for tasks
There is a [docker image available](https://hub.docker.com/r/vikunja/api) with support for http/2 and aggressive caching enabled.
In order to build it from sources run the command below. (Docker >= v19.03)
See [the features page](https://vikunja.io/en/features/) on our website for a more exaustive list or
try it on [try.vikunja.io](https://try.vikunja.io)!
```shell
export DOCKER_BUILDKIT=1
docker build -t vikunja/frontend .
```
## Docs
Refer to Refer [to multi-platform documentation](https://docs.docker.com/build/building/multi-platform/) in order to build for the different platform.
* [Installing](https://vikunja.io/docs/installing/)
* [Build from source](https://vikunja.io/docs/build-from-sources/)
* [Development setup](https://vikunja.io/docs/development/)
* [Makefile](https://vikunja.io/docs/makefile/)
* [Testing](https://vikunja.io/docs/testing/)
## Project setup
All docs can be found on [the vikunja home page](https://vikunja.io/docs/).
```shell
pnpm install
```
### Roadmap
### Compiles and hot-reloads for development
> 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.
```shell
pnpm run serve
```
* [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
### Compiles and minifies for production
See [our roadmap](https://my.vikunja.cloud/share/QFyzYEmEYfSyQfTOmIRSwLUpkFjboaBqQCnaPmWd/auth) (hosted on Vikunja!) for even more!
```shell
pnpm run build
```
* [ ] [Mobile apps](https://code.vikunja.io/app) (seperate repo) *In Progress*
* [ ] [Webapp](https://code.vikunja.io/frontend) (seperate repo) *In Progress*
### Lints and fixes files
## Contributing
```shell
pnpm run lint
```
Fork -> Push -> Pull-Request. Also see the [dev docs](https://vikunja.io/docs/development/) for more infos.
## License
This project is licensed under the GPLv3 License. See the [LICENSE](LICENSE) file for the full license text.
+12
View File
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
curl -X POST http://localhost:3456/api/v1/register -H 'Content-Type: application/json' -d '{"username":"demo","password":"demo","email":"demo@vikunja.io"}'
BEARER=`curl -X POST -H 'Content-Type: application/json' -d '{"username": "demo", "password":"demo"}' localhost:3456/api/v1/login | jq -r '.token'`
echo "Bearer: $BEARER"
curl -X POST localhost:3456/api/v1/tokenTest -H "Authorization: Bearer $BEARER"
curl -X PUT localhost:3456/api/v1/namespaces/1/lists -H 'Content-Type: application/json' -H "Authorization: Bearer $BEARER" -d '{"title":"lorem"}'
curl -X PUT localhost:3456/api/v1/lists/1 -H 'Content-Type: application/json' -H "Authorization: Bearer $BEARER" -d '{"text":"lorem"}'
curl -X PUT -H "Authorization: Bearer $BEARER" localhost:3456/api/v1/tasks/1/attachments -F 'files=@/home/konrad/Pictures/Wallpaper/greg-rakozy-_Q4mepyyjMw-unsplash.jpg'
+29
View File
@@ -0,0 +1,29 @@
### Authorization by token, part 1. Retrieve and save token.
POST http://localhost:8080/api/v1/login
Content-Type: application/json
{
"username": "user3",
"password": "1234"
}
> {% client.global.set("auth_token", response.body.token); %}
### Register
POST http://localhost:8080/api/v1/register
Content-Type: application/json
{
"username": "user",
"password": "1234",
"email": "5@knt.li"
}
###
# Token test
POST http://localhost:8080/api/v1/tokenTest
Authorization: Bearer {{auth_token}}
Content-Type: application/json
###
+70
View File
@@ -0,0 +1,70 @@
# Get all labels
GET http://localhost:8080/api/v1/labels
Authorization: Bearer {{auth_token}}
###
# Add a new label
PUT http://localhost:8080/api/v1/labels
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{
"title": "test5"
}
###
# Delete a label
DELETE http://localhost:8080/api/v1/labels/6
Authorization: Bearer {{auth_token}}
###
# Update a label
POST http://localhost:8080/api/v1/labels/1
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{
"title": "testschinkenbrot",
"description": "käsebrot"
}
###
# Get one label
GET http://localhost:8080/api/v1/labels/1
Authorization: Bearer {{auth_token}}
###
# Get all labels on a task
GET http://localhost:8080/api/v1/tasks/3565/labels
Authorization: Bearer {{auth_token}}
###
# Add a new label to a task
PUT http://localhost:8080/api/v1/tasks/35236365/labels
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{
"label_id": 1
}
###
# Delete a label from a task
DELETE http://localhost:8080/api/v1/tasks/3565/labels/1
Authorization: Bearer {{auth_token}}
###
# Add a new label to a task
POST http://localhost:8080/api/v1/tasks/3565/labels/bulk
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{
"labels": [
{"id": 1},
{"id": 2},
{"id": 3}
]
}
###
+177
View File
@@ -0,0 +1,177 @@
# Get all lists
GET http://localhost:8080/api/v1/namespaces/35/lists
Authorization: Bearer {{auth_token}}
###
# Get one list
GET http://localhost:8080/api/v1/lists/3
Authorization: Bearer {{auth_token}}
###
# Add a new list
PUT http://localhost:8080/api/v1/namespaces/35/lists
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{
"title": "test"
}
###
# Add a new item
PUT http://localhost:8080/api/v1/lists/1
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{
"text": "Task",
"description": "Schinken"
}
###
# Delete a task from a list
DELETE http://localhost:8080/api/v1/lists/14
Authorization: Bearer {{auth_token}}
###
# Get all teams who have access to that list
GET http://localhost:8080/api/v1/lists/28/teams
Authorization: Bearer {{auth_token}}
###
# Give a team access to that list
PUT http://localhost:8080/api/v1/lists/1/teams
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{"team_id":2, "right": 1}
###
# Update a teams access to that list
POST http://localhost:8080/api/v1/lists/1/teams/2
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{"right": 0}
###
# Delete a team from a list
DELETE http://localhost:8080/api/v1/lists/10235/teams/1
Authorization: Bearer {{auth_token}}
###
# Delete a team from a list
DELETE http://localhost:8080/api/v1/lists/10235/teams/1
Authorization: Bearer {{auth_token}}
###
# Get all users who have access to that list
GET http://localhost:8080/api/v1/lists/28/users
Authorization: Bearer {{auth_token}}
###
# Give a user access to that list
PUT http://localhost:8080/api/v1/lists/3/users
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{"userID":"user4", "right":1}
###
# Update a users access to that list
POST http://localhost:8080/api/v1/lists/30/users/3
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{"right":2}
###
# Delete a user from a list
DELETE http://localhost:8080/api/v1/lists/28/users/3
Authorization: Bearer {{auth_token}}
###
# Get all pending tasks
GET http://localhost:8080/api/v1/tasks/all
Authorization: Bearer {{auth_token}}
###
# Get all pending tasks with priorities
GET http://localhost:8080/api/v1/tasks/all?sort=priorityasc
Authorization: Bearer {{auth_token}}
###
# Get all pending tasks in a range
GET http://localhost:8080/api/v1/tasks/all/dueadateasc/1546784000/1548784000
Authorization: Bearer {{auth_token}}
###
# Get all pending tasks in caldav
GET http://localhost:8080/api/v1/tasks/caldav
#Authorization: Bearer {{auth_token}}
###
# Update a task
POST http://localhost:8080/api/v1/tasks/3565
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{
"priority": 0
}
###
# Bulk update multiple tasks at once
POST http://localhost:8080/api/v1/tasks/bulk
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{
"task_ids": [3518,3519,3521],
"text":"bulkupdated"
}
###
# Get all assignees
GET http://localhost:8080/api/v1/tasks/3565/assignees
Authorization: Bearer {{auth_token}}
###
# Add a bunch of assignees
PUT http://localhost:8080/api/v1/tasks/3565/assignees/bulk
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{
"assignees": [
{"id": 17}
]
}
###
# Get all users who have access to a list
GET http://localhost:8080/api/v1/lists/3/users
Authorization: Bearer {{auth_token}}
###
+71
View File
@@ -0,0 +1,71 @@
# Get all namespaces
GET http://localhost:8080/api/v1/namespaces
Authorization: Bearer {{auth_token}}
###
# Get one namespaces
GET http://localhost:8080/api/v1/namespaces/-1
Authorization: Bearer {{auth_token}}
###
# Get all users who have access to that namespace
GET http://localhost:8080/api/v1/namespaces/12/users
Authorization: Bearer {{auth_token}}
###
# Give a user access to that namespace
PUT http://localhost:8080/api/v1/namespaces/1/users
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{"user_id":3, "right": 0}
###
# Update a users access to that namespace
POST http://localhost:8080/api/v1/namespaces/1/users/3
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{"right": 2}
###
# Delete a user from a namespace
DELETE http://localhost:8080/api/v1/namespaces/1/users/2
Authorization: Bearer {{auth_token}}
###
# Get all teams who have access to that namespace
GET http://localhost:8080/api/v1/namespaces/1/teams
Authorization: Bearer {{auth_token}}
###
# Give a team access to that namespace
PUT http://localhost:8080/api/v1/namespaces/1/teams
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{"team_id":3, "right": 0}
###
# Update a teams access to that namespace
POST http://localhost:8080/api/v1/namespaces/1/teams/1
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{"right": 0}
###
# Delete a team from a namespace
DELETE http://localhost:8080/api/v1/namespaces/1/teams/2
Authorization: Bearer {{auth_token}}
###
+29
View File
@@ -0,0 +1,29 @@
# Get all teams
GET http://localhost:8080/api/v1/teams
Authorization: Bearer {{auth_token}}
###
# Get one team
GET http://localhost:8080/api/v1/teams/28
Authorization: Bearer {{auth_token}}
###
# Add a new member to that team
PUT http://localhost:8080/api/v1/teams/28/members
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{
"user_id": 2
}
###
# Delete a member from a team
DELETE http://localhost:8080/api/v1/teams/28/members/2
Authorization: Bearer {{auth_token}}
###
+53
View File
@@ -0,0 +1,53 @@
# Get all users
GET http://localhost:8080/api/v1/user
Authorization: Bearer {{auth_token}}
######
# Search for a user
GET http://localhost:8080/api/v1/users?s=3
Authorization: Bearer {{auth_token}}
###
## Update password
POST http://localhost:8080/api/v1/user/password
Authorization: Bearer {{auth_token}}
Content-Type: application/json
{
"old_password": "1234",
"new_password": "1234"
}
### Request a password to reset a password
POST http://localhost:8080/api/v1/user/password/token
Content-Type: application/json
Accept: application/json
{
"email": "k@knt.li"
}
### Request a token to reset a password
POST http://localhost:8080/api/v1/user/password/reset
Content-Type: application/json
Accept: application/json
{
"token": "eAsZzakgqARnjzXHqsHqZtSUKuiOhoJjHANhgTxUIDBSalhbtdpAdLeywGXzVDBuRQGNpHdMxoHXhLVSlzpJsFvuoJgMdkhRhkNhaQXfufuZCdtUlerZHSJQLgYMUryHIxIREcmZLtWoZVrYyARkCvkyFhcGtoCwQOEjAOEZMQQuxTVoGYfAqcfNggQnerUcXCiRIgRtkusXSnltomhaeyRwAbrckXFeXxUjslgplSGqSTOqJTYuhrSzAVTwNvuYyvuXLaZoNnJEyeVDWlRydnxfgUQjQZOKwCBRWVQPKpZhlslLUyUAMsRQkHITkruQCjDnOGCCRsSNplbNCEuDmMfpWYHSQAcQIDZtbQWkxzpfmHDMQvvKPPrxEnrTErlvTfKDKICFYPQxXNpNE",
"new_password": "1234"
}
### Confirm a users email address
POST http://localhost:8080/api/v1/user/confirm
Content-Type: application/json
Accept: application/json
{
"token": ""
}
###
+8
View File
@@ -0,0 +1,8 @@
#!/bin/bash
ln -s /opt/vikunja/vikunja /usr/bin/vikunja
# 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
sed -i "s/<rootpath>/\/opt\/vikunja\//g" /etc/vikunja/config.yml
sed -i "s/Path: \"\.\/vikunja.db\"/Path: \"\\/opt\/vikunja\/vikunja.db\"/g" /etc/vikunja/config.yml
+8
View File
@@ -0,0 +1,8 @@
Origin: dl.vikunja.io
Label: Vikunja
Codename: strech
Architectures: amd64
Components: main
Description: The debian repo for Vikunja builds.
SignWith: yes
Pull: strech
-59
View File
@@ -1,59 +0,0 @@
[changelog]
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits
| filter(attribute="scope")
| sort(attribute="scope") %}
* *({{commit.scope}})* {{ commit.message | upper_first }}
{%- if commit.breaking %}
{% raw %} {% endraw %}- **BREAKING**: {{commit.breaking_description}}
{%- endif -%}
{%- endfor -%}
{%- for commit in commits %}
{%- if commit.scope -%}
{% else -%}
* {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ commit.id }}))
{% if commit.breaking -%}
{% raw %} {% endraw %}- **BREAKING**: {{commit.breaking_description}}
{% endif -%}
{% endif -%}
{% endfor -%}
{% raw %}\n{% endraw %}\
{% endfor %}\n
"""
#{% for group, commits in commits | group_by(attribute="group") %}
# ### {{ group | upper_first }}
# {% for commit in commits %}\
# - {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }} ([{{ commit.id | truncate(length=7, end="") }}]({{ commit.id }}))
# {% endfor %}\
#{% endfor %}\n
# remove the leading and trailing whitespace from the template
trim = true
[git]
conventional_commits = true
filter_unconventional = false
commit_parsers = [
{ message = ".*(deps).*", group = "Dependencies"},
{ message = "^feat", group = "Features"},
{ message = "^fix", group = "Bug Fixes"},
{ message = "^doc", group = "Documentation"},
{ message = "^perf", group = "Performance"},
{ message = "^refactor", group = "Refactor"},
{ message = "^style", group = "Styling"},
{ message = "^test", group = "Testing"},
{ message = "^chore\\(release\\): prepare for", skip = true},
{ message = "^chore", group = "Miscellaneous Tasks"},
{ body = ".*security", group = "Security"},
{ message = ".*", group = "Other", default_scope = "other"}, # Everything that's not a conventional commit goes into the "Other" category
]
+166
View File
@@ -0,0 +1,166 @@
service:
# This token is used to verify issued JWT tokens.
# Default is a random token which will be generated at each startup of vikunja.
# (This means all already issued tokens will be invalid once you restart vikunja)
JWTSecret: "<jwt-secret>"
# The interface on which to run the webserver
interface: ":3456"
# The URL of the frontend, used to send password reset emails.
frontendurl: ""
# The base path on the file system where the binary and assets are.
# Vikunja will also look in this path for a config file, so you could provide only this variable to point to a folder
# with a config file which will then be used.
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
motd: ""
# Enable sharing of lists via a link
enablelinksharing: true
# Whether to let new users registering themselves or not
enableregistration: true
# Whether to enable task attachments or not
enabletaskattachments: true
# The time zone all timestamps are in
timezone: GMT
# Whether task comments should be enabled or not
enabletaskcomments: true
database:
# Database type to use. Supported types are mysql, postgres and sqlite.
type: "sqlite"
# Database user which is used to connect to the database.
user: "vikunja"
# Databse password
password: ""
# Databse host
host: "localhost"
# Databse to use
database: "vikunja"
# When using sqlite, this is the path where to store the data
Path: "./vikunja.db"
# Sets the max open connections to the database. Only used when using mysql and postgres.
maxopenconnections: 100
# Sets the maximum number of idle connections to the db.
maxidleconnections: 50
# The maximum lifetime of a single db connection in miliseconds.
maxconnectionlifetime: 10000
# Secure connection mode. Only used with postgres.
# (see https://pkg.go.dev/github.com/lib/pq?tab=doc#hdr-Connection_String_Parameters)
sslmode: disable
cache:
# If cache is enabled or not
enabled: false
# Cache type. Possible values are memory or redis, you'll need to enable redis below when using redis
type: memory
# When using memory this defines the maximum size an element can take
maxelementsize: 1000
redis:
# Whether to enable redis or not
enabled: false
# The host of the redis server including its port.
host: 'localhost:6379'
# The password used to authenicate against the redis server
password: ''
# 0 means default database
db: 0
cors:
# Whether to enable or disable cors headers.
# 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.
origins:
- "*"
# How long (in seconds) the results of a preflight request can be cached.
maxage: 0
mailer:
# Whether to enable the mailer or not. If it is disabled, all users are enabled right away and password reset is not possible.
enabled: false
# SMTP Host
host: ""
# SMTP Host port
port: 587
# SMTP username
username: "user"
# SMTP password
password: ""
# Wether to skip verification of the tls certificate on the server
skiptlsverify: false
# The default from address when sending emails
fromemail: "mail@vikunja"
# The length of the mail queue.
queuelength: 100
# The timeout in seconds after which the current open connection to the mailserver will be closed.
queuetimeout: 30
log:
# A folder where all the logfiles should go.
path: <rootpath>logs
# Whether to show any logging at all or none
enabled: true
# Where the normal log should go. Possible values are stdout, stderr, file or off to disable standard logging.
standard: "stdout"
# Change the log level. Possible values (case-insensitive) are CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG.
level: "INFO"
# Whether or not to log database queries. Useful for debugging. Possible values are stdout, stderr, file or off to disable database logging.
database: "off"
# The log level for database log messages. Possible values (case-insensitive) are CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG.
databaselevel: "WARNING"
# Whether to log http requests or not. Possible values are stdout, stderr, file or off to disable http logging.
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"
ratelimit:
# whether or not to enable the rate limit
enabled: false
# The kind on which rates are based. Can be either "user" for a rate limit per user or "ip" for an ip-based rate limit.
kind: user
# The time period in seconds for the limit
period: 60
# The max number of requests a user is allowed to do in the configured time period
limit: 100
# The store where the limit counter for each user is stored. Possible values are "memory" or "redis"
store: memory
files:
# The path where files are stored
basepath: ./files # relative to the binary
# The maximum size of a file, as a human-readable string.
# Warning: The max size is limited 2^64-1 bytes due to the underlying datatype
maxsize: 20MB
migration:
# These are the settings for the wunderlist migrator
wunderlist:
# Wheter to enable the wunderlist migrator or not
enable: false
# The client id, required for making requests to the wunderlist api
# You need to register your vikunja instance at https://developer.wunderlist.com/apps/new to get this
clientid:
# The client secret, also required for making requests to the wunderlist api
clientsecret:
# The url where clients are redirected after they authorized Vikunja to access their wunderlist stuff.
# This needs to match the url you entered when registering your Vikunja instance at wunderlist.
# This is usually the frontend url where the frontend then makes a request to /migration/wunderlist/migrate
# with the code obtained from the wunderlist api.
# Note that the vikunja frontend expects this to be /migrate/wunderlist
redirecturl:
avatar:
# Switch between avatar providers. Possible values are gravatar and default.
# gravatar will fetch the avatar based on the user email.
# default will return a default avatar for every request.
provider: gravatar
# When using gravatar, this is the duration in seconds until a cached gravatar user avatar expires
gravatarexpiration: 3600
-27
View File
@@ -1,27 +0,0 @@
import {defineConfig} from 'cypress'
export default defineConfig({
env: {
API_URL: 'http://localhost:3456/api/v1',
TEST_SECRET: 'averyLongSecretToSe33dtheDB',
},
video: false,
retries: {
runMode: 2,
},
projectId: '181c7x',
e2e: {
specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}',
baseUrl: 'http://127.0.0.1:4173',
experimentalRunAllSpecs: true,
// testIsolation: false,
},
component: {
devServer: {
framework: 'vue',
bundler: 'vite',
},
},
viewportWidth: 1600,
viewportHeight: 900,
})
-48
View File
@@ -1,48 +0,0 @@
# Frontend Testing With Cypress
## Setup
* Enable the [seeder api endpoint](https://vikunja.io/docs/config-options/#testingtoken). You'll then need to add the testingtoken in `cypress.json` or set the `CYPRESS_TEST_SECRET` environment variable.
* Basic configuration happens in the `cypress.json` file
* Overridable with [env](https://docs.cypress.io/guides/guides/environment-variables.html#Option-3-CYPRESS)
* Override base url with `CYPRESS_BASE_URL`
## Fixtures
We're using the [test endpoint](https://vikunja.io/docs/config-options/#testingtoken) of the vikunja api to
seed the database with test data before running the tests.
This ensures better reproducability of tests.
## Running The Tests Locally
### Using Docker
The easiest way to run all frontend tests locally is by using the `docker-compose` file in this repository.
It uses the same configuration as the CI.
To use it, run
```shell
docker-compose up -d
```
Then, once all containers are started, run
```shell
docker-compose run cypress bash
```
to get a shell inside the cypress container.
In that shell you can then execute the tests with
```shell
pnpm run test:e2e
```
### Using The Cypress Dashboard
To open the Cypress Dashboard and run tests from there, run
```shell
pnpm run test:e2e:dev
```
-20
View File
@@ -1,20 +0,0 @@
version: '3'
services:
api:
image: vikunja/api:unstable
environment:
VIKUNJA_LOG_LEVEL: DEBUG
VIKUNJA_SERVICE_TESTINGTOKEN: averyLongSecretToSe33dtheDB
ports:
- 3456:3456
cypress:
image: cypress/browsers:node18.12.0-chrome107
volumes:
- ..:/project
- $HOME/.cache:/home/node/.cache/
user: node
working_dir: /project
environment:
CYPRESS_API_URL: http://api:3456/api/v1
CYPRESS_TEST_SECRET: averyLongSecretToSe33dtheDB
-57
View File
@@ -1,57 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {ListFactory} from '../../factories/list'
import {prepareLists} from './prepareLists'
describe('List History', () => {
createFakeUserAndLogin()
prepareLists()
it('should show a list history on the home page', () => {
cy.intercept(Cypress.env('API_URL') + '/namespaces*').as('loadNamespaces')
cy.intercept(Cypress.env('API_URL') + '/lists/*').as('loadList')
const lists = ListFactory.create(6)
cy.visit('/')
cy.wait('@loadNamespaces')
cy.get('body')
.should('not.contain', 'Last viewed')
cy.visit(`/lists/${lists[0].id}`)
cy.wait('@loadNamespaces')
cy.wait('@loadList')
cy.visit(`/lists/${lists[1].id}`)
cy.wait('@loadNamespaces')
cy.wait('@loadList')
cy.visit(`/lists/${lists[2].id}`)
cy.wait('@loadNamespaces')
cy.wait('@loadList')
cy.visit(`/lists/${lists[3].id}`)
cy.wait('@loadNamespaces')
cy.wait('@loadList')
cy.visit(`/lists/${lists[4].id}`)
cy.wait('@loadNamespaces')
cy.wait('@loadList')
cy.visit(`/lists/${lists[5].id}`)
cy.wait('@loadNamespaces')
cy.wait('@loadList')
// cy.visit('/')
// cy.wait('@loadNamespaces')
// Not using cy.visit here to work around the redirect issue fixed in #1337
cy.get('nav.menu.top-menu a')
.contains('Overview')
.click()
cy.get('body')
.should('contain', 'Last viewed')
cy.get('[data-cy="listCardGrid"]')
.should('not.contain', lists[0].title)
.should('contain', lists[1].title)
.should('contain', lists[2].title)
.should('contain', lists[3].title)
.should('contain', lists[4].title)
.should('contain', lists[5].title)
})
})
-126
View File
@@ -1,126 +0,0 @@
import {formatISO, format} from 'date-fns'
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task'
import {prepareLists} from './prepareLists'
describe('List View Gantt', () => {
createFakeUserAndLogin()
prepareLists()
it('Hides tasks with no dates', () => {
const tasks = TaskFactory.create(1)
cy.visit('/lists/1/gantt')
cy.get('.g-gantt-rows-container')
.should('not.contain', tasks[0].title)
})
it('Shows tasks from the current and next month', () => {
const now = Date.UTC(2022, 8, 25)
cy.clock(now, ['Date'])
const nextMonth = new Date(now)
nextMonth.setDate(1)
nextMonth.setMonth(9)
cy.visit('/lists/1/gantt')
cy.get('.g-timeunits-container')
.should('contain', format(now, 'MMMM'))
.should('contain', format(nextMonth, 'MMMM'))
})
it('Shows tasks with dates', () => {
const now = new Date()
const tasks = TaskFactory.create(1, {
start_date: now.toISOString(),
end_date: new Date(new Date(now).setDate(now.getDate() + 4)).toISOString(),
})
cy.visit('/lists/1/gantt')
cy.get('.g-gantt-rows-container')
.should('not.be.empty')
.should('contain', tasks[0].title)
})
it('Shows tasks with no dates after enabling them', () => {
const tasks = TaskFactory.create(1, {
start_date: null,
end_date: null,
})
cy.visit('/lists/1/gantt')
cy.get('.gantt-options .fancycheckbox')
.contains('Show tasks which don\'t have dates set')
.click()
cy.get('.g-gantt-rows-container')
.should('not.be.empty')
.should('contain', tasks[0].title)
})
it('Drags a task around', () => {
cy.intercept(Cypress.env('API_URL') + '/tasks/*').as('taskUpdate')
const now = new Date()
TaskFactory.create(1, {
start_date: now.toISOString(),
end_date: new Date(new Date(now).setDate(now.getDate() + 4)).toISOString(),
})
cy.visit('/lists/1/gantt')
cy.get('.g-gantt-rows-container .g-gantt-row .g-gantt-row-bars-container div .g-gantt-bar')
.first()
.trigger('mousedown', {which: 1})
.trigger('mousemove', {clientX: 500, clientY: 0})
.trigger('mouseup', {force: true})
cy.wait('@taskUpdate')
})
it('Should change the query parameters when selecting a date range', () => {
const now = Date.UTC(2022, 10, 9)
cy.clock(now, ['Date'])
cy.visit('/lists/1/gantt')
cy.get('.list-gantt .gantt-options .field .control input.input.form-control')
.click()
cy.get('.flatpickr-calendar .flatpickr-innerContainer .dayContainer .flatpickr-day')
.first()
.click()
cy.get('.flatpickr-calendar .flatpickr-innerContainer .dayContainer .flatpickr-day')
.last()
.click()
cy.url().should('contain', 'dateFrom=2022-09-25')
cy.url().should('contain', 'dateTo=2022-11-05')
})
it('Should change the date range based on date query parameters', () => {
cy.visit('/lists/1/gantt?dateFrom=2022-09-25&dateTo=2022-11-05')
cy.get('.g-timeunits-container')
.should('contain', 'September 2022')
.should('contain', 'October 2022')
.should('contain', 'November 2022')
cy.get('.list-gantt .gantt-options .field .control input.input.form-control')
.should('have.value', '25 Sep 2022 to 5 Nov 2022')
})
it('Should open a task when double clicked on it', () => {
const now = new Date()
const tasks = TaskFactory.create(1, {
start_date: formatISO(now),
end_date: formatISO(now.setDate(now.getDate() + 4)),
})
cy.visit('/lists/1/gantt')
cy.get('.gantt-container .g-gantt-chart .g-gantt-row-bars-container .g-gantt-bar')
.dblclick()
cy.url()
.should('contain', `/tasks/${tasks[0].id}`)
})
})
-241
View File
@@ -1,241 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {BucketFactory} from '../../factories/bucket'
import {ListFactory} from '../../factories/list'
import {TaskFactory} from '../../factories/task'
import {prepareLists} from './prepareLists'
describe('List View Kanban', () => {
createFakeUserAndLogin()
prepareLists()
let buckets
beforeEach(() => {
buckets = BucketFactory.create(2)
})
it('Shows all buckets with their tasks', () => {
const data = TaskFactory.create(10, {
list_id: 1,
bucket_id: 1,
})
cy.visit('/lists/1/kanban')
cy.get('.kanban .bucket .title')
.contains(buckets[0].title)
.should('exist')
cy.get('.kanban .bucket .title')
.contains(buckets[1].title)
.should('exist')
cy.get('.kanban .bucket')
.first()
.should('contain', data[0].title)
})
it('Can add a new task to a bucket', () => {
TaskFactory.create(2, {
list_id: 1,
bucket_id: 1,
})
cy.visit('/lists/1/kanban')
cy.get('.kanban .bucket')
.contains(buckets[0].title)
.get('.bucket-footer .button')
.contains('Add another task')
.click()
cy.get('.kanban .bucket')
.contains(buckets[0].title)
.get('.bucket-footer .field .control input.input')
.type('New Task{enter}')
cy.get('.kanban .bucket')
.first()
.should('contain', 'New Task')
})
it('Can create a new bucket', () => {
cy.visit('/lists/1/kanban')
cy.get('.kanban .bucket.new-bucket .button')
.click()
cy.get('.kanban .bucket.new-bucket input.input')
.type('New Bucket{enter}')
cy.wait(1000) // Wait for the request to finish
cy.get('.kanban .bucket .title')
.contains('New Bucket')
.should('exist')
})
it('Can set a bucket limit', () => {
cy.visit('/lists/1/kanban')
cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger')
.first()
.click()
cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item')
.contains('Limit: Not Set')
.click()
cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item .field input.input')
.first()
.type(3)
cy.get('[data-cy="setBucketLimit"]')
.first()
.click()
cy.get('.kanban .bucket .bucket-header span.limit')
.contains('0/3')
.should('exist')
})
it('Can rename a bucket', () => {
cy.visit('/lists/1/kanban')
cy.get('.kanban .bucket .bucket-header .title')
.first()
.type('{selectall}New Bucket Title{enter}')
cy.get('.kanban .bucket .bucket-header .title')
.first()
.should('contain', 'New Bucket Title')
})
it('Can delete a bucket', () => {
cy.visit('/lists/1/kanban')
cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-trigger')
.first()
.click()
cy.get('.kanban .bucket .bucket-header .dropdown.options .dropdown-menu .dropdown-item')
.contains('Delete')
.click()
cy.get('.modal-mask .modal-container .modal-content .header')
.should('contain', 'Delete the bucket')
cy.get('.modal-mask .modal-container .modal-content .actions .button')
.contains('Do it!')
.click()
cy.get('.kanban .bucket .title')
.contains(buckets[0].title)
.should('not.exist')
cy.get('.kanban .bucket .title')
.contains(buckets[1].title)
.should('exist')
})
it('Can drag tasks around', () => {
const tasks = TaskFactory.create(2, {
list_id: 1,
bucket_id: 1,
})
cy.visit('/lists/1/kanban')
cy.get('.kanban .bucket .tasks .task')
.contains(tasks[0].title)
.first()
.drag('.kanban .bucket:nth-child(2) .tasks')
cy.get('.kanban .bucket:nth-child(2) .tasks')
.should('contain', tasks[0].title)
cy.get('.kanban .bucket:nth-child(1) .tasks')
.should('not.contain', tasks[0].title)
})
it('Should navigate to the task when the task card is clicked', () => {
const tasks = TaskFactory.create(5, {
id: '{increment}',
list_id: 1,
bucket_id: 1,
})
cy.visit('/lists/1/kanban')
cy.get('.kanban .bucket .tasks .task')
.contains(tasks[0].title)
.should('be.visible')
.click()
cy.url()
.should('contain', `/tasks/${tasks[0].id}`, { timeout: 1000 })
})
it('Should remove a task from the kanban board when moving it to another list', () => {
const lists = ListFactory.create(2)
BucketFactory.create(2, {
list_id: '{increment}',
})
const tasks = TaskFactory.create(5, {
id: '{increment}',
list_id: 1,
bucket_id: 1,
})
const task = tasks[0]
cy.visit('/lists/1/kanban')
cy.get('.kanban .bucket .tasks .task')
.contains(task.title)
.should('be.visible')
.click()
cy.get('.task-view .action-buttons .button', { timeout: 3000 })
.contains('Move')
.click()
cy.get('.task-view .content.details .field .multiselect.control .input-wrapper input')
.type(`${lists[1].title}{enter}`)
// The requests happen with a 200ms timeout. Because of that, the results are not yet there when cypress
// presses enter and we can't simulate pressing on enter to select the item.
cy.get('.task-view .content.details .field .multiselect.control .search-results')
.children()
.first()
.click()
cy.get('.global-notification', { timeout: 1000 })
.should('contain', 'Success')
cy.go('back')
cy.get('.kanban .bucket')
.should('not.contain', task.title)
})
it('Shows a button to filter the kanban board', () => {
const data = TaskFactory.create(10, {
list_id: 1,
bucket_id: 1,
})
cy.visit('/lists/1/kanban')
cy.get('.list-kanban .filter-container .base-button')
.should('exist')
})
it('Should remove a task from the board when deleting it', () => {
const lists = ListFactory.create(1)
const buckets = BucketFactory.create(2, {
list_id: lists[0].id,
})
const tasks = TaskFactory.create(5, {
list_id: 1,
bucket_id: buckets[0].id,
})
const task = tasks[0]
cy.visit('/lists/1/kanban')
cy.get('.kanban .bucket .tasks .task')
.contains(task.title)
.should('be.visible')
.click()
cy.get('.task-view .action-buttons .button')
.should('be.visible')
.contains('Delete')
.click()
cy.get('.modal-mask .modal-container .modal-content .header')
.should('contain', 'Delete this task')
cy.get('.modal-mask .modal-container .modal-content .actions .button')
.contains('Do it!')
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.kanban .bucket .tasks')
.should('not.contain', task.title)
})
})
-110
View File
@@ -1,110 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {UserListFactory} from '../../factories/users_list'
import {TaskFactory} from '../../factories/task'
import {UserFactory} from '../../factories/user'
import {ListFactory} from '../../factories/list'
import {prepareLists} from './prepareLists'
describe('List View List', () => {
createFakeUserAndLogin()
prepareLists()
it('Should be an empty list', () => {
cy.visit('/lists/1')
cy.url()
.should('contain', '/lists/1/list')
cy.get('.list-title')
.should('contain', 'First List')
cy.get('.list-title-dropdown')
.should('exist')
cy.get('p')
.contains('This list is currently empty.')
.should('exist')
})
it('Should create a new task', () => {
const newTaskTitle = 'New task'
cy.visit('/lists/1')
cy.get('.task-add textarea')
.type(newTaskTitle+'{enter}')
cy.get('.tasks')
.should('contain.text', newTaskTitle)
})
it('Should navigate to the task when the title is clicked', () => {
const tasks = TaskFactory.create(5, {
id: '{increment}',
list_id: 1,
})
cy.visit('/lists/1/list')
cy.get('.tasks .task .tasktext')
.contains(tasks[0].title)
.first()
.click()
cy.url()
.should('contain', `/tasks/${tasks[0].id}`)
})
it('Should not see any elements for a list which is shared read only', () => {
UserFactory.create(2)
UserListFactory.create(1, {
list_id: 2,
user_id: 1,
right: 0,
})
const lists = ListFactory.create(2, {
owner_id: '{increment}',
namespace_id: '{increment}',
})
cy.visit(`/lists/${lists[1].id}/`)
cy.get('.list-title-wrapper .icon')
.should('not.exist')
cy.get('input.input[placeholder="Add a new task..."')
.should('not.exist')
})
it('Should only show the color of a list in the navigation and not in the list view', () => {
const lists = ListFactory.create(1, {
hex_color: '00db60',
})
TaskFactory.create(10, {
list_id: lists[0].id,
})
cy.visit(`/lists/${lists[0].id}/`)
cy.get('.menu-list li .list-menu-link .color-bubble')
.should('have.css', 'background-color', 'rgb(0, 219, 96)')
cy.get('.tasks .color-bubble')
.should('not.exist')
})
it('Should paginate for > 50 tasks', () => {
const tasks = TaskFactory.create(100, {
id: '{increment}',
title: i => `task${i}`,
list_id: 1,
})
cy.visit('/lists/1/list')
cy.get('.tasks')
.should('contain', tasks[1].title)
cy.get('.tasks')
.should('not.contain', tasks[99].title)
cy.get('.card-content .pagination .pagination-link')
.contains('2')
.click()
cy.url()
.should('contain', '?page=2')
cy.get('.tasks')
.should('contain', tasks[99].title)
cy.get('.tasks')
.should('not.contain', tasks[1].title)
})
})
-54
View File
@@ -1,54 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task'
describe('List View Table', () => {
createFakeUserAndLogin()
it('Should show a table with tasks', () => {
const tasks = TaskFactory.create(1)
cy.visit('/lists/1/table')
cy.get('.list-table table.table')
.should('exist')
cy.get('.list-table table.table')
.should('contain', tasks[0].title)
})
it('Should have working column switches', () => {
TaskFactory.create(1)
cy.visit('/lists/1/table')
cy.get('.list-table .filter-container .items .button')
.contains('Columns')
.click()
cy.get('.list-table .filter-container .card.columns-filter .card-content .fancycheckbox .check')
.contains('Priority')
.click()
cy.get('.list-table .filter-container .card.columns-filter .card-content .fancycheckbox .check')
.contains('Done')
.click()
cy.get('.list-table table.table th')
.contains('Priority')
.should('exist')
cy.get('.list-table table.table th')
.contains('Done')
.should('not.exist')
})
it('Should navigate to the task when the title is clicked', () => {
const tasks = TaskFactory.create(5, {
id: '{increment}',
list_id: 1,
})
cy.visit('/lists/1/table')
cy.get('.list-table table.table')
.contains(tasks[0].title)
.click()
cy.url()
.should('contain', `/tasks/${tasks[0].id}`)
})
})
-122
View File
@@ -1,122 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task'
import {prepareLists} from './prepareLists'
describe('Lists', () => {
createFakeUserAndLogin()
let lists
prepareLists((newLists) => (lists = newLists))
it('Should create a new list', () => {
cy.visit('/')
cy.get('.namespace-title .dropdown-trigger')
.click()
cy.get('.namespace-title .dropdown .dropdown-item')
.contains('New list')
.click()
cy.url()
.should('contain', '/lists/new/1')
cy.get('.card-header-title')
.contains('New list')
cy.get('input.input')
.type('New List')
cy.get('.button')
.contains('Create')
.click()
cy.get('.global-notification', { timeout: 1000 }) // Waiting until the request to create the new list is done
.should('contain', 'Success')
cy.url()
.should('contain', '/lists/')
cy.get('.list-title')
.should('contain', 'New List')
})
it('Should redirect to a specific list view after visited', () => {
cy.visit('/lists/1/kanban')
cy.url()
.should('contain', '/lists/1/kanban')
cy.visit('/lists/1')
cy.url()
.should('contain', '/lists/1/kanban')
})
it('Should rename the list in all places', () => {
TaskFactory.create(5, {
id: '{increment}',
list_id: 1,
})
const newListName = 'New list name'
cy.visit('/lists/1')
cy.get('.list-title')
.should('contain', 'First List')
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .menu-list-dropdown-trigger')
.click()
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .dropdown-content')
.contains('Edit')
.click()
cy.get('#title')
.type(`{selectall}${newListName}`)
cy.get('footer.card-footer .button')
.contains('Save')
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.list-title')
.should('contain', newListName)
.should('not.contain', lists[0].title)
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child')
.should('contain', newListName)
.should('not.contain', lists[0].title)
cy.visit('/')
cy.get('.card-content')
.should('contain', newListName)
.should('not.contain', lists[0].title)
})
it('Should remove a list', () => {
cy.visit(`/lists/${lists[0].id}`)
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .menu-list-dropdown-trigger')
.click()
cy.get('.namespace-container .menu.namespaces-lists .menu-list li:first-child .dropdown .dropdown-content')
.contains('Delete')
.click()
cy.url()
.should('contain', '/settings/delete')
cy.get('[data-cy="modalPrimary"]')
.contains('Do it')
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.namespace-container .menu.namespaces-lists .menu-list')
.should('not.contain', lists[0].title)
cy.location('pathname')
.should('equal', '/')
})
it('Should archive a list', () => {
cy.visit(`/lists/${lists[0].id}`)
cy.get('.list-title-dropdown')
.click()
cy.get('.list-title-dropdown .dropdown-menu .dropdown-item')
.contains('Archive')
.click()
cy.get('.modal-content')
.should('contain.text', 'Archive this list')
cy.get('.modal-content [data-cy=modalPrimary]')
.click()
cy.get('.namespace-container .menu.namespaces-lists .menu-list')
.should('not.contain', lists[0].title)
cy.get('main.app-content')
.should('contain.text', 'This list is archived. It is not possible to create new or edit tasks for it.')
})
})
-145
View File
@@ -1,145 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {ListFactory} from '../../factories/list'
import {NamespaceFactory} from '../../factories/namespace'
describe('Namepaces', () => {
createFakeUserAndLogin()
let namespaces
beforeEach(() => {
namespaces = NamespaceFactory.create(1)
ListFactory.create(1)
})
it('Should be all there', () => {
cy.visit('/namespaces')
cy.get('[data-cy="namespace-title"]')
.should('contain', namespaces[0].title)
})
it('Should create a new Namespace', () => {
const newNamespaceTitle = 'New Namespace'
cy.visit('/namespaces')
cy.get('[data-cy="new-namespace"]')
.should('contain', 'New namespace')
.click()
cy.url()
.should('contain', '/namespaces/new')
cy.get('.card-header-title')
.should('contain', 'New namespace')
cy.get('input.input')
.type(newNamespaceTitle)
cy.get('.button')
.contains('Create')
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.namespace-container')
.should('contain', newNamespaceTitle)
cy.url()
.should('contain', '/namespaces')
})
it('Should rename the namespace all places', () => {
const newNamespaces = NamespaceFactory.create(5)
const newNamespaceName = 'New namespace name'
cy.visit('/namespaces')
cy.get(`.namespace-container .menu.namespaces-lists .namespace-title:contains(${newNamespaces[0].title}) .dropdown .dropdown-trigger`)
.click()
cy.get('.namespace-container .menu.namespaces-lists .namespace-title .dropdown .dropdown-content')
.contains('Edit')
.click()
cy.url()
.should('contain', '/settings/edit')
cy.get('#namespacetext')
.invoke('val')
.should('equal', newNamespaces[0].title) // wait until the namespace data is loaded
cy.get('#namespacetext')
.type(`{selectall}${newNamespaceName}`)
cy.get('footer.card-footer .button')
.contains('Save')
.click()
cy.get('.global-notification', { timeout: 1000 })
.should('contain', 'Success')
cy.get('.namespace-container .menu.namespaces-lists')
.should('contain', newNamespaceName)
.should('not.contain', newNamespaces[0].title)
cy.get('[data-cy="namespaces-list"]')
.should('contain', newNamespaceName)
.should('not.contain', newNamespaces[0].title)
})
it('Should remove a namespace when deleting it', () => {
const newNamespaces = NamespaceFactory.create(5)
cy.visit('/')
cy.get(`.namespace-container .menu.namespaces-lists .namespace-title:contains(${newNamespaces[0].title}) .dropdown .dropdown-trigger`)
.click()
cy.get('.namespace-container .menu.namespaces-lists .namespace-title .dropdown .dropdown-content')
.contains('Delete')
.click()
cy.url()
.should('contain', '/settings/delete')
cy.get('[data-cy="modalPrimary"]')
.contains('Do it')
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.namespace-container .menu.namespaces-lists')
.should('not.contain', newNamespaces[0].title)
})
it('Should not show archived lists & namespaces if the filter is not checked', () => {
const n = NamespaceFactory.create(1, {
id: 2,
is_archived: true,
}, false)
ListFactory.create(1, {
id: 2,
namespace_id: n[0].id,
}, false)
ListFactory.create(1, {
id: 3,
is_archived: true,
}, false)
// Initial
cy.visit('/namespaces')
cy.get('.namespace')
.should('not.contain', 'Archived')
// Show archived
cy.get('[data-cy="show-archived-check"] label.check span')
.should('be.visible')
.click()
cy.get('[data-cy="show-archived-check"] input')
.should('be.checked')
cy.get('.namespace')
.should('contain', 'Archived')
// Don't show archived
cy.get('[data-cy="show-archived-check"] label.check span')
.should('be.visible')
.click()
cy.get('[data-cy="show-archived-check"] input')
.should('not.be.checked')
// Second time visiting after unchecking
cy.visit('/namespaces')
cy.get('[data-cy="show-archived-check"] input')
.should('not.be.checked')
cy.get('.namespace')
.should('not.contain', 'Archived')
})
})
-19
View File
@@ -1,19 +0,0 @@
import {ListFactory} from '../../factories/list'
import {NamespaceFactory} from '../../factories/namespace'
import {TaskFactory} from '../../factories/task'
export function createLists() {
NamespaceFactory.create(1)
const lists = ListFactory.create(1, {
title: 'First List'
})
TaskFactory.truncate()
return lists
}
export function prepareLists(setLists = (...args: any[]) => {}) {
beforeEach(() => {
const lists = createLists()
setLists(lists)
})
}
-39
View File
@@ -1,39 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task'
import {ListFactory} from '../../factories/list'
import {NamespaceFactory} from '../../factories/namespace'
import {UserListFactory} from '../../factories/users_list'
describe('Editor', () => {
createFakeUserAndLogin()
beforeEach(() => {
NamespaceFactory.create(1)
ListFactory.create(1)
TaskFactory.truncate()
UserListFactory.truncate()
})
it('Has a preview with checkable checkboxes', () => {
const tasks = TaskFactory.create(1, {
description: `# Test Heading
* Bullet 1
* Bullet 2
* [ ] Checklist
* [x] Checklist checked
`,
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('input[type=checkbox][data-checkbox-num=0]')
.click()
cy.get('.task-view .details.content.description h3 span.is-small.has-text-success')
.contains('Saved!')
.should('exist')
cy.get('.preview.content')
.should('contain', 'Test Heading')
})
})
-35
View File
@@ -1,35 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
describe('The Menu', () => {
createFakeUserAndLogin()
beforeEach(() => {
cy.visit('/')
})
it('Is visible by default on desktop', () => {
cy.get('.namespace-container')
.should('have.class', 'is-active')
})
it('Can be hidden on desktop', () => {
cy.get('button.menu-show-button:visible')
.click()
cy.get('.namespace-container')
.should('not.have.class', 'is-active')
})
it('Is hidden by default on mobile', () => {
cy.viewport('iphone-8')
cy.get('.namespace-container')
.should('not.have.class', 'is-active')
})
it('Is can be shown on mobile', () => {
cy.viewport('iphone-8')
cy.get('button.menu-show-button:visible')
.click()
cy.get('.namespace-container')
.should('have.class', 'is-active')
})
})
-25
View File
@@ -1,25 +0,0 @@
import {LinkShareFactory} from '../../factories/link_sharing'
import {ListFactory} from '../../factories/list'
import {TaskFactory} from '../../factories/task'
describe('Link shares', () => {
it('Can view a link share', () => {
const lists = ListFactory.create(1)
const tasks = TaskFactory.create(10, {
list_id: lists[0].id
})
const linkShares = LinkShareFactory.create(1, {
list_id: lists[0].id,
right: 0,
})
cy.visit(`/share/${linkShares[0].hash}/auth`)
cy.get('h1.title')
.should('contain', lists[0].title)
cy.get('input.input[placeholder="Add a new task..."')
.should('not.exist')
cy.get('.tasks')
.should('contain', tasks[0].title)
})
})
-131
View File
@@ -1,131 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TeamFactory} from '../../factories/team'
import {TeamMemberFactory} from '../../factories/team_member'
import {UserFactory} from '../../factories/user'
describe('Team', () => {
createFakeUserAndLogin()
it('Creates a new team', () => {
TeamFactory.truncate()
cy.visit('/teams')
const newTeamName = 'New Team'
cy.get('a.button')
.contains('Create a new team')
.click()
cy.url()
.should('contain', '/teams/new')
cy.get('.card-header-title')
.contains('Create a new team')
cy.get('input.input')
.type(newTeamName)
cy.get('.button')
.contains('Create')
.click()
cy.url()
.should('contain', '/edit')
cy.get('input#teamtext')
.should('have.value', newTeamName)
})
it('Shows all teams', () => {
TeamMemberFactory.create(10, {
team_id: '{increment}',
})
const teams = TeamFactory.create(10, {
id: '{increment}',
})
cy.visit('/teams')
cy.get('.teams.box')
.should('not.be.empty')
teams.forEach(t => {
cy.get('.teams.box')
.should('contain', t.name)
})
})
it('Allows an admin to edit the team', () => {
TeamMemberFactory.create(1, {
team_id: 1,
admin: true,
})
const teams = TeamFactory.create(1, {
id: 1,
})
cy.visit('/teams/1/edit')
cy.get('.card input.input')
.first()
.type('{selectall}New Team Name')
cy.get('.card .button')
.contains('Save')
.click()
cy.get('table.table td')
.contains('Admin')
.should('exist')
cy.get('.global-notification')
.should('contain', 'Success')
})
it('Does not allow a normal user to edit the team', () => {
TeamMemberFactory.create(1, {
team_id: 1,
admin: false,
})
const teams = TeamFactory.create(1, {
id: 1,
})
cy.visit('/teams/1/edit')
cy.get('.card input.input')
.should('not.exist')
cy.get('table.table td')
.contains('Member')
.should('exist')
})
it('Allows an admin to add members to the team', () => {
TeamMemberFactory.create(1, {
team_id: 1,
admin: true,
})
TeamFactory.create(1, {
id: 1,
})
const users = UserFactory.create(5)
cy.visit('/teams/1/edit')
cy.get('.card')
.contains('Team Members')
.get('.card-content .multiselect .input-wrapper input')
.type(users[1].username)
cy.get('.card')
.contains('Team Members')
.get('.card-content .multiselect .search-results')
.children()
.first()
.click()
cy.get('.card')
.contains('Team Members')
.get('.card-content .button')
.contains('Add to team')
.click()
cy.get('table.table td')
.contains('Admin')
.should('exist')
cy.get('table.table tr')
.should('contain', users[1].username)
.should('contain', 'Member')
cy.get('.global-notification')
.should('contain', 'Success')
})
})
-153
View File
@@ -1,153 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {ListFactory} from '../../factories/list'
import {seed} from '../../support/seed'
import {TaskFactory} from '../../factories/task'
import {NamespaceFactory} from '../../factories/namespace'
import {BucketFactory} from '../../factories/bucket'
import {updateUserSettings} from '../../support/updateUserSettings'
function seedTasks(numberOfTasks = 50, startDueDate = new Date()) {
NamespaceFactory.create(1)
const list = ListFactory.create()[0]
BucketFactory.create(1, {
list_id: list.id,
})
const tasks = []
let dueDate = startDueDate
for (let i = 0; i < numberOfTasks; i++) {
const now = new Date()
dueDate = new Date(new Date(dueDate).setDate(dueDate.getDate() + 2))
tasks.push({
id: i + 1,
list_id: list.id,
done: false,
created_by_id: 1,
title: 'Test Task ' + i,
index: i + 1,
due_date: dueDate.toISOString(),
created: now.toISOString(),
updated: now.toISOString(),
})
}
seed(TaskFactory.table, tasks)
return {tasks, list}
}
describe('Home Page Task Overview', () => {
createFakeUserAndLogin()
it('Should show tasks with a near due date first on the home page overview', () => {
const taskCount = 50
const {tasks} = seedTasks(taskCount)
cy.visit('/')
cy.get('[data-cy="showTasks"] .card .task')
.each(([task], index) => {
expect(task.innerText).to.contain(tasks[index].title)
})
})
it('Should show overdue tasks first, then show other tasks', () => {
const now = new Date()
const oldDate = new Date(new Date(now).setDate(now.getDate() - 14))
const taskCount = 50
const {tasks} = seedTasks(taskCount, oldDate)
cy.visit('/')
cy.get('[data-cy="showTasks"] .card .task')
.each(([task], index) => {
expect(task.innerText).to.contain(tasks[index].title)
})
})
it('Should show a new task with a very soon due date at the top', () => {
const {tasks} = seedTasks()
const newTaskTitle = 'New Task'
cy.visit('/')
TaskFactory.create(1, {
id: 999,
title: newTaskTitle,
due_date: new Date().toISOString(),
}, false)
cy.visit(`/lists/${tasks[0].list_id}/list`)
cy.get('.tasks .task')
.first()
.should('contain.text', newTaskTitle)
cy.visit('/')
cy.get('[data-cy="showTasks"] .card .task')
.first()
.should('contain.text', newTaskTitle)
})
it('Should not show a new task without a date at the bottom when there are > 50 tasks', () => {
// We're not using the api here to create the task in order to verify the flow
const {tasks} = seedTasks(100)
const newTaskTitle = 'New Task'
cy.visit('/')
cy.visit(`/lists/${tasks[0].list_id}/list`)
cy.get('.task-add textarea')
.type(newTaskTitle+'{enter}')
cy.visit('/')
cy.get('[data-cy="showTasks"] .card .task')
.last()
.should('not.contain.text', newTaskTitle)
})
it('Should show a new task without a date at the bottom when there are < 50 tasks', () => {
seedTasks(40)
const newTaskTitle = 'New Task'
TaskFactory.create(1, {
id: 999,
title: newTaskTitle,
}, false)
cy.visit('/')
cy.get('[data-cy="showTasks"] .card .task')
.last()
.should('contain.text', newTaskTitle)
})
it('Should show a task without a due date added via default list at the bottom', () => {
const {list} = seedTasks(40)
updateUserSettings({
default_list_id: list.id,
overdue_tasks_reminders_time: '9:00',
})
const newTaskTitle = 'New Task'
cy.visit('/')
cy.get('.add-task-textarea')
.type(`${newTaskTitle}{enter}`)
cy.get('[data-cy="showTasks"] .card .task')
.last()
.should('contain.text', newTaskTitle)
})
it('Should show the cta buttons for new list when there are no tasks', () => {
TaskFactory.truncate()
cy.visit('/')
cy.get('.home.app-content .content')
.should('contain.text', 'You can create a new list for your new tasks:')
.should('contain.text', 'Or import your lists and tasks from other services into Vikunja:')
})
it('Should not show the cta buttons for new list when there are tasks', () => {
seedTasks()
cy.visit('/')
cy.get('.home.app-content .content')
.should('not.contain.text', 'You can create a new list for your new tasks:')
.should('not.contain.text', 'Or import your lists and tasks from other services into Vikunja:')
})
})
-581
View File
@@ -1,581 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {TaskFactory} from '../../factories/task'
import {ListFactory} from '../../factories/list'
import {TaskCommentFactory} from '../../factories/task_comment'
import {UserFactory} from '../../factories/user'
import {NamespaceFactory} from '../../factories/namespace'
import {UserListFactory} from '../../factories/users_list'
import {TaskAssigneeFactory} from '../../factories/task_assignee'
import {LabelFactory} from '../../factories/labels'
import {LabelTaskFactory} from '../../factories/label_task'
import {BucketFactory} from '../../factories/bucket'
import {TaskAttachmentFactory} from '../../factories/task_attachments'
function addLabelToTaskAndVerify(labelTitle: string) {
cy.get('.task-view .action-buttons .button')
.contains('Add Labels')
.click()
cy.get('.task-view .details.labels-list .multiselect input')
.type(labelTitle)
cy.get('.task-view .details.labels-list .multiselect .search-results')
.children()
.first()
.click()
cy.get('.global-notification', { timeout: 4000 })
.should('contain', 'Success')
cy.get('.task-view .details.labels-list .multiselect .input-wrapper span.tag')
.should('exist')
.should('contain', labelTitle)
}
function uploadAttachmentAndVerify(taskId: number) {
cy.intercept(`${Cypress.env('API_URL')}/tasks/${taskId}/attachments`).as('uploadAttachment')
cy.get('.task-view .action-buttons .button')
.contains('Add Attachments')
.click()
cy.get('input[type=file]', {timeout: 1000})
.selectFile('cypress/fixtures/image.jpg', {force: true}) // The input is not visible, but on purpose
cy.wait('@uploadAttachment')
cy.get('.attachments .attachments .files a.attachment')
.should('exist')
}
describe('Task', () => {
createFakeUserAndLogin()
let namespaces
let lists
let buckets
beforeEach(() => {
// UserFactory.create(1)
namespaces = NamespaceFactory.create(1)
lists = ListFactory.create(1)
buckets = BucketFactory.create(1, {
list_id: lists[0].id,
})
TaskFactory.truncate()
UserListFactory.truncate()
})
it('Should be created new', () => {
cy.visit('/lists/1/list')
cy.get('.input[placeholder="Add a new task…"')
.type('New Task')
cy.get('.button')
.contains('Add')
.click()
cy.get('.tasks .task .tasktext')
.first()
.should('contain', 'New Task')
})
it('Inserts new tasks at the top of the list', () => {
TaskFactory.create(1)
cy.visit('/lists/1/list')
cy.get('.list-is-empty-notice')
.should('not.exist')
cy.get('.input[placeholder="Add a new task…"')
.type('New Task')
cy.get('.button')
.contains('Add')
.click()
cy.wait(1000) // Wait for the request
cy.get('.tasks .task .tasktext')
.first()
.should('contain', 'New Task')
})
it('Marks a task as done', () => {
TaskFactory.create(1)
cy.visit('/lists/1/list')
cy.get('.tasks .task .fancycheckbox label.check')
.first()
.click()
cy.get('.global-notification')
.should('contain', 'Success')
})
it('Can add a task to favorites', () => {
TaskFactory.create(1)
cy.visit('/lists/1/list')
cy.get('.tasks .task .favorite')
.first()
.click()
cy.get('.menu.namespaces-lists')
.should('contain', 'Favorites')
})
describe('Task Detail View', () => {
beforeEach(() => {
TaskCommentFactory.truncate()
LabelTaskFactory.truncate()
})
it('Shows all task details', () => {
const tasks = TaskFactory.create(1, {
id: 1,
index: 1,
description: 'Lorem ipsum dolor sit amet.'
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view h1.title.input')
.should('contain', tasks[0].title)
cy.get('.task-view h1.title.task-id')
.should('contain', '#1')
cy.get('.task-view h6.subtitle')
.should('contain', namespaces[0].title)
.should('contain', lists[0].title)
cy.get('.task-view .details.content.description')
.should('contain', tasks[0].description)
cy.get('.task-view .action-buttons p.created')
.should('contain', 'Created')
})
it('Shows a done label for done tasks', () => {
const tasks = TaskFactory.create(1, {
id: 1,
index: 1,
done: true,
done_at: new Date().toISOString()
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .heading .is-done')
.should('be.visible')
.should('contain', 'Done')
cy.get('.task-view .action-buttons p.created')
.scrollIntoView()
.should('be.visible')
.should('contain', 'Done')
})
it('Can mark a task as done', () => {
const tasks = TaskFactory.create(1, {
id: 1,
done: false,
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .action-buttons .button')
.contains('Mark task done!')
.click()
cy.get('.task-view .heading .is-done')
.should('exist')
.should('contain', 'Done')
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.task-view .action-buttons .button')
.should('contain', 'Mark as undone')
})
it('Shows a task identifier since the list has one', () => {
const lists = ListFactory.create(1, {
id: 1,
identifier: 'TEST',
})
const tasks = TaskFactory.create(1, {
id: 1,
list_id: lists[0].id,
index: 1,
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view h1.title.task-id')
.should('contain', `${lists[0].identifier}-${tasks[0].index}`)
})
it('Can edit the description', () => {
const tasks = TaskFactory.create(1, {
id: 1,
description: 'Lorem ipsum dolor sit amet.'
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .details.content.description .editor button')
.click()
cy.get('.task-view .details.content.description .editor .vue-easymde .EasyMDEContainer .CodeMirror-scroll')
.type('{selectall}New Description')
cy.get('[data-cy="saveEditor"]')
.contains('Save')
.click()
cy.get('.task-view .details.content.description h3 span.is-small.has-text-success')
.contains('Saved!')
.should('exist')
})
it('Can add a new comment', () => {
const tasks = TaskFactory.create(1, {
id: 1,
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .comments .media.comment .editor .vue-easymde .EasyMDEContainer .CodeMirror-scroll')
.should('be.visible')
.type('{selectall}New Comment')
cy.get('.task-view .comments .media.comment .button:not([disabled])')
.contains('Comment')
.should('be.visible')
.click()
cy.get('.task-view .comments .media.comment .editor')
.should('contain', 'New Comment')
cy.get('.global-notification')
.should('contain', 'Success')
})
it('Can move a task to another list', () => {
const lists = ListFactory.create(2)
BucketFactory.create(2, {
list_id: '{increment}'
})
const tasks = TaskFactory.create(1, {
id: 1,
list_id: lists[0].id,
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .action-buttons .button')
.contains('Move')
.click()
cy.get('.task-view .content.details .field .multiselect.control .input-wrapper input')
.type(`${lists[1].title}{enter}`)
// The requests happen with a 200ms timeout. Because of that, the results are not yet there when cypress
// presses enter and we can't simulate pressing on enter to select the item.
cy.get('.task-view .content.details .field .multiselect.control .search-results')
.children()
.first()
.click()
cy.get('.task-view h6.subtitle')
.should('contain', namespaces[0].title)
.should('contain', lists[1].title)
cy.get('.global-notification')
.should('contain', 'Success')
})
it('Can delete a task', () => {
const tasks = TaskFactory.create(1, {
id: 1,
list_id: 1,
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .action-buttons .button')
.should('be.visible')
.contains('Delete')
.click()
cy.get('.modal-mask .modal-container .modal-content .header')
.should('contain', 'Delete this task')
cy.get('.modal-mask .modal-container .modal-content .actions .button')
.contains('Do it!')
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.url()
.should('contain', `/lists/${tasks[0].list_id}/`)
})
it('Can add an assignee to a task', () => {
const users = UserFactory.create(5)
const tasks = TaskFactory.create(1, {
id: 1,
list_id: 1,
})
UserListFactory.create(5, {
list_id: 1,
user_id: '{increment}',
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('[data-cy="taskDetail.assign"]')
.click()
cy.get('.task-view .column.assignees .multiselect input')
.type(users[1].username)
cy.get('.task-view .column.assignees .multiselect .search-results')
.children()
.first()
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.task-view .column.assignees .multiselect .input-wrapper span.assignee')
.should('exist')
})
it('Can remove an assignee from a task', () => {
const users = UserFactory.create(2)
const tasks = TaskFactory.create(1, {
id: 1,
list_id: 1,
})
UserListFactory.create(5, {
list_id: 1,
user_id: '{increment}',
})
TaskAssigneeFactory.create(1, {
task_id: tasks[0].id,
user_id: users[1].id,
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .column.assignees .multiselect .input-wrapper span.assignee')
.get('.remove-assignee')
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.task-view .column.assignees .multiselect .input-wrapper span.assignee')
.should('not.exist')
})
it('Can add a new label to a task', () => {
const tasks = TaskFactory.create(1, {
id: 1,
list_id: 1,
})
LabelFactory.truncate()
const newLabelText = 'some new label'
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .action-buttons .button')
.contains('Add Labels')
.should('be.visible')
.click()
cy.get('.task-view .details.labels-list .multiselect input')
.type(newLabelText)
cy.get('.task-view .details.labels-list .multiselect .search-results')
.children()
.first()
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.task-view .details.labels-list .multiselect .input-wrapper span.tag')
.should('exist')
.should('contain', newLabelText)
})
it('Can add an existing label to a task', () => {
const tasks = TaskFactory.create(1, {
id: 1,
list_id: 1,
})
const labels = LabelFactory.create(1)
LabelTaskFactory.truncate()
cy.visit(`/tasks/${tasks[0].id}`)
addLabelToTaskAndVerify(labels[0].title)
})
it('Can add a label to a task and it shows up on the kanban board afterwards', () => {
const tasks = TaskFactory.create(1, {
id: 1,
list_id: lists[0].id,
bucket_id: buckets[0].id,
})
const labels = LabelFactory.create(1)
LabelTaskFactory.truncate()
cy.visit(`/lists/${lists[0].id}/kanban`)
cy.get('.bucket .task')
.contains(tasks[0].title)
.click()
addLabelToTaskAndVerify(labels[0].title)
cy.get('.modal-content .close')
.click()
cy.get('.bucket .task')
.should('contain.text', labels[0].title)
})
it('Can remove a label from a task', () => {
const tasks = TaskFactory.create(1, {
id: 1,
list_id: 1,
})
const labels = LabelFactory.create(1)
LabelTaskFactory.create(1, {
task_id: tasks[0].id,
label_id: labels[0].id,
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .details.labels-list .multiselect .input-wrapper')
.should('be.visible')
.should('contain', labels[0].title)
cy.get('.task-view .details.labels-list .multiselect .input-wrapper')
.children()
.first()
.get('[data-cy="taskDetail.removeLabel"]')
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.task-view .details.labels-list .multiselect .input-wrapper')
.should('not.contain', labels[0].title)
})
it('Can set a due date for a task', () => {
const tasks = TaskFactory.create(1, {
id: 1,
done: false,
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .action-buttons .button')
.contains('Set Due Date')
.click()
cy.get('.task-view .columns.details .column')
.contains('Due Date')
.get('.date-input .datepicker .show')
.click()
cy.get('.datepicker .datepicker-popup button')
.contains('Tomorrow')
.click()
cy.get('[data-cy="closeDatepicker"]')
.contains('Confirm')
.click()
cy.get('.task-view .columns.details .column')
.contains('Due Date')
.get('.date-input .datepicker-popup')
.should('not.exist')
cy.get('.global-notification')
.should('contain', 'Success')
})
it('Can set a priority for a task', () => {
const tasks = TaskFactory.create(1, {
id: 1,
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .action-buttons .button')
.contains('Set Priority')
.click()
cy.get('.task-view .columns.details .column')
.contains('Priority')
.get('.select select')
.select('Urgent')
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.task-view .columns.details .column')
.contains('Priority')
.get('.select select')
.should('have.value', '4')
})
it('Can set the progress for a task', () => {
const tasks = TaskFactory.create(1, {
id: 1,
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .action-buttons .button')
.contains('Set Progress')
.click()
cy.get('.task-view .columns.details .column')
.contains('Progress')
.get('.select select')
.select('50%')
cy.get('.global-notification')
.should('contain', 'Success')
cy.wait(200)
cy.get('.task-view .columns.details .column')
.contains('Progress')
.get('.select select')
.should('be.visible')
.should('have.value', '0.5')
})
it('Can add an attachment to a task', () => {
TaskAttachmentFactory.truncate()
const tasks = TaskFactory.create(1, {
id: 1,
})
cy.visit(`/tasks/${tasks[0].id}`)
uploadAttachmentAndVerify(tasks[0].id)
})
it('Can add an attachment to a task and see it appearing on kanban', () => {
TaskAttachmentFactory.truncate()
const tasks = TaskFactory.create(1, {
id: 1,
list_id: lists[0].id,
bucket_id: buckets[0].id,
})
const labels = LabelFactory.create(1)
LabelTaskFactory.truncate()
cy.visit(`/lists/${lists[0].id}/kanban`)
cy.get('.bucket .task')
.contains(tasks[0].title)
.click()
uploadAttachmentAndVerify(tasks[0].id)
cy.get('.modal-content .close')
.click()
cy.get('.bucket .task .footer .icon svg.fa-paperclip')
.should('exist')
})
it('Can check items off a checklist', () => {
const tasks = TaskFactory.create(1, {
id: 1,
description: `
This is a checklist:
* [ ] one item
* [ ] another item
* [ ] third item
* [ ] fourth item
* [x] and this one is already done
`,
})
cy.visit(`/tasks/${tasks[0].id}`)
cy.get('.task-view .checklist-summary')
.should('contain.text', '1 of 5 tasks')
cy.get('.editor .content ul > li input[type=checkbox]')
.eq(2)
.click()
cy.get('.editor .content ul > li input[type=checkbox]')
.eq(2)
.should('be.checked')
cy.get('.editor .content input[type=checkbox]')
.should('have.length', 5)
cy.get('.task-view .checklist-summary')
.should('contain.text', '2 of 5 tasks')
})
})
})
-11
View File
@@ -1,11 +0,0 @@
{
"extends": "@vue/tsconfig/tsconfig.web.json",
"include": ["./**/*", "../support/**/*", "../factories/**/*"],
"compilerOptions": {
"baseUrl": ".",
"isolatedModules": false,
"target": "ES2015",
"lib": ["ESNext", "dom"],
"types": ["cypress"]
}
}
-58
View File
@@ -1,58 +0,0 @@
import {UserFactory} from '../../factories/user'
const testAndAssertFailed = fixture => {
cy.visit('/login')
cy.get('input[id=username]').type(fixture.username)
cy.get('input[id=password]').type(fixture.password)
cy.get('.button').contains('Login').click()
cy.wait(5000) // It can take waaaayy too long to log the user in
cy.url().should('include', '/')
cy.get('div.message.danger').contains('Wrong username or password.')
}
const username = 'test'
context('Login', () => {
beforeEach(() => {
UserFactory.create(1, {username})
})
it('Should log in with the right credentials', () => {
const fixture = {
username: 'test',
password: '1234',
}
cy.visit('/login')
cy.get('input[id=username]').type(fixture.username)
cy.get('input[id=password]').type(fixture.password)
cy.get('.button').contains('Login').click()
cy.url().should('include', '/')
cy.clock(1625656161057) // 13:00
cy.get('h2').should('contain', `Hi ${fixture.username}!`)
})
it('Should fail with a bad password', () => {
const fixture = {
username: 'test',
password: '123456',
}
testAndAssertFailed(fixture)
})
it('Should fail with a bad username', () => {
const fixture = {
username: 'loremipsum',
password: '1234',
}
testAndAssertFailed(fixture)
})
it('Should redirect to /login when no user is logged in', () => {
cy.visit('/')
cy.url().should('include', '/login')
})
})
-46
View File
@@ -1,46 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
import {createLists} from '../list/prepareLists'
function logout() {
cy.get('.navbar .username-dropdown-trigger')
.click()
cy.get('.navbar .dropdown-item')
.contains('Logout')
.click()
}
describe('Log out', () => {
createFakeUserAndLogin()
it('Logs the user out', () => {
cy.visit('/')
expect(localStorage.getItem('token')).to.not.eq(null)
logout()
cy.url()
.should('contain', '/login')
.then(() => {
expect(localStorage.getItem('token')).to.eq(null)
})
})
it.skip('Should clear the list history after logging the user out', () => {
const lists = createLists()
cy.visit(`/lists/${lists[0].id}`)
.then(() => {
expect(localStorage.getItem('listHistory')).to.not.eq(null)
})
logout()
cy.wait(1000) // This makes re-loading of the list and associated entities (and the resulting error) visible
cy.url()
.should('contain', '/login')
.then(() => {
expect(localStorage.getItem('listHistory')).to.eq(null)
})
})
})
-48
View File
@@ -1,48 +0,0 @@
// This test assumes no mailer is set up and all users are activated immediately.
import {UserFactory} from '../../factories/user'
context('Registration', () => {
beforeEach(() => {
UserFactory.create(1, {
username: 'test',
})
cy.visit('/', {
onBeforeLoad(win) {
win.localStorage.removeItem('token')
},
})
})
it('Should work without issues', () => {
const fixture = {
username: 'testuser',
password: '123456',
email: 'testuser@example.com',
}
cy.visit('/register')
cy.get('#username').type(fixture.username)
cy.get('#email').type(fixture.email)
cy.get('#password').type(fixture.password)
cy.get('#register-submit').click()
cy.url().should('include', '/')
cy.clock(1625656161057) // 13:00
cy.get('h2').should('contain', `Hi ${fixture.username}!`)
})
it.only('Should fail', () => {
const fixture = {
username: 'test',
password: '123456',
email: 'testuser@example.com',
}
cy.visit('/register')
cy.get('#username').type(fixture.username)
cy.get('#email').type(fixture.email)
cy.get('#password').type(fixture.password)
cy.get('#register-submit').click()
cy.get('div.message.danger').contains('A user with this username already exists.')
})
})
-43
View File
@@ -1,43 +0,0 @@
import {createFakeUserAndLogin} from '../../support/authenticateUser'
describe('User Settings', () => {
createFakeUserAndLogin()
it('Changes the user avatar', () => {
cy.intercept(`${Cypress.env('API_URL')}/user/settings/avatar/upload`).as('uploadAvatar')
cy.visit('/user/settings/avatar')
cy.get('input[name=avatarProvider][value=upload]')
.click()
cy.get('input[type=file]', {timeout: 1000})
.selectFile('cypress/fixtures/image.jpg', {force: true}) // The input is not visible, but on purpose
cy.get('.vue-handler-wrapper.vue-handler-wrapper--south .vue-simple-handler.vue-simple-handler--south')
.trigger('mousedown', {which: 1})
.trigger('mousemove', {clientY: 100})
.trigger('mouseup')
cy.get('[data-cy="uploadAvatar"]')
.contains('Upload Avatar')
.click()
cy.wait('@uploadAvatar')
cy.get('.global-notification')
.should('contain', 'Success')
})
it('Updates the name', () => {
cy.visit('/user/settings/general')
cy.get('.general-settings .control input.input')
.first()
.type('Lorem Ipsum')
cy.get('[data-cy="saveGeneralSettings"]')
.contains('Save')
.click()
cy.get('.global-notification')
.should('contain', 'Success')
cy.get('.navbar .username-dropdown-trigger .username')
.should('contain', 'Lorem Ipsum')
})
})
-19
View File
@@ -1,19 +0,0 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
export class BucketFactory extends Factory {
static table = 'buckets'
static factory() {
const now = new Date()
return {
id: '{increment}',
title: faker.lorem.words(3),
list_id: 1,
created_by_id: 1,
created: now.toISOString(),
updated: now.toISOString(),
}
}
}
-16
View File
@@ -1,16 +0,0 @@
import {Factory} from '../support/factory'
export class LabelTaskFactory extends Factory {
static table = 'label_tasks'
static factory() {
const now = new Date()
return {
id: '{increment}',
task_id: 1,
label_id: 1,
created: now.toISOString(),
}
}
}
-21
View File
@@ -1,21 +0,0 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
export class LabelFactory extends Factory {
static table = 'labels'
static factory() {
const now = new Date()
return {
id: '{increment}',
title: faker.lorem.words(2),
description: faker.lorem.text(10),
hex_color: (Math.random()*0xFFFFFF<<0).toString(16), // random 6-digit hex number
created_by_id: 1,
created: now.toISOString(),
updated: now.toISOString(),
}
}
}
-21
View File
@@ -1,21 +0,0 @@
import {Factory} from '../support/factory'
import {faker} from '@faker-js/faker'
export class LinkShareFactory extends Factory {
static table = 'link_shares'
static factory() {
const now = new Date()
return {
id: '{increment}',
hash: faker.random.word(32),
list_id: 1,
right: 0,
sharing_type: 0,
shared_by_id: 1,
created: now.toISOString(),
updated: now.toISOString(),
}
}
}
-19
View File
@@ -1,19 +0,0 @@
import {Factory} from '../support/factory'
import {faker} from '@faker-js/faker'
export class ListFactory extends Factory {
static table = 'lists'
static factory() {
const now = new Date()
return {
id: '{increment}',
title: faker.lorem.words(3),
owner_id: 1,
namespace_id: 1,
created: now.toISOString(),
updated: now.toISOString(),
}
}
}
-18
View File
@@ -1,18 +0,0 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
export class NamespaceFactory extends Factory {
static table = 'namespaces'
static factory() {
const now = new Date()
return {
id: '{increment}',
title: faker.lorem.words(3),
owner_id: 1,
created: now.toISOString(),
updated: now.toISOString(),
}
}
}
-22
View File
@@ -1,22 +0,0 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
export class TaskFactory extends Factory {
static table = 'tasks'
static factory() {
const now = new Date()
return {
id: '{increment}',
title: faker.lorem.words(3),
done: false,
list_id: 1,
created_by_id: 1,
index: '{increment}',
position: '{increment}',
created: now.toISOString(),
updated: now.toISOString()
}
}
}
-16
View File
@@ -1,16 +0,0 @@
import {Factory} from '../support/factory'
export class TaskAssigneeFactory extends Factory {
static table = 'task_assignees'
static factory() {
const now = new Date()
return {
id: '{increment}',
task_id: 1,
user_id: 1,
created: now.toISOString(),
}
}
}
-16
View File
@@ -1,16 +0,0 @@
import {Factory} from '../support/factory'
export class TaskAttachmentFactory extends Factory {
static table = 'task_attachments'
static factory() {
const now = new Date()
return {
id: '{increment}',
task_id: 1,
file_id: 1,
created: now.toISOString(),
}
}
}
-20
View File
@@ -1,20 +0,0 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
export class TaskCommentFactory extends Factory {
static table = 'task_comments'
static factory() {
const now = new Date()
return {
id: '{increment}',
comment: faker.lorem.text(3),
author_id: 1,
task_id: 1,
created: now.toISOString(),
updated: now.toISOString()
}
}
}
-17
View File
@@ -1,17 +0,0 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
export class TeamFactory extends Factory {
static table = 'teams'
static factory() {
const now = new Date()
return {
name: faker.lorem.words(3),
created_by_id: 1,
created: now.toISOString(),
updated: now.toISOString(),
}
}
}
-14
View File
@@ -1,14 +0,0 @@
import {Factory} from '../support/factory'
export class TeamMemberFactory extends Factory {
static table = 'team_members'
static factory() {
return {
team_id: 1,
user_id: 1,
admin: false,
created: new Date().toISOString(),
}
}
}
-21
View File
@@ -1,21 +0,0 @@
import {faker} from '@faker-js/faker'
import {Factory} from '../support/factory'
export class UserFactory extends Factory {
static table = 'users'
static factory() {
const now = new Date()
return {
id: '{increment}',
username: faker.lorem.word(10) + faker.datatype.uuid(),
password: '$2a$14$dcadBoMBL9jQoOcZK8Fju.cy0Ptx2oZECkKLnaa8ekRoTFe1w7To.', // 1234
status: 0,
issuer: 'local',
created: now.toISOString(),
updated: now.toISOString(),
}
}
}
-18
View File
@@ -1,18 +0,0 @@
import {Factory} from '../support/factory'
export class UserListFactory extends Factory {
static table = 'users_lists'
static factory() {
const now = new Date()
return {
id: '{increment}',
list_id: 1,
user_id: 1,
right: 0,
created: now.toISOString(),
updated: now.toISOString(),
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 872 KiB

-35
View File
@@ -1,35 +0,0 @@
// This authenticates a user and puts the token in local storage which allows us to perform authenticated requests.
// Built after https://github.com/cypress-io/cypress-example-recipes/tree/bd2d6ffb33214884cab343d38e7f9e6ebffb323f/examples/logging-in__jwt
import {UserFactory} from '../factories/user'
export function login(user, cacheAcrossSpecs = false) {
if (!user) {
throw new Error('Needs user')
}
// Caching session when logging in via page visit
cy.session(`user__${user.username}`, () => {
cy.request('POST', `${Cypress.env('API_URL')}/login`, {
username: user.username,
password: '1234',
}).then(({ body }) => {
window.localStorage.setItem('token', body.token)
})
}, {
cacheAcrossSpecs,
})
}
export function createFakeUserAndLogin() {
let user
before(() => {
user = UserFactory.create(1)[0]
})
beforeEach(() => {
login(user, true)
})
return user
}
-37
View File
@@ -1,37 +0,0 @@
/// <reference types="cypress" />
// ***********************************************
// This example commands.ts shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
//
// declare global {
// namespace Cypress {
// interface Chainable {
// login(email: string, password: string): Chainable<void>
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
// }
// }
// }
-12
View File
@@ -1,12 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>Components App</title>
</head>
<body>
<div data-cy-root></div>
</body>
</html>
-29
View File
@@ -1,29 +0,0 @@
// ***********************************************************
// This example support/component.ts is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')
import { mount } from 'cypress/vue'
// Ensure global styles are loaded
import '../../src/styles/global.scss';
Cypress.Commands.add('mount', mount)
// Example use:
// cy.mount(MyComponent)
-10
View File
@@ -1,10 +0,0 @@
import './commands'
import '@4tw/cypress-drag-drop'
// see https://github.com/cypress-io/cypress/issues/702#issuecomment-587127275
Cypress.on('window:before:load', (win) => {
// disable service workers
// @ts-ignore
delete win.navigator.__proto__.ServiceWorker
})
-52
View File
@@ -1,52 +0,0 @@
import {seed} from './seed'
/**
* A factory makes it easy to seed the database with data.
*/
export class Factory {
static table = null
static factory() {
return {}
}
/**
* Seeds a bunch of fake data into the database.
*
* Takes an override object as its single argument which will override the data from the factory.
* If the value of one of the override fields is `{increment}` that value will be replaced with an incrementing
* number through all created entities.
*
* @param override
* @returns {[]}
*/
static create(count = 1, override = {}, truncate = true) {
const data = []
for (let i = 1; i <= count; i++) {
const entry = {
...this.factory(),
...override,
}
for (const e in entry) {
if(typeof entry[e] === 'function') {
entry[e] = entry[e](i)
continue
}
if (entry[e] === '{increment}') {
entry[e] = i
}
}
data.push(entry)
}
seed(this.table, data, truncate)
return data
}
static truncate() {
seed(this.table, null)
}
}
-24
View File
@@ -1,24 +0,0 @@
/**
* Seeds a db table with data. If a data object is provided as the second argument, it will load the fixtures
* file for the table and merge the data from it with the passed data. This allows you to override specific
* fields of the fixtures without having to redeclare the whole fixture.
*
* Passing null as the second argument empties the table.
*
* @param table
* @param data
*/
export function seed(table, data = {}, truncate = true) {
if (data === null) {
data = []
}
cy.request({
method: 'PATCH',
url: `${Cypress.env('API_URL')}/test/${table}?truncate=${truncate ? 'true' : 'false'}`,
headers: {
'Authorization': Cypress.env('TEST_SECRET'),
},
body: data,
})
}
-26
View File
@@ -1,26 +0,0 @@
export function updateUserSettings(settings) {
const token = `Bearer ${window.localStorage.getItem('token')}`
return cy.request({
method: 'GET',
url: `${Cypress.env('API_URL')}/user`,
headers: {
'Authorization': token,
},
})
.its('body')
.then(oldSettings => {
return cy.request({
method: 'POST',
url: `${Cypress.env('API_URL')}/user/settings/general`,
headers: {
'Authorization': token,
},
body: {
...oldSettings,
...settings,
},
})
})
}
-15
View File
@@ -1,15 +0,0 @@
#!/usr/bin/env sh
set -e
echo "info: API URL is $VIKUNJA_API_URL"
echo "info: Sentry enabled: $VIKUNJA_SENTRY_ENABLED"
# Escape the variable to prevent sed from complaining
VIKUNJA_API_URL="$(echo "$VIKUNJA_API_URL" | sed -r 's/([:;])/\\\1/g')"
VIKUNJA_SENTRY_DSN="$(echo "$VIKUNJA_SENTRY_DSN" | sed -r 's/([:;])/\\\1/g')"
sed -ri "s:^(\s*window.API_URL\s*=)\s*.+:\1 '${VIKUNJA_API_URL}':g" /usr/share/nginx/html/index.html
sed -ri "s:^(\s*window.SENTRY_ENABLED\s*=)\s*.+:\1 ${VIKUNJA_SENTRY_ENABLED}:g" /usr/share/nginx/html/index.html
sed -ri "s:^(\s*window.SENTRY_DSN\s*=)\s*.+:\1 '${VIKUNJA_SENTRY_DSN}':g" /usr/share/nginx/html/index.html
date -uIseconds | xargs echo 'info: started at'
-19
View File
@@ -1,19 +0,0 @@
#!/usr/bin/env sh
set -e
if [ ! -f "/proc/net/if_inet6" ]; then
echo "info: IPv6 is not available! Removing IPv6 listen configuration"
find /etc/nginx/conf.d -name '*.conf' -type f | \
while IFS= read -r CONFIG; do
sed -r '/^\s*listen\s*\[::\]:.+$/d' "$CONFIG" > "$CONFIG.temp"
if ! diff -U 5 "$CONFIG" "$CONFIG.temp" > "$CONFIG.diff"; then
echo "info: Removing IPv6 lines from $CONFIG" | \
cat - "$CONFIG.diff"
echo "# IPv6 is disabled because /proc/net/if_inet6 was not found" | \
cat - "$CONFIG.temp" > "$CONFIG"
else
echo "info: Skipping $CONFIG because it does not have IPv6 listen"
fi
rm -f "$CONFIG.temp" "$CONFIG.diff"
done
fi
-112
View File
@@ -1,112 +0,0 @@
# Generated by nginxconfig.io
# https://www.digitalocean.com/community/tools/nginx?domains.0.server.domain=localhost&domains.0.server.documentRoot=%2Fusr%2Fshare%2Fnginx%2Fhtml&domains.0.server.cdnSubdomain=true&domains.0.https.https=false&domains.0.php.php=false&domains.0.routing.index=index.html&domains.0.routing.fallbackHtml=true&domains.0.routing.fallbackPhp=false&global.performance.assetsExpiration=1d&global.performance.mediaExpiration=1d&global.performance.svgExpiration=1d&global.performance.fontsExpiration=1d&global.logging.accessLog=%2Fdev%2Fstdout&global.logging.errorLog=%2Fdev%2Fstderr%20warn&global.logging.logNotFound=true&global.nginx.user=nginx&global.nginx.pid=%2Fvar%2Frun%2Fnginx.pid&global.nginx.clientMaxBodySize=50&global.docker.dockerfile=true&global.tools.modularizedStructure=false&global.tools.symlinkVhost=false
# and then edited manually ;)
pid /tmp/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 65535;
events {
multi_accept on;
worker_connections 1024;
}
http {
charset utf-8;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
types_hash_max_size 2048;
types_hash_bucket_size 64;
# rootless
client_body_temp_path /tmp/client_temp;
proxy_temp_path /tmp/proxy_temp_path;
fastcgi_temp_path /tmp/fastcgi_temp;
uwsgi_temp_path /tmp/uwsgi_temp;
scgi_temp_path /tmp/scgi_temp;
# MIME
include mime.types;
default_type application/octet-stream;
types {
application/manifest+json webmanifest;
}
# Logging
log_format json escape=json
'{'
'"bytes_sent": "$bytes_sent",'
'"http_user_agent": "$http_user_agent",'
'"nginx_version": "$nginx_version",'
'"query_string": "$query_string",'
'"realip_remote_addr": "$realip_remote_addr",'
'"remote_addr": "$remote_addr",'
'"remote_user": "$remote_user",'
'"request_length": "$request_length",'
'"request_method": "$request_method",'
'"request_time": "$request_time",'
'"server_addr": "$server_addr",'
'"server_port": "$server_port",'
'"server_protocol": "$server_protocol",'
'"status": "$status",'
'"time_local": "$time_local",'
'"uri": "$uri"'
'}';
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /dev/stdout main;
error_log /dev/stderr warn;
keepalive_timeout 65;
# compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types
text/plain
text/css
application/json
application/x-javascript
application/javascript
text/xml
application/xml
application/xml+rss
text/javascript
application/vnd.ms-fontobject
application/x-font-ttf
font/opentype
image/svg+xml
image/x-icon
audio/wav;
map_hash_max_size 128;
map_hash_bucket_size 128;
map $sent_http_content_type $expires {
default off;
text/css max;
application/javascript max;
text/javascript max;
application/vnd.ms-fontobject max;
application/x-font-ttf max;
font/opentype max;
font/woff2 max;
image/svg+xml max;
image/x-icon max;
audio/wav max;
~images/ max;
~font/ max;
}
include /etc/nginx/conf.d/*.conf;
}
-85
View File
@@ -1,85 +0,0 @@
server {
listen ${VIKUNJA_HTTP_PORT};
listen [::]:${VIKUNJA_HTTP_PORT};
## Needed when behind HAProxy with SSL termination + HTTP/2 support
listen ${VIKUNJA_HTTP2_PORT} default_server http2 proxy_protocol;
listen [::]:${VIKUNJA_HTTP2_PORT} default_server http2 proxy_protocol;
server_name _;
expires $expires;
root /usr/share/nginx/html;
access_log /dev/stdout ${VIKUNJA_LOG_FORMAT};
# security headers
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';" always;
add_header Permissions-Policy "interest-cohort=()" always;
# . files
location ~ /\.(?!well-known) {
deny all;
}
# assume that everything else is handled by the application router, by injecting the index.html.
location / {
autoindex off;
expires off;
add_header Cache-Control "public, max-age=0, s-maxage=0, must-revalidate" always;
try_files $uri /index.html =404;
}
# Disable caching for sw
location = /sw.js {
autoindex off;
expires off;
add_header Cache-Control "public, max-age=0, s-maxage=0, must-revalidate" always;
}
# Disable caching for webmanifest
location = /manifest.webmanifest {
autoindex off;
expires off;
add_header Cache-Control "public, max-age=0, s-maxage=0, must-revalidate" always;
}
# favicon.ico
location = /favicon.ico {
log_not_found off;
access_log off;
}
# robots.txt
location = /robots.txt {
log_not_found off;
access_log off;
expires -1; # no-cache
}
location = /ready {
return 200 "";
access_log off;
expires -1; # no-cache
}
# all assets contain hash in filename, cache forever
location ^~ /assets/ {
add_header Cache-Control "public, max-age=31536000, s-maxage=31536000, immutable";
try_files $uri =404;
}
# all workbox scripts are compiled with hash in filename, cache forever3
location ^~ /workbox- {
add_header Cache-Control "public, max-age=31536000, s-maxage=31536000, immutable";
try_files $uri =404;
}
# assets, media
location ~* .(txt|webmanifest|css|js|mjs|map|svg|jpg|jpeg|png|ico|ttf|woff|woff2|wav)$ {
try_files $uri $uri/ =404;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html { }
}
+3
View File
@@ -0,0 +1,3 @@
FROM nginx
ADD public /usr/share/nginx/html/docs
ADD nginx.conf /etc/nginx/conf.d/default.conf
+42
View File
@@ -0,0 +1,42 @@
baseurl: https://vikunja.io/docs/
title: Vikunja
theme: vikunja
enableRobotsTXT: true
canonifyURLs: true
pygmentsUseClasses: true
permalinks:
post: /:year/:month/:title/
doc: /:slug/
page: /:slug/
default: /:slug/
params:
description: The to-do app to organize your life
author: The Vikunja Authors
website: https://vikunja.io
fanthomEnabled: false
fathomUrl: fathom.kolaente.de
fathomSiteID: RYKSD
menu:
page:
- name: Home
url: https://vikunja.io/en/
weight: 10
- name: Features
url: https://vikunja.io/en/features
weight: 20
- name: Download
url: https://vikunja.io/en/download
weight: 30
- name: Docs
url: https://vikunja.io/docs
weight: 40
- name: Code
url: https://code.vikunja.io/
weight: 50
- name: Community
url: https://community.vikunja.io/
weight: 60
+25
View File
@@ -0,0 +1,25 @@
---
date: "2019-02-12:00:00+02:00"
title: "Docs"
draft: false
url: "/docs"
type: "doc"
weight: 10
---
# Documentation
This is the documentation for Vikunja.
You can find available articles in the menu on the left.
## About
To learn more about the what, why and how, take a look at [the features page](https://vikunja.io/en/features).
## Start
A good starting point if you want to install and host Vikunja on your server are [the install documentation](installing)
and [available configuration options](config-options).
## Developing
If you want to start contributing to Vikunja, take a look at [the development docs](development).
+34
View File
@@ -0,0 +1,34 @@
---
date: "2019-03-31:00:00+01:00"
title: "Adding new cli commands"
draft: false
type: "doc"
menu:
sidebar:
parent: "development"
---
# Adding new cli commands
All cli-related functions are located in `pkg/cmd`.
Each cli command usually calls a function in another package.
For example, the `vikunja migrate` command calls `migration.Migrate()`.
Vikunja uses the amazing [cobra](https://github.com/spf13/cobra) library for its cli.
Please refer to its documentation for informations about how to use flags etc.
To add a new cli command, add something like the following:
{{< highlight golang >}}
func init() {
rootCmd.AddCommand(myCmd)
}
var myCmd = &cobra.Command{
Use: "My-command",
Short: "A short description about your command.",
Run: func(cmd *cobra.Command, args []string) {
// Call other functions
},
}
{{</ highlight >}}
@@ -0,0 +1,71 @@
---
date: "2019-03-29:00:00+02:00"
title: "Database migrations"
draft: false
type: "doc"
menu:
sidebar:
parent: "development"
---
# Database Migrations
Vikunja runs all database migrations automatically on each start if needed.
Additionally, they can also be run directly by using the `migrate` command.
We use [xormigrate](https://github.com/techknowlogick/xormigrate) to handle migrations,
which is based on gormigrate.
## Add a new migration
All migrations are stored in `pkg/migrations` and files should have the same name as their id.
Each migration should have a function to apply and roll it back, as well as a numeric id (the datetime)
and a more in-depth description of what the migration actually does.
To easily get a new id, run the following on any unix system:
{{< highlight bash >}}
date +%Y%m%d%H%M%S
{{< /highlight >}}
New migrations should be added via the `init()` function to the `migrations` variable.
All migrations are sorted before being executed, since `init()` does not guarantee the order.
When you're adding a new struct, you also need to add it to the `models.GetTables()` function
to ensure it will be created on new installations.
### Example
{{< highlight golang >}}
package migration
import (
"github.com/go-xorm/xorm"
"src.techknowlogick.com/xormigrate"
)
// Used for rollback
type teamMembersMigration20190328074430 struct {
Updated int64 `xorm:"updated"`
}
func (teamMembersMigration20190328074430) TableName() string {
return "team_members"
}
func init() {
migrations = append(migrations, &xormigrate.Migration{
ID: "20190328074430",
Description: "Remove updated from team_members",
Migrate: func(tx *xorm.Engine) error {
return dropTableColum(tx, "team_members", "updated")
},
Rollback: func(tx *xorm.Engine) error {
return tx.Sync2(teamMembersMigration20190328074430{})
},
})
}
{{< /highlight >}}
You should always copy the changed parts of the struct you're changing when adding migraitons.
@@ -0,0 +1,68 @@
---
date: "2019-02-12:00:00+02:00"
title: "Development"
toc: true
draft: false
type: "doc"
menu:
sidebar:
parent: "development"
name: "Development"
---
# Development
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.
A lot of developing tasks are automated using a Makefile, so make sure to [take a look at it]({{< ref "make.md">}}).
## Libraries
We keep all libraries used for Vikunja around in the `vendor/` folder to still be able to build the project even if
some maintainers take their libraries down like [it happened in the past](https://github.com/jteeuwen/go-bindata/issues/5).
## Tests
See [testing]({{< ref "test.md">}}).
#### Development using go modules
If you're able to use go modules, you can clone the project wherever you want to and work from there.
However, when building or running tests, please supply the `-mod=vendor` flag to go so it builds using the
dependencies from the `vendor/` folder.
#### Development-setup without go modules
Some internal packages are referenced using their respective package URL. This can become problematic.
To “trick” the Go tool into thinking this is a clone from the official repository, download the source code
into `$GOPATH/code.vikunja.io/api`. Fork the Vikunja repository, it should then be possible to switch the source directory on the command line.
{{< highlight bash >}}
cd $GOPATH/src/code.vikunja.io/api
{{< /highlight >}}
To be able to create pull requests, the forked repository should be added as a remote to the Vikunja sources, otherwise changes can’t be pushed.
{{< highlight bash >}}
git remote rename origin upstream
git remote add origin git@git.kolaente.de:<USERNAME>/api.git
git fetch --all --prune
{{< /highlight >}}
This should provide a working development environment for Vikunja. Take a look at the Makefile to get an overview about
the available tasks. The most common tasks should be `make test` which will start our test environment and `make build`
which will build a vikunja binary into the working directory. Writing test cases is not mandatory to contribute, but it
is highly encouraged and helps developers sleep at night.
That’s it! You are ready to hack on Vikunja. Test changes, push them to the repository, and open a pull request.
## Static assets
Each Vikunja release contains all static assets directly compiled into the binary.
To prevent this during development, use the `dev` tag when developing.
See the [make docs](make.md#statically-compile-all-templates-into-the-binary) about how to compile with static assets for a release.
+151
View File
@@ -0,0 +1,151 @@
---
date: "2019-02-12:00:00+02:00"
title: "Makefile"
draft: false
type: "doc"
menu:
sidebar:
parent: "development"
---
# Makefile
We scripted a lot of tasks used mostly for developing into the makefile. This documents explains what
taks are available and what they do.
## CI
These tasks are automatically run in our CI every time someone pushes to master or you update a pull request:
* `make lint`
* `make fmt-check`
* `make ineffassign-check`
* `make misspell-check`
* `make goconst-check`
* `make generate`
* `make build`
### clean
{{< highlight bash >}}
make clean
{{< /highlight >}}
Clears all builds and binaries.
### test
{{< highlight bash >}}
make test
{{< /highlight >}}
Runs all tests in Vikunja.
### Format the code
{{< highlight bash >}}
make fmt
{{< /highlight >}}
Formats all source code using `go fmt`.
#### Check formatting
{{< highlight bash >}}
make fmt-check
{{< /highlight >}}
Checks if the code needs to be formatted. Fails if it does.
### Build Vikunja
{{< highlight bash >}}
make build
{{< /highlight >}}
Builds a `vikunja`-binary in the root directory of the repo for the platform it is run on.
### Statically compile all templates into the binary
{{< highlight bash >}}
make generate
{{< /highlight >}}
This generates static code with all templates, meaning no template need to be referenced at runtime.
### Compress the built binary
{{< highlight bash >}}
make compress-build
{{< /highlight >}}
Go binaries are very big.
To make the vikunja binary smaller, we can compress it using [upx](https://upx.github.io/).
### Build Releases
{{< highlight bash >}}
make release
{{< /highlight >}}
Builds binaries for all platforms and zips them with a copy of the `templates/` folder.
All built zip files are stored into `dist/zips/`. Binaries are stored in `dist/binaries/`,
binaries bundled with `templates` are stored in `dist/releases/`.
All cross-platform binaries built using this series of commands are built with the help of
[xgo](https://github.com/techknowlogick/xgo). The make command will automatically install the
binary to be able to use it.
`make release` is actually just a shortcut to execute `make release-dirs release-windows release-linux release-darwin release-copy release-check release-os-package release-zip`.
* `release-dirs` creates all directories needed
* `release-windows`/`release-linux`/`release-darwin` execute xgo to build for their respective platforms
* `release-copy` bundles binaries with a copy of `templates/` to then be zipped
* `release-check` creates sha256 checksums for each binary which will be included in the zip file
* `release-os-package` bundles a binary with a copy of the `templates/` folder, the `sha256` checksum file, a sample `config.yml` and a copy of the license in a folder for each architecture
* `release-compress` compresses all build binaries, see `compress-build`
* `release-zip` makes a zip file for the files created by `release-os-package`
### Build debian packages
{{< highlight bash >}}
make build-deb
{{< /highlight >}}
Will build a `.deb` package into the current folder. You need to have [fpm](https://fpm.readthedocs.io/en/latest/intro.html) installed to be able to do this.
#### Make a debian repo
{{< highlight bash >}}
make reprepro
{{< /highlight >}}
Takes an already built debian package and creates a debian repo structure around it.
Used to be run inside a [docker container](https://git.kolaente.de/konrad/reprepro-docker) in the CI process when releasing.
### Generate swagger definitions from code comments
{{< highlight bash >}}
make do-the-swag
{{< /highlight >}}
Generates swagger definitions from the comments in the code.
#### Check if swagger generation is needed
{{< highlight bash >}}
make got-swag
{{< /highlight >}}
This command is currently more an experiment, use it with caution.
It may bring up wrong results.
### Code-Checks
* `misspell-check`: Checks for commonly misspelled words
* `ineffassign-check`: Checks for ineffectual assignments in the code using [ineffassign](https://github.com/gordonklaus/ineffassign).
* `gocyclo-check`: Calculates cyclomatic complexities of functions using [gocyclo](https://github.com/fzipp/gocyclo).
* `static-check`: Analyzes the code for bugs, improvements and more using [staticcheck](https://staticcheck.io/docs/).
* `gosec-check`: Inspects source code for security problems by scanning the Go AST using the [gosec tool](https://github.com/securego/gosec).
* `goconst-check`: Finds repeated strings that could be replaced by a constant using [goconst](https://github.com/jgautheron/goconst/).
+96
View File
@@ -0,0 +1,96 @@
---
date: "2020-01-19:16:00+02:00"
title: "Migrations"
draft: false
type: "doc"
menu:
sidebar:
parent: "development"
---
# Writing a migrator for Vikunja
It is possible to migrate data from other to-do services to Vikunja.
To make this easier, we have put together a few helpers which are documented on this page.
In general, each migrator implements a migrator interface which is then called from a client.
The interface makes it possible to use helper methods which handle http an focus only on the implementation of the migrator itself.
### Structure
All migrator implementations live in their own package in `pkg/modules/migration/<name-of-the-service>`.
When creating a new migrator, you should place all related code inside that module.
### Migrator interface
The migrator interface is defined as follows:
```go
// Migrator is the basic migrator interface which is shared among all migrators
type Migrator interface {
// Migrate is the interface used to migrate a user's tasks from another platform to vikunja.
// The user object is the user who's tasks will be migrated.
Migrate(user *models.User) error
// AuthURL returns a url for clients to authenticate against.
// The use case for this are Oauth flows, where the server token should remain hidden and not
// known to the frontend.
AuthURL() string
// Name holds the name of the migration.
// This is used to show the name to users and to keep track of users who already migrated.
Name() string
}
```
### Defining http routes
Once your migrator implements the migration interface, it becomes possible to use the helper http handlers.
Their usage is very similar to the [general web handler](https://kolaente.dev/vikunja/web#user-content-defining-routes-using-the-standard-web-handler):
The `RegisterRoutes(m)` method registers all routes with the scheme `/[MigratorName]/(auth|migrate|status)` for the
authUrl, Status and Migrate methods.
```go
// This is an example for the Wunderlist migrator
if config.MigrationWunderlistEnable.GetBool() {
wunderlistMigrationHandler := &migrationHandler.MigrationWeb{
MigrationStruct: func() migration.Migrator {
return &wunderlist.Migration{}
},
}
wunderlistMigrationHandler.RegisterRoutes(m)
}
```
You should also document the routes with [swagger annotations]({{< ref "../practical-instructions/swagger-docs.md" >}}).
### Insertion helper method
There is a method available in the `migration` package which takes a fully nested Vikunja structure and creates it with all relations.
This means you start by adding a namespace, then add lists inside of that namespace, then tasks in the lists and so on.
The root structure must be present as `[]*models.NamespaceWithLists`.
Then call the method like so:
```go
fullVikunjaHierachie, err := convertWunderlistToVikunja(wContent)
if err != nil {
return
}
err = migration.InsertFromStructure(fullVikunjaHierachie, user)
```
### Configuration
You should add at least an option to enable or disable the migration.
Chances are, you'll need some more options for things like client ID and secret
(if the other service uses oAuth as an authentication flow).
The easiest way to implement an on/off switch is to check whether your migration service is enabled or not when
registering the routes, and then simply don't registering the routes in the case it is disabled.
#### Making the migrator public in `/info`
You should make your migrator available in the `/info` endpoint so that frontends can display options to enable them or not.
To do this, add an entry to `pkg/routes/api/v1/info.go`.
+199
View File
@@ -0,0 +1,199 @@
---
date: "2019-02-12:00:00+02:00"
title: "Project structure"
draft: false
type: "doc"
menu:
sidebar:
parent: "development"
---
# Project structure
In general, this api repo has the following structure:
* `docker`
* `docs`
* `pkg`
* `caldav`
* `cmd`
* `config`
* `db`
* `fixtures`
* `files`
* `integration`
* `log`
* `mail`
* `metrics`
* `migration`
* `models`
* `modules`
* `migration`
* `handler`
* `wunderlist`
* `red`
* `routes`
* `api/v1`
* `static`
* `swagger`
* `user`
* `utils`
* `version`
* `REST-Tests`
* `templates`
* `vendor`
This document will explain what these mean and what you can find where.
## Root level
The root directory is where [the config file]({{< ref "../setup/config.md">}}), [Makefile]({{< ref "make.md">}}), license, drone config,
application entry point (`main.go`) and so on are located.
## docker
This directory holds additonal files needed to build and run the docker container, mainly service configuration to properly run Vikunja inside a docker
container.
## pkg
This is where most of the magic happens. Most packages with actual code are located in this folder.
### caldav
This folder holds a simple caldav implementation which is responsible for returning the caldav feature.
### cmd
This package contains all cli-related files and functions.
To learn more about how to add a new command, see [the cli docs]({{< ref "cli.md">}}).
To learn more about how to use this cli, see [the cli usage docs]({{< ref "../usage/cli.md">}}).
### config
This package configures the config. It sets default values and sets up viper and tells it where to look for config files,
how to interpret which env variables for config etc.
If you want to add a new config parameter, you should add default value in this package.
### db
This package contains the db connection handling and db fixtures for testing.
Each other package gets its db connection object from this package.
### files
This package is responsible for all file-related things.
This means it handles saving and retrieving files from the db and the underlying file system.
### integration
All integration tests live here.
See [integration tests]({{< ref "test.md" >}}#integration-tests) for more details.
### log
Similar to `config`, this will set up the logging, based on differen logging backends.
This init is called in `main.go` after the config init is done.
### mail
This package handles all mail sending. To learn how to send a mail, see [sending emails]({{< ref "../practical-instructions/mail.md">}}).
### metrics
This package handles all metrics which are exposed to the prometheus endpoint.
To learn how it works and how to add new metrics, take a look at [how metrics work]({{< ref "../practical-instructions/metrics.md">}}).
### migration
This package handles all migrations.
All migrations are stored and executed here.
To learn more, take a look at the [migrations docs]({{< ref "../development/db-migrations.md">}}).
### models
This is where most of the magic happens.
When adding new features or upgrading existing ones, that most likely happens here.
Because this package is pretty huge, there are several documents and how-to's about it:
* [Adding a feature]({{< ref "../practical-instructions/feature.md">}})
* [Making calls to the database]({{< ref "../practical-instructions/database.md">}})
### modules
#### migration
See [writing a migrator]({{< ref "migration.md" >}}).
### red (redis)
This package initializes a connection to a redis server.
This inizialization is automatically done at the startup of vikunja.
It also has a function (`GetRedis()`) which returns a redis client object you can then use in your package
to talk to redis.
It uses the [go-redis](https://github.com/go-redis/redis) library, please see their configuration on how to use it.
### routes
This package defines all routes which are available for vikunja clients to use.
To add a new route, see [adding a new route]({{< ref "../practical-instructions/feature.md">}}).
#### api/v1
This is where all http-handler functions for the api are stored.
Every handler function which does not use the standard web handler should live here.
### static
All static files generated by `make generate` live here.
### swagger
This is where the [generated]({{< ref "make.md#generate-swagger-definitions-from-code-comments">}} [api docs]({{< ref "../usage/api.md">}}) live.
You usually don't need to touch this package.
### user
All user-related things like registration etc. live in this package.
### utils
A small package, containing some helper functions:
* `MakeRandomString`: Generates a random string of a given length.
* `Sha256`: Calculates a sha256 hash from a given string.
See their function definitions for instructions on how to use them.
### version
The single purpouse of this package is to hold the current vikunja version which gets overridden through build flags
each time `make release` or `make build` is run.
It is a seperate package to avoid import cycles with other packages.
## REST-Tests
Holds all kinds of test files to directly test the api from inside of [jetbrains ide's](https://www.jetbrains.com/help/idea/http-client-in-product-code-editor.html).
These files are currently more an experiment, maybe we will drop them in the future to use something we could integrate in the testing process with drone.
Therefore, this has no claim to be complete yet even working, you're free to change whatever is needed to get it working for you.
## templates
Holds the email templates used to send plain text and html emails for new user registration and password changes.
## vendor
All libraries needed to build Vikunja.
We keep all libraries used for Vikunja around in the `vendor/` folder to still be able to build the project even if
some maintainers take their libraries down like [it happened in the past](https://github.com/jteeuwen/go-bindata/issues/5).
When adding a new dependency, make sure to run `go mod vendor` to put it inside this directory.
+70
View File
@@ -0,0 +1,70 @@
---
date: "2019-02-12:00:00+02:00"
title: "Testing"
draft: false
type: "doc"
menu:
sidebar:
parent: "development"
---
# Testing
You can run unit tests with [our `Makefile`]({{< ref "make.md">}}) with
{{< highlight bash >}}
make test
{{< /highlight >}}
### Running tests with config
You can run tests with all available config variables if you want, enabeling you to run tests for a lot of scenarios.
To use the normal config set the enviroment variable `VIKUNJA_TESTS_USE_CONFIG=1`.
### Show sql queries
When `UNIT_TESTS_VERBOSE=1` is set, all sql queries will be shown when tests are run.
### Fixtures
All tests are run against a set of db fixtures.
These fixtures are defined in `pkg/models/fixtures` in YAML-Files which represent the database structure.
When you add a new test case which requires new database entries to test against, update these files.
# Integration tests
All integration tests live in `pkg/integrations`.
You can run them by executing `make integration-test`.
The integration tests use the same config and fixtures as the unit tests and therefor have the same options available,
see at the beginning of this document.
To run integration tests, use `make integration-test`.
# Initializing db fixtures when writing tests
All db fixtures for all tests live in the `pkg/db/fixtures/` folder as yaml files.
Each file has the same name as the table the fixtures are for.
You should put new fixtures in this folder.
When initializing db fixtures, you are responsible for defining which tables your package needs in your test init function.
Usually, this is done as follows (this code snippet is taken from the `user` package):
```go
err = db.InitTestFixtures("users")
if err != nil {
log.Fatal(err)
}
```
In your actual tests, you then load the fixtures into the in-memory db like so:
```go
db.LoadAndAssertFixtures(t)
```
This will load all fixtures you defined in your test init method.
You should always use this method to load fixtures, the only exception is when your package tests require extra test
fixtures other than db fixtures (like files).
@@ -0,0 +1,38 @@
---
date: "2019-02-12:00:00+02:00"
title: "Database"
draft: false
type: "doc"
menu:
sidebar:
parent: "practical instructions"
---
# Database
Vikunja uses [xorm](http://xorm.io/) as an abstraction layer to handle the database connection.
Please refer to [their](http://xorm.io/docs/) documentation on how to exactly use it.
Inside the `models` package, a variable `x` is available which contains a pointer to an instance of `xorm.Engine`.
This is used whenever you make a call to the database to get or update data.
This xorm instance is set up and initialized every time vikunja is started.
### Adding new database tables
To add a new table to the database, add a an instance of your struct to the `tables` variable in the
init function in `pkg/models/models.go`. Xorm will sync them automatically.
You also need to add a pointer to the `tablesWithPointer` slice to enable caching for all instances of this struct.
To learn more about how to configure your struct to create "good" tables, refer to [the xorm documentaion](http://xorm.io/docs/).
### Adding data to test fixtures
Adding data for test fixtures is done in via `yaml` files insinde of `pkg/models/fixtures`.
The name of the yaml file should equal the table name in the database.
Adding values to it is done via array definition inside of the yaml file.
**Note**: Table and column names need to be in snake_case as that's what is used internally in the database
and for mapping values from the database to xorm so your structs can use it.
@@ -0,0 +1,72 @@
---
date: "2019-02-12:00:00+02:00"
title: "Custom Errors"
draft: false
type: "doc"
menu:
sidebar:
parent: "practical instructions"
---
# Custom Errors
All custom errors are defined in `pkg/models/errors.go`.
You should add new ones in this file.
Custom errors usually have fields for the http return code, a [vikunja-specific error code]({{< ref "../usage/errors.md">}})
and a human-readable error message about what went wrong.
An error consists of multiple functions and definitions:
{{< highlight golang >}}
// This struct holds any information about this specific error.
// In this case, it contains the user ID of a nonexistand user.
// This type should always be a struct, even if it has no values in it.
// ErrUserDoesNotExist represents a "UserDoesNotExist" kind of error.
type ErrUserDoesNotExist struct {
UserID int64
}
// This function is mostly used in unit tests to check if a returned error is of that type.
// Every error type should have one of these.
// The name should always start with IsErr... followed by the name of the error.
// IsErrUserDoesNotExist checks if an error is a ErrUserDoesNotExist.
func IsErrUserDoesNotExist(err error) bool {
_, ok := err.(ErrUserDoesNotExist)
return ok
}
// This is the definition of the actual error type.
// Your error type is _required_ to implement this in order to be able to be returned as an "error" from functions.
func (err ErrUserDoesNotExist) Error() string {
return fmt.Sprintf("User does not exist [user id: %d]", err.UserID)
}
// This const holds the vikunja error code used to be able to identify this error without having to
// rely on an error string.
// This needs to be unique, so you should check whether the error code exists or not.
// The general convention for error codes is as follows:
// * Every "group" errors lives in a thousend something. For example all user issues are 1000-something, all
// list errors are 3000-something and so on.
// * New error codes should be the current max error code + 1. Don't take free numbers to prevent old errors
// which are depricated and removed from being "new ones". For example, if there are error codes 1001, 1002, 1004,
// a new error should be 1005 and not 1003.
// ErrCodeUserDoesNotExist holds the unique world-error code of this error
const ErrCodeUserDoesNotExist = 1005
// This is the implementation which returns an http error which is then passed to the client.
// Here you define the http status code with which one the error will be returned, the vikunja error code and
// a human-readable error message.
// HTTPError holds the http error description
func (err ErrUserDoesNotExist) HTTPError() web.HTTPError {
return web.HTTPError{
HTTPCode: http.StatusNotFound,
Code: ErrCodeUserDoesNotExist,
Message: "The user does not exist.",
}
}
{{< /highlight >}}
@@ -0,0 +1,33 @@
---
date: "2019-02-12:00:00+02:00"
title: "Add a new api endpoint"
draft: false
type: "doc"
menu:
sidebar:
parent: "practical instructions"
---
# Add a new api endpoint/feature
Most of the api endpoints/features of Vikunja are using the [common web handler](https://code.vikunja.io/web).
This is a library created by Vikunja in an effort to facilitate the creation of REST endpoints.
This works by abstracting the handling of CRUD-Requests, including rights check.
You can learn more about the web handler on [the project's repo](https://code.vikunja.io/web).
### Helper for pagination
Pagination limits can be calculated with a helper function, `getLimitFromPageIndex(pageIndex)`
(only available in the `models` package) from any page number.
It returns the `limit` (max-length) and `offset` parameters needed for SQL-Queries.
You can feed this function directly into xorm's `Limit`-Function like so:
{{< highlight golang >}}
lists := []List{}
err := x.Limit(getLimitFromPageIndex(pageIndex, itemsPerPage)).Find(&lists)
{{< /highlight >}}
// TODO: Add a full example from start to finish, like a tutorial on how to create a new endpoint?
@@ -0,0 +1,84 @@
---
date: "2019-02-12:00:00+02:00"
title: "Mailer"
draft: false
type: "doc"
menu:
sidebar:
parent: "practical instructions"
---
# Mailer
This document explains how to use the mailer to send emails and what to do to create a new kind of email to be sent.
## Sending emails
**Note:** You should use mail templates whenever possible (see below).
To send an email, use the function `mail.SendMail(options)`. The options are defined as follows:
{{< highlight golang >}}
type Opts struct {
To string // The email address of the recipent
Subject string // The subject of the mail
Message string // The plaintext message in the mail
HTMLMessage string // The html message
ContentType ContentType // The content type of the mail. Can be either mail.ContentTypePlain, mail.ContentTypeHTML, mail.ContentTypeMultipart. You should set this according to the kind of mail you want to send.
Boundary string
Headers []*header // Other headers to set in the mail.
}
{{< /highlight >}}
## Sending emails based on a template
For each mail with a template, there are two email templates: One for plaintext emails, one for html emails.
These are located in the `templates/mail` folder and follow the conventions of `template-name.{plain|hmtl}.tmpl`,
both the plaintext and html templates are in the same folder.
To send a mail based on a template, use the function `mail.SendMailWithTemplate(to, subject, tpl string, data map[string]interface{})`.
`to` and `subject` are pretty much self-explanatory, `tpl` is the name of the template, without `.html.tmpl` or `.plain.tmpl`.
`data` is a map you can pass additional data to your template.
#### Sending a mail with a template
A basic html email template would look like this:
{{< highlight go-html-template >}}
{{template "mail-header.tmpl" .}}
<p>
Hey there!<br/>
This is a minimal html email example.<br/>
{{.Something}}
</p>
{{template "mail-footer.tmpl"}}
{{< /highlight >}}
And the corresponding plaintext template:
{{< highlight go-text-template >}}
Hey there!
This is a minimal html email example.
{{.Something}}
{{< /highlight >}}
You would then call this like so:
{{< highlight golang >}}
data := make(map[string]interface{})
data["Something"] = "I am some computed value"
to := "test@example.com"
subject := "A simple test mail"
tpl := "demo" // Assuming you saved the templates as demo.plain.tmpl and demo.html.tmpl
mail.SendMailWithTemplate(to, subject, tpl, data)
{{< /highlight >}}
The function does not return an error. If an error occures when sending a mail, it is logged but not returned because sending the mail happens asinchrounly.
Notice the `mail-header.tmpl` and `mail-footer.tmpl` in the template. These populate some basic css, a box for your content and the vikunja logo.
All that's left for you is to put the content in, which then will appear in a beautifully-styled box.
Remeber, these are email templates. This is different from normal html/css, you cannot use whatever you want (because most of the clients are wayyy to outdated).
@@ -0,0 +1,46 @@
---
date: "2019-02-12:00:00+02:00"
title: "Metrics"
draft: false
type: "doc"
menu:
sidebar:
parent: "practical instructions"
---
# Metrics
Metrics work by exposing a `/metrics` endpoint which can then be accessed by prometheus.
To keep the load on the database minimal, metrics are stored and updated in redis.
The `metrics` package provides several functions to create and update metrics.
## New metrics
First, define a `const` with the metric key in redis. This is done in `pkg/metrics/metrics.go`.
To expose a new metric, you need to register it in the `init` function inside of the `metrics` package like so:
{{< highlight golang >}}
// Register total user count metric
promauto.NewGaugeFunc(prometheus.GaugeOpts{
Name: "vikunja_team_count", // The key of the metric. Must be unique.
Help: "The total number of teams on this instance", // A description about the metric itself.
}, func() float64 {
count, _ := GetCount(TeamCountKey) // TeamCountKey is the const we defined earlier.
return float64(count)
})
{{< /highlight >}}
Then you'll need to set the metrics initial value on every startup of vikunja.
This is done in `pkg/routes/routes.go` to avoid cyclic imports.
If metrics are enabled, it checks if a redis connection is available and then sets the initial values.
A convenience function is available if the metric is based on a database struct.
Because metrics are stored in redis, you are responsible to increase or decrease these based on criteria you define.
To do this, use `metrics.UpdateCount(value, key)` where `value` is the amount you want to cange it (you can pass
negative values to decrease it) and `key` it the redis key used to define the metric.
# Using it
A Prometheus config with a Grafana template is available at [our git repo](https://git.kolaente.de/vikunja/monitoring).
@@ -0,0 +1,31 @@
---
date: "2019-02-12:00:00+02:00"
title: "Adding new config options"
draft: false
type: "doc"
menu:
sidebar:
parent: "practical instructions"
---
# Adding new config options
Vikunja uses [viper](https://github.com/spf13/viper) to handle configuration options.
It handles parsing all different configuration sources.
The configuration is done in sections. These are represented with a `.` in viper.
Take a look at `pkg/config/config.go` to understand how these are set.
To add a new config option, you should add a default value to `pkg/config/config.go`.
Default values should always enable the feature to work somehow, or turn it off completely if it always needs
additional configuration.
Make sure to add the new config option to [the config document]({{< ref "../setup/config.md">}}) and the default config file
(`config.yml.sample` at the root of the repository) to make sure it is well documented.
If you're using a computed value as a default, make sure to update the sample config file and debian
post-install scripts to reflect that.
To get a configured option, use `viper.Get("config.option")`.
Take a look at [viper's documentation](https://github.com/spf13/viper#getting-values-from-viper) to learn of the
different ways available to get config options.
@@ -0,0 +1,47 @@
---
date: "2019-02-12:00:00+02:00"
title: "Modifying swagger api docs"
draft: false
type: "doc"
menu:
sidebar:
parent: "practical instructions"
---
# Adding/editing swagger api docs
The api documentation is generated using [swaggo](https://github.com/swaggo/swag) from comments.
### Documenting structs
You should always comment every field which will be exposed as a json in the api.
These comments will show up in the documentation, it'll make it easier for developers using the api.
As an example, this is the definition of a list with all comments:
{{< highlight golang >}}
// 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"`
// 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"`
// The user who created this list.
Owner User `xorm:"-" json:"owner" valid:"-"`
// An array of tasks which belong to the list.
Tasks []*ListTask `xorm:"-" json:"tasks"`
// A unix timestamp when this list was created. You cannot change this value.
Created int64 `xorm:"created" json:"created"`
// A unix timestamp when this list was last updated. You cannot change this value.
Updated int64 `xorm:"updated" json:"updated"`
web.CRUDable `xorm:"-" json:"-"`
web.Rights `xorm:"-" json:"-"`
}
{{< /highlight >}}
+52
View File
@@ -0,0 +1,52 @@
---
date: "2019-02-12:00:00+02:00"
title: "What to backup"
draft: false
type: "doc"
menu:
sidebar:
parent: "setup"
---
# What to backup
Vikunja does not store any data outside of the database.
So, all you need to backup are the contents of that database and maybe the config file.
## MySQL
To create a backup from mysql use the `mysqldump` command:
{{< highlight bash >}}
mysqldump -u <user> -p -h <db-host> <database> > vkunja-backup.sql
{{< /highlight >}}
You will be prompted for the password of the mysql user.
To restore it, simply pipe it back into the `mysql` command:
{{< highlight bash >}}
mysql -u <user> -p -h <db-host> <database> < vkunja-backup.sql
{{< /highlight >}}
## PostgreSQL
To create a backup from PostgreSQL use the `pg_dump` command:
{{< highlight bash >}}
pg_dump -U <user> -h <db-host> <database> > vikunja-backup.sql
{{< /highlight >}}
You might be prompted for the password of the database user.
To restore it, simply pipe it back into the `psql` command:
{{< highlight bash >}}
psql -U <user> -h <db-host> <database> < vikunja-backup.sql
{{< /highlight >}}
For more information, please visit the [relevant PostgreSQL documentation](https://www.postgresql.org/docs/12/backup-dump.html).
## SQLite
To backup sqllite databases, it is enough to copy the database elsewhere.

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