Dashboard: Allow shortlink generation (#27409)

* intial frontend resolution/redirection logic

* backend scaffolding

* enough of the frontend to actually test end to end

* bugfixes

* add tests

* cleanup

* explore too hard for now

* fix build

* Docs: add docs

* FE test

* redirect directly from backend

* validate incoming uids

* add last_seen_at

* format documentation

* more documentation feedback

* very shaky migration of get route to middleware

* persist unix timestamps

* add id, orgId to table

* fixes for orgId scoping

* whoops forgot the middleware

* only redirect to absolute URLs under the AppUrl domain

* move lookup route to /goto/:uid, stop manually setting 404 response code

* renaming things according to PR feedback

* tricky deletion

* sneaky readd

* fix test

* more BE renaming

* FE updates -- no more @ts-ignore hacking :) and accounting for subpath

* Simplify code

Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>

* Short URLs: Drop usage of bus

Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>

* ShortURLService: Make injectable

Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>

* Rename file

Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>

* Add handling of url parsing and creating of full shortURL to backend

* Update test, remove unused imports

* Update pkg/api/short_urls.go

Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>

* Add correct import

* Pass context to short url service

* Remove not needed error log

* Rename dto and field to denote URL rather than path

* Update api docs based on feedback/suggestion

* Rename files to singular

* Revert to send relative path to backend

* Fixes after review

* Return dto when creating short URL that includes the full url

Use full url to provide shorten URL to the user

* Fix after review

* Fix relative url path when creating new short url

Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
Co-authored-by: Ivana <ivana.huckova@gmail.com>
Co-authored-by: Ivana Huckova <30407135+ivanahuckova@users.noreply.github.com>
Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
This commit is contained in:
Pete Davids
2020-10-14 12:48:48 +02:00
committed by GitHub
co-authored by Arve Knudsen Ivana Ivana Huckova Marcus Efraimsson
parent 3225b119d4
commit 65940c7726
13 changed files with 351 additions and 6 deletions
+4
View File
@@ -78,6 +78,7 @@ func (hs *HTTPServer) registerRoutes() {
r.Get("/import/dashboard", reqSignedIn, hs.Index)
r.Get("/dashboards/", reqSignedIn, hs.Index)
r.Get("/dashboards/*", reqSignedIn, hs.Index)
r.Get("/goto/:uid", reqSignedIn, hs.redirectFromShortURL, hs.Index)
r.Get("/explore", reqSignedIn, middleware.EnsureEditorOrViewerCanEdit, hs.Index)
@@ -390,6 +391,9 @@ func (hs *HTTPServer) registerRoutes() {
// error test
r.Get("/metrics/error", Wrap(GenerateError))
// short urls
apiRoute.Post("/short-urls", bind(dtos.CreateShortURLCmd{}), Wrap(hs.createShortURL))
}, reqSignedIn)
// admin api
+10
View File
@@ -0,0 +1,10 @@
package dtos
type ShortURL struct {
UID string `json:"uid"`
URL string `json:"url"`
}
type CreateShortURLCmd struct {
Path string `json:"path"`
}
+2
View File
@@ -12,6 +12,7 @@ import (
"github.com/grafana/grafana/pkg/services/live"
"github.com/grafana/grafana/pkg/services/search"
"github.com/grafana/grafana/pkg/services/shorturls"
"github.com/grafana/grafana/pkg/plugins/backendplugin"
@@ -72,6 +73,7 @@ type HTTPServer struct {
PluginManager *plugins.PluginManager `inject:""`
SearchService *search.SearchService `inject:""`
AlertNG *eval.AlertNG `inject:""`
ShortURLService *shorturls.ShortURLService `inject:""`
Live *live.GrafanaLive
Listener net.Listener
}
+61
View File
@@ -0,0 +1,61 @@
package api
import (
"errors"
"path"
"strings"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util"
)
// createShortURL handles requests to create short URLs.
func (hs *HTTPServer) createShortURL(c *models.ReqContext, cmd dtos.CreateShortURLCmd) Response {
hs.log.Debug("Received request to create short URL", "path", cmd.Path)
cmd.Path = strings.TrimSpace(cmd.Path)
if path.IsAbs(cmd.Path) {
hs.log.Error("Invalid short URL path", "path", cmd.Path)
return Error(400, "Path should be relative", nil)
}
shortURL, err := hs.ShortURLService.CreateShortURL(c.Req.Context(), c.SignedInUser, cmd.Path)
if err != nil {
return Error(500, "Failed to create short URL", err)
}
url := path.Join(setting.AppUrl, "goto", shortURL.Uid)
c.Logger.Debug("Created short URL", "url", url)
dto := dtos.ShortURL{
UID: shortURL.Uid,
URL: url,
}
return JSON(200, dto)
}
func (hs *HTTPServer) redirectFromShortURL(c *models.ReqContext) {
shortURLUID := c.Params(":uid")
if !util.IsValidShortUID(shortURLUID) {
return
}
shortURL, err := hs.ShortURLService.GetShortURLByUID(c.Req.Context(), c.SignedInUser, shortURLUID)
if err != nil {
if errors.Is(err, models.ErrShortURLNotFound) {
hs.log.Debug("Not redirecting short URL since not found")
return
}
hs.log.Error("Short URL redirection error", "err", err)
return
}
hs.log.Debug("Redirecting short URL", "path", shortURL.Path)
c.Redirect(setting.ToAbsUrl(shortURL.Path), 302)
}