- Removed VIKUNJA_VERSION and custom git checkout, because it is not found in the repository. So it is not used anywhere.
- Optimized runner commands order
- Removed run.sh (it is not needed in fact)
Co-authored-by: Yurii Vlasov <yv@itsvit.org>
Reviewed-on: vikunja/api#1375
Co-authored-by: Yurii Vlasov <yuriy@vlasov.pro>
Co-committed-by: Yurii Vlasov <yuriy@vlasov.pro>
Add list subscriptions to namespaces call to enable frontend to show subscription state correctly.
Resolves https://github.com/go-vikunja/frontend/issues/75
Reviewed-on: vikunja/api#1254
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Luca Bernstein <luca@lucabernstein.com>
Co-committed-by: Luca Bernstein <luca@lucabernstein.com>
Prevent Vikunja from sending mail notifications for failed login attempts if CalDav token is used.
Before, as the provided password value was tested against the user password regardless of whether it was a CalDav token, it triggered a failed login attempt email every three times.
Reviewed-on: vikunja/api#1252
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Luca Bernstein <luca@lucabernstein.com>
Co-committed-by: Luca Bernstein <luca@lucabernstein.com>
Fix error log for mailserver closing logic, as default timeout of 15 seconds of mail client package used triggers before our logic leading to error on close.
Resolves https://github.com/go-vikunja/api/issues/48
Reviewed-on: vikunja/api#1253
Reviewed-by: konrad <k@knt.li>
Co-authored-by: Luca Bernstein <luca@lucabernstein.com>
Co-committed-by: Luca Bernstein <luca@lucabernstein.com>
When running the docker container, the sh script will run as PID 1 and intercept any external signals (like docker stop) and won't pass it on to the app. Docker will wait for 10 seconds before proceeding to force kill the app, leading to both an unclean shutdown and an unnecessary wait of 10 seconds.
The exec in the script replaces the shell process with the `su` process, which correctly passes on signals to the app process and triggers a regular shutdown when doing a docker stop.
Co-authored-by: Pavle Portic <git@theedgeofrage.com>
Reviewed-on: vikunja/api#1200
Reviewed-by: konrad <k@knt.li>
Co-authored-by: TheEdgeOfRage <git@theedgeofrage.com>
Co-committed-by: TheEdgeOfRage <git@theedgeofrage.com>
This PR changes the behavoir of sorting tasks. Before, tasks were sorted with null values first. Now, null values are always sorted last which is usually what you want.
Partial fix for https://github.com/go-vikunja/frontend/issues/54
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#1177
Added the configuration key, `service.staticpath`, to serve files from the configuration path on root (/).
Serving static files allows the api service to also serve the frontend content. This is a simple option for deploying Vikunja without needing any other servers or proxies.
Running a complete instance becomes:
VIKUNJA_SERVICE_STATICPATH=/path/to/frontend ./vikunja
Where `/path/to/frontend` is a copy of Vikunja's frontend static files.
## Implementation
Providing a path, via the configuration or environment, adds a static file middleware to serve the path's contents from root (/).
By default, the configuration path is empty and Vikunja's existing behaviour is unchanged.
Co-authored-by: Graham Miln <graham.miln@dssw.co.uk>
Reviewed-on: vikunja/api#1174
Reviewed-by: konrad <k@knt.li>
Co-authored-by: grahammiln <grahammiln@noreply.kolaente.de>
Co-committed-by: grahammiln <grahammiln@noreply.kolaente.de>
# Description
This PR adds API routes to create and manage caldav tokens. These tokens can be used instead of a user password - required for users who are using external auth providers and don't have a password.
Fixes#842
Frontend: vikunja/frontend#1186
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#1065
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [golang.org/x/oauth2](https://github.com/golang/oauth2) | require | digest | `ee48083` -> `6242fa9` |
---
### Configuration
📅 **Schedule**: At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box.
---
This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
Reviewed-on: vikunja/api#1140
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
Previously, we did not check if a list has more tasks than the ones returned. By default, the Microsoft Graph API only returns 10 tasks. If the user had more they would not get imported.
Now we check if there are more pages with tasks and pull them all in until we have everything.
://community.spotify.com/t5/Content-Questions/How-to-disable-all-podcasts/td-p/5180261 PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [github.com/yuin/goldmark](https://github.com/yuin/goldmark) | require | patch | `v1.4.4` -> `v1.4.5` |
---
### Release Notes
<details>
<summary>yuin/goldmark</summary>
### [`v1.4.5`](https://github.com/yuin/goldmark/compare/v1.4.4...v1.4.5)
[Compare Source](https://github.com/yuin/goldmark/compare/v1.4.4...v1.4.5)
</details>
---
### Configuration
📅 **Schedule**: At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box.
---
This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
Reviewed-on: vikunja/api#1112
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
Instead of naeveily checking for all reminders due in the next minute, we now check all reminders in all time zones in the next minutes. This essentially means checking for reminders due in the next 14 or past 12 hours. We then check for each user who would receive a reminder from that result if it is actually due in their time zone.
This should prevent issues where users would get the reminder in the time zone of their server, not in their own.
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#1092
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [github.com/labstack/echo/v4](https://github.com/labstack/echo) | require | patch | `v4.6.2` -> `v4.6.3` |
---
### Release Notes
<details>
<summary>labstack/echo</summary>
### [`v4.6.3`](https://github.com/labstack/echo/blob/master/CHANGELOG.md#v463---2022-01-10)
[Compare Source](https://github.com/labstack/echo/compare/v4.6.2...v4.6.3)
**Fixes**
- Fixed Echo version number in greeting message which was not incremented to `4.6.2` [#​2066](https://github.com/labstack/echo/issues/2066)
</details>
---
### Configuration
📅 **Schedule**: At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box.
---
This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
Reviewed-on: vikunja/api#1089
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
This adds the marble avatar from [boring avatars](https://github.com/boringdesigners/boring-avatars) as an option for user avatars. Each user gets a different one (based on their id).
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#1060
Co-authored-by: konrad <k@knt.li>
Co-committed-by: konrad <k@knt.li>
This PR contains the following updates:
| Package | Type | Update | Change |
|---|---|---|---|
| [golang.org/x/crypto](https://github.com/golang/crypto) | require | digest | `ae814b3` -> `5770296` |
---
### Configuration
📅 **Schedule**: At any time (no schedule defined).
🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.
♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 **Ignore**: Close this PR and you won't be reminded about this update again.
---
- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box.
---
This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
Reviewed-on: vikunja/api#1056
Co-authored-by: renovate <renovatebot@kolaente.de>
Co-committed-by: renovate <renovatebot@kolaente.de>
Since jan 2021, trello requires authentication to access attachments. This commit passes the required auth headers to make downloading card attachments work.
resolves https://github.com/go-vikunja/api/issues/6
Reviewed-on: vikunja/api#858
Reviewed-by: konrad <konrad@kola-entertainments.de>
Co-authored-by: earnest ma <me@earne.link>
Co-committed-by: earnest ma <me@earne.link>
While the request body of a DELETE request *can* have data in it, it is not really supported and pretty much undocumented. As such, it doesn't work in all clients and probably broke with recent updates.
This fixes this by moving all parts of the task relation used to identify it in the url.
More Info: https://stackoverflow.com/a/299696/10924593
Fix lint
Fix lint
Fix loading tasks with search
Fix loading lists
Fix loading task
Fix loading lists and namespaces
Fix tests
Fix user commands
Fix upload
Fix migration handlers
Fix all manual root handlers
Fix session in avatar
Fix session in list duplication & routes
Use sessions in migration code
Make sure the openid stuff uses a session
Add alias for db type in db package
Use sessions for file
Use a session for everything in users
Use a session for everything in users
Make sure to use a session everywhere in models
Create new session from db
Add session handling for user list
Add session handling for unsplash
Add session handling for teams and related
Add session handling for tasks and related entities
Add session handling for task reminders
Add session handling for task relations
Add session handling for task comments
Add session handling for task collections
Add session handling for task attachments
Add session handling for task assignees
Add session handling for saved filters
Add session handling for namespace and related types
Add session handling for namespace and related types
Add session handling for list users
Add session handling for list tests
Add session handling to list teams and related entities
Add session handling for link shares and related entities
Add session handling for labels and related entities
Add session handling for kanban and related entities
Add session handling for bulk task and related entities
Add session handling for lists and related entities
Add session configuration for web handler
Update web handler
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#750
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Add more tests for getting namespaces
Fix namespaces not found
Fix namespaces not found
Make like the default
Update docs & fix docs
Enable searching namespaces by their ids
Enable searching lists by their ids
Enable searching labels by their ids
Enable searching by user ids
Update docs
Add namespace filter
Add task filter for lists
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#748
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Fix tests
Expose email reminder setting through jwt
Set reminders on by default
Fix lint
Make user email configurable
Expose email reminder setting through /info
Don't try to send any reminders if none were found
More spacing for buttons
Fix db time format
Enable reminders by default
Make emails look more like the frontend
Add config to disable it
Add sending emaisl
Add getting all task users and reminding them
Add getting the next reminder in a cron
Move task reminder to separate file
Add cron
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#743
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Fix lint
Fix migration query for postgres
Fix migration statements
Add migration to make all int(11) fields bigint by default
Make all int(11) fields bigint by default
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#741
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Add login via email
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#740
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Refactor adding more details to tasks
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#739
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Add colors for caldav
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#738
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Add more logs
Fix lint
Generate docs
Add swagger docs
Add microsoft todo parsing logic
go mod tidy
Add basic test structure
Add more fields to tasks
rename microsoft todo package
Add getting microsoft todo data
Add structs and helper methods
Add microsoft todo config and routes
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#737
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Fix tests for background images
Generate docs
Fix lint
Do the swag
Add more logging
Remove the default bucket if it was empty
Add launch.json
Make importing backgrounds work
Add comment
Fix getting task attachments
Fix getting trello token
Add trello migration routes and status
Add support for converting checklists
Add test for attachments
Add the actual conversion
Add Trello conversion test
Add migration function stubs
Add basic trello migration structure
Add trello migration config
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#734
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Add config docs
Lint
Move provider-related stuff to separate file
Refactor getting auth providers
Fix tests
Fix user tests
Fix openid tests
Add swagger docs
Fix lint
Fix lint issues
Fix checking if the user already exists
Make sure to create a new namespace for new users
Docs
Add tests for openid
Remove unnessecary err check
Consistently return nil users if creating a new user failed
Move sending confirmation email to separate function
Better variable names
Move checks to separate functions
Refactor creating user into seperate file
Fix creating new local users
Test creating new users from different issuers
Generate a random username right away if no preferred username has been given
Add todo
Cache openid providers
Add getting int clientids
Fix migration
Move creating tokens to auth package
Add getting or creating a third party user
Add parsing claims
Add retreiving auth tokens
Add token callback from openid package
Add check for provider key
Add routes
Start adding openid auth handler
Add config for openid auth
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#713
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Add tests for multiline descriptions and completed state
Fix caldav descriptions
Fix caldav task complete status for OpenTasks
Co-authored-by: Martin Giger <martin@humanoids.be>
Reviewed-on: vikunja/api#697
Co-Authored-By: freaktechnik <martin@humanoids.be>
Co-Committed-By: freaktechnik <martin@humanoids.be>
Add app support info for DAV
Reviewed-on: vikunja/api#692
Co-Authored-By: freaktechnik <martin@humanoids.be>
Co-Committed-By: freaktechnik <martin@humanoids.be>
no need to export from there I think
parse absolute ical timestamps
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-authored-by: Martin Giger <martin@humanoids.be>
Reviewed-on: vikunja/api#691
Co-Authored-By: freaktechnik <martin@humanoids.be>
Co-Committed-By: freaktechnik <martin@humanoids.be>
Cleanup
Update docs for deb
Add building os packages to drone
Add apk packages
Replace version and binlocation strings in nfpm config
Make nfpm config replacable
Fix nfpm config
Add nfpm config
go mod tidy
Add nfpm mage target
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#689
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Fix shadowed error
Panic if a TaskCollection.ReadAll does not return []*models.Task
Fetch tasks for caldav lists
Co-authored-by: kolaente <k@knt.li>
Co-authored-by: konrad <konrad@kola-entertainments.de>
Co-authored-by: Martin Giger <martin@humanoids.be>
Reviewed-on: vikunja/api#641
Co-Authored-By: freaktechnik <martin@humanoids.be>
Co-Committed-By: freaktechnik <martin@humanoids.be>
Add docs todo to PR template
Clarify docs
Fix parsing of descriptions and multi-level values
Add method to write out the file
Only render default value for non-top-level values
Remove comment headings from yaml comments
Add printing config
Add basic parsing of sample config with comments
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#684
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Increase golangci timeout
Fix installing golangci-lint in ci
Remove mage targets replaced by golangci
Run golint in ci
Add goheader linter
Enable & fix more linters
Fix lint issues
Add mage target to automagically fix issues found by golangci
golangci-lint run --fix
Add golangci config
Add golangci mage target
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#676
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Fix lint
Add docs for keyvalue config options
Use keyvalue store to cache unsplash photo results
Cleanup
Use keyvalue store for upload avatar
Use keyvalue store for initials avatar
Fix initializing metrics
Use keyvalue for metrics
Add IncryBy and DecrBy methods to increase or decrease a value
Fix lint
Return custom error if a key does not exist
Init keyvalue storage
Follow the keyvalue storage setting for things like cache and other
Add docs
Add configuration of the storage backend
Add redis keyvalue storage implementation
Add doc comments
Add methods to use storage through the package itself
Add memory implementation for keyvalue store
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#674
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Change method names to avoid doubling db
Assert team test exists
Assert team member test exists
Assert task test exists
Assert task relation test exists
Assert task comment test exists
Better tests for team namespaces
Assert exists in namespace users tests
Assert exists in namespace tests
Assert exists in user list tests
Assert exists in list tests
Better team list tests
Assert label tests exist in db
Assert label task tests exist in db
Assert label task tests exist in db
Assert kanban tests exist in db
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#666
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Fix updating saved filters
Fix filter not loadable because of missing param declaration
Add fancy special cases for postgres exists in db
Add special case for postgrs json
Add read one test
Add rights tests
Fix lint
Fixed getting a single saved filter from db
Add tests for the usual crud methods
Add test stubs and TODOs
Add test for converting saved filter ids to list ids and vice versa
Add test fixture for saved filters and fix existing tests
Fix exposed json variables of filters
Fix creating saved filters table for tests
Add getting saved filters as pseudo namespace
Cleanup
Refactor getting all namespaces to use a map for easier handling of pseudo namespaces
Add custom erros for saved filters
Swagger docs
Fix lint
Add routes for saved filters
Add alias for mage build
Add method to get a saved filter from the lists endpoint
Add getting tasks from a saved filter
Add create, update, delete, read one methods
Add rights methods for saved filters
Fix docs minLength
Add saved filters column
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#655
Co-Authored-By: konrad <konrad@kola-entertainments.de>
Co-Committed-By: konrad <konrad@kola-entertainments.de>
Add tests
Remove the favorites pseudo namespace if there are no lists or tasks favorited
Regenerate swagger docs
Fix favorite lists not being updated because of nonexisting users (the favorite list does not have one)
Make the pseudo favorites list always favorited
Add favorited lists to the favorites pseudo namespace
Add favorite field to list
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#654
Fixed namespace tests
Add test for favorite tasks
Fix favorite tasks not being updated
Fix integration tests
Fix lint
Return a pseudo namespace and list for favorites
Make sure users can only see their favorites
Add condition show tasks from the favorites list
Regenerate swagger docs
Add favorite field to task
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#653
Fix integration tests
Generate swagger docs
Add test for moving a task between buckets
Add check for bucket limit when updating a task
Add fixture to ensure a bucket with a high limit will never exceed the limit
Refactor bucket limit check into seperate function
Add test for creating and fix
Fix unexported field
Add error in case a task was added to a bucket which has its limit already exceeded
Add migration to add new task field
Add limit field to buckets
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#652
Add comment about magefile compile
Switch make to mage commands in drone
Fix misspell
Update docs
Add general release command
Add reprepro command
Make sure the filename contains the proper version
Add deb package building
Add zip command
Preserve file permissions when copying files
Fix release:os-package
Make sure to not create checksums of directories
Cleanup
Only compress what upx is able to compress
Add check command
Add release:os-package command
Add copy command
Add comments
Add compress step
Move releasing binaries to a more general function and add ones of linux + darwin
Add release:windows command
Add release:dir command
Add namespaces for commands
Reorder
Add command to run all checks at once
Add goconst-check
Add gosec-check
Add static-check
Add gocyclo-check
Add ineffasign-check
Add misspell-check
Add command to check for swagger docs regeneration
Add comments
Add command to generate swagger docs
Reorder
Add check for installing golint before running it
Add fmt check command
Add fmt command
Use runAndStreamOutput everywhere
Add aliases and comments
Add todo
Reorder
Add test coverage command
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#651
Add users cli commands to docs
Fix checking for changing username or user email
Add user status change command
Make sure only one user exists with a particular email when updating
Add password reset
Add user id to help
Remove user delete (too many possible side effects, postponed until later)
Make sure to fail on any errors
Fail if changing the username would result in duplicate users
Add user update command
Add user create command
Add command stubs for all commands
Render users in a beautiful table
Started adding user list command
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#632
Fix lint
Update docs
Fix loading all rights (list & namespace)
Add tests
Update web framework
Make tests run again
Update all calls to CanRead methods
Update task attachment & task comment & task rights to return the max right
Update team rights to return the max right
Update namespace rights to return the max right
Update list rights to return the max right
Update link share rights to return the max right
Update label rights to return the max right
Update web dependency
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#626
Don't fail if the last avatar file does not exist when deleting it
Fix lint
Remove old global avatar setting and update docs
Generate docs
Invalidate the avatar cache when uploading a new one
Add debug logs
Add caching for upload avatars
Add cache locks
Fix encoding
Resize the uploaded image to a max of 1024 pixels
Remove the old uploaded avatar if one already exists
Add mimetype check for images
Set avatar provider to upload when uploading an avatar
Add upload avatar provider
Make font size smaller to let the initials still look good in smaller sizes
Add debug log
Add cache and resizing of initials avatars
Make font size depend on avatar size
Add drawing initials avatar
Add initials provider
Make the initials avatar provider the default
Add routes
Add user avatar settings handler methods
Add user avatar provider field
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#622
Fix test name
Fix migrating lists with non utf-8 characters in their name
Fix creating lists with non utf-8 characters
Co-authored-by: kolaente <k@knt.li>
Reviewed-on: vikunja/api#607
Makefile: make add EXTRA_GOFLAG to GOFLAGS
Some commands (`go generate`) only support taking `GOFLAGS` from the environment
but setting `GOFLAGS` environment variable is ineffectual because the variable
of the same name defined in the Makefile shadows it.
We also have a custom `EXTRA_GOFLAGS` variable but we only pass that to `go build`.
Let’s add `EXTRA_GOFLAGS` to the `GOFLAGS` variable in the Makefile to allow passing
custom flags to Go through `EXTRA_GOFLAGS` environment variable.
Co-authored-by: Jan Tojnar <jtojnar@gmail.com>
Reviewed-on: vikunja/api#605
Reviewed-by: konrad <konrad@kola-entertainments.de>
- docker-entrypoint.sh -c fsync=off -c full_page_writes=off# turns of wal
- name:test-postgres-integration
image:postgres:12
image:postgres:14
environment:
POSTGRES_PASSWORD:vikunjatest
POSTGRES_DB:vikunjatest
volumes:
- name:tmp-postgres-integration
path:/var/lib/postgresql/data
commands:
- docker-entrypoint.sh -c fsync=off -c full_page_writes=off# turns of wal
- name:test-postgres-migration
image:postgres:12
image:postgres:14
environment:
POSTGRES_PASSWORD:vikunjatest
POSTGRES_DB:vikunjatest
volumes:
- name:tmp-postgres-migration
path:/var/lib/postgresql/data
commands:
- docker-entrypoint.sh -c fsync=off -c full_page_writes=off# turns of wal
trigger:
branch:
include:
- master
- main
event:
include:
- push
@ -52,64 +108,74 @@ steps:
commands:
- git fetch --tags
- name:build
# We're statically compiling the magefile to avoid race condition issues caused by multiple pipeline steps
# compiling the same magefile at the same time. It's also faster if each step does not need to compile it first.
- name:mage
image:vikunja/golang-build:latest
pull:true
pull:always
environment:
GOPROXY:'https://goproxy.kolaente.de'
commands:
- make build
- mage -compile ./mage-static
- env
when:
event:[push, tag, pull_request ]
- name:build
image:vikunja/golang-build:latest
pull:always
environment:
GOPROXY:'https://goproxy.kolaente.de'
depends_on:[mage ]
commands:
- ./mage-static build:build
when:
event:[push, tag, pull_request ]
- name:lint
image:vikunja/golang-build:latest
pull:true
image:golang:1.19-alpine
pull:always
environment:
GOPROXY:'https://goproxy.kolaente.de'
depends_on:[build ]
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.
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
about:This is the API repo. Please open frontend-related bug reports and discussions in the frontend repo. Not sure if you 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.
# 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;
If you find any security-related issues you don't want to disclose publicly, please use [the contact information on our website](https://vikunja.io/contact/#security).
## Features
* Create TODO lists with tasks
* Reminder for tasks
* Namespaces: A "group" which bundels multiple lists
* Namespaces: A "group" which bundles multiple lists
* Share lists and namespaces with teams and users with granular permissions
* Plenty of details for tasks
@ -35,46 +40,22 @@ try it on [try.vikunja.io](https://try.vikunja.io)!
All docs can be found on [the vikunja home page](https://vikunja.io/docs/).
All docs can be found on [the Vikunja home page](https://vikunja.io/docs/).
### Roadmap
> I know, it's still a long way to go. I'm currently working on a lot of "basic" features, the exiting things will come later. Don't worry, they'll come.
See [the roadmap](https://my.vikunja.cloud/share/QFyzYEmEYfSyQfTOmIRSwLUpkFjboaBqQCnaPmWd/auth) (hosted on Vikunja!) for more!
* [x] Prioritize tasks
* [x] Subtasks
* [x] Repeating tasks
* [x] Get tasks via caldav
* [x] Get all your tasks for an interval (day/month/period)
* [x] Labels for tasks
* [x] Assign users to tasks
* [x] Attachments on tasks
* [x] More sharing features
* [x] Share with individual users
* [x] Share via a world-readable link with or without password, like Nextcloud
* [x] Disable registration, making an instance "invite-only"
* [ ] SSE to notify multiple clients of updates when something was changed
* [ ] "Smart Lists" - Create lists based on filters
* [ ] IMAP-Integration - Send an email to Vikunja to create a new task
* [ ] Webhooks - Trigger other events when an action is done (like completing a task)
* [ ] Performace statistics - Get an overview and beautiful charts about what you got done this month
* [ ] Activity feeds - Get a quick overview about who did what
* [ ] Bulk-edit multiple tasks at once
* [ ] Team-efforts - Requiring a task to be marked as done by multiple members until it's done
* [ ] Global limits for namespaces/lists/tasks
See [our roadmap](https://my.vikunja.cloud/share/QFyzYEmEYfSyQfTOmIRSwLUpkFjboaBqQCnaPmWd/auth) (hosted on Vikunja!) for even more!
# 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 duration of the issed JWT tokens in seconds.
# The default is 259200 seconds (3 Days).
jwtttl: 259200
# The duration of the "remember me" time in seconds. When the login request is made with
# the long param set, the token returned will be valid for this period.
# The default is 2592000 seconds (30 Days).
jwtttllong: 2592000
# The interface on which to run the webserver
interface: ":3456"
# Path to Unix socket. If set, it will be created and used instead of tcp
unixsocket:
# Permission bits for the Unix socket. Note that octal values must be prefixed by "0o", e.g. 0o660
unixsocketmode:
# 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>
# Path on the file system to serve static files from. Set to the path of the frontend files to host frontend alongside the api.
staticpath: ""
# 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
# Enable sharing of project 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
# The time zone all timestamps are in. Please note that time zones have to use [the official tz database names](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). UTC or GMT offsets won't work.
timezone: GMT
# Whether task comments should be enabled or not
enabletaskcomments: true
@ -34,17 +44,32 @@ service:
enabletotp: true
# If not empty, enables logging of crashes and unhandled errors in sentry.
sentrydsn: ''
# If not empty, this will enable `/test/{table}` endpoints which allow to put any content in the database.
# Used to reset the db before frontend tests. Because this is quite a dangerous feature allowing for lots of harm,
# each request made to this endpoint neefs to provide an `Authorization: <token>` header with the token from below. <br/>
# **You should never use this unless you know exactly what you're doing**
testingtoken: ''
# If enabled, vikunja will send an email to everyone who is either assigned to a task or created it when a task reminder
# is due.
enableemailreminders: true
# If true, will allow users to request the complete deletion of their account. When using external authentication methods
# it may be required to coordinate with them in order to delete the account. This setting will not affect the cli commands
# for user deletion.
enableuserdeletion: true
# The maximum size clients will be able to request for user avatars.
# If clients request a size bigger than this, it will be changed on the fly.
maxavatarsize: 1024
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
# Database password
password: ""
# Databse host
# Database host
host: "localhost"
# Databse to use
# Database to use
database: "vikunja"
# When using sqlite, this is the path where to store the data
path: "./vikunja.db"
@ -57,12 +82,22 @@ database:
# Secure connection mode. Only used with postgres.
# (see https://pkg.go.dev/github.com/lib/pq?tab=doc#hdr-Connection_String_Parameters)
sslmode: disable
# The path to the client cert. Only used with postgres.
sslcert: ""
# The path to the client key. Only used with postgres.
sslkey: ""
# The path to the ca cert. Only used with postgres.
sslrootcert: ""
# Enable SSL/TLS for mysql connections. Options: false, true, skip-verify, preferred
tls: false
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
# Cache type. Possible values are "keyvalue", "memory" or "redis".
# When choosing "keyvalue" this setting follows the one configured in the "keyvalue" section.
# When choosing "redis" you will need to configure the redis connection seperately.
type: keyvalue
# When using memory this defines the maximum size an element can take
maxelementsize: 1000
@ -81,7 +116,7 @@ cors:
# Note: If you want to put the frontend and the api on seperate domains or ports, you will need to enable this.
# Otherwise the frontend won't be able to make requests to the api through the browser.
enable: true
# A list of origins which may access the api.
# A list of origins which may access the api. These need to include the protocol (`http://` or `https://`) and port, if any.
origins:
- "*"
# How long (in seconds) the results of a preflight request can be cached.
@ -92,8 +127,11 @@ mailer:
enabled: false
# SMTP Host
host: ""
# SMTP Host port
# SMTP Host port.
# **NOTE:** If you're unable to send mail and the only error you see in the logs is an `EOF`, try setting the port to `25`.
port: 587
# SMTP Auth Type. Can be either `plain`, `login` or `cram-md5`.
authtype: "plain"
# SMTP username
username: "user"
# SMTP password
@ -106,6 +144,8 @@ mailer:
queuelength: 100
# The timeout in seconds after which the current open connection to the mailserver will be closed.
queuetimeout: 30
# By default, vikunja will try to connect with starttls, use this option to force it to use ssl.
forcessl: false
log:
# A folder where all the logfiles should go.
@ -122,8 +162,12 @@ log:
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 has its own logging which usually is unnecessary, which is why it is disabled by default. Possible values are stdout, stderr, file or off to disable standard logging.
echo: "off"
# Whether or not to log events. Useful for debugging. Possible values are stdout, stderr, file or off to disable events logging.
events: "off"
# The log level for event log messages. Possible values (case-insensitive) are ERROR, INFO, DEBUG.
eventslevel: "info"
ratelimit:
# whether or not to enable the rate limit
@ -134,8 +178,10 @@ ratelimit:
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
# The store where the limit counter for each user is stored.
# Possible values are "keyvalue", "memory" or "redis".
# When choosing "keyvalue" this setting follows the one configured in the "keyvalue" section.
store: keyvalue
files:
# The path where files are stored
@ -145,25 +191,10 @@ files:
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:
todoist:
# Wheter to enable the todoist migrator or not
enable: false
# The client id, required for making requests to the wunderlist api
# The client id, required for making requests to the todoist api
# You need to register your vikunja instance at https://developer.todoist.com/appconsole.html to get this
clientid:
# The client secret, also required for making requests to the todoist api
@ -173,25 +204,48 @@ migration:
# This is usually the frontend url where the frontend then makes a request to /migration/todoist/migrate
# with the code obtained from the todoist api.
# Note that the vikunja frontend expects this to be /migrate/todoist
redirecturl:
redirecturl: <frontend url>/migrate/todoist
trello:
# Wheter to enable the trello migrator or not
enable: false
# The client id, required for making requests to the trello api
# You need to register your vikunja instance at https://trello.com/app-key (log in before you visit that link) to get this
key:
# The url where clients are redirected after they authorized Vikunja to access their trello cards.
# This needs to match the url you entered when registering your Vikunja instance at trello.
# This is usually the frontend url where the frontend then makes a request to /migration/trello/migrate
# with the code obtained from the trello api.
# Note that the vikunja frontend expects this to end on /migrate/trello.
redirecturl: <frontend url>/migrate/trello
microsofttodo:
# Wheter to enable the microsoft todo migrator or not
enable: false
# The client id, required for making requests to the microsoft graph api
# See https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#register-an-application
# for information about how to register your vikuinja instance.
clientid:
# The client secret, also required for making requests to the microsoft graph api
clientsecret:
# The url where clients are redirected after they authorized Vikunja to access their microsoft todo tasks.
# This needs to match the url you entered when registering your Vikunja instance at microsoft.
# This is usually the frontend url where the frontend then makes a request to /migration/microsoft-todo/migrate
# with the code obtained from the microsoft graph api.
# Note that the vikunja frontend expects this to be /migrate/microsoft-todo
# 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
backgrounds:
# Whether to enable backgrounds for lists at all.
# Whether to enable backgrounds for projects at all.
enabled: true
providers:
upload:
# Whethere to enable uploaded list backgrounds
# Whether to enable uploaded project backgrounds
enabled: true
unsplash:
# Whether to enable setting backgrounds from unsplash as list backgrounds
# Whether to enable setting backgrounds from unsplash as project backgrounds
enabled: false
# You need to create an application for your installation at https://unsplash.com/oauth/applications/new
# and set the access token below.
@ -201,3 +255,85 @@ backgrounds:
# It will only show in the UI if your application has been approved for Enterprise usage, therefore if
# you’re in Demo mode, you can also find the ID in the URL at the end: https://unsplash.com/oauth/applications/:application_id
applicationid:
# Legal urls
# Will be shown in the frontend if configured here
legal:
imprinturl:
privacyurl:
# Key Value Storage settings
# The Key Value Storage is used for different kinds of things like metrics and a few cache systems.
keyvalue:
# The type of the storage backend. Can be either "memory" or "redis". If "redis" is chosen it needs to be configured seperately.
type: "memory"
auth:
# Local authentication will let users log in and register (if enabled) through the db.
# This is the default auth mechanism and does not require any additional configuration.
local:
# Enable or disable local authentication
enabled: true
# OpenID configuration will allow users to authenticate through a third-party OpenID Connect compatible provider.<br/>
# The provider needs to support the `openid`, `profile` and `email` scopes.<br/>
# **Note:** Some openid providers (like gitlab) only make the email of the user available through openid claims if they have set it to be publicly visible.
# If the email is not public in those cases, authenticating will fail.
# **Note 2:** The frontend expects to be redirected after authentication by the third party
# to <frontend-url>/auth/openid/<auth key>. Please make sure to configure the redirect url with your third party
# auth service accordingy if you're using the default vikunja frontend.
# Take a look at the [default config file](https://kolaente.dev/vikunja/api/src/branch/main/config.yml.sample) for more information about how to configure openid authentication.
openid:
# Enable or disable OpenID Connect authentication
enabled: false
# The url to redirect clients to. Defaults to the configured frontend url. If you're using Vikunja with the official
# frontend, you don't need to change this value.
# **Note:** The redirect url must exactly match the configured redirect url with the third party provider.
# This includes all slashes at the end or protocols.
redirecturl: <frontend url>
# A list of enabled providers
providers:
# The name of the provider as it will appear in the frontend.
- name:
# The auth url to send users to if they want to authenticate using OpenID Connect.
authurl:
# The oidc logouturl that users will be redirected to on logout.
# Leave empty or delete key, if you do not want to be redirected.
logouturl:
# The client ID used to authenticate Vikunja at the OpenID Connect provider.
clientid:
# The client secret used to authenticate Vikunja at the OpenID Connect provider.
clientsecret:
# Prometheus metrics endpoint
metrics:
# If set to true, enables a /metrics endpoint for prometheus to collect metrics about Vikunja.
enabled: false
# If set to a non-empty value the /metrics endpoint will require this as a username via basic auth in combination with the password below.
username:
# If set to a non-empty value the /metrics endpoint will require this as a password via basic auth in combination with the username below.
password:
# Provide default settings for new users. When a new user is created, these settings will automatically be set for the user. If you change them in the config file afterwards they will not be changed back for existing users.
defaultsettings:
# The avatar source for the user. Can be `gravatar`, `initials`, `upload` or `marble`. If you set this to `upload` you'll also need to specify `defaultsettings.avatar_file_id`.
avatar_provider: initials
# The id of the file used as avatar.
avatar_file_id: 0
# If set to true users will get task reminders via email.
email_reminders_enabled: false
# If set to true will allow other users to find this user when searching for parts of their name.
discoverable_by_name: false
# If set to true will allow other users to find this user when searching for their exact email.
discoverable_by_email: false
# If set to true will send an email every day with all overdue tasks at a configured time.
overdue_tasks_reminders_enabled: true
# When to send the overdue task reminder email.
overdue_tasks_reminders_time: 9:00
# The id of the default project. Make sure users actually have access to this project when setting this value.
default_project_id: 0
# Start of the week for the user. `0` is sunday, `1` is monday and so on.
week_start: 0
# The language of the user interface. Must be an ISO 639-1 language code. Will default to the browser language the user uses when signing up.
language: <unset>
# The time zone of each individual user. This will affect when users get reminders and overdue task emails.
Vikunja provides a simple observer pattern mechanism through events and listeners.
The basic principle of events is always the same: Something happens (=An event is fired) and something reacts to it (=A listener is called).
Vikunja supports this principle through the `events` package.
It is built upon the excellent [watermill](https://watermill.io) library.
Currently, it only supports dispatching events through Go Channels which makes it configuration-less.
More methods of dispatching events (like kafka or rabbitmq) are available in watermill and could be enabled with a PR.
This document explains how events and listeners work in Vikunja, how to use them and how to create new ones.
{{<table_of_contents>}}
## Events
### Definition
Each event has to implement this interface:
{{<highlightgolang>}}
type Event interface {
Name() string
}
{{</highlight>}}
An event can contain whatever data you need.
When an event is dispatched, all of the data it contains will be marshaled into json for dispatching.
You then get the event with all its data back in the listener, see below.
#### Naming Convention
Event names should roughly have the entity they're dealing with on the left and the action on the right of the name, separated by `.`.
There's no limit to how "deep" or specifig an event name can be.
The name should have the most general concept it's describing at the left, getting more specific on the right of it.
#### Location
All events for a package should be declared in the `events.go` file of that package.
### Creating a New Event
The easiest way to create a new event is to generate it with mage:
```
mage dev:make-event <event-name><package>
```
The function takes the name of the event as the first argument and the package where the event should be created as the second argument.
Events will be appended to the `pkg/<module>/events.go` file.
Both parameters are mandatory.
The event type name is automatically camel-cased and gets the `Event` suffix if the provided name does not already have one.
The event name is derived from the type name and stripped of the `.event` suffix.
The generated event will look something like the example below.
### Dispatching events
To dispatch an event, simply call the `events.Dispatch` method and pass in the event as parameter.
### Example
The `TaskCreatedEvent` is declared in the `pkg/models/events.go` file as follows:
{{<highlightgolang>}}
// TaskCreatedEvent represents an event where a task has been created
type TaskCreatedEvent struct {
Task *Task
Doer web.Auth
}
// Name defines the name for TaskCreatedEvent
func (t *TaskCreatedEvent) Name() string {
return "task.created"
}
{{</highlight>}}
It is dispatched in the `createTask` function of the `models` package:
{{<highlightgolang>}}
func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err error) {
// ...
err = events.Dispatch(&TaskCreatedEvent{
Task: t,
Doer: a,
})
// ...
}
{{</highlight>}}
As you can see, the curent task and doer are injected into it.
### Special Events
#### `BootedEvent`
Once Vikunja is fully initialized, right before the api web server is started, this event is fired.
## Listeners
A listener is a piece of code that gets executed asynchronously when an event is dispatched.
A single event can have multiple listeners who are independent of each other.
### Definition
All listeners must implement this interface:
{{<highlightgolang>}}
// Listener represents something that listens to events
type Listener interface {
Handle(msg *message.Message) error
Name() string
}
{{</highlight>}}
The `Handle` method is executed when the event this listener listens on is dispatched.
* As the single parameter, it gets the payload of the event, which is the event struct when it was dispatched decoded as json object and passed as a slice of bytes.
To use it you'll need to unmarshal it. Unfortunately there's no way to pass an already populated event object to the function because we would not know what type it has when parsing it.
* If the handler returns an error, the listener is retried 5 times, with an exponentional back-off period in between retries.
If it still fails after the fifth retry, the event is nack'd and it's up to the event dispatcher to resend it.
You can learn more about this mechanism in the [watermill documentation](https://watermill.io/docs/middlewares/#retry).
The `Name` method needs to return a unique listener name for this listener.
It should follow the same convention as event names, see above.
### Creating a New Listener
The easiest way to create a new listener for an event is with mage:
Vikunja uses [Mage](https://magefile.org/) to script common development tasks and even releasing.
Mage is a pure go solution which allows for greater flexibility and things like better parallelization.
This document explains what tasks are available and what they do.
{{<table_of_contents>}}
## Installation
To use mage, you'll need to install the mage cli.
To install it, run the following command:
```
go install github.com/magefile/mage
```
## Categories
There are multiple categories of subcommands in the magefile:
* `build`: Contains commands to build a single binary
* `check`: Contains commands to statically check the source code
* `release`: Contains commands to release Vikunja with everything that's required
* `test`: Contains commands to run all kinds of tests
* `dev`: Contains commands to run development tasks
* `misc`: Commands which do not belong in either of the other categories
## CI
These tasks are automatically run in our CI every time someone pushes to main or you update a pull request:
* `mage check:lint`
* `mage check:fmt`
* `mage check:ineffassign`
* `mage check:misspell`
* `mage check:goconst`
* `mage build:generate`
* `mage build:build`
## Build
### Build Vikunja
{{<highlightbash>}}
mage build:build
{{</highlight>}}
or
{{<highlightbash>}}
mage build
{{</highlight>}}
Builds a `vikunja`-binary in the root directory of the repo for the platform it is run on.
### clean
{{<highlightbash>}}
mage build:clean
{{</highlight>}}
Cleans all build and executable files
## Check
All check sub-commands exit with a status code of 1 if the check fails.
Various code-checks are available:
* `mage check:all`: Runs fmt-check, lint, got-swag, misspell-check, ineffasign-check, gocyclo-check, static-check, gosec-check, goconst-check all in parallel
* `mage check:fmt`: Checks if the code is properly formatted with go fmt
* `mage check:go-sec`: Checks the source code for potential security issues by scanning the Go AST using the [gosec tool](https://github.com/securego/gosec)
* `mage check:goconst`: Checks for repeated strings that could be replaced by a constant using [goconst](https://github.com/jgautheron/goconst/)
* `mage check:gocyclo`: Checks for the cyclomatic complexity of the source code using [gocyclo](https://github.com/fzipp/gocyclo)
* `mage check:got-swag`: Checks if the swagger docs need to be re-generated from the code annotations
* `mage check:ineffassign`: Checks the source code for ineffectual assigns using [ineffassign](https://github.com/gordonklaus/ineffassign)
* `mage check:lint`: Runs golint on all packages
* `mage check:misspell`: Checks the source code for misspellings
* `mage check:static`: Statically analyzes the source code about a range of different problems using [staticcheck](https://staticcheck.io/docs/)
## Release
### Build Releases
{{<highlightbash>}}
mage 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 mage command will automatically install the
binary to be able to use it.
`mage release:release` is a shortcut to execute `mage release:dirs release:windows release:linux release:darwin release:copy release:check release:os-package release:zip`.
* `mage release:dirs` creates all directories needed
* `mage release:windows`/`release:linux`/`release:darwin` execute xgo to build for their respective platforms
* `mage release:copy` bundles binaries with a copy of the `LICENSE` and sample config files to then be zipped
* `mage release:check` creates sha256 checksums for each binary which will be included in the zip file
* `mage release:os-package` bundles a binary with the `sha256` checksum file, a sample `config.yml` and a copy of the license in a folder for each architecture
* `mage release:compress` compresses all build binaries with `upx` to save space
* `mage release:zip` paclages a zip file for the files created by `release:os-package`
### Build os packages
{{<highlightbash>}}
mage release:packages
{{</highlight>}}
Will build `.deb`, `.rpm` and `.apk` packages to `dist/os-packages`.
### Make a debian repo
{{<highlightbash>}}
mage release: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.
## Test
### unit
{{<highlightbash>}}
mage test:unit
{{</highlight>}}
Runs all tests except integration tests.
### coverage
{{<highlightbash>}}
mage test:coverage
{{</highlight>}}
Runs all tests except integration tests and generates a `coverage.html` file to inspect the code coverage.
### integration
{{<highlightbash>}}
mage test:integration
{{</highlight>}}
Runs all integration tests.
## Dev
### Create a new migration
{{<highlightbash>}}
mage dev:create-migration
{{</highlight>}}
Creates a new migration with the current date.
Will ask for the name of the struct you want to create a migration for.
See also [migration docs]({{< ref "mage.md" >}}).
## Misc
### Format the code
{{<highlightbash>}}
mage fmt
{{</highlight>}}
Formats all source code using `go fmt`.
### Generate swagger definitions from code comments
{{<highlightbash>}}
mage do-the-swag
{{</highlight>}}
Generates swagger definitions from the comment annotations in the code.
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
{{<highlightbash>}}
make clean
{{</highlight>}}
Clears all builds and binaries.
### test
{{<highlightbash>}}
make test
{{</highlight>}}
Runs all tests in Vikunja.
### Format the code
{{<highlightbash>}}
make fmt
{{</highlight>}}
Formats all source code using `go fmt`.
#### Check formatting
{{<highlightbash>}}
make fmt-check
{{</highlight>}}
Checks if the code needs to be formatted. Fails if it does.
### Build Vikunja
{{<highlightbash>}}
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
{{<highlightbash>}}
make generate
{{</highlight>}}
This generates static code with all templates, meaning no template need to be referenced at runtime.
### Compress the built binary
{{<highlightbash>}}
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
{{<highlightbash>}}
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
{{<highlightbash>}}
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
{{<highlightbash>}}
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
{{<highlightbash>}}
make do-the-swag
{{</highlight>}}
Generates swagger definitions from the comments in the code.
#### Check if swagger generation is needed
{{<highlightbash>}}
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/).
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):
@ -52,23 +78,35 @@ authUrl, Status and Migrate methods.
Vikunjs provides a simple abstraction to send notifications per mail and in the database.
{{<table_of_contents>}}
## Definition
Each notification has to implement this interface:
{{<highlightgolang>}}
type Notification interface {
ToMail() *Mail
ToDB() interface{}
Name() string
}
{{</highlight>}}
Both functions return the formatted messages for mail and database.
A notification will only be sent or recorded for those of the two methods which don't return `nil`.
For example, if your notification should not be recorded in the database but only sent out per mail, it is enough to let the `ToDB` function return `nil`.
### Mail notifications
A list of chainable functions is available to compose a mail:
{{<highlightgolang>}}
mail := NewMail().
// The optional sender of the mail message.
From("test@example.com").
// The optional receipient of the mail message. Uses the mail address of the notifiable if omitted.
To("test@otherdomain.com").
// The subject of the mail to send.
Subject("Testmail").
// The greeting, or "intro" line of the mail.
Greeting("Hi there,").
// A line of text
Line("This is a line of text").
// An action can contain a title and a url. It gets rendered as a big button in the mail.
// Note that you can have only one action per mail.
// All lines added before an action will appearr in the mail before the button, all lines
// added afterwards will appear after it.
Action("The Action", "https://example.com").
// Another line of text.
Line("This should be an outro line").
{{</highlight>}}
If not provided, the `from` field of the mail contains the value configured in [`mailer.fromemail`](https://vikunja.io/docs/config-options/#fromemail).
### Database notifications
All data returned from the `ToDB()` method is serialized to json and saved into the database, along with the id of the
notifiable, the name of the notification and a time stamp.
If you don't use the database notification, the `Name()` function can return an empty string.
## Creating a new notification
The easiest way to generate a mail is by using the `mage dev:make-notification` command.
It takes the name of the notification and the package where the notification will be created.
## Notifiables
Notifiables can receive a notification.
A notifiable is defined with this interface:
{{<highlightgolang>}}
type Notifiable interface {
// Should return the email address this notifiable has.
RouteForMail() string
// Should return the id of the notifiable entity
RouteForDB() int64
}
{{</highlight>}}
The `User` type from the `user` package implements this interface.
## Sending a notification
Sending a notification is done with the `Notify` method from the `notifications` package.
It takes a notifiable and a notification as input.
For example, the email confirm notification when a new user registers is sent like this:
{{<highlightgolang>}}
n := &EmailConfirmNotification{
User: update.User,
IsNew: false,
}
err = notifications.Notify(update.User, n)
return
{{</highlight>}}
## Testing
The `mail` package provides a `Fake()` method which you should call in the `MainTest` functions of your package.
If it was called, no mails are being sent and you can instead assert they have been sent with the `AssertSent` method.
When testing, you should call the `notifications.Fake()` method in the `TestMain` function of the package you want to test.
This prevents any notifications from being sent and lets you assert a notifications has been sent like this:
In general, this api repo has the following structure:
This document explains what each package does.
* `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.
{{<table_of_contents>}}
## Root level
The root directory is where [the config file]({{< ref "../setup/config.md">}}), [Makefile]({{< ref "make.md">}}), license, drone config,
The root directory is where [the config file]({{< ref "../setup/config.md">}}), [Magefile]({{< ref "mage.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.
This folder holds a simple caldav implementation which is responsible for the caldav feature.
### cmd
@ -73,10 +37,15 @@ To learn more about how to use this cli, see [the cli usage docs]({{< ref "../us
### 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.
This package configures handling of Vikunja's runtime configuration.
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.
See also the [docs about adding a new configuration parameter]({{< ref "config.md" >}}).
### cron
See [how to add a cron task]({{< ref "cron.md" >}}).
### db
@ -100,17 +69,17 @@ 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">}}).
This package handles all mail sending. To learn how to send a mail, see [notifications]({{< ref "notifications.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">}}).
To learn how it works and how to add new metrics, take a look at [how metrics work]({{< ref "metrics.md">}}).
### migration
This package handles all migrations.
All migrations are stored and executed here.
All migrations are stored and executed in this package.
To learn more, take a look at the [migrations docs]({{< ref "../development/db-migrations.md">}}).
@ -121,11 +90,35 @@ When adding new features or upgrading existing ones, that most likely happens he
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">}})
* [Adding a feature]({{< ref "feature.md">}})
* [Making calls to the database]({{< ref "database.md">}})
### modules
Everything that can have multiple implementations (like a task migrator from a third-party task provider) lives in a
respective sub package in this package.
#### auth
Contains openid related authentication.
#### avatar
Contains all possible avatar providers a user can choose to set their avatar.
#### background
All project background providers are in sub-packages of this package.
#### dump
Handles everything related to the `dump` and `restore` commands of Vikunja.
#### keyvalue
A simple key-value store with an implementation for memory and redis.
Can be used to cache values.
#### migration
See [writing a migrator]({{< ref "migration.md" >}}).
@ -140,23 +133,22 @@ 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.
**Note**: Only use this package directly if you have to use a direct redis connection.
In most cases, using the `keyvalue` package is a better fit.
### 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">}}).
To add a new route, see [adding a new route]({{< ref "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.
This is where the [generated]({{< ref "mage.md#generate-swagger-definitions-from-code-comments">}} [api docs]({{< ref "../usage/api.md">}}) live.
You usually don't need to touch this package.
### user
@ -175,25 +167,5 @@ 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.
each time `mage release` or `mage 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.
// The id of the file this project has set as background
BackgroundFileID int64 `xorm:"null" json:"-"`
// Holds extra information about the background set since some background providers require attribution or similar. If not null, the background can be accessed at /projects/{projectID}/background
// Contains a very small version of the project background to use as a blurry preview until the actual background is loaded. Check out https://blurha.sh/ to learn how it works.
You can run unit tests with [our `Makefile`]({{< ref "make.md">}}) with
{{<table_of_contents>}}
## API Tests
The following parts are about the kinds of tests in the API package and how to run them.
### Prerequesites
To run any kind of test, you need to specify Vikunja's [root path](https://vikunja.io/docs/config-options/#rootpath).
This is required to make sure all test fixtures are correctly loaded.
The easies way to do that is to set the environment variable `VIKUNJA_SERVICE_ROOTPATH` to the path where you cloned the working directory.
### Unit tests
To run unit tests with [mage]({{< ref "mage.md">}}), execute
{{<highlightbash>}}
make test
mage test:unit
{{</highlight>}}
In Vikunja, everything that is not an integration test counts as unit test - even if it accesses the db.
This definition is a bit blurry, but we haven't found a better one yet.
### Integration tests
All integration tests live in `pkg/integrations`.
You can run them by executing `mage test:integration`.
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 `mage test:integration`.
### 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.
We use this in CI to run all tests with different databases.
To use the normal config set the enviroment variable `VIKUNJA_TESTS_USE_CONFIG=1`.
### Show sql queries
### Showing sql queries
When `UNIT_TESTS_VERBOSE=1` is set, all sql queries will be shown when tests are run.
When the environment variable `UNIT_TESTS_VERBOSE=1` is set, all sql queries will be shown during the test run.
### Fixtures
@ -33,17 +62,7 @@ These fixtures are defined in `pkg/models/fixtures` in YAML-Files which represen
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
#### 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.
@ -52,19 +71,39 @@ 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
{{<highlightgo>}}
err = db.InitTestFixtures("users")
if err != nil {
log.Fatal(err)
}
```
{{</highlight>}}
In your actual tests, you then load the fixtures into the in-memory db like so:
```go
{{<highlightgo>}}
db.LoadAndAssertFixtures(t)
```
{{</highlight>}}
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).
## Frontend tests
The frontend has end to end tests with Cypress that use a Vikunja instance and drive a browser against it.
Check out the docs [in the frontend repo](https://kolaente.dev/vikunja/frontend/src/branch/main/cypress/README.md) about how they work and how to get them running.
### Unit Tests
To run the frontend unit tests, run
{{<highlightbash>}}
pnpm run test:unit
{{</highlight>}}
The frontend also has a watcher available that re-runs all unit tests every time you change something.
All translation strings are stored in `src/i18n/lang/`.
New strings should be added only in the `en.json` file.
Strings in other languages will be synced through weblate and should not be added directly as a PR/commit in the frontend repo.
## Requesting a new language
If you want to start translating Vikunja in a language not yet available in Vikunja, please request the language through the crowdin interface.
If you have issues with this or need a discussion before doing so, please [contact us](https://vikunja.io/contact/) or [start a discussion in the forum](https://community.vikunja.io).
Once at least 50% of all translation strings are translated and approved, they will be added and distributed with the Vikunja frontend for users to select and use Vikunja with them.
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:
{{<highlightgolang>}}
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:
{{<highlightgo-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:
{{<highlightgo-text-template>}}
Hey there!
This is a minimal html email example.
{{.Something}}
{{</highlight>}}
You would then call this like so:
{{<highlightgolang>}}
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).
Vikunja being a go application, has no other dependencies than go itself.
All libraries are bundeled inside the repo in the `vendor/` folder, so all it boils down to are these steps:
To completely build Vikunja from source, you need to build the api and frontend.
1. Make sure [Go](https://golang.org/doc/install) is properly installed on your system. You'll need at least Go `1.9`.
2. Make sure [Make](https://www.gnu.org/software/make/) is properly installed on your system.
3. Clone the repo with `git clone https://code.vikunja.io/api`
3. Run `make build` in the source of this repo. This will build a binary in the root of the repo which will be able to run on your system.
{{<table_of_contents>}}
## API
The Vikunja API has no other dependencies than go itself.
That means compiling it boils down to these steps:
1. Make sure [Go](https://golang.org/doc/install) is properly installed on your system. You'll need at least Go `1.17`.
2. Make sure [Mage](https://magefile.org) is properly installed on your system.
3. Clone the repo with `git clone https://code.vikunja.io/api` and switch into the directory.
4. Run `mage build:build` in the source of this repo. This will build a binary in the root of the repo which will be able to run on your system.
*Note:* Static ressources such as email templates are built into the binary.
For these to work, you may need to run `make generate` before building the vikunja binary.
When builing entirely with `make`, you dont need to do this, `make generate` will be run automatically when running `make build`.
For these to work, you may need to run `mage build:generate` before building the vikunja binary.
When builing entirely with `mage`, you dont need to do this, `mage build:generate` will be run automatically when running `mage build:build`.
# Build for different architectures
### Build for different architectures
To build for other platforms and architectures than the one you're currently on, simply run `make release` or `make release-{linux|windows|darwin}`.
To build for other platforms and architectures than the one you're currently on, simply run `mage release:release` or `mage release:{linux|windows|darwin}`.
More options are available, please refer to the [makefile docs]({{< ref "../development/make.md">}}) for more details.
More options are available, please refer to the [magefile docs]({{< ref "../development/mage.md">}}) for more details.
## Frontend
The code for the frontend is located at [code.vikunja.io/frontend](https://code.vikunja.io/frontend).
1. Make sure you have [pnpm](https://pnpm.io/installation) properly installed on your system.
2. Clone the repo with `git clone https://code.vikunja.io/frontend` and switch into the directory.
3. Install all dependencies with `pnpm install`
4. Build the frontend with `pnpm run build`. This will result in a static js bundle in the `dist/` folder which you can deploy.
@ -17,6 +17,8 @@ We'll use [docker compose](https://docs.docker.com/compose/) to make handling th
> If you have any issues setting up vikunja, please don't hesitate to reach out to us via [matrix](https://riot.im/app/#/room/!dCRiCiLaCCFVNlDnYs:matrix.org?via=matrix.org), the [community forum](https://community.vikunja.io/) or even [email](mailto:hello@vikunja.io).
{{<table_of_contents>}}
## Preparations (optional)
Create a directory for the project where all data and the compose file will live in.
@ -69,7 +76,7 @@ This defines four services, each with their own container:
* An api service which runs the vikunja api. Most of the core logic lives here.
* The frontend which will make vikunja actually usable for most people.
* A database container which will store all lists, tasks, etc. We're using mariadb here, but you're free to use mysql or postgres if you want.
* A database container which will store all projects, tasks, etc. We're using mariadb here, but you're free to use mysql or postgres if you want.
* A proxy service which makes the frontend and api available on the same port, redirecting all requests to `/api` to the api container.
If you already have a proxy on your host, you may want to check out the [reverse proxy examples]() to use that.
By default, it uses port 80 on the host.
@ -87,15 +94,22 @@ server {
proxy_pass http://frontend:80;
}
location /api/ {
location ~* ^/(api|dav|\.well-known)/ {
proxy_pass http://api:3456;
client_max_body_size 20M;
}
}
{{</highlight>}}
This is a simple proxy configuration which will forward all requests to `/api/` to the api container and everything else to the frontend.
**Note:** Even if you want to make your installation available under a different port, you don't need to change anything in this configuration.
<divclass="notification is-info">
<b>NOTE:</b> Even if you want to make your installation available under a different port, you don't need to change anything in this configuration.
</div>
<divclass="notification is-warning">
<b>NOTE:</b> If you change the max upload size in Vikunja's settings, you'll need to also change the <code>client_max_body_size</code> in the nginx proxy config.
</div>
## Run it
@ -187,7 +201,6 @@ You should see something like this:
This example assumes [traefik](https://traefik.io) version 2 installed and configured to [use docker as a configuration provider](https://docs.traefik.io/providers/docker/).
We also make a few assumtions here which you'll most likely need to adjust for your traefik setup:
We also make a few assumptions here which you'll most likely need to adjust for your traefik setup:
* Your domain is `vikunja.example.com`
* The entrypoint you want to make vikunja available from is called `https`
<b>NOTE:</b> If you change the max upload size in Vikunja's settings, you'll need to also change the <code>client_max_body_size</code> in the nginx proxy config.
You should also add 2 empty folders for mariadb and vikunja inside Synology's
docker main folders:
* Docker
* vikunja
* mariadb
Synology has its own GUI for managing Docker containers... But it's easier via docker compose.
To do that, you can
* either activate SSH and paste the adapted compose file in a terminal (using Putty or similar)
* without activating SSH as a "custom script" (go to Control Panel / Task Scheduler / Create / Scheduled Task / User-defined script)
* without activating SSH, by using Portainer (you have to install first, check out [this tutorial](https://www.portainer.io/blog/how-to-install-portainer-on-a-synology-nas) for exmple):
1. Go to **Dashboard / Stacks** click the button **"Add Stack"**
2. Give it the name Vikunja and paste the adapted docker compose file
3. Deploy the Stack with the "Deploy Stack" button:
You may want to change the volumes to match the rest of your setup.
Once deployed, you might want to change the [`PUID` and `GUID` settings]({{< ref "install-backend.md">}}#setting-user-and-group-id-of-the-user-running-vikunja) or [set the time zone]({{< ref "config.md">}}#timezone).
After registering all your users, you might also want to [disable the user registration]({{<ref "config.md">}}#enableregistration).
On this page you will find examples about how to set up Vikunja with a third-party OpenID provider.
To add another example, please [edit this document](https://kolaente.dev/vikunja/api/src/branch/main/docs/content/doc/setup/openid-examples.md) and send a PR.
- Navigate to https://console.cloud.google.com/apis/credentials in the target project
- Create a new OAuth client ID
- Configure an authorized redirect URI of https://vikunja.mydomain.com/auth/openid/google
Note that there currently seems to be no way to stop creation of new users, even when enableregistration is false in the configuration. This means that this approach works well only with an "Internal Organization" app for Google Workspace, which limits the allowed users to organizational accounts only. External / public applications will potentially allow every Google user to register.
These examples assume you have an instance of the backend running on your server listening on port `3456`.
If you've changed this setting, you need to update the server configurations accordingly.
{{<table_of_contents>}}
## NGINX
Below are two example configurations which you can put in your `nginx.conf`:
@ -43,12 +45,17 @@ server {
index index.html index.htm;
}
location /api/ {
location ~* ^/(api|dav|\.well-known)/ {
proxy_pass http://localhost:3456;
client_max_body_size 20M;
}
}
{{</highlight>}}
<divclass="notification is-warning">
<b>NOTE:</b> If you change the max upload size in Vikunja's settings, you'll need to also change the <code>client_max_body_size</code> in the nginx proxy config.
</div>
### without gzip
{{<highlightconf>}}
@ -62,12 +69,33 @@ server {
index index.html index.htm;
}
location /api/ {
location ~* ^/(api|dav|\.well-known)/ {
proxy_pass http://localhost:3456;
client_max_body_size 20M;
}
}
{{</highlight>}}
<divclass="notification is-warning">
<b>NOTE:</b> If you change the max upload size in Vikunja's settings, you'll need to also change the <code>client_max_body_size</code> in the nginx proxy config.
</div>
## NGINX Proxy Manager (NPM)
1. Create a standard Proxy Host for the Vikunja Frontend within NPM and point it to the URL you plan to use. The next several steps will enable the Proxy Host to successfully navigate to the API (on port 3456).
2. Verify that the page will pull up in your browser. (Do not bother trying to log in. It won't work. Trust me.)
3. Now, we'll work with the NPM container, so you need to identify the container name for your NPM installation. e.g. NGINX-PM
4. From the command line, enter `sudo docker exec -it [NGINX-PM container name] /bin/bash` and navigate to the proxy hosts folder where the `.conf` files are stashed. Probably `/data/nginx/proxy_host`. (This folder is a persistent folder created in the NPM container and mounted by NPM.)
5. Locate the `.conf` file where the server_name inside the file matches your Vikunja Proxy Host. Once found, add the following code, unchanged, just above the existing location block in that file. (They are listed by number, not name.)
```
location ~* ^/(api|dav|\.well-known)/ {
proxy_pass http://api:3456;
client_max_body_size 20M;
}
```
6. After saving the edited file, return to NPM's UI browser window and refresh the page to verify your Proxy Host for Vikunja is still online.
7. Now, switch over to your Vikunja browswer window and hit refresh. If you configured your URL correctly in original Vikunja container, you should be all set and the browser will correctly show Vikunja. If not, you'll need to adjust the address in the top of the login subscreen to match your proxy address.
## Apache
Put the following config in `cat /etc/apache2/sites-available/vikunja.conf`:
@ -82,14 +110,18 @@ Put the following config in `cat /etc/apache2/sites-available/vikunja.conf`:
Vikunja itself is always fully capable of handling utf-8 characters.
However, your database might be not.
Vikunja itself will work just fine until you want to use non-latin characters in your tasks/projects/etc.
On this page, you will find information about how to fully ensure non-latin characters like aüäß or emojis work
with your installation.
{{<table_of_contents>}}
## Postgresql & SQLite
Postgresql and SQLite should handle utf-8 just fine - If you discover any issues nonetheless, please
[drop us a message](https://vikunja.io/contact/).
## MySQL
MySQL is not able to handle utf-8 by default.
To fix this, follow the steps below.
To find out if your db supports utf-8, run the following in a shell or similar, assuming the database
you're using for vikunja is called `vikunja`:
{{<highlightsql>}}
SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name = 'vikunja';
{{</highlight>}}
This will get you a result like the following:
```
+----------------------------+
| default_character_set_name |
+----------------------------+
| latin1 |
+----------------------------+
1 row in set (0.001 sec)
```
The charset `latin1` means the db is encoded in the `latin1` encoding which does not support utf-8 characters.
(The following guide is based on [this thread from stackoverflow](https://dba.stackexchange.com/a/104866))
### 0. Backup your database
Before attempting any conversion, please [back up your database]({{< ref "backups.md">}}).
### 1. Create a pre-conversion script
Copy the following sql statements in a file called `preAlterTables.sql` and replace all occurences of `vikunja` with
the name of your database:
{{<highlightsql>}}
use information_schema;
SELECT concat("ALTER DATABASE `",table_schema,"` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;") as _sql
FROM `TABLES` where table_schema like 'vikunja' and TABLE_TYPE='BASE TABLE' group by table_schema;
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name,"` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;") as _sql
FROM `TABLES` where table_schema like 'vikunja' and TABLE_TYPE='BASE TABLE' group by table_schema, table_name;
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name, "` CHANGE `",column_name,"``",column_name,"` ",data_type,"(",character_maximum_length,") CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",IF(is_nullable="YES"," NULL"," NOT NULL"),";") as _sql
FROM `COLUMNS` where table_schema like 'vikunja' and data_type in ('varchar','char');
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name, "` CHANGE `",column_name,"``",column_name,"` ",data_type," CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci",IF(is_nullable="YES"," NULL"," NOT NULL"),";") as _sql
FROM `COLUMNS` where table_schema like 'vikunja' and data_type in ('text','tinytext','mediumtext','longtext');
{{</highlight>}}
### 2. Run the pre-conversion script
Running this will create the actual migration script for your particular database structure and save it in a file called `alterTables.sql`:
{{<highlightbash>}}
mysql -uroot <preAlterTables.sql|egrep'^ALTER'> alterTables.sql
{{</highlight>}}
### 3. Convert the database
At this point converting is just a matter of executing the previously generated sql script:
{{<highlightbash>}}
mysql -uroot <alterTables.sql
{{</highlight>}}
### 4. Verify it was successfully converted
If everything worked as intended, your db collation should now look like this:
{{<highlightsql>}}
SELECT default_character_set_name FROM information_schema.SCHEMATA WHERE schema_name = 'vikunja';
The Vikunja api and frontend are available in two different release flavors.
{{<table_of_contents>}}
## Stable
Stable releases have a fixed version number like `0.18.2` and are published at irregular intervals whenever a new version is ready.
They receive few bugfixes and security patches.
We use [Semantic Versioning](#) for these releases.
## Unstable
Unstable versions are build every time a PR is merged or a commit to the main development branch is made.
As such, they contain the current development code and are more likely to have bugs.
There might be multiple new such builds a day.
Versions contain the last stable version, the number of commits since then and the commit the currently running binary was built from.
They look like this: `v0.18.1+269-5cc4927b9e`
The demo instance at [try.vikunja.io](https://try.vikunja.io) automatically updates and always runs the last unstable build.
## Switching between versions
First you should create a backup of your current setup!
Switching between versions is the same process as [upgrading]({{< ref install-backend.md >}}#updating).
Simply replace the stable binary with an unstable one or vice-versa.
For installations using docker, it is as simple as using the `unstable` or `latest` tag to switch between versions.
**Note:** While switching from stable to unstable should work without any problem, switching back might work but is not recommended and might break your instance.
To switch from unstable back to stable the best way is to wait for the next stable release after the used unstable build and then upgrade to that.
* `-n`, `--name` string: The id of the migration you want to roll back until.
### `restore`
Restores a previously created dump from a zip file, see `dump`.
Usage:
{{<highlightbash>}}
$ vikunja restore <pathtodumpzipfile>
{{</highlight>}}
### `testmail`
Sends a test mail using the configured smtp connection.
Usage:
{{<highlightbash>}}
$ vikunja testmail <emailtosendthetestmailto>
{{</highlight>}}
### `user`
Bundles a few commands to manage users.
#### `user change-status`
Enable or disable a user. Will toggle the current status if no flag (`--enable` or `--disable`) is provided.
Usage:
{{<highlightbash>}}
$ vikunja user change-status <userid><flags>
{{</highlight>}}
Flags:
* `-d`, `--disable`: Disable the user.
* `-e`, `--enable`: Enable the user.
#### `user create`
Create a new user.
Usage:
{{<highlightbash>}}
$ vikunja user create <flags>
{{</highlight>}}
Flags:
* `-a`, `--avatar-provider`: The avatar provider of the new user. Optional.
* `-e`, `--email`: The email address of the new user.
* `-p`, `--password`: The password of the new user. You will be asked to enter it if not provided through the flag.
* `-u`, `--username`: The username of the new user.
#### `user delete`
Start the user deletion process.
If called without the `--now` flag, this command will only trigger an email to the user in order for them to confirm and start the deletion process (this is the same behavoir as if the user requested their deletion via the web interface).
With the flag the user is deleted **immediately**.
**USE WITH CAUTION.**
{{<highlightbash>}}
$ vikunja user delete <id><flags>
{{</highlight>}}
Flags:
* `-n`, `--now` If provided, deletes the user immediately instead of emailing them first.
#### `user list`
Shows a list of all users.
Usage:
{{<highlightbash>}}
$ vikunja user list
{{</highlight>}}
#### `user reset-password`
Reset a users password, either through mailing them a reset link or directly.
Usage:
{{<highlightbash>}}
$ vikunja user reset-password <flags>
{{</highlight>}}
Flags:
* `-d`, `--direct`: If provided, reset the password directly instead of sending the user a reset mail.
* `-p`, `--password`: The new password of the user. Only used in combination with --direct. You will be asked to enter it if not provided through the flag.
#### `user update`
Update an existing user.
Usage:
{{<highlightbash>}}
$ vikunja user update <userid>
{{</highlight>}}
Flags:
* `-a`, `--avatar-provider`: The new avatar provider of the new user.
* `-e`, `--email`: The new email address of the user.
* `-u`, `--username`: The new username of the user.
### `version`
@ -82,22 +205,3 @@ Usage:
{{<highlightbash>}}
$ vikunja web
{{</highlight>}}
### `dump`
Creates a zip file with all vikunja-related files.
This includes config, version, all files and the full database.
Usage:
{{<highlightbash>}}
$ vikunja dump
{{</highlight>}}
### `restore`
Restores a previously created dump from a zip file, see `dump`.
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."
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>.
packagecmd
import(
"bufio"
"fmt"
"os"
"strconv"
"strings"
"time"
"github.com/asaskevich/govalidator"
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/api/pkg/initialize"
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/models"
"code.vikunja.io/api/pkg/user"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
"golang.org/x/term"
"xorm.io/xorm"
)
var(
userFlagUsernamestring
userFlagEmailstring
userFlagPasswordstring
userFlagAvatar="default"
userFlagResetPasswordDirectlybool
userFlagEnableUserbool
userFlagDisableUserbool
userFlagDeleteNowbool
)
funcinit(){
// User create flags
userCreateCmd.Flags().StringVarP(&userFlagUsername,"username","u","","The username of the new user.")
_=userCreateCmd.MarkFlagRequired("username")
userCreateCmd.Flags().StringVarP(&userFlagEmail,"email","e","","The email address of the new user.")
_=userCreateCmd.MarkFlagRequired("email")
userCreateCmd.Flags().StringVarP(&userFlagPassword,"password","p","","The password of the new user. You will be asked to enter it if not provided through the flag.")
userCreateCmd.Flags().StringVarP(&userFlagAvatar,"avatar-provider","a","","The avatar provider of the new user. Optional.")
// User update flags
userUpdateCmd.Flags().StringVarP(&userFlagUsername,"username","u","","The new username of the user.")
userUpdateCmd.Flags().StringVarP(&userFlagEmail,"email","e","","The new email address of the user.")
userUpdateCmd.Flags().StringVarP(&userFlagAvatar,"avatar-provider","a","","The new avatar provider of the new user.")
// Reset PW flags
userResetPasswordCmd.Flags().BoolVarP(&userFlagResetPasswordDirectly,"direct","d",false,"If provided, reset the password directly instead of sending the user a reset mail.")
userResetPasswordCmd.Flags().StringVarP(&userFlagPassword,"password","p","","The new password of the user. Only used in combination with --direct. You will be asked to enter it if not provided through the flag.")
// Change status flags
userChangeEnabledCmd.Flags().BoolVarP(&userFlagDisableUser,"disable","d",false,"Disable the user.")
userChangeEnabledCmd.Flags().BoolVarP(&userFlagEnableUser,"enable","e",false,"Enable the user.")
// User deletion flags
userDeleteCmd.Flags().BoolVarP(&userFlagDeleteNow,"now","n",false,"If provided, deletes the user immediately instead of sending them an email first.")
log.Fatalf("Could not update user password: %s",err)
}
fmt.Println("Password updated successfully.")
}else{
err:=user.RequestUserPasswordResetToken(s,u)
iferr!=nil{
_=s.Rollback()
log.Fatalf("Could not send password reset email: %s",err)
}
fmt.Println("Password reset email sent successfully.")
}
iferr:=s.Commit();err!=nil{
log.Fatalf("Could not send password reset email: %s",err)
}
},
}
varuserChangeEnabledCmd=&cobra.Command{
Use:"change-status [user id]",
Short:"Enable or disable a user. Will toggle the current status if no flag (--enable or --disable) is provided.",
PreRun:func(cmd*cobra.Command,args[]string){
initialize.FullInit()
},
Args:cobra.ExactArgs(1),
Run:func(cmd*cobra.Command,args[]string){
s:=db.NewSession()
defers.Close()
u:=getUserFromArg(s,args[0])
ifuserFlagEnableUser{
u.Status=user.StatusActive
}elseifuserFlagDisableUser{
u.Status=user.StatusDisabled
}else{
ifu.Status==user.StatusActive{
u.Status=user.StatusDisabled
}else{
u.Status=user.StatusActive
}
}
_,err:=user.UpdateUser(s,u,false)
iferr!=nil{
_=s.Rollback()
log.Fatalf("Could not enable the user")
}
iferr:=s.Commit();err!=nil{
log.Fatalf("Error saving everything: %s",err)
}
fmt.Printf("User status successfully changed, status is now \"%s\"\n",u.Status)
},
}
varuserDeleteCmd=&cobra.Command{
Use:"delete [user id]",
Short:"Delete an existing user.",
Long:"Kick off the user deletion process. If call without the --now flag, this command will only trigger an email to the user in order for them to confirm and start the deletion process. With the flag the user is deleted immediately. USE WITH CAUTION.",
Args:cobra.ExactArgs(1),
PreRun:func(cmd*cobra.Command,args[]string){
initialize.FullInit()
},
Run:func(cmd*cobra.Command,args[]string){
ifuserFlagDeleteNow{
fmt.Println("You requested to delete the user immediately. Are you sure?")
fmt.Println(`To confirm, please type "yes, I confirm" in all uppercase:`)
cr:=bufio.NewReader(os.Stdin)
text,err:=cr.ReadString('\n')
iferr!=nil{
log.Fatalf("could not read confirmation message: %s",err)
}
iftext!="YES, I CONFIRM\n"{
log.Fatalf("invalid confirmation message")
}
}
s:=db.NewSession()
defers.Close()
iferr:=s.Begin();err!=nil{
log.Fatalf("Count not start transaction: %s",err)
}
u:=getUserFromArg(s,args[0])
ifuserFlagDeleteNow{
err:=models.DeleteUser(s,u)
iferr!=nil{
_=s.Rollback()
log.Fatalf("Error removing the user: %s",err)
}
}else{
err:=user.RequestDeletion(s,u)
iferr!=nil{
_=s.Rollback()
log.Fatalf("Could not request user deletion: %s",err)
}
}
iferr:=s.Commit();err!=nil{
log.Fatalf("Error saving everything: %s",err)
}
ifuserFlagDeleteNow{
fmt.Println("User deleted successfully.")
}else{
fmt.Println("User scheduled for deletion successfully.")
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.