Compare commits

...

18 Commits

Author SHA1 Message Date
viehlieb 4567a68065 do the swag 2023-02-10 21:44:08 +01:00
viehlieb 8d46490db0 add openid.md as readme for feature: 950 assigning group through oidc claim 2023-02-10 21:32:40 +01:00
viehlieb 1b191c36e4 add config.yml.sample for seting up vikunja_scope and group assignment feature 2023-02-10 21:32:40 +01:00
viehlieb 2eb0bb9c14 remove user from all oidc teams if token is empty 2023-02-10 21:32:40 +01:00
viehlieb b32656c46f make provider scopes more robust add default openid profile email 2023-02-10 21:32:40 +01:00
viehlieb b272e46d4d add functionality for deleting user only from oidc teams which are not present in the current token 2023-02-10 21:32:40 +01:00
viehlieb af1e71f256 change method function to GetOrCreateTeamsByOIDCAndNames 2023-02-10 21:32:40 +01:00
viehlieb a2d5f06cde do the swag 2023-02-10 21:32:39 +01:00
viehlieb 3ef25e7be5 add functionality to assign user to teams through oidc custom claim 2023-02-10 21:32:39 +01:00
viehlieb d3fa4a04c0 add TeamData struct to openid.go 2023-02-10 21:32:39 +01:00
viehlieb 5061028f20 add VikunjaGroups to claums struct in openid.go 2023-02-10 21:32:39 +01:00
viehlieb 8b109fbcda add scope to provider 2023-02-10 21:32:39 +01:00
viehlieb 962e09174f add functionality of searching teams by oidcId and name to teams.go 2023-02-10 21:32:39 +01:00
viehlieb db1f1423bb add OidcIDto teams 2023-02-10 21:32:39 +01:00
viehlieb ae8e3d9108 add errors to user 2023-02-10 21:10:03 +01:00
viehlieb 83fdd06aac migration to add idcID to teams 2023-02-10 21:09:49 +01:00
viehlieb 7366fa996e wip assign groups via oidc 2023-02-10 21:07:01 +01:00
viehlieb 2715a55620 introduce functionality to assign/create team via group claim 2023-02-10 21:06:43 +01:00
12 changed files with 975 additions and 658 deletions

View File

@ -303,6 +303,10 @@ auth:
clientid:
# The client secret used to authenticate Vikunja at the OpenID Connect provider.
clientsecret:
# The scope necessary to use oidc.
# If you want to use the Feature to create and assign to vikunja teams via oidc, you have to add the custom "vikunja_scope".
# e.g. scope: openid email profile vikunja_scope
scope: openid email profile
# Prometheus metrics endpoint
metrics:

View File

@ -0,0 +1,43 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2021 Vikunja and contributors. All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public Licensee as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public Licensee for more details.
//
// You should have received a copy of the GNU Affero General Public Licensee
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package migration
import (
"src.techknowlogick.com/xormigrate"
"xorm.io/xorm"
)
type teams20230104152903 struct {
OidcID string `xorm:"varchar(250) null" maxLength:"250" json:"oidc_id"`
}
func (teams20230104152903) TableName() string {
return "teams"
}
func init() {
migrations = append(migrations, &xormigrate.Migration{
ID: "20230104152903",
Description: "Adding OidcID to teams",
Migrate: func(tx *xorm.Engine) error {
return tx.Sync2(teams20230104152903{})
},
Rollback: func(tx *xorm.Engine) error {
return nil
},
})
}

View File

@ -1072,7 +1072,6 @@ func (err ErrTeamNameCannotBeEmpty) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusBadRequest, Code: ErrCodeTeamNameCannotBeEmpty, Message: "The team name cannot be empty"}
}
// ErrTeamDoesNotExist represents an error where a team does not exist
type ErrTeamDoesNotExist struct {
TeamID int64
}
@ -1191,6 +1190,51 @@ func (err ErrTeamDoesNotHaveAccessToList) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusForbidden, Code: ErrCodeTeamDoesNotHaveAccessToList, Message: "This team does not have access to the list."}
}
type ErrTeamsDoNotExist struct {
Name string
}
// IsErrTeamDoNotExist checks if an error is ErrTeamDoesNotExist.
func IsErrTeamsDoNotExist(err error) bool {
_, ok := err.(ErrTeamsDoNotExist)
return ok
}
func (err ErrTeamsDoNotExist) Error() string {
return fmt.Sprintf("Team does not exist [Team Name: %v]", err.Name)
}
// ErrCodeTeamDoesNotExist holds the unique world-error code of this error
const ErrCodeTeamsDoNotExist = 6008
// HTTPError holds the http error description
func (err ErrTeamsDoNotExist) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeTeamDoesNotExist, Message: "No team with given name exists."}
}
// ErrOIDCTeamsDoNotExistForUser represents an error where an oidcTeam does not exist for the user
type ErrOIDCTeamsDoNotExistForUser struct {
UserID int64
}
// IsErrOIDCTeamsDoNotExistForUser checks if an error is ErrOIDCTeamsDoNotExistForUser.
func IsErrOIDCTeamsDoNotExistForUser(err error) bool {
_, ok := err.(ErrTeamDoesNotExist)
return ok
}
func (err ErrOIDCTeamsDoNotExistForUser) Error() string {
return fmt.Sprintf("No Oidc exists for User [User ID: %d]", err.UserID)
}
// ErrCodeTeamDoesNotExist holds the unique world-error code of this error
const ErrCodeOIDCTeamsDoNotExistForUser = 6009
// HTTPError holds the http error description
func (err ErrOIDCTeamsDoNotExistForUser) HTTPError() web.HTTPError {
return web.HTTPError{HTTPCode: http.StatusNotFound, Code: ErrCodeTeamDoesNotExist, Message: "This team does not exist."}
}
// ====================
// User <-> List errors
// ====================

View File

@ -109,6 +109,21 @@ func (tm *TeamMember) Delete(s *xorm.Session, a web.Auth) (err error) {
return
}
func (tm *TeamMember) CheckMembership(s *xorm.Session) (exists bool, err error) {
member, err := user2.GetUserByUsername(s, tm.Username)
if err != nil {
return
}
tm.UserID = member.ID
exists, err = s.
Where("team_id = ? AND user_id = ?", tm.TeamID, tm.UserID).
Get(&TeamMember{})
if exists {
return
}
return exists, ErrUserIsMemberOfTeam{tm.UserID, tm.UserID}
}
// Update toggles a team member's admin status
// @Summary Toggle a team member's admin status
// @Description If a user is team admin, this will make them member and vise-versa.

View File

@ -20,6 +20,7 @@ import (
"time"
"code.vikunja.io/api/pkg/db"
"code.vikunja.io/api/pkg/log"
"code.vikunja.io/api/pkg/events"
"code.vikunja.io/api/pkg/user"
@ -38,6 +39,8 @@ type Team struct {
// The team's description.
Description string `xorm:"longtext null" json:"description"`
CreatedByID int64 `xorm:"bigint not null INDEX" json:"-"`
// The team's oidc id delivered by the oidc provider
OidcID string `xorm:"varchar(250) null" maxLength:"250" json:"oidc_id"`
// The user who created this team.
CreatedBy *user.User `xorm:"-" json:"created_by"`
@ -79,7 +82,7 @@ type TeamMember struct {
}
// TableName makes beautiful table names
func (*TeamMember) TableName() string {
func (TeamMember) TableName() string {
return "team_members"
}
@ -91,6 +94,12 @@ type TeamUser struct {
TeamID int64 `json:"-"`
}
type TeamData struct {
TeamName string
OidcID string
Description string
}
// GetTeamByID gets a team by its ID
func GetTeamByID(s *xorm.Session, id int64) (team *Team, err error) {
if id < 1 {
@ -120,6 +129,52 @@ func GetTeamByID(s *xorm.Session, id int64) (team *Team, err error) {
return
}
// GetTeamByName gets teams by name
func GetTeamsByName(s *xorm.Session, name string) (teams []*Team, err error) {
if name == "" {
return teams, ErrTeamsDoNotExist{name}
}
var ts []*Team
err = s.
Where("name = ?", name).
Find(&ts)
if err != nil || len(ts) == 0 {
return ts, ErrTeamsDoNotExist{name}
}
teams = ts
return teams, err
}
// GetTeamByOidcIDAndName gets teams where oidc_id and name match parameters
// For oidc team creation oidcID and Name need to be set
func GetTeamByOidcIDAndName(s *xorm.Session, oidcID string, teamName string) (team Team, err error) {
exists, err := s.
Table("teams").
Where("oidc_id = ? AND name = ?", oidcID, teamName).
Get(&team)
log.Debugf("GetTeamByOidcIDAndName: %v, exists: %v", team.Name, exists)
if exists && err == nil {
return team, nil
}
return team, ErrTeamsDoNotExist{oidcID}
}
func FindAllOidcTeamIDsForUser(s *xorm.Session, userID int64) (ts []int64, err error) {
err = s.
Table("team_members").
Where("user_id = ? ", userID).
Join("RIGHT", "teams", "teams.id = team_members.team_id").
Where("teams.oidc_id != ?", "").
Cols("teams.id").
Find(&ts)
if ts == nil || err != nil {
return ts, ErrOIDCTeamsDoNotExistForUser{userID}
}
return ts, nil
}
func addMoreInfoToTeams(s *xorm.Session, teams []*Team) (err error) {
if len(teams) == 0 {
@ -270,8 +325,8 @@ func (t *Team) Create(s *xorm.Session, a web.Auth) (err error) {
return
}
// Insert the current user as member and admin
tm := TeamMember{TeamID: t.ID, Username: doer.Username, Admin: true}
var admin = true
tm := TeamMember{TeamID: t.ID, Username: doer.Username, Admin: admin}
if err = tm.Create(s, doer); err != nil {
return err
}
@ -282,6 +337,11 @@ func (t *Team) Create(s *xorm.Session, a web.Auth) (err error) {
})
}
func (t *Team) ManageAdminRight(teamMember TeamMember, admin bool) {
// Insert the current user as member and admin
teamMember.Admin = admin
}
// Delete deletes a team
// @Summary Deletes a team
// @Description Delets a team. This will also remove the access for all users in that team.

View File

@ -20,6 +20,7 @@ import (
"context"
"encoding/json"
"errors"
"fmt"
"math/rand"
"net/http"
"time"
@ -53,16 +54,23 @@ type Provider struct {
AuthURL string `json:"auth_url"`
LogoutURL string `json:"logout_url"`
ClientID string `json:"client_id"`
Scope string `json:"scope"`
ClientSecret string `json:"-"`
openIDProvider *oidc.Provider
Oauth2Config *oauth2.Config `json:"-"`
}
type TeamData struct {
TeamName string
OidcID string
Description string
}
type claims struct {
Email string `json:"email"`
Name string `json:"name"`
PreferredUsername string `json:"preferred_username"`
Nickname string `json:"nickname"`
Email string `json:"email"`
Name string `json:"name"`
PreferredUsername string `json:"preferred_username"`
Nickname string `json:"nickname"`
Teams []string `json:"groups"`
VikunjaGroups interface{} `json:"vikunja_groups"`
}
func init() {
@ -142,6 +150,7 @@ func HandleCallback(c echo.Context) error {
// Extract custom claims
cl := &claims{}
err = idToken.Claims(cl)
if err != nil {
log.Errorf("Error getting token claims for provider %s: %v", provider.Name, err)
@ -189,22 +198,150 @@ func HandleCallback(c echo.Context) error {
// Check if we have seen this user before
u, err := getOrCreateUser(s, cl, idToken.Issuer, idToken.Subject)
if err != nil {
_ = s.Rollback()
log.Errorf("Error creating new user for provider %s: %v", provider.Name, err)
return handler.HandleHTTPError(err, c)
}
err = s.Commit()
// does the oidc token contain well formed "vikunja_groups" through vikunja_scope
teamData, err := getTeamDataFromToken(cl.VikunjaGroups, provider)
if err != nil {
log.Errorf("Error creating teams for user and vikunja groups %s: %v", cl.VikunjaGroups, err)
return handler.HandleHTTPError(err, c)
}
//find old teams for user through oidc
oldOidcTeams, _ := models.FindAllOidcTeamIDsForUser(s, u.ID)
var oidcTeams []int64
if len(teamData) > 0 {
// check if we have seen these teams before.
// find or create Teams and assign user as teammember.
log.Debugf("TeamData is set %v", teamData)
teams, err := GetOrCreateTeamsByOIDCAndNames(s, teamData, u)
if err != nil {
log.Errorf("Error verifying team for name %v, got %v", cl.Name, teams, err)
return err
}
for _, team := range teams {
tm := models.TeamMember{TeamID: team.ID, Username: u.Username}
exists, err := tm.CheckMembership(s)
if !exists {
err = tm.Create(s, u)
if err != nil {
log.Debugf("Could not assign %v to %v. %v", u.Username, team.Name, err)
}
} else {
log.Debugf("Team exists? %v or error: %v", exists, err)
}
oidcTeams = append(oidcTeams, team.ID)
}
}
SignOutFromOrDeleteTeamsByID(s, u, notIn(oldOidcTeams, oidcTeams))
err = s.Commit()
if err != nil {
_ = s.Rollback()
log.Errorf("Error creating new Team for provider %s: %v", provider.Name, err)
return handler.HandleHTTPError(err, c)
}
// Create token
return auth.NewUserAuthTokenResponse(u, c, false)
}
func SignOutFromOrDeleteTeamsByID(s *xorm.Session, u *user.User, teamIDs []int64) {
for _, teamID := range teamIDs {
tm := models.TeamMember{TeamID: teamID, Username: u.Username}
err := tm.Delete(s, u)
if err != nil {
team, err := models.GetTeamByID(s, teamID)
if err != nil {
log.Errorf("Cannot find team with id: %v, err: %v", teamID, err)
} else {
err = team.Delete(s, u)
if err != nil {
log.Errorf("Cannot delete team %v", err)
}
}
}
}
}
func getTeamDataFromToken(groups interface{}, provider *Provider) (teamData []TeamData, err error) {
teamData = []TeamData{}
if groups != nil {
el := groups.([]interface{})
for _, data := range el {
team := data.(map[string]interface{})
var name string
var description string
var oidcID string
if team["name"] != nil {
name = team["name"].(string)
}
if team["description"] != nil {
description = team["description"].(string)
}
if team["oidcID"] != nil {
switch t := team["oidcID"].(type) {
case int64:
oidcID = fmt.Sprintf("%v", team["oidcID"])
case string:
oidcID = string(team["oidcID"].(string))
case float64:
fl := float64(team["oidcID"].(float64))
oidcID = fmt.Sprintf("%v", fl)
default:
log.Errorf("No oidcID assigned for %v or type %v not supported", team, t)
}
}
if name == "" || oidcID == "" {
log.Errorf("Claim of your custom scope does not hold name or oidcID for automatic group assignment through oidc provider. Please check %s", provider.Name)
return teamData, &user.ErrOpenIDCustomScopeMalformed{}
}
teamData = append(teamData, TeamData{TeamName: name, OidcID: oidcID, Description: description})
}
}
return teamData, nil
}
func CreateTeamWithData(s *xorm.Session, teamData TeamData, u *user.User) (team *models.Team, err error) {
tea := &models.Team{
Name: teamData.TeamName,
Description: teamData.Description,
OidcID: teamData.OidcID,
}
log.Debugf("Teams: %v", tea.OidcID)
err = tea.Create(s, u)
return tea, err
}
// this functions creates an array of existing teams that was generated from the oidc data.
func GetOrCreateTeamsByOIDCAndNames(s *xorm.Session, teamData []TeamData, u *user.User) (te []models.Team, err error) {
te = []models.Team{}
// Procedure can only be successful if oidcID is set and converted to string
for _, oidcTeam := range teamData {
team, err := models.GetTeamByOidcIDAndName(s, oidcTeam.OidcID, oidcTeam.TeamName)
if err != nil {
log.Debugf("Team with oidc_id %v and name %v does not exist. Create Team.. ", oidcTeam.OidcID, oidcTeam.TeamName)
newTeam, err := CreateTeamWithData(s, oidcTeam, u)
if err != nil {
return te, err
}
te = append(te, *newTeam)
} else {
log.Debugf("Team with oidc_id %v and name %v already exists.", team.OidcID, team.Name)
te = append(te, team)
}
}
log.Debugf("Array: %v", te)
return te, err
}
func getOrCreateUser(s *xorm.Session, cl *claims, issuer, subject string) (u *user.User, err error) {
// Check if the user exists for that issuer and subject
u, err = user.GetUserWithEmail(s, &user.User{
Issuer: issuer,
@ -275,3 +412,23 @@ func getOrCreateUser(s *xorm.Session, cl *claims, issuer, subject string) (u *us
return
}
// find the elements which appear in slice1,but not in slice2
func notIn(slice1 []int64, slice2 []int64) []int64 {
var diff []int64
for _, s1 := range slice1 {
found := false
for _, s2 := range slice2 {
if s1 == s2 {
found = true
break
}
}
// String not found. We add it to return slice
if !found {
diff = append(diff, s1)
}
}
return diff
}

View File

@ -0,0 +1,99 @@
regarding:
https://kolaente.dev/vikunja/api/pulls/1279
# Assign teams via oidc
This PR adds the functionality to assign users to teams via oidc.
Read carefully and brief your administrators to use this feature.
Tested with oidc provider authentik.
To distinguish between groups created in vikunja and groups generated via oidc, there is an attribute neccessary, which is called: *oidcID*
## Setup
Edit config.yml to include scope: openid profile email vikunja_scope
For authentik to use group assignment feature:
- go to: .../if/admin/#/core/property-mappings
- create a new mapping called "vikunja_scope"
There is a field to enter python expressions that will be delivered with the oidc token.
- write a small script, for adding group information to vikunja_scope.
```python
groupsDict = {"vikunja_groups": []}
for group in request.user.ak_groups.all():
groupsDict["vikunja_groups"].append({"name": group.name, "oidcID": group.num_pk})
return groupsDict
"""
output example:
{
"vikunja_groups": [
{
"name": "team 1",
"oidcID": 33349
},
{
"name": "team 2",
"oidcID": 35933
}
]
}
"""
```
Now when you log in via oidc there will be a list of scopes you are claiming from your oidc provider.
You should see "the description you entered in the oidc provider's admin area"
- Log in and go to teams.
- You will see "(sso: XXXXX)" written next to each team you were asigned through oidc.
## IMPORTANT NOTES:
**SSO/OIDC teams cannot be edited.**
**It is crucial to call the element "vikunja_groups" since this is the name vikunja is looking for.**
**Additionally, make sure to deliver an "oidcID" and a "name".**
____________________________________________________________________________
## BEHAVIOR
*(.. examples for "team1" ..)*
1. *Token delivers team.name +team.oidcId and Vikunja team does not exist:* \
New team will be created called "team 1" with attribute oidcId: "33929"
2. *In Vikunja Team with name "team 1" already exists in vikunja, but has no oidcID set:* \
new team will be created called "team 1" with attribute oidcId: "33929"
3. *In Vikunja Team with name "team 1" already exists in vikunja, but has different oidcID set:* \
new team will be created called "team 1" with attribute oidcId: "33929"
4. *In Vikunja Team with oidcID "33929" already exists in vikunja, but has different name than "team1":* \
new team will be created called "team 1" with attribute oidcId: "33929"
5. *Scope vikunja_scope is not set:* \
nothing happens
6. *oidcID is not set:* \
You'll get error.
Custom Scope malformed
"The custom scope set by the OIDC provider is malformed. Please make sure the openid provider sets the data correctly for your scope. Check especially to have set an oidcID."
7. *In Vikunja I am in "team 3" with oidcID "", but the token does not deliver any data for "team 3":* \
You will stay in team 3 since it was not set by the oidc provider
8. *In Vikunja I am in "team 3" with oidcID "12345", but the token does not deliver any data for "team 3"*:\
You will be signed out of all teams, which have an oidcID set and are not contained in the token.
Especially if you've been the last team member, the team will be deleted.

View File

@ -125,6 +125,10 @@ func getProviderFromMap(pi map[string]interface{}) (provider *Provider, err erro
logoutURL = ""
}
scope, _ := pi["scope"].(string)
if scope == "" {
scope = "openid profile email"
}
provider = &Provider{
Name: pi["name"].(string),
Key: k,
@ -132,6 +136,7 @@ func getProviderFromMap(pi map[string]interface{}) (provider *Provider, err erro
OriginalAuthURL: pi["authurl"].(string),
ClientSecret: pi["clientsecret"].(string),
LogoutURL: logoutURL,
Scope: scope,
}
cl, is := pi["clientid"].(int)

View File

@ -7620,11 +7620,36 @@ const docTemplate = `{
},
"created_by": {
"description": "The user who initially created the bucket.",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"filter_by": {
"description": "The field name of the field to filter by",
"type": "array",
"items": {
"type": "string"
}
},
"filter_comparator": {
"description": "The comparator for field and value",
"type": "array",
"items": {
"type": "string"
}
},
"filter_concat": {
"description": "The way all filter conditions are concatenated together, can be either \"and\" or \"or\".,",
"type": "string"
},
"filter_include_nulls": {
"description": "If set to true, the result will also include null values",
"type": "boolean"
},
"filter_value": {
"description": "The value of the field name to filter by",
"type": "array",
"items": {
"type": "string"
}
},
"id": {
"description": "The unique, numeric id of this bucket.",
@ -7643,10 +7668,24 @@ const docTemplate = `{
"description": "The list this bucket belongs to.",
"type": "integer"
},
"order_by": {
"description": "The query parameter to order the items by. This can be either asc or desc, with asc being the default.",
"type": "array",
"items": {
"type": "string"
}
},
"position": {
"description": "The position this bucket has when querying all buckets. See the tasks.position property on how to use this.",
"type": "number"
},
"sort_by": {
"description": "The query parameter to sort by. This is for ex. done, priority, etc.",
"type": "array",
"items": {
"type": "string"
}
},
"tasks": {
"description": "All tasks which belong to this bucket.",
"type": "array",
@ -7662,7 +7701,9 @@ const docTemplate = `{
"updated": {
"description": "A timestamp when this bucket was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.BulkAssignees": {
@ -7674,7 +7715,9 @@ const docTemplate = `{
"items": {
"$ref": "#/definitions/user.User"
}
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.BulkTask": {
@ -7708,11 +7751,7 @@ const docTemplate = `{
},
"created_by": {
"description": "The user who initially created the task.",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"description": {
"description": "The task description.",
@ -7784,11 +7823,7 @@ const docTemplate = `{
},
"related_tasks": {
"description": "All related tasks, grouped by their relation kind",
"allOf": [
{
"$ref": "#/definitions/models.RelatedTaskMap"
}
]
"$ref": "#/definitions/models.RelatedTaskMap"
},
"reminder_dates": {
"description": "An array of datetimes when the user wants to be reminded of the task.",
@ -7803,11 +7838,7 @@ const docTemplate = `{
},
"repeat_mode": {
"description": "Can have three possible values which will trigger when the task is marked as done: 0 = repeats after the amount specified in repeat_after, 1 = repeats all dates each months (ignoring repeat_after), 3 = repeats from the current date rather than the last set date.",
"allOf": [
{
"$ref": "#/definitions/models.TaskRepeatMode"
}
]
"type": "integer"
},
"start_date": {
"description": "When this task starts.",
@ -7815,11 +7846,7 @@ const docTemplate = `{
},
"subscription": {
"description": "The subscription status for the user reading this task. You can only read this property, use the subscription endpoints to modify it.\nWill only returned when retreiving one task.",
"allOf": [
{
"$ref": "#/definitions/models.Subscription"
}
]
"$ref": "#/definitions/models.Subscription"
},
"task_ids": {
"description": "A list of task ids to update",
@ -7836,7 +7863,9 @@ const docTemplate = `{
"updated": {
"description": "A timestamp when this task was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.DatabaseNotifications": {
@ -7864,7 +7893,9 @@ const docTemplate = `{
"read_at": {
"description": "When this notification is marked as read, this will be updated with the current timestamp.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.Label": {
@ -7876,11 +7907,7 @@ const docTemplate = `{
},
"created_by": {
"description": "The user who created this label",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"description": {
"description": "The label description.",
@ -7904,7 +7931,9 @@ const docTemplate = `{
"updated": {
"description": "A timestamp when this label was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.LabelTask": {
@ -7917,7 +7946,9 @@ const docTemplate = `{
"label_id": {
"description": "The label id you want to associate with a task.",
"type": "integer"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.LabelTaskBulk": {
@ -7929,7 +7960,9 @@ const docTemplate = `{
"items": {
"$ref": "#/definitions/models.Label"
}
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.LinkSharing": {
@ -7957,36 +7990,26 @@ const docTemplate = `{
},
"right": {
"description": "The right this list is shared with. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0,
"maximum": 2,
"allOf": [
{
"$ref": "#/definitions/models.Right"
}
]
"maximum": 2
},
"shared_by": {
"description": "The user who shared this list",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"sharing_type": {
"description": "The kind of this link. 0 = undefined, 1 = without password, 2 = with password.",
"type": "integer",
"default": 0,
"maximum": 2,
"allOf": [
{
"$ref": "#/definitions/models.SharingType"
}
]
"maximum": 2
},
"updated": {
"description": "A timestamp when this share was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.List": {
@ -8035,11 +8058,7 @@ const docTemplate = `{
},
"owner": {
"description": "The user who created this list.",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"position": {
"description": "The position this list has when querying all lists. See the tasks.position property on how to use this.",
@ -8047,11 +8066,7 @@ const docTemplate = `{
},
"subscription": {
"description": "The subscription status for the user reading this list. You can only read this property, use the subscription endpoints to modify it.\nWill only returned when retreiving one list.",
"allOf": [
{
"$ref": "#/definitions/models.Subscription"
}
]
"$ref": "#/definitions/models.Subscription"
},
"title": {
"description": "The title of the list. You'll see this in the namespace overview.",
@ -8062,7 +8077,9 @@ const docTemplate = `{
"updated": {
"description": "A timestamp when this list was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.ListDuplicate": {
@ -8070,16 +8087,14 @@ const docTemplate = `{
"properties": {
"list": {
"description": "The copied list",
"allOf": [
{
"$ref": "#/definitions/models.List"
}
]
"$ref": "#/definitions/models.List"
},
"namespace_id": {
"description": "The target namespace ID",
"type": "integer"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.ListUser": {
@ -8095,13 +8110,9 @@ const docTemplate = `{
},
"right": {
"description": "The right this user has. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0,
"maximum": 2,
"allOf": [
{
"$ref": "#/definitions/models.Right"
}
]
"maximum": 2
},
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
@ -8110,7 +8121,9 @@ const docTemplate = `{
"user_id": {
"description": "The username.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.Message": {
@ -8148,19 +8161,11 @@ const docTemplate = `{
},
"owner": {
"description": "The user who owns this namespace",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"subscription": {
"description": "The subscription status for the user reading this namespace. You can only read this property, use the subscription endpoints to modify it.\nWill only returned when retreiving one namespace.",
"allOf": [
{
"$ref": "#/definitions/models.Subscription"
}
]
"$ref": "#/definitions/models.Subscription"
},
"title": {
"description": "The name of this namespace.",
@ -8171,7 +8176,9 @@ const docTemplate = `{
"updated": {
"description": "A timestamp when this namespace was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.NamespaceUser": {
@ -8187,13 +8194,9 @@ const docTemplate = `{
},
"right": {
"description": "The right this user has. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0,
"maximum": 2,
"allOf": [
{
"$ref": "#/definitions/models.Right"
}
]
"maximum": 2
},
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
@ -8202,7 +8205,9 @@ const docTemplate = `{
"user_id": {
"description": "The username.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.NamespaceWithLists": {
@ -8237,19 +8242,11 @@ const docTemplate = `{
},
"owner": {
"description": "The user who owns this namespace",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"subscription": {
"description": "The subscription status for the user reading this namespace. You can only read this property, use the subscription endpoints to modify it.\nWill only returned when retreiving one namespace.",
"allOf": [
{
"$ref": "#/definitions/models.Subscription"
}
]
"$ref": "#/definitions/models.Subscription"
},
"title": {
"description": "The name of this namespace.",
@ -8260,7 +8257,9 @@ const docTemplate = `{
"updated": {
"description": "A timestamp when this namespace was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.RelatedTaskMap": {
@ -8272,50 +8271,6 @@ const docTemplate = `{
}
}
},
"models.RelationKind": {
"type": "string",
"enum": [
"unknown",
"subtask",
"parenttask",
"related",
"duplicateof",
"duplicates",
"blocking",
"blocked",
"precedes",
"follows",
"copiedfrom",
"copiedto"
],
"x-enum-varnames": [
"RelationKindUnknown",
"RelationKindSubtask",
"RelationKindParenttask",
"RelationKindRelated",
"RelationKindDuplicateOf",
"RelationKindDuplicates",
"RelationKindBlocking",
"RelationKindBlocked",
"RelationKindPreceeds",
"RelationKindFollows",
"RelationKindCopiedFrom",
"RelationKindCopiedTo"
]
},
"models.Right": {
"type": "integer",
"enum": [
0,
1,
2
],
"x-enum-varnames": [
"RightRead",
"RightWrite",
"RightAdmin"
]
},
"models.SavedFilter": {
"type": "object",
"properties": {
@ -8329,11 +8284,7 @@ const docTemplate = `{
},
"filters": {
"description": "The actual filters this filter contains",
"allOf": [
{
"$ref": "#/definitions/models.TaskCollection"
}
]
"$ref": "#/definitions/models.TaskCollection"
},
"id": {
"description": "The unique numeric id of this saved filter",
@ -8345,11 +8296,7 @@ const docTemplate = `{
},
"owner": {
"description": "The user who owns this filter",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"title": {
"description": "The title of the filter.",
@ -8360,22 +8307,11 @@ const docTemplate = `{
"updated": {
"description": "A timestamp when this filter was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.SharingType": {
"type": "integer",
"enum": [
0,
1,
2
],
"x-enum-varnames": [
"SharingTypeUnknown",
"SharingTypeWithoutPassword",
"SharingTypeWithPassword"
]
},
"models.Subscription": {
"type": "object",
"properties": {
@ -8396,12 +8332,10 @@ const docTemplate = `{
},
"user": {
"description": "The user who made this subscription",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
}
"$ref": "#/definitions/user.User"
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.Task": {
@ -8435,11 +8369,7 @@ const docTemplate = `{
},
"created_by": {
"description": "The user who initially created the task.",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"description": {
"description": "The task description.",
@ -8511,11 +8441,7 @@ const docTemplate = `{
},
"related_tasks": {
"description": "All related tasks, grouped by their relation kind",
"allOf": [
{
"$ref": "#/definitions/models.RelatedTaskMap"
}
]
"$ref": "#/definitions/models.RelatedTaskMap"
},
"reminder_dates": {
"description": "An array of datetimes when the user wants to be reminded of the task.",
@ -8530,11 +8456,7 @@ const docTemplate = `{
},
"repeat_mode": {
"description": "Can have three possible values which will trigger when the task is marked as done: 0 = repeats after the amount specified in repeat_after, 1 = repeats all dates each months (ignoring repeat_after), 3 = repeats from the current date rather than the last set date.",
"allOf": [
{
"$ref": "#/definitions/models.TaskRepeatMode"
}
]
"type": "integer"
},
"start_date": {
"description": "When this task starts.",
@ -8542,11 +8464,7 @@ const docTemplate = `{
},
"subscription": {
"description": "The subscription status for the user reading this task. You can only read this property, use the subscription endpoints to modify it.\nWill only returned when retreiving one task.",
"allOf": [
{
"$ref": "#/definitions/models.Subscription"
}
]
"$ref": "#/definitions/models.Subscription"
},
"title": {
"description": "The task text. This is what you'll see in the list.",
@ -8556,7 +8474,9 @@ const docTemplate = `{
"updated": {
"description": "A timestamp when this task was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TaskAssginee": {
@ -8567,7 +8487,9 @@ const docTemplate = `{
},
"user_id": {
"type": "integer"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TaskAttachment": {
@ -8587,7 +8509,9 @@ const docTemplate = `{
},
"task_id": {
"type": "integer"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TaskCollection": {
@ -8635,7 +8559,9 @@ const docTemplate = `{
"items": {
"type": "string"
}
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TaskComment": {
@ -8655,7 +8581,9 @@ const docTemplate = `{
},
"updated": {
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TaskRelation": {
@ -8667,11 +8595,7 @@ const docTemplate = `{
},
"created_by": {
"description": "The user who created this relation",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"other_task_id": {
"description": "The ID of the other task, the task which is being related.",
@ -8679,31 +8603,16 @@ const docTemplate = `{
},
"relation_kind": {
"description": "The kind of the relation.",
"allOf": [
{
"$ref": "#/definitions/models.RelationKind"
}
]
"type": "string"
},
"task_id": {
"description": "The ID of the \"base\" task, the task which has a relation to another.",
"type": "integer"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TaskRepeatMode": {
"type": "integer",
"enum": [
0,
1,
2
],
"x-enum-varnames": [
"TaskRepeatModeDefault",
"TaskRepeatModeMonth",
"TaskRepeatModeFromCurrentDate"
]
},
"models.Team": {
"type": "object",
"properties": {
@ -8713,11 +8622,7 @@ const docTemplate = `{
},
"created_by": {
"description": "The user who created this team.",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"description": {
"description": "The team's description.",
@ -8740,10 +8645,17 @@ const docTemplate = `{
"maxLength": 250,
"minLength": 1
},
"oidc_id": {
"description": "The team's oidc id delivered by the oidc provider",
"type": "string",
"maxLength": 250
},
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TeamList": {
@ -8759,13 +8671,9 @@ const docTemplate = `{
},
"right": {
"description": "The right this team has. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0,
"maximum": 2,
"allOf": [
{
"$ref": "#/definitions/models.Right"
}
]
"maximum": 2
},
"team_id": {
"description": "The team id.",
@ -8774,7 +8682,9 @@ const docTemplate = `{
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TeamMember": {
@ -8795,7 +8705,9 @@ const docTemplate = `{
"username": {
"description": "The username of the member. We use this to prevent automated user id entering.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TeamNamespace": {
@ -8811,13 +8723,9 @@ const docTemplate = `{
},
"right": {
"description": "The right this team has. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0,
"maximum": 2,
"allOf": [
{
"$ref": "#/definitions/models.Right"
}
]
"maximum": 2
},
"team_id": {
"description": "The team id.",
@ -8826,7 +8734,9 @@ const docTemplate = `{
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TeamUser": {
@ -8862,7 +8772,8 @@ const docTemplate = `{
"type": "string",
"maxLength": 250,
"minLength": 1
}
},
"web.Auth": {}
}
},
"models.TeamWithRight": {
@ -8874,11 +8785,7 @@ const docTemplate = `{
},
"created_by": {
"description": "The user who created this team.",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"description": {
"description": "The team's description.",
@ -8901,13 +8808,22 @@ const docTemplate = `{
"maxLength": 250,
"minLength": 1
},
"oidc_id": {
"description": "The team's oidc id delivered by the oidc provider",
"type": "string",
"maxLength": 250
},
"right": {
"$ref": "#/definitions/models.Right"
"description": "The right this team has. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0
},
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.UserWithRight": {
@ -8931,7 +8847,9 @@ const docTemplate = `{
"type": "string"
},
"right": {
"$ref": "#/definitions/models.Right"
"description": "The right this user has. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0
},
"updated": {
"description": "A timestamp when this task was last updated. You cannot change this value.",
@ -8942,7 +8860,8 @@ const docTemplate = `{
"type": "string",
"maxLength": 250,
"minLength": 1
}
},
"web.Auth": {}
}
},
"notifications.DatabaseNotification": {
@ -8997,6 +8916,9 @@ const docTemplate = `{
},
"name": {
"type": "string"
},
"scope": {
"type": "string"
}
}
},
@ -9174,7 +9096,8 @@ const docTemplate = `{
"type": "string",
"maxLength": 250,
"minLength": 1
}
},
"web.Auth": {}
}
},
"v1.LinkShareAuth": {

View File

@ -7611,11 +7611,36 @@
},
"created_by": {
"description": "The user who initially created the bucket.",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"filter_by": {
"description": "The field name of the field to filter by",
"type": "array",
"items": {
"type": "string"
}
},
"filter_comparator": {
"description": "The comparator for field and value",
"type": "array",
"items": {
"type": "string"
}
},
"filter_concat": {
"description": "The way all filter conditions are concatenated together, can be either \"and\" or \"or\".,",
"type": "string"
},
"filter_include_nulls": {
"description": "If set to true, the result will also include null values",
"type": "boolean"
},
"filter_value": {
"description": "The value of the field name to filter by",
"type": "array",
"items": {
"type": "string"
}
},
"id": {
"description": "The unique, numeric id of this bucket.",
@ -7634,10 +7659,24 @@
"description": "The list this bucket belongs to.",
"type": "integer"
},
"order_by": {
"description": "The query parameter to order the items by. This can be either asc or desc, with asc being the default.",
"type": "array",
"items": {
"type": "string"
}
},
"position": {
"description": "The position this bucket has when querying all buckets. See the tasks.position property on how to use this.",
"type": "number"
},
"sort_by": {
"description": "The query parameter to sort by. This is for ex. done, priority, etc.",
"type": "array",
"items": {
"type": "string"
}
},
"tasks": {
"description": "All tasks which belong to this bucket.",
"type": "array",
@ -7653,7 +7692,9 @@
"updated": {
"description": "A timestamp when this bucket was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.BulkAssignees": {
@ -7665,7 +7706,9 @@
"items": {
"$ref": "#/definitions/user.User"
}
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.BulkTask": {
@ -7699,11 +7742,7 @@
},
"created_by": {
"description": "The user who initially created the task.",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"description": {
"description": "The task description.",
@ -7775,11 +7814,7 @@
},
"related_tasks": {
"description": "All related tasks, grouped by their relation kind",
"allOf": [
{
"$ref": "#/definitions/models.RelatedTaskMap"
}
]
"$ref": "#/definitions/models.RelatedTaskMap"
},
"reminder_dates": {
"description": "An array of datetimes when the user wants to be reminded of the task.",
@ -7794,11 +7829,7 @@
},
"repeat_mode": {
"description": "Can have three possible values which will trigger when the task is marked as done: 0 = repeats after the amount specified in repeat_after, 1 = repeats all dates each months (ignoring repeat_after), 3 = repeats from the current date rather than the last set date.",
"allOf": [
{
"$ref": "#/definitions/models.TaskRepeatMode"
}
]
"type": "integer"
},
"start_date": {
"description": "When this task starts.",
@ -7806,11 +7837,7 @@
},
"subscription": {
"description": "The subscription status for the user reading this task. You can only read this property, use the subscription endpoints to modify it.\nWill only returned when retreiving one task.",
"allOf": [
{
"$ref": "#/definitions/models.Subscription"
}
]
"$ref": "#/definitions/models.Subscription"
},
"task_ids": {
"description": "A list of task ids to update",
@ -7827,7 +7854,9 @@
"updated": {
"description": "A timestamp when this task was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.DatabaseNotifications": {
@ -7855,7 +7884,9 @@
"read_at": {
"description": "When this notification is marked as read, this will be updated with the current timestamp.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.Label": {
@ -7867,11 +7898,7 @@
},
"created_by": {
"description": "The user who created this label",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"description": {
"description": "The label description.",
@ -7895,7 +7922,9 @@
"updated": {
"description": "A timestamp when this label was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.LabelTask": {
@ -7908,7 +7937,9 @@
"label_id": {
"description": "The label id you want to associate with a task.",
"type": "integer"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.LabelTaskBulk": {
@ -7920,7 +7951,9 @@
"items": {
"$ref": "#/definitions/models.Label"
}
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.LinkSharing": {
@ -7948,36 +7981,26 @@
},
"right": {
"description": "The right this list is shared with. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0,
"maximum": 2,
"allOf": [
{
"$ref": "#/definitions/models.Right"
}
]
"maximum": 2
},
"shared_by": {
"description": "The user who shared this list",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"sharing_type": {
"description": "The kind of this link. 0 = undefined, 1 = without password, 2 = with password.",
"type": "integer",
"default": 0,
"maximum": 2,
"allOf": [
{
"$ref": "#/definitions/models.SharingType"
}
]
"maximum": 2
},
"updated": {
"description": "A timestamp when this share was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.List": {
@ -8026,11 +8049,7 @@
},
"owner": {
"description": "The user who created this list.",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"position": {
"description": "The position this list has when querying all lists. See the tasks.position property on how to use this.",
@ -8038,11 +8057,7 @@
},
"subscription": {
"description": "The subscription status for the user reading this list. You can only read this property, use the subscription endpoints to modify it.\nWill only returned when retreiving one list.",
"allOf": [
{
"$ref": "#/definitions/models.Subscription"
}
]
"$ref": "#/definitions/models.Subscription"
},
"title": {
"description": "The title of the list. You'll see this in the namespace overview.",
@ -8053,7 +8068,9 @@
"updated": {
"description": "A timestamp when this list was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.ListDuplicate": {
@ -8061,16 +8078,14 @@
"properties": {
"list": {
"description": "The copied list",
"allOf": [
{
"$ref": "#/definitions/models.List"
}
]
"$ref": "#/definitions/models.List"
},
"namespace_id": {
"description": "The target namespace ID",
"type": "integer"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.ListUser": {
@ -8086,13 +8101,9 @@
},
"right": {
"description": "The right this user has. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0,
"maximum": 2,
"allOf": [
{
"$ref": "#/definitions/models.Right"
}
]
"maximum": 2
},
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
@ -8101,7 +8112,9 @@
"user_id": {
"description": "The username.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.Message": {
@ -8139,19 +8152,11 @@
},
"owner": {
"description": "The user who owns this namespace",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"subscription": {
"description": "The subscription status for the user reading this namespace. You can only read this property, use the subscription endpoints to modify it.\nWill only returned when retreiving one namespace.",
"allOf": [
{
"$ref": "#/definitions/models.Subscription"
}
]
"$ref": "#/definitions/models.Subscription"
},
"title": {
"description": "The name of this namespace.",
@ -8162,7 +8167,9 @@
"updated": {
"description": "A timestamp when this namespace was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.NamespaceUser": {
@ -8178,13 +8185,9 @@
},
"right": {
"description": "The right this user has. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0,
"maximum": 2,
"allOf": [
{
"$ref": "#/definitions/models.Right"
}
]
"maximum": 2
},
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
@ -8193,7 +8196,9 @@
"user_id": {
"description": "The username.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.NamespaceWithLists": {
@ -8228,19 +8233,11 @@
},
"owner": {
"description": "The user who owns this namespace",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"subscription": {
"description": "The subscription status for the user reading this namespace. You can only read this property, use the subscription endpoints to modify it.\nWill only returned when retreiving one namespace.",
"allOf": [
{
"$ref": "#/definitions/models.Subscription"
}
]
"$ref": "#/definitions/models.Subscription"
},
"title": {
"description": "The name of this namespace.",
@ -8251,7 +8248,9 @@
"updated": {
"description": "A timestamp when this namespace was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.RelatedTaskMap": {
@ -8263,50 +8262,6 @@
}
}
},
"models.RelationKind": {
"type": "string",
"enum": [
"unknown",
"subtask",
"parenttask",
"related",
"duplicateof",
"duplicates",
"blocking",
"blocked",
"precedes",
"follows",
"copiedfrom",
"copiedto"
],
"x-enum-varnames": [
"RelationKindUnknown",
"RelationKindSubtask",
"RelationKindParenttask",
"RelationKindRelated",
"RelationKindDuplicateOf",
"RelationKindDuplicates",
"RelationKindBlocking",
"RelationKindBlocked",
"RelationKindPreceeds",
"RelationKindFollows",
"RelationKindCopiedFrom",
"RelationKindCopiedTo"
]
},
"models.Right": {
"type": "integer",
"enum": [
0,
1,
2
],
"x-enum-varnames": [
"RightRead",
"RightWrite",
"RightAdmin"
]
},
"models.SavedFilter": {
"type": "object",
"properties": {
@ -8320,11 +8275,7 @@
},
"filters": {
"description": "The actual filters this filter contains",
"allOf": [
{
"$ref": "#/definitions/models.TaskCollection"
}
]
"$ref": "#/definitions/models.TaskCollection"
},
"id": {
"description": "The unique numeric id of this saved filter",
@ -8336,11 +8287,7 @@
},
"owner": {
"description": "The user who owns this filter",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"title": {
"description": "The title of the filter.",
@ -8351,22 +8298,11 @@
"updated": {
"description": "A timestamp when this filter was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.SharingType": {
"type": "integer",
"enum": [
0,
1,
2
],
"x-enum-varnames": [
"SharingTypeUnknown",
"SharingTypeWithoutPassword",
"SharingTypeWithPassword"
]
},
"models.Subscription": {
"type": "object",
"properties": {
@ -8387,12 +8323,10 @@
},
"user": {
"description": "The user who made this subscription",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
}
"$ref": "#/definitions/user.User"
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.Task": {
@ -8426,11 +8360,7 @@
},
"created_by": {
"description": "The user who initially created the task.",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"description": {
"description": "The task description.",
@ -8502,11 +8432,7 @@
},
"related_tasks": {
"description": "All related tasks, grouped by their relation kind",
"allOf": [
{
"$ref": "#/definitions/models.RelatedTaskMap"
}
]
"$ref": "#/definitions/models.RelatedTaskMap"
},
"reminder_dates": {
"description": "An array of datetimes when the user wants to be reminded of the task.",
@ -8521,11 +8447,7 @@
},
"repeat_mode": {
"description": "Can have three possible values which will trigger when the task is marked as done: 0 = repeats after the amount specified in repeat_after, 1 = repeats all dates each months (ignoring repeat_after), 3 = repeats from the current date rather than the last set date.",
"allOf": [
{
"$ref": "#/definitions/models.TaskRepeatMode"
}
]
"type": "integer"
},
"start_date": {
"description": "When this task starts.",
@ -8533,11 +8455,7 @@
},
"subscription": {
"description": "The subscription status for the user reading this task. You can only read this property, use the subscription endpoints to modify it.\nWill only returned when retreiving one task.",
"allOf": [
{
"$ref": "#/definitions/models.Subscription"
}
]
"$ref": "#/definitions/models.Subscription"
},
"title": {
"description": "The task text. This is what you'll see in the list.",
@ -8547,7 +8465,9 @@
"updated": {
"description": "A timestamp when this task was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TaskAssginee": {
@ -8558,7 +8478,9 @@
},
"user_id": {
"type": "integer"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TaskAttachment": {
@ -8578,7 +8500,9 @@
},
"task_id": {
"type": "integer"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TaskCollection": {
@ -8626,7 +8550,9 @@
"items": {
"type": "string"
}
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TaskComment": {
@ -8646,7 +8572,9 @@
},
"updated": {
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TaskRelation": {
@ -8658,11 +8586,7 @@
},
"created_by": {
"description": "The user who created this relation",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"other_task_id": {
"description": "The ID of the other task, the task which is being related.",
@ -8670,31 +8594,16 @@
},
"relation_kind": {
"description": "The kind of the relation.",
"allOf": [
{
"$ref": "#/definitions/models.RelationKind"
}
]
"type": "string"
},
"task_id": {
"description": "The ID of the \"base\" task, the task which has a relation to another.",
"type": "integer"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TaskRepeatMode": {
"type": "integer",
"enum": [
0,
1,
2
],
"x-enum-varnames": [
"TaskRepeatModeDefault",
"TaskRepeatModeMonth",
"TaskRepeatModeFromCurrentDate"
]
},
"models.Team": {
"type": "object",
"properties": {
@ -8704,11 +8613,7 @@
},
"created_by": {
"description": "The user who created this team.",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"description": {
"description": "The team's description.",
@ -8731,10 +8636,17 @@
"maxLength": 250,
"minLength": 1
},
"oidc_id": {
"description": "The team's oidc id delivered by the oidc provider",
"type": "string",
"maxLength": 250
},
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TeamList": {
@ -8750,13 +8662,9 @@
},
"right": {
"description": "The right this team has. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0,
"maximum": 2,
"allOf": [
{
"$ref": "#/definitions/models.Right"
}
]
"maximum": 2
},
"team_id": {
"description": "The team id.",
@ -8765,7 +8673,9 @@
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TeamMember": {
@ -8786,7 +8696,9 @@
"username": {
"description": "The username of the member. We use this to prevent automated user id entering.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TeamNamespace": {
@ -8802,13 +8714,9 @@
},
"right": {
"description": "The right this team has. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0,
"maximum": 2,
"allOf": [
{
"$ref": "#/definitions/models.Right"
}
]
"maximum": 2
},
"team_id": {
"description": "The team id.",
@ -8817,7 +8725,9 @@
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.TeamUser": {
@ -8853,7 +8763,8 @@
"type": "string",
"maxLength": 250,
"minLength": 1
}
},
"web.Auth": {}
}
},
"models.TeamWithRight": {
@ -8865,11 +8776,7 @@
},
"created_by": {
"description": "The user who created this team.",
"allOf": [
{
"$ref": "#/definitions/user.User"
}
]
"$ref": "#/definitions/user.User"
},
"description": {
"description": "The team's description.",
@ -8892,13 +8799,22 @@
"maxLength": 250,
"minLength": 1
},
"oidc_id": {
"description": "The team's oidc id delivered by the oidc provider",
"type": "string",
"maxLength": 250
},
"right": {
"$ref": "#/definitions/models.Right"
"description": "The right this team has. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0
},
"updated": {
"description": "A timestamp when this relation was last updated. You cannot change this value.",
"type": "string"
}
},
"web.CRUDable": {},
"web.Rights": {}
}
},
"models.UserWithRight": {
@ -8922,7 +8838,9 @@
"type": "string"
},
"right": {
"$ref": "#/definitions/models.Right"
"description": "The right this user has. 0 = Read only, 1 = Read \u0026 Write, 2 = Admin. See the docs for more details.",
"type": "integer",
"default": 0
},
"updated": {
"description": "A timestamp when this task was last updated. You cannot change this value.",
@ -8933,7 +8851,8 @@
"type": "string",
"maxLength": 250,
"minLength": 1
}
},
"web.Auth": {}
}
},
"notifications.DatabaseNotification": {
@ -8988,6 +8907,9 @@
},
"name": {
"type": "string"
},
"scope": {
"type": "string"
}
}
},
@ -9165,7 +9087,8 @@
"type": "string",
"maxLength": 250,
"minLength": 1
}
},
"web.Auth": {}
}
},
"v1.LinkShareAuth": {

View File

@ -58,9 +58,30 @@ definitions:
value.
type: string
created_by:
allOf:
- $ref: '#/definitions/user.User'
$ref: '#/definitions/user.User'
description: The user who initially created the bucket.
filter_by:
description: The field name of the field to filter by
items:
type: string
type: array
filter_comparator:
description: The comparator for field and value
items:
type: string
type: array
filter_concat:
description: The way all filter conditions are concatenated together, can
be either "and" or "or".,
type: string
filter_include_nulls:
description: If set to true, the result will also include null values
type: boolean
filter_value:
description: The value of the field name to filter by
items:
type: string
type: array
id:
description: The unique, numeric id of this bucket.
type: integer
@ -76,10 +97,22 @@ definitions:
list_id:
description: The list this bucket belongs to.
type: integer
order_by:
description: The query parameter to order the items by. This can be either
asc or desc, with asc being the default.
items:
type: string
type: array
position:
description: The position this bucket has when querying all buckets. See the
tasks.position property on how to use this.
type: number
sort_by:
description: The query parameter to sort by. This is for ex. done, priority,
etc.
items:
type: string
type: array
tasks:
description: All tasks which belong to this bucket.
items:
@ -93,6 +126,8 @@ definitions:
description: A timestamp when this bucket was last updated. You cannot change
this value.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.BulkAssignees:
properties:
@ -101,6 +136,8 @@ definitions:
items:
$ref: '#/definitions/user.User'
type: array
web.CRUDable: {}
web.Rights: {}
type: object
models.BulkTask:
properties:
@ -126,8 +163,7 @@ definitions:
value.
type: string
created_by:
allOf:
- $ref: '#/definitions/user.User'
$ref: '#/definitions/user.User'
description: The user who initially created the task.
description:
description: The task description.
@ -192,8 +228,7 @@ definitions:
sort by this later.
type: integer
related_tasks:
allOf:
- $ref: '#/definitions/models.RelatedTaskMap'
$ref: '#/definitions/models.RelatedTaskMap'
description: All related tasks, grouped by their relation kind
reminder_dates:
description: An array of datetimes when the user wants to be reminded of the
@ -207,18 +242,16 @@ definitions:
increase all remindes and the due date by its amount.
type: integer
repeat_mode:
allOf:
- $ref: '#/definitions/models.TaskRepeatMode'
description: 'Can have three possible values which will trigger when the task
is marked as done: 0 = repeats after the amount specified in repeat_after,
1 = repeats all dates each months (ignoring repeat_after), 3 = repeats from
the current date rather than the last set date.'
type: integer
start_date:
description: When this task starts.
type: string
subscription:
allOf:
- $ref: '#/definitions/models.Subscription'
$ref: '#/definitions/models.Subscription'
description: |-
The subscription status for the user reading this task. You can only read this property, use the subscription endpoints to modify it.
Will only returned when retreiving one task.
@ -235,6 +268,8 @@ definitions:
description: A timestamp when this task was last updated. You cannot change
this value.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.DatabaseNotifications:
properties:
@ -259,6 +294,8 @@ definitions:
description: When this notification is marked as read, this will be updated
with the current timestamp.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.Label:
properties:
@ -267,8 +304,7 @@ definitions:
value.
type: string
created_by:
allOf:
- $ref: '#/definitions/user.User'
$ref: '#/definitions/user.User'
description: The user who created this label
description:
description: The label description.
@ -290,6 +326,8 @@ definitions:
description: A timestamp when this label was last updated. You cannot change
this value.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.LabelTask:
properties:
@ -300,6 +338,8 @@ definitions:
label_id:
description: The label id you want to associate with a task.
type: integer
web.CRUDable: {}
web.Rights: {}
type: object
models.LabelTaskBulk:
properties:
@ -308,6 +348,8 @@ definitions:
items:
$ref: '#/definitions/models.Label'
type: array
web.CRUDable: {}
web.Rights: {}
type: object
models.LinkSharing:
properties:
@ -330,27 +372,26 @@ definitions:
it after the link share has been created.
type: string
right:
allOf:
- $ref: '#/definitions/models.Right'
default: 0
description: The right this list is shared with. 0 = Read only, 1 = Read &
Write, 2 = Admin. See the docs for more details.
maximum: 2
type: integer
shared_by:
allOf:
- $ref: '#/definitions/user.User'
$ref: '#/definitions/user.User'
description: The user who shared this list
sharing_type:
allOf:
- $ref: '#/definitions/models.SharingType'
default: 0
description: The kind of this link. 0 = undefined, 1 = without password, 2
= with password.
maximum: 2
type: integer
updated:
description: A timestamp when this share was last updated. You cannot change
this value.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.List:
properties:
@ -392,16 +433,14 @@ definitions:
namespace_id:
type: integer
owner:
allOf:
- $ref: '#/definitions/user.User'
$ref: '#/definitions/user.User'
description: The user who created this list.
position:
description: The position this list has when querying all lists. See the tasks.position
property on how to use this.
type: number
subscription:
allOf:
- $ref: '#/definitions/models.Subscription'
$ref: '#/definitions/models.Subscription'
description: |-
The subscription status for the user reading this list. You can only read this property, use the subscription endpoints to modify it.
Will only returned when retreiving one list.
@ -414,16 +453,19 @@ definitions:
description: A timestamp when this list was last updated. You cannot change
this value.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.ListDuplicate:
properties:
list:
allOf:
- $ref: '#/definitions/models.List'
$ref: '#/definitions/models.List'
description: The copied list
namespace_id:
description: The target namespace ID
type: integer
web.CRUDable: {}
web.Rights: {}
type: object
models.ListUser:
properties:
@ -435,12 +477,11 @@ definitions:
description: The unique, numeric id of this list <-> user relation.
type: integer
right:
allOf:
- $ref: '#/definitions/models.Right'
default: 0
description: The right this user has. 0 = Read only, 1 = Read & Write, 2 =
Admin. See the docs for more details.
maximum: 2
type: integer
updated:
description: A timestamp when this relation was last updated. You cannot change
this value.
@ -448,6 +489,8 @@ definitions:
user_id:
description: The username.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.Message:
properties:
@ -475,12 +518,10 @@ definitions:
description: Whether or not a namespace is archived.
type: boolean
owner:
allOf:
- $ref: '#/definitions/user.User'
$ref: '#/definitions/user.User'
description: The user who owns this namespace
subscription:
allOf:
- $ref: '#/definitions/models.Subscription'
$ref: '#/definitions/models.Subscription'
description: |-
The subscription status for the user reading this namespace. You can only read this property, use the subscription endpoints to modify it.
Will only returned when retreiving one namespace.
@ -493,6 +534,8 @@ definitions:
description: A timestamp when this namespace was last updated. You cannot
change this value.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.NamespaceUser:
properties:
@ -504,12 +547,11 @@ definitions:
description: The unique, numeric id of this namespace <-> user relation.
type: integer
right:
allOf:
- $ref: '#/definitions/models.Right'
default: 0
description: The right this user has. 0 = Read only, 1 = Read & Write, 2 =
Admin. See the docs for more details.
maximum: 2
type: integer
updated:
description: A timestamp when this relation was last updated. You cannot change
this value.
@ -517,6 +559,8 @@ definitions:
user_id:
description: The username.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.NamespaceWithLists:
properties:
@ -542,12 +586,10 @@ definitions:
$ref: '#/definitions/models.List'
type: array
owner:
allOf:
- $ref: '#/definitions/user.User'
$ref: '#/definitions/user.User'
description: The user who owns this namespace
subscription:
allOf:
- $ref: '#/definitions/models.Subscription'
$ref: '#/definitions/models.Subscription'
description: |-
The subscription status for the user reading this namespace. You can only read this property, use the subscription endpoints to modify it.
Will only returned when retreiving one namespace.
@ -560,6 +602,8 @@ definitions:
description: A timestamp when this namespace was last updated. You cannot
change this value.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.RelatedTaskMap:
additionalProperties:
@ -567,44 +611,6 @@ definitions:
$ref: '#/definitions/models.Task'
type: array
type: object
models.RelationKind:
enum:
- unknown
- subtask
- parenttask
- related
- duplicateof
- duplicates
- blocking
- blocked
- precedes
- follows
- copiedfrom
- copiedto
type: string
x-enum-varnames:
- RelationKindUnknown
- RelationKindSubtask
- RelationKindParenttask
- RelationKindRelated
- RelationKindDuplicateOf
- RelationKindDuplicates
- RelationKindBlocking
- RelationKindBlocked
- RelationKindPreceeds
- RelationKindFollows
- RelationKindCopiedFrom
- RelationKindCopiedTo
models.Right:
enum:
- 0
- 1
- 2
type: integer
x-enum-varnames:
- RightRead
- RightWrite
- RightAdmin
models.SavedFilter:
properties:
created:
@ -615,8 +621,7 @@ definitions:
description: The description of the filter
type: string
filters:
allOf:
- $ref: '#/definitions/models.TaskCollection'
$ref: '#/definitions/models.TaskCollection'
description: The actual filters this filter contains
id:
description: The unique numeric id of this saved filter
@ -626,8 +631,7 @@ definitions:
a separate namespace together with favorite lists.
type: boolean
owner:
allOf:
- $ref: '#/definitions/user.User'
$ref: '#/definitions/user.User'
description: The user who owns this filter
title:
description: The title of the filter.
@ -638,17 +642,9 @@ definitions:
description: A timestamp when this filter was last updated. You cannot change
this value.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.SharingType:
enum:
- 0
- 1
- 2
type: integer
x-enum-varnames:
- SharingTypeUnknown
- SharingTypeWithoutPassword
- SharingTypeWithPassword
models.Subscription:
properties:
created:
@ -664,9 +660,10 @@ definitions:
description: The numeric ID of the subscription
type: integer
user:
allOf:
- $ref: '#/definitions/user.User'
$ref: '#/definitions/user.User'
description: The user who made this subscription
web.CRUDable: {}
web.Rights: {}
type: object
models.Task:
properties:
@ -692,8 +689,7 @@ definitions:
value.
type: string
created_by:
allOf:
- $ref: '#/definitions/user.User'
$ref: '#/definitions/user.User'
description: The user who initially created the task.
description:
description: The task description.
@ -758,8 +754,7 @@ definitions:
sort by this later.
type: integer
related_tasks:
allOf:
- $ref: '#/definitions/models.RelatedTaskMap'
$ref: '#/definitions/models.RelatedTaskMap'
description: All related tasks, grouped by their relation kind
reminder_dates:
description: An array of datetimes when the user wants to be reminded of the
@ -773,18 +768,16 @@ definitions:
increase all remindes and the due date by its amount.
type: integer
repeat_mode:
allOf:
- $ref: '#/definitions/models.TaskRepeatMode'
description: 'Can have three possible values which will trigger when the task
is marked as done: 0 = repeats after the amount specified in repeat_after,
1 = repeats all dates each months (ignoring repeat_after), 3 = repeats from
the current date rather than the last set date.'
type: integer
start_date:
description: When this task starts.
type: string
subscription:
allOf:
- $ref: '#/definitions/models.Subscription'
$ref: '#/definitions/models.Subscription'
description: |-
The subscription status for the user reading this task. You can only read this property, use the subscription endpoints to modify it.
Will only returned when retreiving one task.
@ -796,6 +789,8 @@ definitions:
description: A timestamp when this task was last updated. You cannot change
this value.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.TaskAssginee:
properties:
@ -803,6 +798,8 @@ definitions:
type: string
user_id:
type: integer
web.CRUDable: {}
web.Rights: {}
type: object
models.TaskAttachment:
properties:
@ -816,6 +813,8 @@ definitions:
type: integer
task_id:
type: integer
web.CRUDable: {}
web.Rights: {}
type: object
models.TaskCollection:
properties:
@ -853,6 +852,8 @@ definitions:
items:
type: string
type: array
web.CRUDable: {}
web.Rights: {}
type: object
models.TaskComment:
properties:
@ -866,6 +867,8 @@ definitions:
type: integer
updated:
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.TaskRelation:
properties:
@ -874,30 +877,20 @@ definitions:
value.
type: string
created_by:
allOf:
- $ref: '#/definitions/user.User'
$ref: '#/definitions/user.User'
description: The user who created this relation
other_task_id:
description: The ID of the other task, the task which is being related.
type: integer
relation_kind:
allOf:
- $ref: '#/definitions/models.RelationKind'
description: The kind of the relation.
type: string
task_id:
description: The ID of the "base" task, the task which has a relation to another.
type: integer
web.CRUDable: {}
web.Rights: {}
type: object
models.TaskRepeatMode:
enum:
- 0
- 1
- 2
type: integer
x-enum-varnames:
- TaskRepeatModeDefault
- TaskRepeatModeMonth
- TaskRepeatModeFromCurrentDate
models.Team:
properties:
created:
@ -905,8 +898,7 @@ definitions:
this value.
type: string
created_by:
allOf:
- $ref: '#/definitions/user.User'
$ref: '#/definitions/user.User'
description: The user who created this team.
description:
description: The team's description.
@ -924,10 +916,16 @@ definitions:
maxLength: 250
minLength: 1
type: string
oidc_id:
description: The team's oidc id delivered by the oidc provider
maxLength: 250
type: string
updated:
description: A timestamp when this relation was last updated. You cannot change
this value.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.TeamList:
properties:
@ -939,12 +937,11 @@ definitions:
description: The unique, numeric id of this list <-> team relation.
type: integer
right:
allOf:
- $ref: '#/definitions/models.Right'
default: 0
description: The right this team has. 0 = Read only, 1 = Read & Write, 2 =
Admin. See the docs for more details.
maximum: 2
type: integer
team_id:
description: The team id.
type: integer
@ -952,6 +949,8 @@ definitions:
description: A timestamp when this relation was last updated. You cannot change
this value.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.TeamMember:
properties:
@ -970,6 +969,8 @@ definitions:
description: The username of the member. We use this to prevent automated
user id entering.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.TeamNamespace:
properties:
@ -981,12 +982,11 @@ definitions:
description: The unique, numeric id of this namespace <-> team relation.
type: integer
right:
allOf:
- $ref: '#/definitions/models.Right'
default: 0
description: The right this team has. 0 = Read only, 1 = Read & Write, 2 =
Admin. See the docs for more details.
maximum: 2
type: integer
team_id:
description: The team id.
type: integer
@ -994,6 +994,8 @@ definitions:
description: A timestamp when this relation was last updated. You cannot change
this value.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.TeamUser:
properties:
@ -1024,6 +1026,7 @@ definitions:
maxLength: 250
minLength: 1
type: string
web.Auth: {}
type: object
models.TeamWithRight:
properties:
@ -1032,8 +1035,7 @@ definitions:
this value.
type: string
created_by:
allOf:
- $ref: '#/definitions/user.User'
$ref: '#/definitions/user.User'
description: The user who created this team.
description:
description: The team's description.
@ -1051,12 +1053,21 @@ definitions:
maxLength: 250
minLength: 1
type: string
oidc_id:
description: The team's oidc id delivered by the oidc provider
maxLength: 250
type: string
right:
$ref: '#/definitions/models.Right'
default: 0
description: The right this team has. 0 = Read only, 1 = Read & Write, 2 =
Admin. See the docs for more details.
type: integer
updated:
description: A timestamp when this relation was last updated. You cannot change
this value.
type: string
web.CRUDable: {}
web.Rights: {}
type: object
models.UserWithRight:
properties:
@ -1075,7 +1086,10 @@ definitions:
description: The full name of the user.
type: string
right:
$ref: '#/definitions/models.Right'
default: 0
description: The right this user has. 0 = Read only, 1 = Read & Write, 2 =
Admin. See the docs for more details.
type: integer
updated:
description: A timestamp when this task was last updated. You cannot change
this value.
@ -1085,6 +1099,7 @@ definitions:
maxLength: 250
minLength: 1
type: string
web.Auth: {}
type: object
notifications.DatabaseNotification:
properties:
@ -1124,6 +1139,8 @@ definitions:
type: string
name:
type: string
scope:
type: string
type: object
todoist.Migration:
properties:
@ -1253,6 +1270,7 @@ definitions:
maxLength: 250
minLength: 1
type: string
web.Auth: {}
type: object
v1.LinkShareAuth:
properties:

View File

@ -426,6 +426,32 @@ func (err *ErrNoOpenIDEmailProvided) HTTPError() web.HTTPError {
}
}
// ErrNoOpenIDEmailProvided represents a "NoEmailProvided" kind of error.
type ErrOpenIDCustomScopeMalformed struct {
}
// IsErrNoEmailProvided checks if an error is a ErrNoOpenIDEmailProvided.
func IsErrOpenIDCustomScopeMalformed(err error) bool {
_, ok := err.(*ErrOpenIDCustomScopeMalformed)
return ok
}
func (err *ErrOpenIDCustomScopeMalformed) Error() string {
return "Custom Scope malformed"
}
// ErrCodeNoOpenIDEmailProvided holds the unique world-error code of this error
const ErrCodeOpenIDCustomScopeMalformed = 1022
// HTTPError holds the http error description
func (err *ErrOpenIDCustomScopeMalformed) HTTPError() web.HTTPError {
return web.HTTPError{
HTTPCode: http.StatusPreconditionFailed,
Code: ErrCodeOpenIDCustomScopeMalformed,
Message: "The custom scope set by the OIDC provider is malformed. Please make sure the openid provider sets the data correctly for your scope. Check especially to have set an oidcID",
}
}
// ErrAccountDisabled represents a "AccountDisabled" kind of error.
type ErrAccountDisabled struct {
UserID int64