1
0

Docs improvements

This commit is contained in:
kolaente
2021-07-14 00:25:12 +02:00
parent 4216ed7277
commit 7ee535de47
19 changed files with 232 additions and 317 deletions

View File

@ -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:

View 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.

View 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).

View 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.

View File

@ -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 >}}

View File

@ -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 cant 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.
Thats 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" >}}).

View 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 >}}

View File

@ -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 >}}

View 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?

View File

@ -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

View 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).

View File

@ -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

View File

@ -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

View File

@ -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.

View 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 >}}

View File

@ -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