Docs improvements
This commit is contained in:
@ -1,6 +1,6 @@
|
||||
---
|
||||
date: "2019-03-31:00:00+01:00"
|
||||
title: "Adding new cli commands"
|
||||
title: "Cli Commands"
|
||||
draft: false
|
||||
type: "doc"
|
||||
menu:
|
||||
|
41
docs/content/doc/development/config.md
Normal file
41
docs/content/doc/development/config.md
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
date: "2019-02-12:00:00+02:00"
|
||||
title: "Configuration Options"
|
||||
draft: false
|
||||
type: "doc"
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "development"
|
||||
---
|
||||
|
||||
# Configuration options
|
||||
|
||||
All configuration variables are declared in the `config` package.
|
||||
It uses [viper](https://github.com/spf13/viper) under the hood to handle setting defaults and parsing config files.
|
||||
Viper handles parsing all different configuration sources.
|
||||
|
||||
## Adding new config options
|
||||
|
||||
To make handling configuration parameters a bit easier, we introduced a `Key` string type in the `config` package which
|
||||
you can call directly to get a config value.
|
||||
|
||||
To add a new config option, you should add a new key const to `pkg/config/config.go` and possibly a default value.
|
||||
Default values should always enable the feature to work or turn it off completely if it always needs
|
||||
additional configuration.
|
||||
|
||||
Make sure to also add the new config option to the default config file (`config.yml.sample` at the root of the repository)
|
||||
with an explanatory comment to make sure it is well documented.
|
||||
Then run `mage generate-docs` to generate the configuration docs from the sample file.
|
||||
|
||||
## Getting Configuration Values
|
||||
|
||||
To retreive a configured value call the key with a getter for the type you need.
|
||||
For example:
|
||||
|
||||
{{< highlight golang >}}
|
||||
if config.CacheEnabled.GetBool() {
|
||||
// Do something with enabled caches
|
||||
}
|
||||
{{< /highlight >}}
|
||||
|
||||
Take a look at the methods declared on the type to see what's available.
|
35
docs/content/doc/development/cron.md
Normal file
35
docs/content/doc/development/cron.md
Normal file
@ -0,0 +1,35 @@
|
||||
---
|
||||
title: "Cron Tasks"
|
||||
date: 2021-07-13T23:21:52+02:00
|
||||
draft: false
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "development"
|
||||
---
|
||||
|
||||
# How to add a cron job task
|
||||
|
||||
Cron jobs are tasks which run on a predefined schedule.
|
||||
Vikunja uses these through a light wrapper package around the excellent [github.com/robfig/cron](https://github.com/robfig/cron) package.
|
||||
|
||||
The package exposes a `cron.Schedule` method with two arguments: The first one to define the schedule when the cron task
|
||||
should run, and the second one with the actual function to run at the schedule.
|
||||
You would then create a new function to register your the actual cron task in your package.
|
||||
|
||||
A basic function to register a cron task looks like this:
|
||||
|
||||
{{< highlight golang >}}
|
||||
func RegisterSomeCronTask() {
|
||||
err := cron.Schedule("0 * * * *", func() {
|
||||
// Do something every hour
|
||||
}
|
||||
}
|
||||
{{< /highlight >}}
|
||||
|
||||
Call the register method in the `FullInit()` method of the `init` package to actually register it.
|
||||
|
||||
## Schedule Syntax
|
||||
|
||||
The cron syntax uses the same on you may know from unix systems.
|
||||
|
||||
It is described in detail [here](https://pkg.go.dev/github.com/robfig/cron#hdr-CRON_Expression_Format).
|
40
docs/content/doc/development/database.md
Normal file
40
docs/content/doc/development/database.md
Normal file
@ -0,0 +1,40 @@
|
||||
---
|
||||
date: "2019-02-12:00:00+02:00"
|
||||
title: "Database"
|
||||
draft: false
|
||||
type: "doc"
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "development"
|
||||
---
|
||||
|
||||
# Database
|
||||
|
||||
Vikunja uses [xorm](http://xorm.io/) as an abstraction layer to handle the database connection.
|
||||
Please refer to [their](http://xorm.io/docs/) documentation on how to exactly use it.
|
||||
|
||||
{{< table_of_contents >}}
|
||||
|
||||
## Using the database
|
||||
|
||||
When using the common web handlers, you get an `xorm.Session` to do database manipulations.
|
||||
In other packages, use the `db.NewSession()` method to get a new database session.
|
||||
|
||||
## Adding new database tables
|
||||
|
||||
To add a new table to the database, create the struct and [add a migration for it]({{< ref "db-migrations.md" >}}).
|
||||
|
||||
To learn more about how to configure your struct to create "good" tables, refer to [the xorm documentaion](http://xorm.io/docs/).
|
||||
|
||||
In most cases you will also need to implement the `TableName() string` method on the new struct to make sure the table
|
||||
name matches the rest of the tables - plural.
|
||||
|
||||
## Adding data to test fixtures
|
||||
|
||||
Adding data for test fixtures can be done via `yaml` files in `pkg/models/fixtures`.
|
||||
|
||||
The name of the yaml file should match the table name in the database.
|
||||
Adding values to it is done via array definition inside it.
|
||||
|
||||
**Note**: Table and column names need to be in snake_case as that's what is used internally in the database
|
||||
and for mapping values from the database to xorm so your structs can use it.
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
date: "2019-03-29:00:00+02:00"
|
||||
title: "Database migrations"
|
||||
title: "Database Migrations"
|
||||
draft: false
|
||||
type: "doc"
|
||||
menu:
|
||||
@ -37,6 +37,11 @@ All migrations are sorted before being executed, since `init()` does not guarant
|
||||
When you're adding a new struct, you also need to add it to the `models.GetTables()` function
|
||||
to ensure it will be created on new installations.
|
||||
|
||||
### Generating a new migration stub
|
||||
|
||||
You can easily generate a pre-filled migration stub by running `mage dev:make-migration`.
|
||||
It will ask you for a table name and generate an empty migration similar to the example shown below.
|
||||
|
||||
### Example
|
||||
|
||||
{{< highlight golang >}}
|
||||
|
@ -12,56 +12,11 @@ menu:
|
||||
|
||||
# Development
|
||||
|
||||
We use go modules to vendor libraries for Vikunja, so you'll need at least go `1.11` to use these.
|
||||
If you don't intend to add new dependencies, go `1.9` and above should be fine.
|
||||
We use go modules to manage third-party libraries for Vikunja, so you'll need at least go `1.11` to use these.
|
||||
|
||||
To contribute to Vikunja, fork the project and work on the main branch.
|
||||
|
||||
A lot of developing tasks are automated using a Magefile, so make sure to [take a look at it]({{< ref "mage.md">}}).
|
||||
|
||||
{{< table_of_contents >}}
|
||||
|
||||
## Libraries
|
||||
|
||||
We keep all libraries used for Vikunja around in the `vendor/` folder to still be able to build the project even if
|
||||
some maintainers take their libraries down like [it happened in the past](https://github.com/jteeuwen/go-bindata/issues/5).
|
||||
|
||||
## Tests
|
||||
|
||||
See [testing]({{< ref "test.md">}}).
|
||||
|
||||
#### Development using go modules
|
||||
|
||||
If you're able to use go modules, you can clone the project wherever you want to and work from there.
|
||||
|
||||
#### Development-setup without go modules
|
||||
|
||||
Some internal packages are referenced using their respective package URL. This can become problematic.
|
||||
To “trick” the Go tool into thinking this is a clone from the official repository, download the source code
|
||||
into `$GOPATH/code.vikunja.io/api`. Fork the Vikunja repository, it should then be possible to switch the source directory on the command line.
|
||||
|
||||
{{< highlight bash >}}
|
||||
cd $GOPATH/src/code.vikunja.io/api
|
||||
{{< /highlight >}}
|
||||
|
||||
To be able to create pull requests, the forked repository should be added as a remote to the Vikunja sources, otherwise changes can’t be pushed.
|
||||
|
||||
{{< highlight bash >}}
|
||||
git remote rename origin upstream
|
||||
git remote add origin git@git.kolaente.de:<USERNAME>/api.git
|
||||
git fetch --all --prune
|
||||
{{< /highlight >}}
|
||||
|
||||
This should provide a working development environment for Vikunja. Take a look at the Magefile to get an overview about
|
||||
the available tasks. The most common tasks should be `mage test:unit` which will start our test environment and `mage build:build`
|
||||
which will build a vikunja binary into the working directory. Writing test cases is not mandatory to contribute, but it
|
||||
is highly encouraged and helps developers sleep at night.
|
||||
|
||||
That’s it! You are ready to hack on Vikunja. Test changes, push them to the repository, and open a pull request.
|
||||
|
||||
## Static assets
|
||||
|
||||
Each Vikunja release contains all static assets directly compiled into the binary.
|
||||
To prevent this during development, use the `dev` tag when developing.
|
||||
|
||||
See the [mage docs](mage.md#statically-compile-all-templates-into-the-binary) about how to compile with static assets for a release.
|
||||
Make sure to check the other doc articles for specific development tasks like [testing]({{< ref "test.md">}}),
|
||||
[database migrations]({{< ref "db-migrations.md" >}}) and the [project structure]({{< ref "structure.md" >}}).
|
||||
|
72
docs/content/doc/development/errors.md
Normal file
72
docs/content/doc/development/errors.md
Normal file
@ -0,0 +1,72 @@
|
||||
---
|
||||
date: "2019-02-12:00:00+02:00"
|
||||
title: "Custom Errors"
|
||||
draft: false
|
||||
type: "doc"
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "development"
|
||||
---
|
||||
|
||||
# Custom Errors
|
||||
|
||||
All custom errors are defined in `pkg/models/errors.go`.
|
||||
You should add new ones in this file.
|
||||
|
||||
Custom errors usually have fields for the http return code, a [vikunja-specific error code]({{< ref "../usage/errors.md">}})
|
||||
and a human-readable error message about what went wrong.
|
||||
|
||||
An error consists of multiple functions and definitions:
|
||||
|
||||
{{< highlight golang >}}
|
||||
// This struct holds any information about this specific error.
|
||||
// In this case, it contains the user ID of a nonexistand user.
|
||||
// This type should always be a struct, even if it has no values in it.
|
||||
|
||||
// ErrUserDoesNotExist represents a "UserDoesNotExist" kind of error.
|
||||
type ErrUserDoesNotExist struct {
|
||||
UserID int64
|
||||
}
|
||||
|
||||
// This function is mostly used in unit tests to check if a returned error is of that type.
|
||||
// Every error type should have one of these.
|
||||
// The name should always start with IsErr... followed by the name of the error.
|
||||
|
||||
// IsErrUserDoesNotExist checks if an error is a ErrUserDoesNotExist.
|
||||
func IsErrUserDoesNotExist(err error) bool {
|
||||
_, ok := err.(ErrUserDoesNotExist)
|
||||
return ok
|
||||
}
|
||||
|
||||
// This is the definition of the actual error type.
|
||||
// Your error type is _required_ to implement this in order to be able to be returned as an "error" from functions.
|
||||
func (err ErrUserDoesNotExist) Error() string {
|
||||
return fmt.Sprintf("User does not exist [user id: %d]", err.UserID)
|
||||
}
|
||||
|
||||
// This const holds the vikunja error code used to be able to identify this error without having to
|
||||
// rely on an error string.
|
||||
// This needs to be unique, so you should check whether the error code exists or not.
|
||||
// The general convention for error codes is as follows:
|
||||
// * Every "group" errors lives in a thousend something. For example all user issues are 1000-something, all
|
||||
// list errors are 3000-something and so on.
|
||||
// * New error codes should be the current max error code + 1. Don't take free numbers to prevent old errors
|
||||
// which are depricated and removed from being "new ones". For example, if there are error codes 1001, 1002, 1004,
|
||||
// a new error should be 1005 and not 1003.
|
||||
|
||||
// ErrCodeUserDoesNotExist holds the unique world-error code of this error
|
||||
const ErrCodeUserDoesNotExist = 1005
|
||||
|
||||
// This is the implementation which returns an http error which is then passed to the client.
|
||||
// Here you define the http status code with which one the error will be returned, the vikunja error code and
|
||||
// a human-readable error message.
|
||||
|
||||
// HTTPError holds the http error description
|
||||
func (err ErrUserDoesNotExist) HTTPError() web.HTTPError {
|
||||
return web.HTTPError{
|
||||
HTTPCode: http.StatusNotFound,
|
||||
Code: ErrCodeUserDoesNotExist,
|
||||
Message: "The user does not exist.",
|
||||
}
|
||||
}
|
||||
{{< /highlight >}}
|
@ -28,11 +28,11 @@ This document explains how events and listeners work in Vikunja, how to use them
|
||||
|
||||
Each event has to implement this interface:
|
||||
|
||||
```golang
|
||||
{{< highlight golang >}}
|
||||
type Event interface {
|
||||
Name() string
|
||||
}
|
||||
```
|
||||
{{< /highlight >}}
|
||||
|
||||
An event can contain whatever data you need.
|
||||
|
||||
@ -75,7 +75,7 @@ To dispatch an event, simply call the `events.Dispatch` method and pass in the e
|
||||
|
||||
The `TaskCreatedEvent` is declared in the `pkg/models/events.go` file as follows:
|
||||
|
||||
```golang
|
||||
{{< highlight golang >}}
|
||||
// TaskCreatedEvent represents an event where a task has been created
|
||||
type TaskCreatedEvent struct {
|
||||
Task *Task
|
||||
@ -86,11 +86,11 @@ type TaskCreatedEvent struct {
|
||||
func (t *TaskCreatedEvent) Name() string {
|
||||
return "task.created"
|
||||
}
|
||||
```
|
||||
{{< /highlight >}}
|
||||
|
||||
It is dispatched in the `createTask` function of the `models` package:
|
||||
|
||||
```golang
|
||||
{{< highlight golang >}}
|
||||
func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err error) {
|
||||
|
||||
// ...
|
||||
@ -102,7 +102,7 @@ func createTask(s *xorm.Session, t *Task, a web.Auth, updateAssignees bool) (err
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
{{< /highlight >}}
|
||||
|
||||
As you can see, the curent task and doer are injected into it.
|
||||
|
||||
@ -122,13 +122,13 @@ A single event can have multiple listeners who are independent of each other.
|
||||
|
||||
All listeners must implement this interface:
|
||||
|
||||
```golang
|
||||
{{< highlight golang >}}
|
||||
// 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.
|
||||
@ -165,7 +165,7 @@ See the example below.
|
||||
|
||||
### Example
|
||||
|
||||
```golang
|
||||
{{< highlight golang >}}
|
||||
// RegisterListeners registers all event listeners
|
||||
func RegisterListeners() {
|
||||
events.RegisterListener((&ListCreatedEvent{}).Name(), &IncreaseListCounter{})
|
||||
@ -183,13 +183,13 @@ func (s *IncreaseTaskCounter) Name() string {
|
||||
func (s *IncreaseTaskCounter) Handle(payload message.Payload) (err error) {
|
||||
return keyvalue.IncrBy(metrics.TaskCountKey, 1)
|
||||
}
|
||||
```
|
||||
{{< /highlight >}}
|
||||
|
||||
## Testing
|
||||
|
||||
When testing, you should call the `events.Fake()` method in the `TestMain` function of the package you want to test.
|
||||
This prevents any events from being fired and lets you assert an event has been dispatched like so:
|
||||
|
||||
```golang
|
||||
{{< highlight golang >}}
|
||||
events.AssertDispatched(t, &TaskCreatedEvent{})
|
||||
```
|
||||
{{< /highlight >}}
|
||||
|
33
docs/content/doc/development/feature.md
Normal file
33
docs/content/doc/development/feature.md
Normal file
@ -0,0 +1,33 @@
|
||||
---
|
||||
date: "2019-02-12:00:00+02:00"
|
||||
title: "New API Endpoints"
|
||||
draft: false
|
||||
type: "doc"
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "development"
|
||||
---
|
||||
|
||||
# Add a new api endpoint/feature
|
||||
|
||||
Most of the api endpoints/features of Vikunja are using the [common web handler](https://code.vikunja.io/web).
|
||||
This is a library created by Vikunja in an effort to facilitate the creation of REST endpoints.
|
||||
|
||||
This works by abstracting the handling of CRUD-Requests, including rights check.
|
||||
|
||||
You can learn more about the web handler on [the project's repo](https://code.vikunja.io/web).
|
||||
|
||||
### Helper for pagination
|
||||
|
||||
Pagination limits can be calculated with a helper function, `getLimitFromPageIndex(pageIndex)`
|
||||
(only available in the `models` package) from any page number.
|
||||
It returns the `limit` (max-length) and `offset` parameters needed for SQL-Queries.
|
||||
|
||||
You can feed this function directly into xorm's `Limit`-Function like so:
|
||||
|
||||
{{< highlight golang >}}
|
||||
lists := []List{}
|
||||
err := x.Limit(getLimitFromPageIndex(pageIndex, itemsPerPage)).Find(&lists)
|
||||
{{< /highlight >}}
|
||||
|
||||
// TODO: Add a full example from start to finish, like a tutorial on how to create a new endpoint?
|
@ -57,15 +57,13 @@ These tasks are automatically run in our CI every time someone pushes to main or
|
||||
mage build: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
|
||||
or
|
||||
|
||||
{{< highlight bash >}}
|
||||
mage build:generate
|
||||
mage build
|
||||
{{< /highlight >}}
|
||||
|
||||
This generates static code with all templates, meaning no template need to be referenced at runtime.
|
||||
Builds a `vikunja`-binary in the root directory of the repo for the platform it is run on.
|
||||
|
||||
### clean
|
||||
|
||||
@ -73,7 +71,7 @@ This generates static code with all templates, meaning no template need to be re
|
||||
mage build:clean
|
||||
{{< /highlight >}}
|
||||
|
||||
Cleans all build, executable and bindata files
|
||||
Cleans all build and executable files
|
||||
|
||||
## Check
|
||||
|
||||
@ -173,6 +171,8 @@ mage dev:create-migration
|
||||
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
|
||||
|
48
docs/content/doc/development/metrics.md
Normal file
48
docs/content/doc/development/metrics.md
Normal file
@ -0,0 +1,48 @@
|
||||
---
|
||||
date: "2019-02-12:00:00+02:00"
|
||||
title: "Metrics"
|
||||
draft: false
|
||||
type: "doc"
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "development"
|
||||
---
|
||||
|
||||
# Metrics
|
||||
|
||||
Metrics work by exposing a `/metrics` endpoint which can then be accessed by prometheus.
|
||||
|
||||
To keep the load on the database minimal, metrics are stored and updated in redis.
|
||||
The `metrics` package provides several functions to create and update metrics.
|
||||
|
||||
{{< table_of_contents >}}
|
||||
|
||||
## Exposing New Metrics
|
||||
|
||||
First, define a `const` with the metric key in redis. This is done in `pkg/metrics/metrics.go`.
|
||||
|
||||
To expose a new metric, you need to register it in the `init` function inside of the `metrics` package like so:
|
||||
|
||||
{{< highlight golang >}}
|
||||
// Register total user count metric
|
||||
promauto.NewGaugeFunc(prometheus.GaugeOpts{
|
||||
Name: "vikunja_team_count", // The key of the metric. Must be unique.
|
||||
Help: "The total number of teams on this instance", // A description about the metric itself.
|
||||
}, func() float64 {
|
||||
count, _ := GetCount(TeamCountKey) // TeamCountKey is the const we defined earlier.
|
||||
return float64(count)
|
||||
})
|
||||
{{< /highlight >}}
|
||||
|
||||
Then you'll need to set the metrics initial value on every startup of vikunja.
|
||||
This is done in `pkg/routes/routes.go` to avoid cyclic imports.
|
||||
If metrics are enabled, it checks if a redis connection is available and then sets the initial values.
|
||||
A convenience function is available if the metric is based on a database struct.
|
||||
|
||||
Because metrics are stored in redis, you are responsible to increase or decrease these based on criteria you define.
|
||||
To do this, use `metrics.UpdateCount(value, key)` where `value` is the amount you want to cange it (you can pass
|
||||
negative values to decrease it) and `key` it the redis key used to define the metric.
|
||||
|
||||
## Using it
|
||||
|
||||
A Prometheus config with a Grafana template is available at [our git repo](https://git.kolaente.de/vikunja/monitoring).
|
@ -63,7 +63,7 @@ if config.MigrationWunderlistEnable.GetBool() {
|
||||
}
|
||||
```
|
||||
|
||||
You should also document the routes with [swagger annotations]({{< ref "../practical-instructions/swagger-docs.md" >}}).
|
||||
You should also document the routes with [swagger annotations]({{< ref "swagger-docs.md" >}}).
|
||||
|
||||
## Insertion helper method
|
||||
|
||||
|
@ -18,13 +18,13 @@ Vikunjs provides a simple abstraction to send notifications per mail and in the
|
||||
|
||||
Each notification has to implement this interface:
|
||||
|
||||
```golang
|
||||
{{< highlight golang >}}
|
||||
type Notification interface {
|
||||
ToMail() *Mail
|
||||
ToDB() interface{}
|
||||
Name() string
|
||||
}
|
||||
```
|
||||
{{< /highlight >}}
|
||||
|
||||
Both functions return the formatted messages for mail and database.
|
||||
|
||||
@ -35,7 +35,7 @@ For example, if your notification should not be recorded in the database but onl
|
||||
|
||||
A list of chainable functions is available to compose a mail:
|
||||
|
||||
```golang
|
||||
{{< highlight golang >}}
|
||||
mail := NewMail().
|
||||
// The optional sender of the mail message.
|
||||
From("test@example.com").
|
||||
@ -54,7 +54,7 @@ mail := NewMail().
|
||||
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).
|
||||
|
||||
@ -75,14 +75,14 @@ It takes the name of the notification and the package where the notification wil
|
||||
Notifiables can receive a notification.
|
||||
A notifiable is defined with this interface:
|
||||
|
||||
```golang
|
||||
{{< highlight golang >}}
|
||||
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.
|
||||
|
||||
@ -93,7 +93,7 @@ It takes a notifiable and a notification as input.
|
||||
|
||||
For example, the email confirm notification when a new user registers is sent like this:
|
||||
|
||||
```golang
|
||||
{{< highlight golang >}}
|
||||
n := &EmailConfirmNotification{
|
||||
User: update.User,
|
||||
IsNew: false,
|
||||
@ -101,7 +101,7 @@ n := &EmailConfirmNotification{
|
||||
|
||||
err = notifications.Notify(update.User, n)
|
||||
return
|
||||
```
|
||||
{{< /highlight >}}
|
||||
|
||||
## Testing
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
date: "2019-02-12:00:00+02:00"
|
||||
title: "Project structure"
|
||||
title: "Project Structure"
|
||||
draft: false
|
||||
type: "doc"
|
||||
menu:
|
||||
@ -10,40 +10,7 @@ menu:
|
||||
|
||||
# Project structure
|
||||
|
||||
In general, this api repo has the following structure:
|
||||
|
||||
* `docker`
|
||||
* `docs`
|
||||
* `pkg`
|
||||
* `caldav`
|
||||
* `cmd`
|
||||
* `config`
|
||||
* `db`
|
||||
* `fixtures`
|
||||
* `files`
|
||||
* `integration`
|
||||
* `log`
|
||||
* `mail`
|
||||
* `metrics`
|
||||
* `migration`
|
||||
* `models`
|
||||
* `modules`
|
||||
* `migration`
|
||||
* `handler`
|
||||
* `wunderlist`
|
||||
* `red`
|
||||
* `routes`
|
||||
* `api/v1`
|
||||
* `static`
|
||||
* `swagger`
|
||||
* `user`
|
||||
* `utils`
|
||||
* `version`
|
||||
* `REST-Tests`
|
||||
* `templates`
|
||||
* `vendor`
|
||||
|
||||
This document will explain what these mean and what you can find where.
|
||||
This document explains what each package does.
|
||||
|
||||
{{< table_of_contents >}}
|
||||
|
||||
@ -52,18 +19,13 @@ This document will explain what these mean and what you can find where.
|
||||
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
|
||||
|
||||
@ -75,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
|
||||
|
||||
@ -102,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">}}).
|
||||
|
||||
@ -123,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 list 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" >}}).
|
||||
@ -142,20 +133,19 @@ 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 `mage generate` live here.
|
||||
|
||||
### swagger
|
||||
|
||||
This is where the [generated]({{< ref "mage.md#generate-swagger-definitions-from-code-comments">}} [api docs]({{< ref "../usage/api.md">}}) live.
|
||||
@ -179,23 +169,3 @@ See their function definitions for instructions on how to use them.
|
||||
The single purpouse of this package is to hold the current vikunja version which gets overridden through build flags
|
||||
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.
|
||||
|
73
docs/content/doc/development/swagger-docs.md
Normal file
73
docs/content/doc/development/swagger-docs.md
Normal file
@ -0,0 +1,73 @@
|
||||
---
|
||||
date: "2019-02-12:00:00+02:00"
|
||||
title: "Modifying Swagger API Docs"
|
||||
draft: false
|
||||
type: "doc"
|
||||
menu:
|
||||
sidebar:
|
||||
parent: "development"
|
||||
---
|
||||
|
||||
# Modifying swagger api docs
|
||||
|
||||
The api documentation is generated using [swaggo](https://github.com/swaggo/swag) from comments.
|
||||
|
||||
{{< table_of_contents >}}
|
||||
|
||||
## Documenting structs
|
||||
|
||||
You should always comment every field which will be exposed as a json in the api.
|
||||
These comments will show up in the documentation, it'll make it easier for developers using the api.
|
||||
|
||||
As an example, this is the definition of a list with all comments:
|
||||
|
||||
{{< highlight golang >}}
|
||||
// List represents a list of tasks
|
||||
type List struct {
|
||||
// The unique, numeric id of this list.
|
||||
ID int64 `xorm:"bigint autoincr not null unique pk" json:"id" param:"list"`
|
||||
// The title of the list. You'll see this in the namespace overview.
|
||||
Title string `xorm:"varchar(250)" json:"title" valid:"required,runelength(3|250)" minLength:"3" maxLength:"250"`
|
||||
// The description of the list.
|
||||
Description string `xorm:"varchar(1000)" json:"description" valid:"runelength(0|1000)" maxLength:"1000"`
|
||||
OwnerID int64 `xorm:"bigint INDEX" json:"-"`
|
||||
NamespaceID int64 `xorm:"bigint INDEX" json:"-" param:"namespace"`
|
||||
|
||||
// The user who created this list.
|
||||
Owner User `xorm:"-" json:"owner" valid:"-"`
|
||||
// An array of tasks which belong to the list.
|
||||
Tasks []*ListTask `xorm:"-" json:"tasks"`
|
||||
|
||||
// A unix timestamp when this list was created. You cannot change this value.
|
||||
Created int64 `xorm:"created" json:"created"`
|
||||
// A unix timestamp when this list was last updated. You cannot change this value.
|
||||
Updated int64 `xorm:"updated" json:"updated"`
|
||||
|
||||
web.CRUDable `xorm:"-" json:"-"`
|
||||
web.Rights `xorm:"-" json:"-"`
|
||||
}
|
||||
{{< /highlight >}}
|
||||
|
||||
## Documenting api Endpoints
|
||||
|
||||
All api routes should be documented with a comment above the handler function.
|
||||
When generating the api docs with mage, the swagger cli will pick these up and put them in a neat document.
|
||||
|
||||
A comment looks like this:
|
||||
|
||||
{{< highlight golang >}}
|
||||
// @Summary Login
|
||||
// @Description Logs a user in. Returns a JWT-Token to authenticate further requests.
|
||||
// @tags user
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param credentials body user.Login true "The login credentials"
|
||||
// @Success 200 {object} auth.Token
|
||||
// @Failure 400 {object} models.Message "Invalid user password model."
|
||||
// @Failure 412 {object} models.Message "Invalid totp passcode."
|
||||
// @Failure 403 {object} models.Message "Invalid username or password."
|
||||
// @Router /login [post]
|
||||
func Login(c echo.Context) error {
|
||||
// Handler logic
|
||||
}
|
||||
{{< /highlight >}}
|
@ -10,7 +10,7 @@ menu:
|
||||
|
||||
# Testing
|
||||
|
||||
You can run unit tests with [our `Magefile`]({{< ref "mage.md">}}) with
|
||||
You can run unit tests with [mage]({{< ref "mage.md">}}) with
|
||||
|
||||
{{< highlight bash >}}
|
||||
mage test:unit
|
||||
|
Reference in New Issue
Block a user