mirror of
https://github.com/grafana/grafana.git
synced 2025-12-22 04:34:27 +08:00
Compare commits
3 Commits
docs/add-t
...
emil/20221
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f46046255 | ||
|
|
be1984cd36 | ||
|
|
dbbae9f944 |
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/api/dtos"
|
"github.com/grafana/grafana/pkg/api/dtos"
|
||||||
"github.com/grafana/grafana/pkg/api/response"
|
"github.com/grafana/grafana/pkg/api/response"
|
||||||
"github.com/grafana/grafana/pkg/models"
|
"github.com/grafana/grafana/pkg/models"
|
||||||
|
"github.com/grafana/grafana/pkg/models/errs"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
"github.com/grafana/grafana/pkg/web"
|
"github.com/grafana/grafana/pkg/web"
|
||||||
@@ -17,7 +18,7 @@ import (
|
|||||||
func (hs *HTTPServer) createShortURL(c *models.ReqContext) response.Response {
|
func (hs *HTTPServer) createShortURL(c *models.ReqContext) response.Response {
|
||||||
cmd := dtos.CreateShortURLCmd{}
|
cmd := dtos.CreateShortURLCmd{}
|
||||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||||
return response.Err(models.ErrShortURLBadRequest.Errorf("bad request data: %w", err))
|
return response.Err(errs.ErrShorturlBadRequest.Errorf("bad request data: %w", err))
|
||||||
}
|
}
|
||||||
hs.log.Debug("Received request to create short URL", "path", cmd.Path)
|
hs.log.Debug("Received request to create short URL", "path", cmd.Path)
|
||||||
shortURL, err := hs.ShortURLService.CreateShortURL(c.Req.Context(), c.SignedInUser, cmd.Path)
|
shortURL, err := hs.ShortURLService.CreateShortURL(c.Req.Context(), c.SignedInUser, cmd.Path)
|
||||||
@@ -45,7 +46,7 @@ func (hs *HTTPServer) redirectFromShortURL(c *models.ReqContext) {
|
|||||||
|
|
||||||
shortURL, err := hs.ShortURLService.GetShortURLByUID(c.Req.Context(), c.SignedInUser, shortURLUID)
|
shortURL, err := hs.ShortURLService.GetShortURLByUID(c.Req.Context(), c.SignedInUser, shortURLUID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if models.ErrShortURLNotFound.Is(err) {
|
if errs.ErrShorturlNotFound.Is(err) {
|
||||||
hs.log.Debug("Not redirecting short URL since not found")
|
hs.log.Debug("Not redirecting short URL since not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
7
pkg/models/errs/Makefile
Normal file
7
pkg/models/errs/Makefile
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
SRCS=$(wildcard *.hcl)
|
||||||
|
OBJS=$(SRCS:.hcl=.gen.go)
|
||||||
|
|
||||||
|
all: $(OBJS)
|
||||||
|
|
||||||
|
%.gen.go: %.hcl errutil.tmpl
|
||||||
|
eish generate --source=$< --template=./errutil.tmpl --package=errs > $@
|
||||||
39
pkg/models/errs/errutil.tmpl
Normal file
39
pkg/models/errs/errutil.tmpl
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// Code generated by Errata. DO NOT EDIT.
|
||||||
|
// Errata Schema Version: {{ SchemaVersion }}
|
||||||
|
// Grafana errors schema version: 1
|
||||||
|
// Hash: {{ Hash }}
|
||||||
|
package {{ Package }}
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/grafana/grafana/pkg/util/errutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
{%- for code, error in Errors sorted %}
|
||||||
|
Err{{ code | constantize }} = errutil.NewBase(
|
||||||
|
{%- if error.Cause %}
|
||||||
|
errutil.Status{{ error.Cause }},
|
||||||
|
{%- else %}
|
||||||
|
errutil.StatusMissing, // Fixme: Set 'cause' to one of the statuses defined as "errutil.Status*".
|
||||||
|
{%- endif %}
|
||||||
|
{{ code | stringformat:"%q" }},
|
||||||
|
{%- if error.Message && !error.Labels.template %}
|
||||||
|
errutil.WithPublicMessage(`{{ error.Message | escape_backtick -}}`),
|
||||||
|
{%- endif %}
|
||||||
|
{%- if error.Labels.severity %}
|
||||||
|
errutil.WithLogLevel(errutil.Level{{ error.Labels.severity | capfirst }}),
|
||||||
|
{%- endif %}
|
||||||
|
{%- if error.Guide %}
|
||||||
|
errutil.WithGuide(`{{ error.Guide | escape_backtick -}}`),
|
||||||
|
{%- endif %}
|
||||||
|
){%- if error.Labels.template %}.MustTemplate(
|
||||||
|
{%- if error.Labels.logMessage %}
|
||||||
|
`{{ error.Labels.logMessage | escape_backtick -}}`,
|
||||||
|
errutil.WithPublic(`{{ error.Message | escape_backtick -}}`),
|
||||||
|
{%- else %}
|
||||||
|
`{{ error.Message | escape_backtick -}}`,
|
||||||
|
errutil.WithPublicFromLog(),
|
||||||
|
{%- endif %}
|
||||||
|
){%- endif %}
|
||||||
|
{%- endfor %}
|
||||||
|
)
|
||||||
3
pkg/models/errs/gen.go
Normal file
3
pkg/models/errs/gen.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package errs
|
||||||
|
|
||||||
|
//go:generate make all
|
||||||
42
pkg/models/errs/shorturl.gen.go
Normal file
42
pkg/models/errs/shorturl.gen.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// Code generated by Errata. DO NOT EDIT.
|
||||||
|
// Errata Schema Version: 0.1
|
||||||
|
// Grafana errors schema version: 1
|
||||||
|
// Hash: 41882bb99ce21663b620467357c47a06
|
||||||
|
package errs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/grafana/grafana/pkg/util/errutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrShorturlAbsolutePath = errutil.NewBase(
|
||||||
|
errutil.StatusValidationFailed,
|
||||||
|
"shorturl.absolutePath",
|
||||||
|
errutil.WithPublicMessage(`Path should be relative`),
|
||||||
|
errutil.WithGuide(`Try removing any prefixing ` + "`" + `/` + "`" + ` to your path.`),
|
||||||
|
)
|
||||||
|
ErrShorturlBadRequest = errutil.NewBase(
|
||||||
|
errutil.StatusBadRequest,
|
||||||
|
"shorturl.badRequest",
|
||||||
|
errutil.WithPublicMessage(`Bad request`),
|
||||||
|
)
|
||||||
|
ErrShorturlInternal = errutil.NewBase(
|
||||||
|
errutil.StatusInternal,
|
||||||
|
"shorturl.internal",
|
||||||
|
errutil.WithPublicMessage(`Internal server error`),
|
||||||
|
)
|
||||||
|
ErrShorturlInvalidPath = errutil.NewBase(
|
||||||
|
errutil.StatusValidationFailed,
|
||||||
|
"shorturl.invalidPath",
|
||||||
|
errutil.WithPublicMessage(`Invalid short URL path`),
|
||||||
|
errutil.WithGuide(`There is something wrong with the path you've submitted. It might
|
||||||
|
contain unsupported characters or path-components .. to move up in the
|
||||||
|
hierarchy, which is not supported by the shorturl service.
|
||||||
|
`),
|
||||||
|
)
|
||||||
|
ErrShorturlNotFound = errutil.NewBase(
|
||||||
|
errutil.StatusNotFound,
|
||||||
|
"shorturl.notFound",
|
||||||
|
errutil.WithPublicMessage(`Could not find the specified short URL`),
|
||||||
|
)
|
||||||
|
)
|
||||||
32
pkg/models/errs/shorturl.hcl
Normal file
32
pkg/models/errs/shorturl.hcl
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
version = "0.1"
|
||||||
|
|
||||||
|
error "shorturl.badRequest" {
|
||||||
|
message = "Bad request"
|
||||||
|
cause = "BadRequest"
|
||||||
|
}
|
||||||
|
|
||||||
|
error "shorturl.notFound" {
|
||||||
|
message = "Could not find the specified short URL"
|
||||||
|
cause = "NotFound"
|
||||||
|
}
|
||||||
|
|
||||||
|
error "shorturl.absolutePath" {
|
||||||
|
message = "Path should be relative"
|
||||||
|
cause = "ValidationFailed"
|
||||||
|
guide = "Try removing any prefixing `/` to your path."
|
||||||
|
}
|
||||||
|
|
||||||
|
error "shorturl.invalidPath" {
|
||||||
|
message = "Invalid short URL path"
|
||||||
|
cause = "ValidationFailed"
|
||||||
|
guide = <<EOF
|
||||||
|
There is something wrong with the path you've submitted. It might
|
||||||
|
contain unsupported characters or path-components .. to move up in the
|
||||||
|
hierarchy, which is not supported by the shorturl service.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
error "shorturl.internal" {
|
||||||
|
message = "Internal server error"
|
||||||
|
cause = "Internal"
|
||||||
|
}
|
||||||
@@ -2,16 +2,6 @@ package models
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/util/errutil"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrShortURLBadRequest = errutil.NewBase(errutil.StatusBadRequest, "shorturl.bad-request")
|
|
||||||
ErrShortURLNotFound = errutil.NewBase(errutil.StatusNotFound, "shorturl.not-found")
|
|
||||||
ErrShortURLAbsolutePath = errutil.NewBase(errutil.StatusValidationFailed, "shorturl.absolute-path", errutil.WithPublicMessage("Path should be relative"))
|
|
||||||
ErrShortURLInvalidPath = errutil.NewBase(errutil.StatusValidationFailed, "shorturl.invalid-path", errutil.WithPublicMessage("Invalid short URL path"))
|
|
||||||
ErrShortURLInternal = errutil.NewBase(errutil.StatusInternal, "shorturl.internal")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ShortUrl struct {
|
type ShortUrl struct {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/db"
|
"github.com/grafana/grafana/pkg/infra/db"
|
||||||
"github.com/grafana/grafana/pkg/models"
|
"github.com/grafana/grafana/pkg/models"
|
||||||
|
"github.com/grafana/grafana/pkg/models/errs"
|
||||||
"github.com/grafana/grafana/pkg/services/user"
|
"github.com/grafana/grafana/pkg/services/user"
|
||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
)
|
)
|
||||||
@@ -39,7 +40,7 @@ func (s ShortURLService) GetShortURLByUID(ctx context.Context, user *user.Signed
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !exists {
|
if !exists {
|
||||||
return models.ErrShortURLNotFound.Errorf("short URL not found")
|
return errs.ErrShorturlNotFound.Errorf("short URL not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -67,10 +68,10 @@ func (s ShortURLService) CreateShortURL(ctx context.Context, user *user.SignedIn
|
|||||||
relPath = strings.TrimSpace(relPath)
|
relPath = strings.TrimSpace(relPath)
|
||||||
|
|
||||||
if path.IsAbs(relPath) {
|
if path.IsAbs(relPath) {
|
||||||
return nil, models.ErrShortURLAbsolutePath.Errorf("expected relative path: %s", relPath)
|
return nil, errs.ErrShorturlAbsolutePath.Errorf("expected relative path: %s", relPath)
|
||||||
}
|
}
|
||||||
if strings.Contains(relPath, "../") {
|
if strings.Contains(relPath, "../") {
|
||||||
return nil, models.ErrShortURLInvalidPath.Errorf("path cannot contain '../': %s", relPath)
|
return nil, errs.ErrShorturlInvalidPath.Errorf("path cannot contain '../': %s", relPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
@@ -87,7 +88,7 @@ func (s ShortURLService) CreateShortURL(ctx context.Context, user *user.SignedIn
|
|||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, models.ErrShortURLInternal.Errorf("failed to insert shorturl: %w", err)
|
return nil, errs.ErrShorturlInternal.Errorf("failed to insert shorturl: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &shortURL, nil
|
return &shortURL, nil
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana/pkg/models/errs"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/db"
|
"github.com/grafana/grafana/pkg/infra/db"
|
||||||
@@ -81,7 +83,7 @@ func TestShortURLService(t *testing.T) {
|
|||||||
|
|
||||||
shortURL, err := service.GetShortURLByUID(context.Background(), user, "testnotfounduid")
|
shortURL, err := service.GetShortURLByUID(context.Background(), user, "testnotfounduid")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.True(t, models.ErrShortURLNotFound.Is(err))
|
require.True(t, errs.ErrShorturlNotFound.Is(err))
|
||||||
require.Nil(t, shortURL)
|
require.Nil(t, shortURL)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ type Base struct {
|
|||||||
messageID string
|
messageID string
|
||||||
publicMessage string
|
publicMessage string
|
||||||
logLevel LogLevel
|
logLevel LogLevel
|
||||||
|
guide string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBase initializes a [Base] that is used to construct [Error].
|
// NewBase initializes a [Base] that is used to construct [Error].
|
||||||
@@ -54,6 +55,17 @@ func WithLogLevel(lvl LogLevel) BaseOpt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithGuide adds a longer text intended to support a user to resolve
|
||||||
|
// the error.
|
||||||
|
//
|
||||||
|
// Used as a functional option to [NewBase].
|
||||||
|
func WithGuide(guide string) BaseOpt {
|
||||||
|
return func(b Base) Base {
|
||||||
|
b.guide = guide
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WithPublicMessage sets the default public message that will be used
|
// WithPublicMessage sets the default public message that will be used
|
||||||
// for errors based on this [Base].
|
// for errors based on this [Base].
|
||||||
//
|
//
|
||||||
@@ -171,6 +183,9 @@ type Error struct {
|
|||||||
PublicPayload map[string]interface{}
|
PublicPayload map[string]interface{}
|
||||||
// LogLevel provides a suggested level of logging for the error.
|
// LogLevel provides a suggested level of logging for the error.
|
||||||
LogLevel LogLevel
|
LogLevel LogLevel
|
||||||
|
// Guide is a longer text intended to support a user to resolve
|
||||||
|
// the error.
|
||||||
|
Guide string
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON returns an error, we do not want raw [Error]s being
|
// MarshalJSON returns an error, we do not want raw [Error]s being
|
||||||
@@ -229,6 +244,7 @@ type PublicError struct {
|
|||||||
MessageID string `json:"messageId"`
|
MessageID string `json:"messageId"`
|
||||||
Message string `json:"message,omitempty"`
|
Message string `json:"message,omitempty"`
|
||||||
Extra map[string]interface{} `json:"extra,omitempty"`
|
Extra map[string]interface{} `json:"extra,omitempty"`
|
||||||
|
Guide string `json:"guide,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Public returns a subset of the error with non-sensitive information
|
// Public returns a subset of the error with non-sensitive information
|
||||||
@@ -249,5 +265,6 @@ func (e Error) Public() PublicError {
|
|||||||
MessageID: e.MessageID,
|
MessageID: e.MessageID,
|
||||||
Message: message,
|
Message: message,
|
||||||
Extra: e.PublicPayload,
|
Extra: e.PublicPayload,
|
||||||
|
Guide: e.Guide,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user