Revert "feat: add time range parser"
continuous-integration/drone/pr Build is failing Details

This reverts commit b9cd2d1a77.
This commit is contained in:
kolaente 2022-01-08 22:10:55 +01:00
parent 7822265655
commit e28c4bd3b9
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
4 changed files with 104 additions and 316 deletions

View File

@ -16,152 +16,146 @@ This document describes the different errors Vikunja can return.
## Generic
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|--------------------------|
| 0001 | 403 | Generic forbidden error. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 0001 | 403 | Generic forbidden error. |
## User
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|------------------------------------------------------------|
| 1001 | 400 | A user with this username already exists. |
| 1002 | 400 | A user with this email address already exists. |
| 1004 | 400 | No username and password specified. |
| 1005 | 404 | The user does not exist. |
| 1006 | 400 | Could not get the user id. |
| 1008 | 412 | No password reset token provided. |
| 1009 | 412 | Invalid password reset token. |
| 1010 | 412 | Invalid email confirm token. |
| 1011 | 412 | Wrong username or password. |
| 1012 | 412 | Email address of the user not confirmed. |
| 1013 | 412 | New password is empty. |
| 1014 | 412 | Old password is empty. |
| 1015 | 412 | Totp is already enabled for this user. |
| 1016 | 412 | Totp is not enabled for this user. |
| 1017 | 412 | The provided Totp passcode is invalid. |
| 1018 | 412 | The provided user avatar provider type setting is invalid. |
| 1019 | 412 | No openid email address was provided. |
| 1020 | 412 | This user account is disabled. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 1001 | 400 | A user with this username already exists. |
| 1002 | 400 | A user with this email address already exists. |
| 1004 | 400 | No username and password specified. |
| 1005 | 404 | The user does not exist. |
| 1006 | 400 | Could not get the user id. |
| 1008 | 412 | No password reset token provided. |
| 1009 | 412 | Invalid password reset token. |
| 1010 | 412 | Invalid email confirm token. |
| 1011 | 412 | Wrong username or password. |
| 1012 | 412 | Email address of the user not confirmed. |
| 1013 | 412 | New password is empty. |
| 1014 | 412 | Old password is empty. |
| 1015 | 412 | Totp is already enabled for this user. |
| 1016 | 412 | Totp is not enabled for this user. |
| 1017 | 412 | The provided Totp passcode is invalid. |
| 1018 | 412 | The provided user avatar provider type setting is invalid. |
| 1019 | 412 | No openid email address was provided. |
| 1020 | 412 | This user account is disabled. |
## Validation
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|---------------------------------------------------------------------------------------------------------|
| 2001 | 400 | ID cannot be empty or 0. |
| 2002 | 400 | Some of the request data was invalid. The response contains an aditional array with all invalid fields. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 2001 | 400 | ID cannot be empty or 0. |
| 2002 | 400 | Some of the request data was invalid. The response contains an aditional array with all invalid fields. |
## List
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------------------------------------------------------------------------------------------------------------------------|
| 3001 | 404 | The list does not exist. |
| 3004 | 403 | The user needs to have read permissions on that list to perform that action. |
| 3005 | 400 | The list title cannot be empty. |
| 3006 | 404 | The list share does not exist. |
| 3007 | 400 | A list with this identifier already exists. |
| 3008 | 412 | The list is archived and can therefore only be accessed read only. This is also true for all tasks associated with this list. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 3001 | 404 | The list does not exist. |
| 3004 | 403 | The user needs to have read permissions on that list to perform that action. |
| 3005 | 400 | The list title cannot be empty. |
| 3006 | 404 | The list share does not exist. |
| 3007 | 400 | A list with this identifier already exists. |
| 3008 | 412 | The list is archived and can therefore only be accessed read only. This is also true for all tasks associated with this list. |
## Task
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|----------------------------------------------------------------------------|
| 4001 | 400 | The list task text cannot be empty. |
| 4002 | 404 | The list task does not exist. |
| 4003 | 403 | All bulk editing tasks must belong to the same list. |
| 4004 | 403 | Need at least one task when bulk editing tasks. |
| 4005 | 403 | The user does not have the right to see the task. |
| 4006 | 403 | The user tried to set a parent task as the task itself. |
| 4007 | 400 | The user tried to create a task relation with an invalid kind of relation. |
| 4008 | 409 | The user tried to create a task relation which already exists. |
| 4009 | 404 | The task relation does not exist. |
| 4010 | 400 | Cannot relate a task with itself. |
| 4011 | 404 | The task attachment does not exist. |
| 4012 | 400 | The task attachment is too large. |
| 4013 | 400 | The task sort param is invalid. |
| 4014 | 400 | The task sort order is invalid. |
| 4015 | 404 | The task comment does not exist. |
| 4016 | 403 | Invalid task field. |
| 4017 | 403 | Invalid task filter comparator. |
| 4018 | 403 | Invalid task filter concatinator. |
| 4019 | 403 | Invalid task filter value. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 4001 | 400 | The list task text cannot be empty. |
| 4002 | 404 | The list task does not exist. |
| 4003 | 403 | All bulk editing tasks must belong to the same list. |
| 4004 | 403 | Need at least one task when bulk editing tasks. |
| 4005 | 403 | The user does not have the right to see the task. |
| 4006 | 403 | The user tried to set a parent task as the task itself. |
| 4007 | 400 | The user tried to create a task relation with an invalid kind of relation. |
| 4008 | 409 | The user tried to create a task relation which already exists. |
| 4009 | 404 | The task relation does not exist. |
| 4010 | 400 | Cannot relate a task with itself. |
| 4011 | 404 | The task attachment does not exist. |
| 4012 | 400 | The task attachment is too large. |
| 4013 | 400 | The task sort param is invalid. |
| 4014 | 400 | The task sort order is invalid. |
| 4015 | 404 | The task comment does not exist. |
| 4016 | 403 | Invalid task field. |
| 4017 | 403 | Invalid task filter comparator. |
| 4018 | 403 | Invalid task filter concatinator. |
| 4019 | 403 | Invalid task filter value. |
## Namespace
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------------------------------------------------------------------|
| 5001 | 404 | The namspace does not exist. |
| 5003 | 403 | The user does not have access to the specified namespace. |
| 5006 | 400 | The namespace name cannot be empty. |
| 5009 | 403 | The user needs to have namespace read access to perform that action. |
| 5010 | 403 | This team does not have access to that namespace. |
| 5011 | 409 | This user has already access to that namespace. |
| 5012 | 412 | The namespace is archived and can therefore only be accessed read only. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 5001 | 404 | The namspace does not exist. |
| 5003 | 403 | The user does not have access to the specified namespace. |
| 5006 | 400 | The namespace name cannot be empty. |
| 5009 | 403 | The user needs to have namespace read access to perform that action. |
| 5010 | 403 | This team does not have access to that namespace. |
| 5011 | 409 | This user has already access to that namespace. |
| 5012 | 412 | The namespace is archived and can therefore only be accessed read only. |
## Team
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------------------------------------------------------------|
| 6001 | 400 | The team name cannot be emtpy. |
| 6002 | 404 | The team does not exist. |
| 6004 | 409 | The team already has access to that namespace or list. |
| 6005 | 409 | The user is already a member of that team. |
| 6006 | 400 | Cannot delete the last team member. |
| 6007 | 403 | The team does not have access to the list to perform that action. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 6001 | 400 | The team name cannot be emtpy. |
| 6002 | 404 | The team does not exist. |
| 6004 | 409 | The team already has access to that namespace or list. |
| 6005 | 409 | The user is already a member of that team. |
| 6006 | 400 | Cannot delete the last team member. |
| 6007 | 403 | The team does not have access to the list to perform that action. |
## User List Access
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|---------------------------------------------|
| 7002 | 409 | The user already has access to that list. |
| 7003 | 403 | The user does not have access to that list. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 7002 | 409 | The user already has access to that list. |
| 7003 | 403 | The user does not have access to that list. |
## Label
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|----------------------------------------------|
| 8001 | 403 | This label already exists on that task. |
| 8002 | 404 | The label does not exist. |
| 8003 | 403 | The user does not have access to this label. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 8001 | 403 | This label already exists on that task. |
| 8002 | 404 | The label does not exist. |
| 8003 | 403 | The user does not have access to this label. |
## Right
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-----------------------|
| 9001 | 403 | The right is invalid. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 9001 | 403 | The right is invalid. |
## Kanban
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-----------------------------------------------------------------------------------------------|
| 10001 | 404 | The bucket does not exist. |
| 10002 | 400 | The bucket does not belong to that list. |
| 10003 | 412 | You cannot remove the last bucket on a list. |
| 10004 | 412 | You cannot add the task to this bucket as it already exceeded the limit of tasks it can hold. |
| 10005 | 412 | There can be only one done bucket per list. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 10001 | 404 | The bucket does not exist. |
| 10002 | 400 | The bucket does not belong to that list. |
| 10003 | 412 | You cannot remove the last bucket on a list. |
| 10004 | 412 | You cannot add the task to this bucket as it already exceeded the limit of tasks it can hold. |
| 10005 | 412 | There can be only one done bucket per list. |
## Saved Filters
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|--------------------------------------------------|
| 11001 | 404 | The saved filter does not exist. |
| 11002 | 412 | Saved filters are not available for link shares. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 11001 | 404 | The saved filter does not exist. |
| 11002 | 412 | Saved filters are not available for link shares. |
## Subscriptions
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------------------------------------------------------------------|
| 12001 | 412 | The subscription entity type is invalid. |
| 12002 | 412 | The user is already subscribed to the entity itself or a parent entity. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 12001 | 412 | The subscription entity type is invalid. |
| 12002 | 412 | The user is already subscribed to the entity itself or a parent entity. |
## Link Shares
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|--------------------------------------------------------------------------------|
| 13001 | 412 | This link share requires a password for authentication, but none was provided. |
| 13002 | 403 | The provided link share password was invalid. |
## Time Ranges
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------------------------------|
| 14001 | 412 | The provided time range is invalid. |
| ErrorCode | HTTP Status Code | Description |
|-----------|------------------|-------------|
| 13001 | 412 | This link share requires a password for authentication, but none was provided. |
| 13002 | 403 | The provided link share password was invalid. |

View File

@ -1,51 +0,0 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2022 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 parse_time
import (
"fmt"
"net/http"
"code.vikunja.io/web"
)
// ErrInvalidTimeRange represents a "InvalidTimeRange" kind of error. Used if the provided time range is invalid.
type ErrInvalidTimeRange struct {
Range string
}
// IsErrInvalidTimeRange checks if an error is a ErrInvalidTimeRange.
func IsErrInvalidTimeRange(err error) bool {
_, ok := err.(*ErrInvalidTimeRange)
return ok
}
func (err *ErrInvalidTimeRange) Error() string {
return fmt.Sprintf("Time range '%s' is invalid", err.Range)
}
// ErrCodeInvalidTimeRange holds the unique world-error code of this error
const ErrCodeInvalidTimeRange = 14001
// HTTPError holds the http error description
func (err *ErrInvalidTimeRange) HTTPError() web.HTTPError {
return web.HTTPError{
HTTPCode: http.StatusPreconditionFailed,
Code: ErrCodeInvalidTimeRange,
Message: "The time range is invalid.",
}
}

View File

@ -1,79 +0,0 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2022 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 parse_time
import (
"strconv"
"strings"
"time"
)
func ParseTimeRange(timeRange string) (from time.Time, to time.Time, err error) {
timeRange = strings.ReplaceAll(timeRange, " ", "")
var parts []string
var factor int
if strings.Index(timeRange, "-") > 0 {
parts = strings.Split(timeRange, "-")
factor = -1
} else {
parts = strings.Split(timeRange, "+")
factor = 1
}
if len(parts) != 2 {
return from, to, &ErrInvalidTimeRange{Range: timeRange}
}
// Find the duration that is not "now"
var dur string
dur = parts[0]
if dur == "now" {
dur = parts[1]
}
to = time.Now()
var diff time.Duration
diff, err = parseTimeDuration(dur)
if err != nil {
return
}
from = time.Now().Add(diff * time.Duration(factor))
// Make sure from is always before to
if to.Unix() < from.Unix() {
return to, from, nil
}
return
}
func parseTimeDuration(timeAmount string) (amount time.Duration, err error) {
if strings.Index(timeAmount, "d") > -1 {
var a int
a, err = strconv.Atoi(strings.ReplaceAll(timeAmount, "d", ""))
if err != nil {
return
}
return time.Duration(a) * 24 * time.Hour, nil
}
return time.ParseDuration(timeAmount)
}

View File

@ -1,76 +0,0 @@
// Vikunja is a to-do list application to facilitate your life.
// Copyright 2018-2022 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 parse_time
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestParseTimeRange(t *testing.T) {
t.Run("last 7 days", func(t *testing.T) {
from, to, err := ParseTimeRange("now - 7d")
assert.NoError(t, err)
assert.Equal(t, time.Now().Add(time.Hour*24*7*-1).Unix(), from.Unix())
assert.Equal(t, time.Now().Unix(), to.Unix())
})
t.Run("last 7 days, but different", func(t *testing.T) {
from, to, err := ParseTimeRange("7d - now")
assert.NoError(t, err)
assert.Equal(t, time.Now().Add(time.Hour*24*7*-1).Unix(), from.Unix())
assert.Equal(t, time.Now().Unix(), to.Unix())
})
t.Run("last 24h", func(t *testing.T) {
from, to, err := ParseTimeRange("24h - now")
assert.NoError(t, err)
assert.Equal(t, time.Now().Add(time.Hour*24*-1).Unix(), from.Unix())
assert.Equal(t, time.Now().Unix(), to.Unix())
})
t.Run("next 7 days", func(t *testing.T) {
from, to, err := ParseTimeRange("now + 7d")
assert.NoError(t, err)
assert.Equal(t, time.Now().Unix(), from.Unix())
assert.Equal(t, time.Now().Add(time.Hour*24*7).Unix(), to.Unix())
})
t.Run("next 24h", func(t *testing.T) {
from, to, err := ParseTimeRange("now + 24h")
assert.NoError(t, err)
assert.Equal(t, time.Now().Unix(), from.Unix())
assert.Equal(t, time.Now().Add(time.Hour*24).Unix(), to.Unix())
})
t.Run("range with only now", func(t *testing.T) {
_, _, err := ParseTimeRange("now")
assert.Error(t, err)
assert.True(t, IsErrInvalidTimeRange(err))
})
t.Run("range with only one duration part", func(t *testing.T) {
_, _, err := ParseTimeRange("7d")
assert.Error(t, err)
assert.True(t, IsErrInvalidTimeRange(err))
})
t.Run("invalid date range", func(t *testing.T) {
_, _, err := ParseTimeRange("now-7y")
assert.Error(t, err)
})
}