mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: Refactor api handlers to use web.Bind (#42199)
* Chore: Refactor api handlers to use web.Bind * fix comments * fix comment * trying to fix most of the tests and force routing.Wrap type check * fix library panels tests * fix frontend logging tests * allow passing nil as a response to skip writing * return nil instead of the response * rewrite login handler function types * remove handlerFuncCtx * make linter happy * remove old bindings from the libraryelements * restore comments
This commit is contained in:
@@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
@@ -11,9 +12,14 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
func (hs *HTTPServer) AdminCreateUser(c *models.ReqContext, form dtos.AdminCreateUserForm) response.Response {
|
||||
func (hs *HTTPServer) AdminCreateUser(c *models.ReqContext) response.Response {
|
||||
form := dtos.AdminCreateUserForm{}
|
||||
if err := web.Bind(c.Req, &form); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd := models.CreateUserCommand{
|
||||
Login: form.Login,
|
||||
Email: form.Email,
|
||||
@@ -56,7 +62,11 @@ func (hs *HTTPServer) AdminCreateUser(c *models.ReqContext, form dtos.AdminCreat
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
||||
func AdminUpdateUserPassword(c *models.ReqContext, form dtos.AdminUpdateUserPasswordForm) response.Response {
|
||||
func AdminUpdateUserPassword(c *models.ReqContext) response.Response {
|
||||
form := dtos.AdminUpdateUserPasswordForm{}
|
||||
if err := web.Bind(c.Req, &form); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
userID := c.ParamsInt64(":id")
|
||||
|
||||
if len(form.Password) < 4 {
|
||||
@@ -87,7 +97,11 @@ func AdminUpdateUserPassword(c *models.ReqContext, form dtos.AdminUpdateUserPass
|
||||
}
|
||||
|
||||
// PUT /api/admin/users/:id/permissions
|
||||
func (hs *HTTPServer) AdminUpdateUserPermissions(c *models.ReqContext, form dtos.AdminUpdateUserPermissionsForm) response.Response {
|
||||
func (hs *HTTPServer) AdminUpdateUserPermissions(c *models.ReqContext) response.Response {
|
||||
form := dtos.AdminUpdateUserPermissionsForm{}
|
||||
if err := web.Bind(c.Req, &form); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
userID := c.ParamsInt64(":id")
|
||||
|
||||
err := updateUserPermissions(hs.SQLStore, userID, form.IsGrafanaAdmin)
|
||||
@@ -182,7 +196,11 @@ func (hs *HTTPServer) AdminGetUserAuthTokens(c *models.ReqContext) response.Resp
|
||||
}
|
||||
|
||||
// POST /api/admin/users/:id/revoke-auth-token
|
||||
func (hs *HTTPServer) AdminRevokeUserAuthToken(c *models.ReqContext, cmd models.RevokeAuthTokenCmd) response.Response {
|
||||
func (hs *HTTPServer) AdminRevokeUserAuthToken(c *models.ReqContext) response.Response {
|
||||
cmd := models.RevokeAuthTokenCmd{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
userID := c.ParamsInt64(":id")
|
||||
return hs.revokeUserAuthTokenInternal(c, userID, cmd)
|
||||
}
|
||||
|
||||
@@ -315,12 +315,13 @@ func putAdminScenario(t *testing.T, desc string, url string, routePattern string
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
sc.context.OrgRole = role
|
||||
|
||||
return hs.AdminUpdateUserPermissions(c, cmd)
|
||||
return hs.AdminUpdateUserPermissions(c)
|
||||
})
|
||||
|
||||
sc.m.Put(routePattern, sc.defaultHandler)
|
||||
@@ -370,12 +371,13 @@ func adminRevokeUserAuthTokenScenario(t *testing.T, desc string, url string, rou
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.userAuthTokenService = fakeAuthTokenService
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
sc.context.OrgRole = models.ROLE_ADMIN
|
||||
|
||||
return hs.AdminRevokeUserAuthToken(c, cmd)
|
||||
return hs.AdminRevokeUserAuthToken(c)
|
||||
})
|
||||
|
||||
sc.m.Post(routePattern, sc.defaultHandler)
|
||||
@@ -470,10 +472,11 @@ func adminCreateUserScenario(t *testing.T, desc string, url string, routePattern
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
|
||||
return hs.AdminCreateUser(c, cmd)
|
||||
return hs.AdminCreateUser(c)
|
||||
})
|
||||
|
||||
sc.m.Post(routePattern, sc.defaultHandler)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
@@ -132,7 +133,11 @@ func GetAlerts(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
// POST /api/alerts/test
|
||||
func (hs *HTTPServer) AlertTest(c *models.ReqContext, dto dtos.AlertTestCommand) response.Response {
|
||||
func (hs *HTTPServer) AlertTest(c *models.ReqContext) response.Response {
|
||||
dto := dtos.AlertTestCommand{}
|
||||
if err := web.Bind(c.Req, &dto); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if _, idErr := dto.Dashboard.Get("id").Int64(); idErr != nil {
|
||||
return response.Error(400, "The dashboard needs to be saved at least once before you can test an alert rule", nil)
|
||||
}
|
||||
@@ -276,7 +281,11 @@ func GetAlertNotificationByUID(c *models.ReqContext) response.Response {
|
||||
return response.JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func CreateAlertNotification(c *models.ReqContext, cmd models.CreateAlertNotificationCommand) response.Response {
|
||||
func CreateAlertNotification(c *models.ReqContext) response.Response {
|
||||
cmd := models.CreateAlertNotificationCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
if err := bus.DispatchCtx(c.Req.Context(), &cmd); err != nil {
|
||||
@@ -293,7 +302,11 @@ func CreateAlertNotification(c *models.ReqContext, cmd models.CreateAlertNotific
|
||||
return response.JSON(200, dtos.NewAlertNotification(cmd.Result))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateAlertNotification(c *models.ReqContext, cmd models.UpdateAlertNotificationCommand) response.Response {
|
||||
func (hs *HTTPServer) UpdateAlertNotification(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateAlertNotificationCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
err := hs.fillWithSecureSettingsData(c.Req.Context(), &cmd)
|
||||
@@ -324,7 +337,11 @@ func (hs *HTTPServer) UpdateAlertNotification(c *models.ReqContext, cmd models.U
|
||||
return response.JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateAlertNotificationByUID(c *models.ReqContext, cmd models.UpdateAlertNotificationWithUidCommand) response.Response {
|
||||
func (hs *HTTPServer) UpdateAlertNotificationByUID(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateAlertNotificationWithUidCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.Uid = web.Params(c.Req)[":uid"]
|
||||
|
||||
@@ -444,7 +461,11 @@ func DeleteAlertNotificationByUID(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
// POST /api/alert-notifications/test
|
||||
func NotificationTest(c *models.ReqContext, dto dtos.NotificationTestCommand) response.Response {
|
||||
func NotificationTest(c *models.ReqContext) response.Response {
|
||||
dto := dtos.NotificationTestCommand{}
|
||||
if err := web.Bind(c.Req, &dto); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd := &alerting.NotificationTestCommand{
|
||||
OrgID: c.OrgId,
|
||||
ID: dto.ID,
|
||||
@@ -470,7 +491,11 @@ func NotificationTest(c *models.ReqContext, dto dtos.NotificationTestCommand) re
|
||||
}
|
||||
|
||||
// POST /api/alerts/:alertId/pause
|
||||
func PauseAlert(c *models.ReqContext, dto dtos.PauseAlertCommand) response.Response {
|
||||
func PauseAlert(c *models.ReqContext) response.Response {
|
||||
dto := dtos.PauseAlertCommand{}
|
||||
if err := web.Bind(c.Req, &dto); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
alertID := c.ParamsInt64(":alertId")
|
||||
result := make(map[string]interface{})
|
||||
result["alertId"] = alertID
|
||||
@@ -523,7 +548,11 @@ func PauseAlert(c *models.ReqContext, dto dtos.PauseAlertCommand) response.Respo
|
||||
}
|
||||
|
||||
// POST /api/admin/pause-all-alerts
|
||||
func PauseAllAlerts(c *models.ReqContext, dto dtos.PauseAllAlertsCommand) response.Response {
|
||||
func PauseAllAlerts(c *models.ReqContext) response.Response {
|
||||
dto := dtos.PauseAllAlertsCommand{}
|
||||
if err := web.Bind(c.Req, &dto); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
updateCmd := models.PauseAllAlertCommand{
|
||||
Paused: dto.Paused,
|
||||
}
|
||||
|
||||
@@ -166,12 +166,13 @@ func postAlertScenario(t *testing.T, desc string, url string, routePattern strin
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
sc.context.OrgRole = role
|
||||
|
||||
return PauseAlert(c, cmd)
|
||||
return PauseAlert(c)
|
||||
})
|
||||
|
||||
sc.m.Post(routePattern, sc.defaultHandler)
|
||||
|
||||
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/annotations"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
func GetAnnotations(c *models.ReqContext) response.Response {
|
||||
@@ -51,7 +53,11 @@ func (e *CreateAnnotationError) Error() string {
|
||||
return e.message
|
||||
}
|
||||
|
||||
func PostAnnotation(c *models.ReqContext, cmd dtos.PostAnnotationsCmd) response.Response {
|
||||
func PostAnnotation(c *models.ReqContext) response.Response {
|
||||
cmd := dtos.PostAnnotationsCmd{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if canSave, err := canSaveByDashboardID(c, cmd.DashboardId); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
@@ -98,7 +104,11 @@ func formatGraphiteAnnotation(what string, data string) string {
|
||||
return text
|
||||
}
|
||||
|
||||
func PostGraphiteAnnotation(c *models.ReqContext, cmd dtos.PostGraphiteAnnotationsCmd) response.Response {
|
||||
func PostGraphiteAnnotation(c *models.ReqContext) response.Response {
|
||||
cmd := dtos.PostGraphiteAnnotationsCmd{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
repo := annotations.GetRepository()
|
||||
|
||||
if cmd.What == "" {
|
||||
@@ -149,7 +159,11 @@ func PostGraphiteAnnotation(c *models.ReqContext, cmd dtos.PostGraphiteAnnotatio
|
||||
})
|
||||
}
|
||||
|
||||
func UpdateAnnotation(c *models.ReqContext, cmd dtos.UpdateAnnotationsCmd) response.Response {
|
||||
func UpdateAnnotation(c *models.ReqContext) response.Response {
|
||||
cmd := dtos.UpdateAnnotationsCmd{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
annotationID := c.ParamsInt64(":annotationId")
|
||||
|
||||
repo := annotations.GetRepository()
|
||||
@@ -175,7 +189,11 @@ func UpdateAnnotation(c *models.ReqContext, cmd dtos.UpdateAnnotationsCmd) respo
|
||||
return response.Success("Annotation updated")
|
||||
}
|
||||
|
||||
func PatchAnnotation(c *models.ReqContext, cmd dtos.PatchAnnotationsCmd) response.Response {
|
||||
func PatchAnnotation(c *models.ReqContext) response.Response {
|
||||
cmd := dtos.PatchAnnotationsCmd{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
annotationID := c.ParamsInt64(":annotationId")
|
||||
|
||||
repo := annotations.GetRepository()
|
||||
@@ -223,7 +241,11 @@ func PatchAnnotation(c *models.ReqContext, cmd dtos.PatchAnnotationsCmd) respons
|
||||
return response.Success("Annotation patched")
|
||||
}
|
||||
|
||||
func DeleteAnnotations(c *models.ReqContext, cmd dtos.DeleteAnnotationsCmd) response.Response {
|
||||
func DeleteAnnotations(c *models.ReqContext) response.Response {
|
||||
cmd := dtos.DeleteAnnotationsCmd{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
repo := annotations.GetRepository()
|
||||
|
||||
err := repo.Delete(&annotations.DeleteParams{
|
||||
|
||||
@@ -275,12 +275,13 @@ func postAnnotationScenario(t *testing.T, desc string, url string, routePattern
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
sc.context.OrgRole = role
|
||||
|
||||
return PostAnnotation(c, cmd)
|
||||
return PostAnnotation(c)
|
||||
})
|
||||
|
||||
fakeAnnoRepo = &fakeAnnotationsRepo{}
|
||||
@@ -299,12 +300,13 @@ func putAnnotationScenario(t *testing.T, desc string, url string, routePattern s
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
sc.context.OrgRole = role
|
||||
|
||||
return UpdateAnnotation(c, cmd)
|
||||
return UpdateAnnotation(c)
|
||||
})
|
||||
|
||||
fakeAnnoRepo = &fakeAnnotationsRepo{}
|
||||
@@ -322,12 +324,13 @@ func patchAnnotationScenario(t *testing.T, desc string, url string, routePattern
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
sc.context.OrgRole = role
|
||||
|
||||
return PatchAnnotation(c, cmd)
|
||||
return PatchAnnotation(c)
|
||||
})
|
||||
|
||||
fakeAnnoRepo = &fakeAnnotationsRepo{}
|
||||
@@ -346,12 +349,13 @@ func deleteAnnotationsScenario(t *testing.T, desc string, url string, routePatte
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
sc.context.OrgRole = role
|
||||
|
||||
return DeleteAnnotations(c, cmd)
|
||||
return DeleteAnnotations(c)
|
||||
})
|
||||
|
||||
fakeAnnoRepo = &fakeAnnotationsRepo{}
|
||||
|
||||
142
pkg/api/api.go
142
pkg/api/api.go
@@ -4,13 +4,10 @@ package api
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/go-macaron/binding"
|
||||
"github.com/grafana/grafana/pkg/api/avatar"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/frontendlogging"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
@@ -35,7 +32,6 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
authorize := acmiddleware.Middleware(hs.AccessControl)
|
||||
authorizeInOrg := acmiddleware.AuthorizeInOrgMiddleware(hs.AccessControl, hs.SQLStore)
|
||||
quota := middleware.Quota(hs.QuotaService)
|
||||
bind := binding.Bind
|
||||
|
||||
r := hs.RouteRegister
|
||||
|
||||
@@ -116,19 +112,19 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
r.Get("/verify", hs.Index)
|
||||
r.Get("/signup", hs.Index)
|
||||
r.Get("/api/user/signup/options", routing.Wrap(GetSignUpOptions))
|
||||
r.Post("/api/user/signup", quota("user"), bind(dtos.SignUpForm{}), routing.Wrap(SignUp))
|
||||
r.Post("/api/user/signup/step2", bind(dtos.SignUpStep2Form{}), routing.Wrap(hs.SignUpStep2))
|
||||
r.Post("/api/user/signup", quota("user"), routing.Wrap(SignUp))
|
||||
r.Post("/api/user/signup/step2", routing.Wrap(hs.SignUpStep2))
|
||||
|
||||
// invited
|
||||
r.Get("/api/user/invite/:code", routing.Wrap(GetInviteInfoByCode))
|
||||
r.Post("/api/user/invite/complete", bind(dtos.CompleteInviteForm{}), routing.Wrap(hs.CompleteInvite))
|
||||
r.Post("/api/user/invite/complete", routing.Wrap(hs.CompleteInvite))
|
||||
|
||||
// reset password
|
||||
r.Get("/user/password/send-reset-email", reqNotSignedIn, hs.Index)
|
||||
r.Get("/user/password/reset", hs.Index)
|
||||
|
||||
r.Post("/api/user/password/send-reset-email", bind(dtos.SendResetPasswordEmailForm{}), routing.Wrap(SendResetPasswordEmail))
|
||||
r.Post("/api/user/password/reset", bind(dtos.ResetUserPasswordForm{}), routing.Wrap(ResetPassword))
|
||||
r.Post("/api/user/password/send-reset-email", routing.Wrap(SendResetPasswordEmail))
|
||||
r.Post("/api/user/password/reset", routing.Wrap(ResetPassword))
|
||||
|
||||
// dashboard snapshots
|
||||
r.Get("/dashboard/snapshot/*", reqNoAuth, hs.Index)
|
||||
@@ -145,7 +141,7 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
// user (signed in)
|
||||
apiRoute.Group("/user", func(userRoute routing.RouteRegister) {
|
||||
userRoute.Get("/", routing.Wrap(GetSignedInUser))
|
||||
userRoute.Put("/", bind(models.UpdateUserCommand{}), routing.Wrap(UpdateSignedInUser))
|
||||
userRoute.Put("/", routing.Wrap(UpdateSignedInUser))
|
||||
userRoute.Post("/using/:id", routing.Wrap(UserSetUsingOrg))
|
||||
userRoute.Get("/orgs", routing.Wrap(GetSignedInUserOrgList))
|
||||
userRoute.Get("/teams", routing.Wrap(GetSignedInUserTeamList))
|
||||
@@ -153,17 +149,17 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
userRoute.Post("/stars/dashboard/:id", routing.Wrap(StarDashboard))
|
||||
userRoute.Delete("/stars/dashboard/:id", routing.Wrap(UnstarDashboard))
|
||||
|
||||
userRoute.Put("/password", bind(models.ChangeUserPasswordCommand{}), routing.Wrap(ChangeUserPassword))
|
||||
userRoute.Put("/password", routing.Wrap(ChangeUserPassword))
|
||||
userRoute.Get("/quotas", routing.Wrap(GetUserQuotas))
|
||||
userRoute.Put("/helpflags/:id", routing.Wrap(SetHelpFlag))
|
||||
// For dev purpose
|
||||
userRoute.Get("/helpflags/clear", routing.Wrap(ClearHelpFlags))
|
||||
|
||||
userRoute.Get("/preferences", routing.Wrap(hs.GetUserPreferences))
|
||||
userRoute.Put("/preferences", bind(dtos.UpdatePrefsCmd{}), routing.Wrap(hs.UpdateUserPreferences))
|
||||
userRoute.Put("/preferences", routing.Wrap(hs.UpdateUserPreferences))
|
||||
|
||||
userRoute.Get("/auth-tokens", routing.Wrap(hs.GetUserAuthTokens))
|
||||
userRoute.Post("/revoke-auth-token", bind(models.RevokeAuthTokenCmd{}), routing.Wrap(hs.RevokeUserAuthToken))
|
||||
userRoute.Post("/revoke-auth-token", routing.Wrap(hs.RevokeUserAuthToken))
|
||||
}, reqSignedInNoAnonymous)
|
||||
|
||||
apiRoute.Group("/users", func(usersRoute routing.RouteRegister) {
|
||||
@@ -175,21 +171,21 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
usersRoute.Get("/:id/orgs", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersRead, userIDScope)), routing.Wrap(GetUserOrgList))
|
||||
// query parameters /users/lookup?loginOrEmail=admin@example.com
|
||||
usersRoute.Get("/lookup", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersRead, ac.ScopeGlobalUsersAll)), routing.Wrap(GetUserByLoginOrEmail))
|
||||
usersRoute.Put("/:id", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersWrite, userIDScope)), bind(models.UpdateUserCommand{}), routing.Wrap(UpdateUser))
|
||||
usersRoute.Put("/:id", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersWrite, userIDScope)), routing.Wrap(UpdateUser))
|
||||
usersRoute.Post("/:id/using/:orgId", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersWrite, userIDScope)), routing.Wrap(UpdateUserActiveOrg))
|
||||
})
|
||||
|
||||
// team (admin permission required)
|
||||
apiRoute.Group("/teams", func(teamsRoute routing.RouteRegister) {
|
||||
teamsRoute.Post("/", bind(models.CreateTeamCommand{}), routing.Wrap(hs.CreateTeam))
|
||||
teamsRoute.Put("/:teamId", bind(models.UpdateTeamCommand{}), routing.Wrap(hs.UpdateTeam))
|
||||
teamsRoute.Post("/", routing.Wrap(hs.CreateTeam))
|
||||
teamsRoute.Put("/:teamId", routing.Wrap(hs.UpdateTeam))
|
||||
teamsRoute.Delete("/:teamId", routing.Wrap(hs.DeleteTeamByID))
|
||||
teamsRoute.Get("/:teamId/members", routing.Wrap(hs.GetTeamMembers))
|
||||
teamsRoute.Post("/:teamId/members", bind(models.AddTeamMemberCommand{}), routing.Wrap(hs.AddTeamMember))
|
||||
teamsRoute.Put("/:teamId/members/:userId", bind(models.UpdateTeamMemberCommand{}), routing.Wrap(hs.UpdateTeamMember))
|
||||
teamsRoute.Post("/:teamId/members", routing.Wrap(hs.AddTeamMember))
|
||||
teamsRoute.Put("/:teamId/members/:userId", routing.Wrap(hs.UpdateTeamMember))
|
||||
teamsRoute.Delete("/:teamId/members/:userId", routing.Wrap(hs.RemoveTeamMember))
|
||||
teamsRoute.Get("/:teamId/preferences", routing.Wrap(hs.GetTeamPreferences))
|
||||
teamsRoute.Put("/:teamId/preferences", bind(dtos.UpdatePrefsCmd{}), routing.Wrap(hs.UpdateTeamPreferences))
|
||||
teamsRoute.Put("/:teamId/preferences", routing.Wrap(hs.UpdateTeamPreferences))
|
||||
}, reqCanAccessTeams)
|
||||
|
||||
// team without requirement of user to be org admin
|
||||
@@ -207,22 +203,22 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
// current org
|
||||
apiRoute.Group("/org", func(orgRoute routing.RouteRegister) {
|
||||
userIDScope := ac.Scope("users", "id", ac.Parameter(":userId"))
|
||||
orgRoute.Put("/", authorize(reqOrgAdmin, ac.EvalPermission(ActionOrgsWrite)), bind(dtos.UpdateOrgForm{}), routing.Wrap(UpdateCurrentOrg))
|
||||
orgRoute.Put("/address", authorize(reqOrgAdmin, ac.EvalPermission(ActionOrgsWrite)), bind(dtos.UpdateOrgAddressForm{}), routing.Wrap(UpdateCurrentOrgAddress))
|
||||
orgRoute.Put("/", authorize(reqOrgAdmin, ac.EvalPermission(ActionOrgsWrite)), routing.Wrap(UpdateCurrentOrg))
|
||||
orgRoute.Put("/address", authorize(reqOrgAdmin, ac.EvalPermission(ActionOrgsWrite)), routing.Wrap(UpdateCurrentOrgAddress))
|
||||
orgRoute.Get("/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead, ac.ScopeUsersAll)), routing.Wrap(hs.GetOrgUsersForCurrentOrg))
|
||||
orgRoute.Get("/users/search", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRead, ac.ScopeUsersAll)), routing.Wrap(hs.SearchOrgUsersWithPaging))
|
||||
orgRoute.Post("/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersAdd, ac.ScopeUsersAll)), quota("user"), bind(models.AddOrgUserCommand{}), routing.Wrap(hs.AddOrgUserToCurrentOrg))
|
||||
orgRoute.Patch("/users/:userId", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRoleUpdate, userIDScope)), bind(models.UpdateOrgUserCommand{}), routing.Wrap(hs.UpdateOrgUserForCurrentOrg))
|
||||
orgRoute.Post("/users", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersAdd, ac.ScopeUsersAll)), quota("user"), routing.Wrap(hs.AddOrgUserToCurrentOrg))
|
||||
orgRoute.Patch("/users/:userId", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRoleUpdate, userIDScope)), routing.Wrap(hs.UpdateOrgUserForCurrentOrg))
|
||||
orgRoute.Delete("/users/:userId", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionOrgUsersRemove, userIDScope)), routing.Wrap(hs.RemoveOrgUserForCurrentOrg))
|
||||
|
||||
// invites
|
||||
orgRoute.Get("/invites", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), routing.Wrap(GetPendingOrgInvites))
|
||||
orgRoute.Post("/invites", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), quota("user"), bind(dtos.AddInviteForm{}), routing.Wrap(AddOrgInvite))
|
||||
orgRoute.Post("/invites", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), quota("user"), routing.Wrap(AddOrgInvite))
|
||||
orgRoute.Patch("/invites/:code/revoke", authorize(reqOrgAdmin, ac.EvalPermission(ac.ActionUsersCreate)), routing.Wrap(RevokeInvite))
|
||||
|
||||
// prefs
|
||||
orgRoute.Get("/preferences", authorize(reqOrgAdmin, ac.EvalPermission(ActionOrgsPreferencesRead)), routing.Wrap(hs.GetOrgPreferences))
|
||||
orgRoute.Put("/preferences", authorize(reqOrgAdmin, ac.EvalPermission(ActionOrgsPreferencesWrite)), bind(dtos.UpdatePrefsCmd{}), routing.Wrap(hs.UpdateOrgPreferences))
|
||||
orgRoute.Put("/preferences", authorize(reqOrgAdmin, ac.EvalPermission(ActionOrgsPreferencesWrite)), routing.Wrap(hs.UpdateOrgPreferences))
|
||||
})
|
||||
|
||||
// current org without requirement of user to be org admin
|
||||
@@ -231,7 +227,7 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
})
|
||||
|
||||
// create new org
|
||||
apiRoute.Post("/orgs", authorizeInOrg(reqSignedIn, acmiddleware.UseGlobalOrg, ac.EvalPermission(ActionOrgsCreate)), quota("org"), bind(models.CreateOrgCommand{}), routing.Wrap(hs.CreateOrg))
|
||||
apiRoute.Post("/orgs", authorizeInOrg(reqSignedIn, acmiddleware.UseGlobalOrg, ac.EvalPermission(ActionOrgsCreate)), quota("org"), routing.Wrap(hs.CreateOrg))
|
||||
|
||||
// search all orgs
|
||||
apiRoute.Get("/orgs", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseGlobalOrg, ac.EvalPermission(ActionOrgsRead)), routing.Wrap(SearchOrgs))
|
||||
@@ -240,15 +236,15 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
apiRoute.Group("/orgs/:orgId", func(orgsRoute routing.RouteRegister) {
|
||||
userIDScope := ac.Scope("users", "id", ac.Parameter(":userId"))
|
||||
orgsRoute.Get("/", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ActionOrgsRead)), routing.Wrap(GetOrgByID))
|
||||
orgsRoute.Put("/", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ActionOrgsWrite)), bind(dtos.UpdateOrgForm{}), routing.Wrap(UpdateOrg))
|
||||
orgsRoute.Put("/address", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ActionOrgsWrite)), bind(dtos.UpdateOrgAddressForm{}), routing.Wrap(UpdateOrgAddress))
|
||||
orgsRoute.Put("/", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ActionOrgsWrite)), routing.Wrap(UpdateOrg))
|
||||
orgsRoute.Put("/address", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ActionOrgsWrite)), routing.Wrap(UpdateOrgAddress))
|
||||
orgsRoute.Delete("/", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ActionOrgsDelete)), routing.Wrap(DeleteOrgByID))
|
||||
orgsRoute.Get("/users", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersRead, ac.ScopeUsersAll)), routing.Wrap(hs.GetOrgUsers))
|
||||
orgsRoute.Post("/users", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersAdd, ac.ScopeUsersAll)), bind(models.AddOrgUserCommand{}), routing.Wrap(hs.AddOrgUser))
|
||||
orgsRoute.Patch("/users/:userId", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersRoleUpdate, userIDScope)), bind(models.UpdateOrgUserCommand{}), routing.Wrap(hs.UpdateOrgUser))
|
||||
orgsRoute.Post("/users", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersAdd, ac.ScopeUsersAll)), routing.Wrap(hs.AddOrgUser))
|
||||
orgsRoute.Patch("/users/:userId", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersRoleUpdate, userIDScope)), routing.Wrap(hs.UpdateOrgUser))
|
||||
orgsRoute.Delete("/users/:userId", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ac.ActionOrgUsersRemove, userIDScope)), routing.Wrap(hs.RemoveOrgUser))
|
||||
orgsRoute.Get("/quotas", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ActionOrgsQuotasRead)), routing.Wrap(hs.GetOrgQuotas))
|
||||
orgsRoute.Put("/quotas/:target", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ActionOrgsQuotasWrite)), bind(models.UpdateOrgQuotaCmd{}), routing.Wrap(hs.UpdateOrgQuota))
|
||||
orgsRoute.Put("/quotas/:target", authorizeInOrg(reqGrafanaAdmin, acmiddleware.UseOrgFromContextParams, ac.EvalPermission(ActionOrgsQuotasWrite)), routing.Wrap(hs.UpdateOrgQuota))
|
||||
})
|
||||
|
||||
// orgs (admin routes)
|
||||
@@ -257,21 +253,21 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
// auth api keys
|
||||
apiRoute.Group("/auth/keys", func(keysRoute routing.RouteRegister) {
|
||||
keysRoute.Get("/", routing.Wrap(GetAPIKeys))
|
||||
keysRoute.Post("/", quota("api_key"), bind(models.AddApiKeyCommand{}), routing.Wrap(hs.AddAPIKey))
|
||||
keysRoute.Post("/additional", quota("api_key"), bind(models.AddApiKeyCommand{}), routing.Wrap(hs.AdditionalAPIKey))
|
||||
keysRoute.Post("/", quota("api_key"), routing.Wrap(hs.AddAPIKey))
|
||||
keysRoute.Post("/additional", quota("api_key"), routing.Wrap(hs.AdditionalAPIKey))
|
||||
keysRoute.Delete("/:id", routing.Wrap(DeleteAPIKey))
|
||||
}, reqOrgAdmin)
|
||||
|
||||
// Preferences
|
||||
apiRoute.Group("/preferences", func(prefRoute routing.RouteRegister) {
|
||||
prefRoute.Post("/set-home-dash", bind(models.SavePreferencesCommand{}), routing.Wrap(SetHomeDashboard))
|
||||
prefRoute.Post("/set-home-dash", routing.Wrap(SetHomeDashboard))
|
||||
})
|
||||
|
||||
// Data sources
|
||||
apiRoute.Group("/datasources", func(datasourceRoute routing.RouteRegister) {
|
||||
datasourceRoute.Get("/", authorize(reqOrgAdmin, ac.EvalPermission(ActionDatasourcesRead, ScopeDatasourcesAll)), routing.Wrap(hs.GetDataSources))
|
||||
datasourceRoute.Post("/", authorize(reqOrgAdmin, ac.EvalPermission(ActionDatasourcesCreate)), quota("data_source"), bind(models.AddDataSourceCommand{}), routing.Wrap(AddDataSource))
|
||||
datasourceRoute.Put("/:id", authorize(reqOrgAdmin, ac.EvalPermission(ActionDatasourcesWrite, ScopeDatasourceID)), bind(models.UpdateDataSourceCommand{}), routing.Wrap(hs.UpdateDataSource))
|
||||
datasourceRoute.Post("/", authorize(reqOrgAdmin, ac.EvalPermission(ActionDatasourcesCreate)), quota("data_source"), routing.Wrap(AddDataSource))
|
||||
datasourceRoute.Put("/:id", authorize(reqOrgAdmin, ac.EvalPermission(ActionDatasourcesWrite, ScopeDatasourceID)), routing.Wrap(hs.UpdateDataSource))
|
||||
datasourceRoute.Delete("/:id", authorize(reqOrgAdmin, ac.EvalPermission(ActionDatasourcesDelete, ScopeDatasourceID)), routing.Wrap(hs.DeleteDataSourceById))
|
||||
datasourceRoute.Delete("/uid/:uid", authorize(reqOrgAdmin, ac.EvalPermission(ActionDatasourcesDelete, ScopeDatasourceUID)), routing.Wrap(hs.DeleteDataSourceByUID))
|
||||
datasourceRoute.Delete("/name/:name", authorize(reqOrgAdmin, ac.EvalPermission(ActionDatasourcesDelete, ScopeDatasourceName)), routing.Wrap(hs.DeleteDataSourceByName))
|
||||
@@ -291,13 +287,13 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
apiRoute.Get("/plugins/errors", routing.Wrap(hs.GetPluginErrorsList))
|
||||
|
||||
apiRoute.Group("/plugins", func(pluginRoute routing.RouteRegister) {
|
||||
pluginRoute.Post("/:pluginId/install", bind(dtos.InstallPluginCommand{}), routing.Wrap(hs.InstallPlugin))
|
||||
pluginRoute.Post("/:pluginId/install", routing.Wrap(hs.InstallPlugin))
|
||||
pluginRoute.Post("/:pluginId/uninstall", routing.Wrap(hs.UninstallPlugin))
|
||||
}, reqGrafanaAdmin)
|
||||
|
||||
apiRoute.Group("/plugins", func(pluginRoute routing.RouteRegister) {
|
||||
pluginRoute.Get("/:pluginId/dashboards/", routing.Wrap(hs.GetPluginDashboards))
|
||||
pluginRoute.Post("/:pluginId/settings", bind(models.UpdatePluginSettingCmd{}), routing.Wrap(hs.UpdatePluginSetting))
|
||||
pluginRoute.Post("/:pluginId/settings", routing.Wrap(hs.UpdatePluginSetting))
|
||||
pluginRoute.Get("/:pluginId/metrics", routing.Wrap(hs.CollectPluginMetrics))
|
||||
}, reqOrgAdmin)
|
||||
|
||||
@@ -312,16 +308,16 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
apiRoute.Group("/folders", func(folderRoute routing.RouteRegister) {
|
||||
folderRoute.Get("/", routing.Wrap(hs.GetFolders))
|
||||
folderRoute.Get("/id/:id", routing.Wrap(hs.GetFolderByID))
|
||||
folderRoute.Post("/", bind(models.CreateFolderCommand{}), routing.Wrap(hs.CreateFolder))
|
||||
folderRoute.Post("/", routing.Wrap(hs.CreateFolder))
|
||||
|
||||
folderRoute.Group("/:uid", func(folderUidRoute routing.RouteRegister) {
|
||||
folderUidRoute.Get("/", routing.Wrap(hs.GetFolderByUID))
|
||||
folderUidRoute.Put("/", bind(models.UpdateFolderCommand{}), routing.Wrap(hs.UpdateFolder))
|
||||
folderUidRoute.Put("/", routing.Wrap(hs.UpdateFolder))
|
||||
folderUidRoute.Delete("/", routing.Wrap(hs.DeleteFolder))
|
||||
|
||||
folderUidRoute.Group("/permissions", func(folderPermissionRoute routing.RouteRegister) {
|
||||
folderPermissionRoute.Get("/", routing.Wrap(hs.GetFolderPermissionList))
|
||||
folderPermissionRoute.Post("/", bind(dtos.UpdateDashboardAclCommand{}), routing.Wrap(hs.UpdateFolderPermissions))
|
||||
folderPermissionRoute.Post("/", routing.Wrap(hs.UpdateFolderPermissions))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -331,22 +327,22 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
dashboardRoute.Get("/uid/:uid", routing.Wrap(hs.GetDashboard))
|
||||
dashboardRoute.Delete("/uid/:uid", routing.Wrap(hs.DeleteDashboardByUID))
|
||||
|
||||
dashboardRoute.Post("/calculate-diff", bind(dtos.CalculateDiffOptions{}), routing.Wrap(CalculateDashboardDiff))
|
||||
dashboardRoute.Post("/trim", bind(models.TrimDashboardCommand{}), routing.Wrap(hs.TrimDashboard))
|
||||
dashboardRoute.Post("/calculate-diff", routing.Wrap(CalculateDashboardDiff))
|
||||
dashboardRoute.Post("/trim", routing.Wrap(hs.TrimDashboard))
|
||||
|
||||
dashboardRoute.Post("/db", bind(models.SaveDashboardCommand{}), routing.Wrap(hs.PostDashboard))
|
||||
dashboardRoute.Post("/db", routing.Wrap(hs.PostDashboard))
|
||||
dashboardRoute.Get("/home", routing.Wrap(hs.GetHomeDashboard))
|
||||
dashboardRoute.Get("/tags", GetDashboardTags)
|
||||
dashboardRoute.Post("/import", bind(dtos.ImportDashboardCommand{}), routing.Wrap(hs.ImportDashboard))
|
||||
dashboardRoute.Post("/import", routing.Wrap(hs.ImportDashboard))
|
||||
|
||||
dashboardRoute.Group("/id/:dashboardId", func(dashIdRoute routing.RouteRegister) {
|
||||
dashIdRoute.Get("/versions", routing.Wrap(GetDashboardVersions))
|
||||
dashIdRoute.Get("/versions/:id", routing.Wrap(GetDashboardVersion))
|
||||
dashIdRoute.Post("/restore", bind(dtos.RestoreDashboardVersionCommand{}), routing.Wrap(hs.RestoreDashboardVersion))
|
||||
dashIdRoute.Post("/restore", routing.Wrap(hs.RestoreDashboardVersion))
|
||||
|
||||
dashIdRoute.Group("/permissions", func(dashboardPermissionRoute routing.RouteRegister) {
|
||||
dashboardPermissionRoute.Get("/", routing.Wrap(hs.GetDashboardPermissionList))
|
||||
dashboardPermissionRoute.Post("/", bind(dtos.UpdateDashboardAclCommand{}), routing.Wrap(hs.UpdateDashboardPermissions))
|
||||
dashboardPermissionRoute.Post("/", routing.Wrap(hs.UpdateDashboardPermissions))
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -363,8 +359,8 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
playlistRoute.Get("/:id/items", ValidateOrgPlaylist, routing.Wrap(GetPlaylistItems))
|
||||
playlistRoute.Get("/:id/dashboards", ValidateOrgPlaylist, routing.Wrap(GetPlaylistDashboards))
|
||||
playlistRoute.Delete("/:id", reqEditorRole, ValidateOrgPlaylist, routing.Wrap(DeletePlaylist))
|
||||
playlistRoute.Put("/:id", reqEditorRole, bind(models.UpdatePlaylistCommand{}), ValidateOrgPlaylist, routing.Wrap(UpdatePlaylist))
|
||||
playlistRoute.Post("/", reqEditorRole, bind(models.CreatePlaylistCommand{}), routing.Wrap(CreatePlaylist))
|
||||
playlistRoute.Put("/:id", reqEditorRole, ValidateOrgPlaylist, routing.Wrap(UpdatePlaylist))
|
||||
playlistRoute.Post("/", reqEditorRole, routing.Wrap(CreatePlaylist))
|
||||
})
|
||||
|
||||
// Search
|
||||
@@ -372,14 +368,14 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
apiRoute.Get("/search/", routing.Wrap(Search))
|
||||
|
||||
// metrics
|
||||
apiRoute.Post("/tsdb/query", authorize(reqSignedIn, ac.EvalPermission(ActionDatasourcesQuery)), bind(dtos.MetricRequest{}), routing.Wrap(hs.QueryMetrics))
|
||||
apiRoute.Post("/tsdb/query", authorize(reqSignedIn, ac.EvalPermission(ActionDatasourcesQuery)), routing.Wrap(hs.QueryMetrics))
|
||||
|
||||
// DataSource w/ expressions
|
||||
apiRoute.Post("/ds/query", authorize(reqSignedIn, ac.EvalPermission(ActionDatasourcesQuery)), bind(dtos.MetricRequest{}), routing.Wrap(hs.QueryMetricsV2))
|
||||
apiRoute.Post("/ds/query", authorize(reqSignedIn, ac.EvalPermission(ActionDatasourcesQuery)), routing.Wrap(hs.QueryMetricsV2))
|
||||
|
||||
apiRoute.Group("/alerts", func(alertsRoute routing.RouteRegister) {
|
||||
alertsRoute.Post("/test", bind(dtos.AlertTestCommand{}), routing.Wrap(hs.AlertTest))
|
||||
alertsRoute.Post("/:alertId/pause", reqEditorRole, bind(dtos.PauseAlertCommand{}), routing.Wrap(PauseAlert))
|
||||
alertsRoute.Post("/test", routing.Wrap(hs.AlertTest))
|
||||
alertsRoute.Post("/:alertId/pause", reqEditorRole, routing.Wrap(PauseAlert))
|
||||
alertsRoute.Get("/:alertId", ValidateOrgAlert, routing.Wrap(GetAlert))
|
||||
alertsRoute.Get("/", routing.Wrap(GetAlerts))
|
||||
alertsRoute.Get("/states-for-dashboard", routing.Wrap(GetAlertStatesForDashboard))
|
||||
@@ -391,13 +387,13 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
|
||||
apiRoute.Group("/alert-notifications", func(alertNotifications routing.RouteRegister) {
|
||||
alertNotifications.Get("/", routing.Wrap(GetAlertNotifications))
|
||||
alertNotifications.Post("/test", bind(dtos.NotificationTestCommand{}), routing.Wrap(NotificationTest))
|
||||
alertNotifications.Post("/", bind(models.CreateAlertNotificationCommand{}), routing.Wrap(CreateAlertNotification))
|
||||
alertNotifications.Put("/:notificationId", bind(models.UpdateAlertNotificationCommand{}), routing.Wrap(hs.UpdateAlertNotification))
|
||||
alertNotifications.Post("/test", routing.Wrap(NotificationTest))
|
||||
alertNotifications.Post("/", routing.Wrap(CreateAlertNotification))
|
||||
alertNotifications.Put("/:notificationId", routing.Wrap(hs.UpdateAlertNotification))
|
||||
alertNotifications.Get("/:notificationId", routing.Wrap(GetAlertNotificationByID))
|
||||
alertNotifications.Delete("/:notificationId", routing.Wrap(DeleteAlertNotification))
|
||||
alertNotifications.Get("/uid/:uid", routing.Wrap(GetAlertNotificationByUID))
|
||||
alertNotifications.Put("/uid/:uid", bind(models.UpdateAlertNotificationWithUidCommand{}), routing.Wrap(hs.UpdateAlertNotificationByUID))
|
||||
alertNotifications.Put("/uid/:uid", routing.Wrap(hs.UpdateAlertNotificationByUID))
|
||||
alertNotifications.Delete("/uid/:uid", routing.Wrap(DeleteAlertNotificationByUID))
|
||||
}, reqEditorRole)
|
||||
|
||||
@@ -407,22 +403,22 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
})
|
||||
|
||||
apiRoute.Get("/annotations", routing.Wrap(GetAnnotations))
|
||||
apiRoute.Post("/annotations/mass-delete", reqOrgAdmin, bind(dtos.DeleteAnnotationsCmd{}), routing.Wrap(DeleteAnnotations))
|
||||
apiRoute.Post("/annotations/mass-delete", reqOrgAdmin, routing.Wrap(DeleteAnnotations))
|
||||
|
||||
apiRoute.Group("/annotations", func(annotationsRoute routing.RouteRegister) {
|
||||
annotationsRoute.Post("/", bind(dtos.PostAnnotationsCmd{}), routing.Wrap(PostAnnotation))
|
||||
annotationsRoute.Post("/", routing.Wrap(PostAnnotation))
|
||||
annotationsRoute.Delete("/:annotationId", routing.Wrap(DeleteAnnotationByID))
|
||||
annotationsRoute.Put("/:annotationId", bind(dtos.UpdateAnnotationsCmd{}), routing.Wrap(UpdateAnnotation))
|
||||
annotationsRoute.Patch("/:annotationId", bind(dtos.PatchAnnotationsCmd{}), routing.Wrap(PatchAnnotation))
|
||||
annotationsRoute.Post("/graphite", reqEditorRole, bind(dtos.PostGraphiteAnnotationsCmd{}), routing.Wrap(PostGraphiteAnnotation))
|
||||
annotationsRoute.Put("/:annotationId", routing.Wrap(UpdateAnnotation))
|
||||
annotationsRoute.Patch("/:annotationId", routing.Wrap(PatchAnnotation))
|
||||
annotationsRoute.Post("/graphite", reqEditorRole, routing.Wrap(PostGraphiteAnnotation))
|
||||
annotationsRoute.Get("/tags", routing.Wrap(GetAnnotationTags))
|
||||
})
|
||||
|
||||
apiRoute.Post("/frontend-metrics", bind(metrics.PostFrontendMetricsCommand{}), routing.Wrap(hs.PostFrontendMetrics))
|
||||
apiRoute.Post("/frontend-metrics", routing.Wrap(hs.PostFrontendMetrics))
|
||||
|
||||
apiRoute.Group("/live", func(liveRoute routing.RouteRegister) {
|
||||
// the channel path is in the name
|
||||
liveRoute.Post("/publish", bind(dtos.LivePublishCmd{}), routing.Wrap(hs.Live.HandleHTTPPublish))
|
||||
liveRoute.Post("/publish", routing.Wrap(hs.Live.HandleHTTPPublish))
|
||||
|
||||
// POST influx line protocol.
|
||||
liveRoute.Post("/push/:streamId", hs.LivePushGateway.Handle)
|
||||
@@ -450,14 +446,14 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
})
|
||||
|
||||
// short urls
|
||||
apiRoute.Post("/short-urls", bind(dtos.CreateShortURLCmd{}), routing.Wrap(hs.createShortURL))
|
||||
apiRoute.Post("/short-urls", routing.Wrap(hs.createShortURL))
|
||||
}, reqSignedIn)
|
||||
|
||||
// admin api
|
||||
r.Group("/api/admin", func(adminRoute routing.RouteRegister) {
|
||||
adminRoute.Get("/settings", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionSettingsRead)), routing.Wrap(hs.AdminGetSettings))
|
||||
adminRoute.Get("/stats", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionServerStatsRead)), routing.Wrap(AdminGetStats))
|
||||
adminRoute.Post("/pause-all-alerts", reqGrafanaAdmin, bind(dtos.PauseAllAlertsCommand{}), routing.Wrap(PauseAllAlerts))
|
||||
adminRoute.Post("/pause-all-alerts", reqGrafanaAdmin, routing.Wrap(PauseAllAlerts))
|
||||
|
||||
adminRoute.Post("/provisioning/dashboards/reload", authorize(reqGrafanaAdmin, ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersDashboards)), routing.Wrap(hs.AdminProvisioningReloadDashboards))
|
||||
adminRoute.Post("/provisioning/plugins/reload", authorize(reqGrafanaAdmin, ac.EvalPermission(ActionProvisioningReload, ScopeProvisionersPlugins)), routing.Wrap(hs.AdminProvisioningReloadPlugins))
|
||||
@@ -474,18 +470,18 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
r.Group("/api/admin/users", func(adminUserRoute routing.RouteRegister) {
|
||||
userIDScope := ac.Scope("global", "users", "id", ac.Parameter(":id"))
|
||||
|
||||
adminUserRoute.Post("/", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersCreate)), bind(dtos.AdminCreateUserForm{}), routing.Wrap(hs.AdminCreateUser))
|
||||
adminUserRoute.Put("/:id/password", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersPasswordUpdate, userIDScope)), bind(dtos.AdminUpdateUserPasswordForm{}), routing.Wrap(AdminUpdateUserPassword))
|
||||
adminUserRoute.Put("/:id/permissions", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersPermissionsUpdate, userIDScope)), bind(dtos.AdminUpdateUserPermissionsForm{}), routing.Wrap(hs.AdminUpdateUserPermissions))
|
||||
adminUserRoute.Post("/", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersCreate)), routing.Wrap(hs.AdminCreateUser))
|
||||
adminUserRoute.Put("/:id/password", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersPasswordUpdate, userIDScope)), routing.Wrap(AdminUpdateUserPassword))
|
||||
adminUserRoute.Put("/:id/permissions", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersPermissionsUpdate, userIDScope)), routing.Wrap(hs.AdminUpdateUserPermissions))
|
||||
adminUserRoute.Delete("/:id", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersDelete, userIDScope)), routing.Wrap(AdminDeleteUser))
|
||||
adminUserRoute.Post("/:id/disable", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersDisable, userIDScope)), routing.Wrap(hs.AdminDisableUser))
|
||||
adminUserRoute.Post("/:id/enable", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersEnable, userIDScope)), routing.Wrap(AdminEnableUser))
|
||||
adminUserRoute.Get("/:id/quotas", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersQuotasList, userIDScope)), routing.Wrap(GetUserQuotas))
|
||||
adminUserRoute.Put("/:id/quotas/:target", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersQuotasUpdate, userIDScope)), bind(models.UpdateUserQuotaCmd{}), routing.Wrap(UpdateUserQuota))
|
||||
adminUserRoute.Put("/:id/quotas/:target", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersQuotasUpdate, userIDScope)), routing.Wrap(UpdateUserQuota))
|
||||
|
||||
adminUserRoute.Post("/:id/logout", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersLogout, userIDScope)), routing.Wrap(hs.AdminLogoutUser))
|
||||
adminUserRoute.Get("/:id/auth-tokens", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersAuthTokenList, userIDScope)), routing.Wrap(hs.AdminGetUserAuthTokens))
|
||||
adminUserRoute.Post("/:id/revoke-auth-token", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersAuthTokenUpdate, userIDScope)), bind(models.RevokeAuthTokenCmd{}), routing.Wrap(hs.AdminRevokeUserAuthToken))
|
||||
adminUserRoute.Post("/:id/revoke-auth-token", authorize(reqGrafanaAdmin, ac.EvalPermission(ac.ActionUsersAuthTokenUpdate, userIDScope)), routing.Wrap(hs.AdminRevokeUserAuthToken))
|
||||
})
|
||||
|
||||
// rendering
|
||||
@@ -499,7 +495,7 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
r.Get("/avatar/:hash", avatarCacheServer.Handler)
|
||||
|
||||
// Snapshots
|
||||
r.Post("/api/snapshots/", reqSnapshotPublicModeOrSignedIn, bind(models.CreateDashboardSnapshotCommand{}), CreateDashboardSnapshot)
|
||||
r.Post("/api/snapshots/", reqSnapshotPublicModeOrSignedIn, CreateDashboardSnapshot)
|
||||
r.Get("/api/snapshot/shared-options/", reqSignedIn, GetSharingOptions)
|
||||
r.Get("/api/snapshots/:key", routing.Wrap(GetDashboardSnapshot))
|
||||
r.Get("/api/snapshots-delete/:deleteKey", reqSnapshotPublicModeOrSignedIn, routing.Wrap(DeleteDashboardSnapshotByDeleteKey))
|
||||
@@ -508,5 +504,5 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
// Frontend logs
|
||||
sourceMapStore := frontendlogging.NewSourceMapStore(hs.Cfg, hs.pluginStaticRouteResolver, frontendlogging.ReadSourceMapFromFS)
|
||||
r.Post("/log", middleware.RateLimit(hs.Cfg.Sentry.EndpointRPS, hs.Cfg.Sentry.EndpointBurst, time.Now),
|
||||
bind(frontendlogging.FrontendSentryEvent{}), routing.Wrap(NewFrontendLogMessageHandler(sourceMapStore)))
|
||||
routing.Wrap(NewFrontendLogMessageHandler(sourceMapStore)))
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
@@ -9,6 +10,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/apikeygen"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
// GetAPIKeys returns a list of API keys
|
||||
@@ -58,7 +60,11 @@ func DeleteAPIKey(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
// AddAPIKey adds an API key
|
||||
func (hs *HTTPServer) AddAPIKey(c *models.ReqContext, cmd models.AddApiKeyCommand) response.Response {
|
||||
func (hs *HTTPServer) AddAPIKey(c *models.ReqContext) response.Response {
|
||||
cmd := models.AddApiKeyCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if !cmd.Role.IsValid() {
|
||||
return response.Error(400, "Invalid role specified", nil)
|
||||
}
|
||||
@@ -129,7 +135,11 @@ func (hs *HTTPServer) AddAPIKey(c *models.ReqContext, cmd models.AddApiKeyComman
|
||||
}
|
||||
|
||||
// AddAPIKey adds an additional API key to a service account
|
||||
func (hs *HTTPServer) AdditionalAPIKey(c *models.ReqContext, cmd models.AddApiKeyCommand) response.Response {
|
||||
func (hs *HTTPServer) AdditionalAPIKey(c *models.ReqContext) response.Response {
|
||||
cmd := models.AddApiKeyCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if !hs.Cfg.FeatureToggles["service-accounts"] {
|
||||
return response.Error(500, "Requires services-accounts feature", errors.New("feature missing"))
|
||||
}
|
||||
@@ -137,5 +147,5 @@ func (hs *HTTPServer) AdditionalAPIKey(c *models.ReqContext, cmd models.AddApiKe
|
||||
return response.Error(500, "Can't create service account while adding additional API key", nil)
|
||||
}
|
||||
|
||||
return hs.AddAPIKey(c, cmd)
|
||||
return hs.AddAPIKey(c)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -52,10 +54,6 @@ func loggedInUserScenarioWithRole(t *testing.T, desc string, method string, url
|
||||
return sc.handlerFunc(sc.context)
|
||||
}
|
||||
|
||||
if sc.handlerFuncCtx != nil {
|
||||
return sc.handlerFuncCtx(context.Background(), sc.context)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -81,10 +79,6 @@ func anonymousUserScenario(t *testing.T, desc string, method string, url string,
|
||||
return sc.handlerFunc(sc.context)
|
||||
}
|
||||
|
||||
if sc.handlerFuncCtx != nil {
|
||||
return sc.handlerFuncCtx(context.Background(), sc.context)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -154,7 +148,6 @@ type scenarioContext struct {
|
||||
context *models.ReqContext
|
||||
resp *httptest.ResponseRecorder
|
||||
handlerFunc handlerFunc
|
||||
handlerFuncCtx handlerFuncCtx
|
||||
defaultHandler web.Handler
|
||||
req *http.Request
|
||||
url string
|
||||
@@ -167,7 +160,6 @@ func (sc *scenarioContext) exec() {
|
||||
|
||||
type scenarioFunc func(c *scenarioContext)
|
||||
type handlerFunc func(c *models.ReqContext) response.Response
|
||||
type handlerFuncCtx func(ctx context.Context, c *models.ReqContext) response.Response
|
||||
|
||||
func getContextHandler(t *testing.T, cfg *setting.Cfg) *contexthandler.ContextHandler {
|
||||
t.Helper()
|
||||
@@ -376,3 +368,8 @@ func callAPI(server *web.Mux, method, path string, body io.Reader, t *testing.T)
|
||||
server.ServeHTTP(recorder, req)
|
||||
return recorder
|
||||
}
|
||||
|
||||
func mockRequestBody(v interface{}) io.ReadCloser {
|
||||
b, _ := json.Marshal(v)
|
||||
return io.NopCloser(bytes.NewReader(b))
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
@@ -49,7 +50,11 @@ func dashboardGuardianResponse(err error) response.Response {
|
||||
return response.Error(403, "Access denied to this dashboard", nil)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) TrimDashboard(c *models.ReqContext, cmd models.TrimDashboardCommand) response.Response {
|
||||
func (hs *HTTPServer) TrimDashboard(c *models.ReqContext) response.Response {
|
||||
cmd := models.TrimDashboardCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
var err error
|
||||
dash := cmd.Dashboard
|
||||
meta := cmd.Meta
|
||||
@@ -277,7 +282,15 @@ func (hs *HTTPServer) deleteDashboard(c *models.ReqContext) response.Response {
|
||||
})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) PostDashboard(c *models.ReqContext, cmd models.SaveDashboardCommand) response.Response {
|
||||
func (hs *HTTPServer) PostDashboard(c *models.ReqContext) response.Response {
|
||||
cmd := models.SaveDashboardCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
return hs.postDashboard(c, cmd)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) postDashboard(c *models.ReqContext, cmd models.SaveDashboardCommand) response.Response {
|
||||
ctx := c.Req.Context()
|
||||
var err error
|
||||
cmd.OrgId = c.OrgId
|
||||
@@ -585,7 +598,11 @@ func GetDashboardVersion(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
// POST /api/dashboards/calculate-diff performs diffs on two dashboards
|
||||
func CalculateDashboardDiff(c *models.ReqContext, apiOptions dtos.CalculateDiffOptions) response.Response {
|
||||
func CalculateDashboardDiff(c *models.ReqContext) response.Response {
|
||||
apiOptions := dtos.CalculateDiffOptions{}
|
||||
if err := web.Bind(c.Req, &apiOptions); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
guardianBase := guardian.New(c.Req.Context(), apiOptions.Base.DashboardId, c.OrgId, c.SignedInUser)
|
||||
if canSave, err := guardianBase.CanSave(); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
@@ -629,7 +646,11 @@ func CalculateDashboardDiff(c *models.ReqContext, apiOptions dtos.CalculateDiffO
|
||||
}
|
||||
|
||||
// RestoreDashboardVersion restores a dashboard to the given version.
|
||||
func (hs *HTTPServer) RestoreDashboardVersion(c *models.ReqContext, apiCmd dtos.RestoreDashboardVersionCommand) response.Response {
|
||||
func (hs *HTTPServer) RestoreDashboardVersion(c *models.ReqContext) response.Response {
|
||||
apiCmd := dtos.RestoreDashboardVersionCommand{}
|
||||
if err := web.Bind(c.Req, &apiCmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
dash, rsp := getDashboardHelper(c.Req.Context(), c.OrgId, c.ParamsInt64(":dashboardId"), "")
|
||||
if rsp != nil {
|
||||
return rsp
|
||||
@@ -657,7 +678,7 @@ func (hs *HTTPServer) RestoreDashboardVersion(c *models.ReqContext, apiCmd dtos.
|
||||
saveCmd.Message = fmt.Sprintf("Restored from version %d", version.Version)
|
||||
saveCmd.FolderId = dash.FolderId
|
||||
|
||||
return hs.PostDashboard(c, saveCmd)
|
||||
return hs.postDashboard(c, saveCmd)
|
||||
}
|
||||
|
||||
func GetDashboardTags(c *models.ReqContext) {
|
||||
|
||||
@@ -2,12 +2,14 @@ package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
func (hs *HTTPServer) GetDashboardPermissionList(c *models.ReqContext) response.Response {
|
||||
@@ -50,7 +52,11 @@ func (hs *HTTPServer) GetDashboardPermissionList(c *models.ReqContext) response.
|
||||
return response.JSON(200, filteredAcls)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateDashboardPermissions(c *models.ReqContext, apiCmd dtos.UpdateDashboardAclCommand) response.Response {
|
||||
func (hs *HTTPServer) UpdateDashboardPermissions(c *models.ReqContext) response.Response {
|
||||
apiCmd := dtos.UpdateDashboardAclCommand{}
|
||||
if err := web.Bind(c.Req, &apiCmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if err := validatePermissionsUpdate(apiCmd); err != nil {
|
||||
return response.Error(400, err.Error(), err)
|
||||
}
|
||||
|
||||
@@ -433,11 +433,12 @@ func updateDashboardPermissionScenario(t *testing.T, ctx updatePermissionContext
|
||||
sc := setupScenarioContext(t, ctx.url)
|
||||
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(ctx.cmd)
|
||||
sc.context = c
|
||||
sc.context.OrgId = testOrgID
|
||||
sc.context.UserId = testUserID
|
||||
|
||||
return hs.UpdateDashboardPermissions(c, ctx.cmd)
|
||||
return hs.UpdateDashboardPermissions(c)
|
||||
})
|
||||
|
||||
sc.m.Post(ctx.routePattern, sc.defaultHandler)
|
||||
|
||||
@@ -1122,10 +1122,11 @@ func postDashboardScenario(t *testing.T, desc string, url string, routePattern s
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.SignedInUser = &models.SignedInUser{OrgId: cmd.OrgId, UserId: cmd.UserId}
|
||||
|
||||
return hs.PostDashboard(c, cmd)
|
||||
return hs.PostDashboard(c)
|
||||
})
|
||||
|
||||
origNewDashboardService := dashboards.NewService
|
||||
@@ -1154,6 +1155,7 @@ func postDiffScenario(t *testing.T, desc string, url string, routePattern string
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.SignedInUser = &models.SignedInUser{
|
||||
OrgId: testOrgID,
|
||||
@@ -1161,7 +1163,7 @@ func postDiffScenario(t *testing.T, desc string, url string, routePattern string
|
||||
}
|
||||
sc.context.OrgRole = role
|
||||
|
||||
return CalculateDashboardDiff(c, cmd)
|
||||
return CalculateDashboardDiff(c)
|
||||
})
|
||||
|
||||
sc.m.Post(routePattern, sc.defaultHandler)
|
||||
@@ -1188,6 +1190,7 @@ func restoreDashboardVersionScenario(t *testing.T, desc string, url string, rout
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.SignedInUser = &models.SignedInUser{
|
||||
OrgId: testOrgID,
|
||||
@@ -1195,7 +1198,7 @@ func restoreDashboardVersionScenario(t *testing.T, desc string, url string, rout
|
||||
}
|
||||
sc.context.OrgRole = models.ROLE_ADMIN
|
||||
|
||||
return hs.RestoreDashboardVersion(c, cmd)
|
||||
return hs.RestoreDashboardVersion(c)
|
||||
})
|
||||
|
||||
origProvisioningService := dashboards.NewProvisioningService
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sort"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
@@ -211,7 +212,11 @@ func validateURL(tp string, u string) response.Response {
|
||||
return nil
|
||||
}
|
||||
|
||||
func AddDataSource(c *models.ReqContext, cmd models.AddDataSourceCommand) response.Response {
|
||||
func AddDataSource(c *models.ReqContext) response.Response {
|
||||
cmd := models.AddDataSourceCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
datasourcesLogger.Debug("Received command to add data source", "url", cmd.Url)
|
||||
cmd.OrgId = c.OrgId
|
||||
if resp := validateURL(cmd.Type, cmd.Url); resp != nil {
|
||||
@@ -235,7 +240,11 @@ func AddDataSource(c *models.ReqContext, cmd models.AddDataSourceCommand) respon
|
||||
})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateDataSource(c *models.ReqContext, cmd models.UpdateDataSourceCommand) response.Response {
|
||||
func (hs *HTTPServer) UpdateDataSource(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateDataSourceCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
datasourcesLogger.Debug("Received command to update data source", "url", cmd.Url)
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.Id = c.ParamsInt64(":id")
|
||||
|
||||
@@ -80,10 +80,13 @@ func TestAddDataSource_InvalidURL(t *testing.T) {
|
||||
sc := setupScenarioContext(t, "/api/datasources")
|
||||
|
||||
sc.m.Post(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
return AddDataSource(c, models.AddDataSourceCommand{
|
||||
Name: "Test",
|
||||
Url: "invalid:url",
|
||||
c.Req.Body = mockRequestBody(models.AddDataSourceCommand{
|
||||
Name: "Test",
|
||||
Url: "invalid:url",
|
||||
Access: "direct",
|
||||
Type: "test",
|
||||
})
|
||||
return AddDataSource(c)
|
||||
}))
|
||||
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
@@ -110,10 +113,13 @@ func TestAddDataSource_URLWithoutProtocol(t *testing.T) {
|
||||
sc := setupScenarioContext(t, "/api/datasources")
|
||||
|
||||
sc.m.Post(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
return AddDataSource(c, models.AddDataSourceCommand{
|
||||
Name: name,
|
||||
Url: url,
|
||||
c.Req.Body = mockRequestBody(models.AddDataSourceCommand{
|
||||
Name: name,
|
||||
Url: url,
|
||||
Access: "direct",
|
||||
Type: "test",
|
||||
})
|
||||
return AddDataSource(c)
|
||||
}))
|
||||
|
||||
sc.fakeReqWithParams("POST", sc.url, map[string]string{}).exec()
|
||||
@@ -128,10 +134,13 @@ func TestUpdateDataSource_InvalidURL(t *testing.T) {
|
||||
sc := setupScenarioContext(t, "/api/datasources/1234")
|
||||
|
||||
sc.m.Put(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
return AddDataSource(c, models.AddDataSourceCommand{
|
||||
Name: "Test",
|
||||
Url: "invalid:url",
|
||||
c.Req.Body = mockRequestBody(models.AddDataSourceCommand{
|
||||
Name: "Test",
|
||||
Url: "invalid:url",
|
||||
Access: "direct",
|
||||
Type: "test",
|
||||
})
|
||||
return AddDataSource(c)
|
||||
}))
|
||||
|
||||
sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
|
||||
@@ -158,10 +167,13 @@ func TestUpdateDataSource_URLWithoutProtocol(t *testing.T) {
|
||||
sc := setupScenarioContext(t, "/api/datasources/1234")
|
||||
|
||||
sc.m.Put(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
return AddDataSource(c, models.AddDataSourceCommand{
|
||||
Name: name,
|
||||
Url: url,
|
||||
c.Req.Body = mockRequestBody(models.AddDataSourceCommand{
|
||||
Name: name,
|
||||
Url: url,
|
||||
Access: "direct",
|
||||
Type: "test",
|
||||
})
|
||||
return AddDataSource(c)
|
||||
}))
|
||||
|
||||
sc.fakeReqWithParams("PUT", sc.url, map[string]string{}).exec()
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/apierrors"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
@@ -59,7 +60,11 @@ func (hs *HTTPServer) GetFolderByID(c *models.ReqContext) response.Response {
|
||||
return response.JSON(200, toFolderDto(c.Req.Context(), g, folder))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) CreateFolder(c *models.ReqContext, cmd models.CreateFolderCommand) response.Response {
|
||||
func (hs *HTTPServer) CreateFolder(c *models.ReqContext) response.Response {
|
||||
cmd := models.CreateFolderCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore)
|
||||
folder, err := s.CreateFolder(c.Req.Context(), cmd.Title, cmd.Uid)
|
||||
if err != nil {
|
||||
@@ -77,7 +82,11 @@ func (hs *HTTPServer) CreateFolder(c *models.ReqContext, cmd models.CreateFolder
|
||||
return response.JSON(200, toFolderDto(c.Req.Context(), g, folder))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateFolder(c *models.ReqContext, cmd models.UpdateFolderCommand) response.Response {
|
||||
func (hs *HTTPServer) UpdateFolder(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateFolderCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore)
|
||||
err := s.UpdateFolder(c.Req.Context(), web.Params(c.Req)[":uid"], &cmd)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/apierrors"
|
||||
@@ -58,7 +59,11 @@ func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Res
|
||||
return response.JSON(200, filteredAcls)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext, apiCmd dtos.UpdateDashboardAclCommand) response.Response {
|
||||
func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext) response.Response {
|
||||
apiCmd := dtos.UpdateDashboardAclCommand{}
|
||||
if err := web.Bind(c.Req, &apiCmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if err := validatePermissionsUpdate(apiCmd); err != nil {
|
||||
return response.Error(400, err.Error(), err)
|
||||
}
|
||||
|
||||
@@ -402,11 +402,12 @@ func updateFolderPermissionScenario(t *testing.T, ctx updatePermissionContext, h
|
||||
sc := setupScenarioContext(t, ctx.url)
|
||||
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(ctx.cmd)
|
||||
sc.context = c
|
||||
sc.context.OrgId = testOrgID
|
||||
sc.context.UserId = testUserID
|
||||
|
||||
return hs.UpdateFolderPermissions(c, ctx.cmd)
|
||||
return hs.UpdateFolderPermissions(c)
|
||||
})
|
||||
|
||||
sc.m.Post(ctx.routePattern, sc.defaultHandler)
|
||||
|
||||
@@ -148,10 +148,11 @@ func createFolderScenario(t *testing.T, desc string, url string, routePattern st
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.SignedInUser = &models.SignedInUser{OrgId: testOrgID, UserId: testUserID}
|
||||
|
||||
return hs.CreateFolder(c, cmd)
|
||||
return hs.CreateFolder(c)
|
||||
})
|
||||
|
||||
origNewFolderService := dashboards.NewFolderService
|
||||
@@ -182,10 +183,11 @@ func updateFolderScenario(t *testing.T, desc string, url string, routePattern st
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.SignedInUser = &models.SignedInUser{OrgId: testOrgID, UserId: testUserID}
|
||||
|
||||
return hs.UpdateFolder(c, cmd)
|
||||
return hs.UpdateFolder(c)
|
||||
})
|
||||
|
||||
origNewFolderService := dashboards.NewFolderService
|
||||
|
||||
@@ -1,19 +1,27 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/getsentry/sentry-go"
|
||||
"github.com/grafana/grafana/pkg/api/frontendlogging"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
var frontendLogger = log.New("frontend")
|
||||
|
||||
type frontendLogMessageHandler func(c *models.ReqContext, event frontendlogging.FrontendSentryEvent) response.Response
|
||||
type frontendLogMessageHandler func(c *models.ReqContext) response.Response
|
||||
|
||||
func NewFrontendLogMessageHandler(store *frontendlogging.SourceMapStore) frontendLogMessageHandler {
|
||||
return func(c *models.ReqContext, event frontendlogging.FrontendSentryEvent) response.Response {
|
||||
return func(c *models.ReqContext) response.Response {
|
||||
event := frontendlogging.FrontendSentryEvent{}
|
||||
if err := web.Bind(c.Req, &event); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
|
||||
var msg = "unknown"
|
||||
|
||||
if len(event.Message) > 0 {
|
||||
|
||||
@@ -3,7 +3,6 @@ package api
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
@@ -84,9 +83,10 @@ func logSentryEventScenario(t *testing.T, desc string, event frontendlogging.Fro
|
||||
|
||||
loggingHandler := NewFrontendLogMessageHandler(sourceMapStore)
|
||||
|
||||
handler := routing.Wrap(func(w http.ResponseWriter, c *models.ReqContext) response.Response {
|
||||
handler := routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
return loggingHandler(c, event)
|
||||
c.Req.Body = mockRequestBody(event)
|
||||
return loggingHandler(c)
|
||||
})
|
||||
|
||||
sc.m.Post(sc.url, handler)
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
func (hs *HTTPServer) PostFrontendMetrics(c *models.ReqContext, cmd metrics.PostFrontendMetricsCommand) response.Response {
|
||||
func (hs *HTTPServer) PostFrontendMetrics(c *models.ReqContext) response.Response {
|
||||
cmd := metrics.PostFrontendMetricsCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
for _, event := range cmd.Events {
|
||||
name := strings.Replace(event.Name, "-", "_", -1)
|
||||
if recorder, ok := metrics.FrontendMetrics[name]; ok {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package frontendlogging
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
@@ -93,3 +94,16 @@ func (event *FrontendSentryEvent) ToLogContext(store *SourceMapStore) log15.Ctx
|
||||
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (event *FrontendSentryEvent) MarshalJSON() ([]byte, error) {
|
||||
eventJSON, err := json.Marshal(event.Event)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exceptionJSON, err := json.Marshal(map[string]interface{}{"exception": event.Exception})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
exceptionJSON[0] = ','
|
||||
return append(eventJSON[:len(eventJSON)-1], exceptionJSON...), nil
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ func (user *LDAPUserDTO) FetchOrgs(ctx context.Context) error {
|
||||
}
|
||||
|
||||
// ReloadLDAPCfg reloads the LDAP configuration
|
||||
func (hs *HTTPServer) ReloadLDAPCfg() response.Response {
|
||||
func (hs *HTTPServer) ReloadLDAPCfg(c *models.ReqContext) response.Response {
|
||||
if !ldap.IsEnabled() {
|
||||
return response.Error(http.StatusBadRequest, "LDAP is not enabled", nil)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
@@ -67,7 +68,7 @@ func genPKCECode() (string, string, error) {
|
||||
return string(ascii), pkce, nil
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) response.Response {
|
||||
loginInfo := models.LoginInfo{
|
||||
AuthModule: "oauth",
|
||||
}
|
||||
@@ -79,7 +80,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
HttpStatus: http.StatusNotFound,
|
||||
PublicMessage: "OAuth not enabled",
|
||||
})
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
connect, err := hs.SocialService.GetConnector(name)
|
||||
@@ -88,7 +89,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
HttpStatus: http.StatusNotFound,
|
||||
PublicMessage: fmt.Sprintf("No OAuth with name %s configured", name),
|
||||
})
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
errorParam := ctx.Query("error")
|
||||
@@ -96,7 +97,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
errorDesc := ctx.Query("error_description")
|
||||
oauthLogger.Error("failed to login ", "error", errorParam, "errorDesc", errorDesc)
|
||||
hs.handleOAuthLoginErrorWithRedirect(ctx, loginInfo, login.ErrProviderDeniedRequest, "error", errorParam, "errorDesc", errorDesc)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
code := ctx.Query("code")
|
||||
@@ -128,7 +129,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
HttpStatus: http.StatusInternalServerError,
|
||||
PublicMessage: "An internal error occurred",
|
||||
})
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
hashedState := hashStatecode(state, provider.ClientSecret)
|
||||
@@ -138,7 +139,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
}
|
||||
|
||||
ctx.Redirect(connect.AuthCodeURL(state, opts...))
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
cookieState := ctx.GetCookie(OauthStateCookieName)
|
||||
@@ -151,7 +152,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
HttpStatus: http.StatusInternalServerError,
|
||||
PublicMessage: "login.OAuthLogin(missing saved state)",
|
||||
})
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
queryState := hashStatecode(ctx.Query("state"), provider.ClientSecret)
|
||||
@@ -161,7 +162,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
HttpStatus: http.StatusInternalServerError,
|
||||
PublicMessage: "login.OAuthLogin(state mismatch)",
|
||||
})
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
oauthClient, err := hs.SocialService.GetOAuthHttpClient(name)
|
||||
@@ -171,7 +172,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
HttpStatus: http.StatusInternalServerError,
|
||||
PublicMessage: "login.OAuthLogin(" + err.Error() + ")",
|
||||
})
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
oauthCtx := context.WithValue(context.Background(), oauth2.HTTPClient, oauthClient)
|
||||
@@ -193,7 +194,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
PublicMessage: "login.OAuthLogin(NewTransportWithCode)",
|
||||
Err: err,
|
||||
})
|
||||
return
|
||||
return nil
|
||||
}
|
||||
// token.TokenType was defaulting to "bearer", which is out of spec, so we explicitly set to "Bearer"
|
||||
token.TokenType = "Bearer"
|
||||
@@ -216,7 +217,7 @@ func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
Err: err,
|
||||
})
|
||||
}
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
oauthLogger.Debug("OAuthLogin got user info", "userInfo", userInfo)
|
||||
@@ -224,26 +225,26 @@ func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
// validate that we got at least an email address
|
||||
if userInfo.Email == "" {
|
||||
hs.handleOAuthLoginErrorWithRedirect(ctx, loginInfo, login.ErrNoEmail)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// validate that the email is allowed to login to grafana
|
||||
if !connect.IsEmailAllowed(userInfo.Email) {
|
||||
hs.handleOAuthLoginErrorWithRedirect(ctx, loginInfo, login.ErrEmailNotAllowed)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
loginInfo.ExternalUser = *buildExternalUserInfo(token, userInfo, name)
|
||||
loginInfo.User, err = syncUser(ctx, &loginInfo.ExternalUser, connect)
|
||||
if err != nil {
|
||||
hs.handleOAuthLoginErrorWithRedirect(ctx, loginInfo, err)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
// login
|
||||
if err := hs.loginUserWithUser(loginInfo.User, ctx); err != nil {
|
||||
hs.handleOAuthLoginErrorWithRedirect(ctx, loginInfo, err)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
|
||||
loginInfo.HTTPStatus = http.StatusOK
|
||||
@@ -254,12 +255,13 @@ func (hs *HTTPServer) OAuthLogin(ctx *models.ReqContext) {
|
||||
if err := hs.ValidateRedirectTo(redirectTo); err == nil {
|
||||
cookies.DeleteCookie(ctx.Resp, "redirect_to", hs.CookieOptionsFromCfg)
|
||||
ctx.Redirect(redirectTo)
|
||||
return
|
||||
return nil
|
||||
}
|
||||
ctx.Logger.Debug("Ignored invalid redirect_to cookie value", "redirect_to", redirectTo)
|
||||
}
|
||||
|
||||
ctx.Redirect(setting.AppSubUrl + "/")
|
||||
return nil
|
||||
}
|
||||
|
||||
// buildExternalUserInfo returns a ExternalUserInfo struct from OAuth user profile
|
||||
|
||||
@@ -118,8 +118,9 @@ func TestLoginErrorCookieAPIEndpoint(t *testing.T) {
|
||||
SecretsService: secretsService,
|
||||
}
|
||||
|
||||
sc.defaultHandler = routing.Wrap(func(w http.ResponseWriter, c *models.ReqContext) {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
hs.LoginView(c)
|
||||
return response.Empty(http.StatusOK)
|
||||
})
|
||||
|
||||
cfg.LoginCookieName = "grafana_session"
|
||||
@@ -166,12 +167,13 @@ func TestLoginViewRedirect(t *testing.T) {
|
||||
}
|
||||
hs.Cfg.CookieSecure = true
|
||||
|
||||
sc.defaultHandler = routing.Wrap(func(w http.ResponseWriter, c *models.ReqContext) {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.IsSignedIn = true
|
||||
c.SignedInUser = &models.SignedInUser{
|
||||
UserId: 10,
|
||||
}
|
||||
hs.LoginView(c)
|
||||
return response.Empty(http.StatusOK)
|
||||
})
|
||||
|
||||
redirectCases := []redirectCase{
|
||||
@@ -340,7 +342,7 @@ func TestLoginPostRedirect(t *testing.T) {
|
||||
}
|
||||
hs.Cfg.CookieSecure = true
|
||||
|
||||
sc.defaultHandler = routing.Wrap(func(w http.ResponseWriter, c *models.ReqContext) response.Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Header.Set("Content-Type", "application/json")
|
||||
c.Req.Body = io.NopCloser(bytes.NewBufferString(`{"user":"admin","password":"admin"}`))
|
||||
return hs.LoginPost(c)
|
||||
@@ -504,8 +506,9 @@ func TestLoginOAuthRedirect(t *testing.T) {
|
||||
SocialService: mock,
|
||||
}
|
||||
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
hs.LoginView(c)
|
||||
return response.Empty(http.StatusOK)
|
||||
})
|
||||
|
||||
setting.OAuthAutoLogin = true
|
||||
@@ -529,9 +532,10 @@ func TestLoginInternal(t *testing.T) {
|
||||
log: log.New("test"),
|
||||
}
|
||||
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.URL.RawQuery = "disableAutoLogin=true"
|
||||
hs.LoginView(c)
|
||||
return response.Empty(http.StatusOK)
|
||||
})
|
||||
|
||||
setting.OAuthAutoLogin = true
|
||||
@@ -580,12 +584,13 @@ func setupAuthProxyLoginTest(t *testing.T, enableLoginToken bool) *scenarioConte
|
||||
SocialService: &mockSocialService{},
|
||||
}
|
||||
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.IsSignedIn = true
|
||||
c.SignedInUser = &models.SignedInUser{
|
||||
UserId: 10,
|
||||
}
|
||||
hs.LoginView(c)
|
||||
return response.Empty(http.StatusOK)
|
||||
})
|
||||
|
||||
sc.cfg.AuthProxyEnabled = true
|
||||
@@ -616,7 +621,7 @@ func TestLoginPostRunLokingHook(t *testing.T) {
|
||||
HooksService: hookService,
|
||||
}
|
||||
|
||||
sc.defaultHandler = routing.Wrap(func(w http.ResponseWriter, c *models.ReqContext) response.Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Header.Set("Content-Type", "application/json")
|
||||
c.Req.Body = io.NopCloser(bytes.NewBufferString(`{"user":"admin","password":"admin"}`))
|
||||
x := hs.LoginPost(c)
|
||||
|
||||
@@ -16,11 +16,16 @@ import (
|
||||
"github.com/grafana/grafana/pkg/plugins/adapters"
|
||||
"github.com/grafana/grafana/pkg/tsdb/grafanads"
|
||||
"github.com/grafana/grafana/pkg/tsdb/legacydata"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
// QueryMetricsV2 returns query metrics.
|
||||
// POST /api/ds/query DataSource query w/ expressions
|
||||
func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext, reqDTO dtos.MetricRequest) response.Response {
|
||||
func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext) response.Response {
|
||||
reqDTO := dtos.MetricRequest{}
|
||||
if err := web.Bind(c.Req, &reqDTO); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if len(reqDTO.Queries) == 0 {
|
||||
return response.Error(http.StatusBadRequest, "No queries found in query", nil)
|
||||
}
|
||||
@@ -162,7 +167,11 @@ func (hs *HTTPServer) handleGetDataSourceError(err error, datasourceRef interfac
|
||||
|
||||
// QueryMetrics returns query metrics
|
||||
// POST /api/tsdb/query
|
||||
func (hs *HTTPServer) QueryMetrics(c *models.ReqContext, reqDto dtos.MetricRequest) response.Response {
|
||||
func (hs *HTTPServer) QueryMetrics(c *models.ReqContext) response.Response {
|
||||
reqDto := dtos.MetricRequest{}
|
||||
if err := web.Bind(c.Req, &reqDto); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if len(reqDto.Queries) == 0 {
|
||||
return response.Error(http.StatusBadRequest, "No queries found in query", nil)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
@@ -78,7 +79,11 @@ func getOrgHelper(ctx context.Context, orgID int64) response.Response {
|
||||
}
|
||||
|
||||
// POST /api/orgs
|
||||
func (hs *HTTPServer) CreateOrg(c *models.ReqContext, cmd models.CreateOrgCommand) response.Response {
|
||||
func (hs *HTTPServer) CreateOrg(c *models.ReqContext) response.Response {
|
||||
cmd := models.CreateOrgCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
acEnabled := hs.Cfg.FeatureToggles["accesscontrol"]
|
||||
if !acEnabled && !(setting.AllowUserOrgCreate || c.IsGrafanaAdmin) {
|
||||
return response.Error(403, "Access denied", nil)
|
||||
@@ -101,12 +106,20 @@ func (hs *HTTPServer) CreateOrg(c *models.ReqContext, cmd models.CreateOrgComman
|
||||
}
|
||||
|
||||
// PUT /api/org
|
||||
func UpdateCurrentOrg(c *models.ReqContext, form dtos.UpdateOrgForm) response.Response {
|
||||
func UpdateCurrentOrg(c *models.ReqContext) response.Response {
|
||||
form := dtos.UpdateOrgForm{}
|
||||
if err := web.Bind(c.Req, &form); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
return updateOrgHelper(c.Req.Context(), form, c.OrgId)
|
||||
}
|
||||
|
||||
// PUT /api/orgs/:orgId
|
||||
func UpdateOrg(c *models.ReqContext, form dtos.UpdateOrgForm) response.Response {
|
||||
func UpdateOrg(c *models.ReqContext) response.Response {
|
||||
form := dtos.UpdateOrgForm{}
|
||||
if err := web.Bind(c.Req, &form); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
return updateOrgHelper(c.Req.Context(), form, c.ParamsInt64(":orgId"))
|
||||
}
|
||||
|
||||
@@ -123,12 +136,20 @@ func updateOrgHelper(ctx context.Context, form dtos.UpdateOrgForm, orgID int64)
|
||||
}
|
||||
|
||||
// PUT /api/org/address
|
||||
func UpdateCurrentOrgAddress(c *models.ReqContext, form dtos.UpdateOrgAddressForm) response.Response {
|
||||
func UpdateCurrentOrgAddress(c *models.ReqContext) response.Response {
|
||||
form := dtos.UpdateOrgAddressForm{}
|
||||
if err := web.Bind(c.Req, &form); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
return updateOrgAddressHelper(c.Req.Context(), form, c.OrgId)
|
||||
}
|
||||
|
||||
// PUT /api/orgs/:orgId/address
|
||||
func UpdateOrgAddress(c *models.ReqContext, form dtos.UpdateOrgAddressForm) response.Response {
|
||||
func UpdateOrgAddress(c *models.ReqContext) response.Response {
|
||||
form := dtos.UpdateOrgAddressForm{}
|
||||
if err := web.Bind(c.Req, &form); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
return updateOrgAddressHelper(c.Req.Context(), form, c.ParamsInt64(":orgId"))
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
@@ -30,7 +31,11 @@ func GetPendingOrgInvites(c *models.ReqContext) response.Response {
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
func AddOrgInvite(c *models.ReqContext, inviteDto dtos.AddInviteForm) response.Response {
|
||||
func AddOrgInvite(c *models.ReqContext) response.Response {
|
||||
inviteDto := dtos.AddInviteForm{}
|
||||
if err := web.Bind(c.Req, &inviteDto); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if !inviteDto.Role.IsValid() {
|
||||
return response.Error(400, "Invalid role specified", nil)
|
||||
}
|
||||
@@ -165,7 +170,11 @@ func GetInviteInfoByCode(c *models.ReqContext) response.Response {
|
||||
})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) CompleteInvite(c *models.ReqContext, completeInvite dtos.CompleteInviteForm) response.Response {
|
||||
func (hs *HTTPServer) CompleteInvite(c *models.ReqContext) response.Response {
|
||||
completeInvite := dtos.CompleteInviteForm{}
|
||||
if err := web.Bind(c.Req, &completeInvite); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
query := models.GetTempUserByCodeQuery{Code: completeInvite.InviteCode}
|
||||
|
||||
if err := bus.DispatchCtx(c.Req.Context(), &query); err != nil {
|
||||
|
||||
@@ -3,21 +3,31 @@ package api
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
// POST /api/org/users
|
||||
func (hs *HTTPServer) AddOrgUserToCurrentOrg(c *models.ReqContext, cmd models.AddOrgUserCommand) response.Response {
|
||||
func (hs *HTTPServer) AddOrgUserToCurrentOrg(c *models.ReqContext) response.Response {
|
||||
cmd := models.AddOrgUserCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.OrgId = c.OrgId
|
||||
return hs.addOrgUserHelper(c.Req.Context(), cmd)
|
||||
}
|
||||
|
||||
// POST /api/orgs/:orgId/users
|
||||
func (hs *HTTPServer) AddOrgUser(c *models.ReqContext, cmd models.AddOrgUserCommand) response.Response {
|
||||
func (hs *HTTPServer) AddOrgUser(c *models.ReqContext) response.Response {
|
||||
cmd := models.AddOrgUserCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.OrgId = c.ParamsInt64(":orgId")
|
||||
return hs.addOrgUserHelper(c.Req.Context(), cmd)
|
||||
}
|
||||
@@ -128,7 +138,8 @@ func (hs *HTTPServer) getOrgUsersHelper(ctx context.Context, query *models.GetOr
|
||||
|
||||
// SearchOrgUsersWithPaging is an HTTP handler to search for org users with paging.
|
||||
// GET /api/org/users/search
|
||||
func (hs *HTTPServer) SearchOrgUsersWithPaging(ctx context.Context, c *models.ReqContext) response.Response {
|
||||
func (hs *HTTPServer) SearchOrgUsersWithPaging(c *models.ReqContext) response.Response {
|
||||
ctx := c.Req.Context()
|
||||
perPage := c.QueryInt("perpage")
|
||||
if perPage <= 0 {
|
||||
perPage = 1000
|
||||
@@ -168,14 +179,22 @@ func (hs *HTTPServer) SearchOrgUsersWithPaging(ctx context.Context, c *models.Re
|
||||
}
|
||||
|
||||
// PATCH /api/org/users/:userId
|
||||
func (hs *HTTPServer) UpdateOrgUserForCurrentOrg(c *models.ReqContext, cmd models.UpdateOrgUserCommand) response.Response {
|
||||
func (hs *HTTPServer) UpdateOrgUserForCurrentOrg(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateOrgUserCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.UserId = c.ParamsInt64(":userId")
|
||||
return hs.updateOrgUserHelper(c.Req.Context(), cmd)
|
||||
}
|
||||
|
||||
// PATCH /api/orgs/:orgId/users/:userId
|
||||
func (hs *HTTPServer) UpdateOrgUser(c *models.ReqContext, cmd models.UpdateOrgUserCommand) response.Response {
|
||||
func (hs *HTTPServer) UpdateOrgUser(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateOrgUserCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.OrgId = c.ParamsInt64(":orgId")
|
||||
cmd.UserId = c.ParamsInt64(":userId")
|
||||
return hs.updateOrgUserHelper(c.Req.Context(), cmd)
|
||||
|
||||
@@ -57,7 +57,7 @@ func TestOrgUsersAPIEndpoint_userLoggedIn(t *testing.T) {
|
||||
loggedInUserScenario(t, "When calling GET on", "api/org/users/search", func(sc *scenarioContext) {
|
||||
setUpGetOrgUsersDB(t, sqlStore)
|
||||
|
||||
sc.handlerFuncCtx = hs.SearchOrgUsersWithPaging
|
||||
sc.handlerFunc = hs.SearchOrgUsersWithPaging
|
||||
sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec()
|
||||
|
||||
require.Equal(t, http.StatusOK, sc.resp.Code)
|
||||
@@ -75,7 +75,7 @@ func TestOrgUsersAPIEndpoint_userLoggedIn(t *testing.T) {
|
||||
loggedInUserScenario(t, "When calling GET with page and limit query parameters on", "api/org/users/search", func(sc *scenarioContext) {
|
||||
setUpGetOrgUsersDB(t, sqlStore)
|
||||
|
||||
sc.handlerFuncCtx = hs.SearchOrgUsersWithPaging
|
||||
sc.handlerFunc = hs.SearchOrgUsersWithPaging
|
||||
sc.fakeReqWithParams("GET", sc.url, map[string]string{"perpage": "2", "page": "2"}).exec()
|
||||
|
||||
require.Equal(t, http.StatusOK, sc.resp.Code)
|
||||
|
||||
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
@@ -9,9 +10,14 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
func SendResetPasswordEmail(c *models.ReqContext, form dtos.SendResetPasswordEmailForm) response.Response {
|
||||
func SendResetPasswordEmail(c *models.ReqContext) response.Response {
|
||||
form := dtos.SendResetPasswordEmailForm{}
|
||||
if err := web.Bind(c.Req, &form); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if setting.LDAPEnabled || setting.AuthProxyEnabled {
|
||||
return response.Error(401, "Not allowed to reset password when LDAP or Auth Proxy is enabled", nil)
|
||||
}
|
||||
@@ -34,7 +40,11 @@ func SendResetPasswordEmail(c *models.ReqContext, form dtos.SendResetPasswordEma
|
||||
return response.Success("Email sent")
|
||||
}
|
||||
|
||||
func ResetPassword(c *models.ReqContext, form dtos.ResetUserPasswordForm) response.Response {
|
||||
func ResetPassword(c *models.ReqContext) response.Response {
|
||||
form := dtos.ResetUserPasswordForm{}
|
||||
if err := web.Bind(c.Req, &form); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
query := models.ValidateResetPasswordCodeQuery{Code: form.Code}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
|
||||
@@ -2,10 +2,12 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
func ValidateOrgPlaylist(c *models.ReqContext) {
|
||||
@@ -138,7 +140,11 @@ func DeletePlaylist(c *models.ReqContext) response.Response {
|
||||
return response.JSON(200, "")
|
||||
}
|
||||
|
||||
func CreatePlaylist(c *models.ReqContext, cmd models.CreatePlaylistCommand) response.Response {
|
||||
func CreatePlaylist(c *models.ReqContext) response.Response {
|
||||
cmd := models.CreatePlaylistCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
if err := bus.DispatchCtx(c.Req.Context(), &cmd); err != nil {
|
||||
@@ -148,7 +154,11 @@ func CreatePlaylist(c *models.ReqContext, cmd models.CreatePlaylistCommand) resp
|
||||
return response.JSON(200, cmd.Result)
|
||||
}
|
||||
|
||||
func UpdatePlaylist(c *models.ReqContext, cmd models.UpdatePlaylistCommand) response.Response {
|
||||
func UpdatePlaylist(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdatePlaylistCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.Id = c.ParamsInt64(":id")
|
||||
|
||||
|
||||
@@ -149,7 +149,11 @@ func (hs *HTTPServer) GetPluginSettingByID(c *models.ReqContext) response.Respon
|
||||
return response.JSON(200, dto)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdatePluginSetting(c *models.ReqContext, cmd models.UpdatePluginSettingCmd) response.Response {
|
||||
func (hs *HTTPServer) UpdatePluginSetting(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdatePluginSettingCmd{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
pluginID := web.Params(c.Req)[":pluginId"]
|
||||
|
||||
if _, exists := hs.pluginStore.Plugin(c.Req.Context(), pluginID); !exists {
|
||||
@@ -208,7 +212,11 @@ func (hs *HTTPServer) GetPluginMarkdown(c *models.ReqContext) response.Response
|
||||
return resp
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) ImportDashboard(c *models.ReqContext, apiCmd dtos.ImportDashboardCommand) response.Response {
|
||||
func (hs *HTTPServer) ImportDashboard(c *models.ReqContext) response.Response {
|
||||
apiCmd := dtos.ImportDashboardCommand{}
|
||||
if err := web.Bind(c.Req, &apiCmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
var err error
|
||||
if apiCmd.PluginId == "" && apiCmd.Dashboard == nil {
|
||||
return response.Error(422, "Dashboard must be set", nil)
|
||||
@@ -387,7 +395,11 @@ func (hs *HTTPServer) GetPluginErrorsList(_ *models.ReqContext) response.Respons
|
||||
return response.JSON(200, hs.pluginErrorResolver.PluginErrors())
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) InstallPlugin(c *models.ReqContext, dto dtos.InstallPluginCommand) response.Response {
|
||||
func (hs *HTTPServer) InstallPlugin(c *models.ReqContext) response.Response {
|
||||
dto := dtos.InstallPluginCommand{}
|
||||
if err := web.Bind(c.Req, &dto); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
pluginID := web.Params(c.Req)[":pluginId"]
|
||||
|
||||
err := hs.pluginStore.Add(c.Req.Context(), pluginID, dto.Version, plugins.AddOpts{})
|
||||
|
||||
@@ -2,11 +2,13 @@ package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -16,7 +18,11 @@ const (
|
||||
)
|
||||
|
||||
// POST /api/preferences/set-home-dash
|
||||
func SetHomeDashboard(c *models.ReqContext, cmd models.SavePreferencesCommand) response.Response {
|
||||
func SetHomeDashboard(c *models.ReqContext) response.Response {
|
||||
cmd := models.SavePreferencesCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.UserId = c.UserId
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
@@ -50,7 +56,11 @@ func (hs *HTTPServer) getPreferencesFor(ctx context.Context, orgID, userID, team
|
||||
}
|
||||
|
||||
// PUT /api/user/preferences
|
||||
func (hs *HTTPServer) UpdateUserPreferences(c *models.ReqContext, dtoCmd dtos.UpdatePrefsCmd) response.Response {
|
||||
func (hs *HTTPServer) UpdateUserPreferences(c *models.ReqContext) response.Response {
|
||||
dtoCmd := dtos.UpdatePrefsCmd{}
|
||||
if err := web.Bind(c.Req, &dtoCmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
return hs.updatePreferencesFor(c.Req.Context(), c.OrgId, c.UserId, 0, &dtoCmd)
|
||||
}
|
||||
|
||||
@@ -81,6 +91,10 @@ func (hs *HTTPServer) GetOrgPreferences(c *models.ReqContext) response.Response
|
||||
}
|
||||
|
||||
// PUT /api/org/preferences
|
||||
func (hs *HTTPServer) UpdateOrgPreferences(c *models.ReqContext, dtoCmd dtos.UpdatePrefsCmd) response.Response {
|
||||
func (hs *HTTPServer) UpdateOrgPreferences(c *models.ReqContext) response.Response {
|
||||
dtoCmd := dtos.UpdatePrefsCmd{}
|
||||
if err := web.Bind(c.Req, &dtoCmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
return hs.updatePreferencesFor(c.Req.Context(), c.OrgId, 0, 0, &dtoCmd)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -29,7 +31,11 @@ func (hs *HTTPServer) getOrgQuotasHelper(c *models.ReqContext, orgID int64) resp
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateOrgQuota(c *models.ReqContext, cmd models.UpdateOrgQuotaCmd) response.Response {
|
||||
func (hs *HTTPServer) UpdateOrgQuota(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateOrgQuotaCmd{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if !hs.Cfg.Quota.Enabled {
|
||||
return response.Error(404, "Quotas not enabled", nil)
|
||||
}
|
||||
@@ -59,7 +65,11 @@ func GetUserQuotas(c *models.ReqContext) response.Response {
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
func UpdateUserQuota(c *models.ReqContext, cmd models.UpdateUserQuotaCmd) response.Response {
|
||||
func UpdateUserQuota(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateUserQuotaCmd{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if !setting.Quota.Enabled {
|
||||
return response.Error(404, "Quotas not enabled", nil)
|
||||
}
|
||||
|
||||
@@ -12,16 +12,10 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func Wrap(action interface{}) web.Handler {
|
||||
func Wrap(handler func(c *models.ReqContext) response.Response) web.Handler {
|
||||
return func(c *models.ReqContext) {
|
||||
var res response.Response
|
||||
val, err := c.Invoke(action)
|
||||
if err == nil && val != nil && len(val) > 0 {
|
||||
res = val[0].Interface().(response.Response)
|
||||
} else {
|
||||
res = ServerError(err)
|
||||
if res := handler(c); res != nil {
|
||||
res.WriteTo(c)
|
||||
}
|
||||
|
||||
res.WriteTo(c)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
@@ -15,7 +16,11 @@ import (
|
||||
)
|
||||
|
||||
// createShortURL handles requests to create short URLs.
|
||||
func (hs *HTTPServer) createShortURL(c *models.ReqContext, cmd dtos.CreateShortURLCmd) response.Response {
|
||||
func (hs *HTTPServer) createShortURL(c *models.ReqContext) response.Response {
|
||||
cmd := dtos.CreateShortURLCmd{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
hs.log.Debug("Received request to create short URL", "path", cmd.Path)
|
||||
|
||||
cmd.Path = strings.TrimSpace(cmd.Path)
|
||||
|
||||
@@ -64,10 +64,11 @@ func createShortURLScenario(t *testing.T, desc string, url string, routePattern
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.SignedInUser = &models.SignedInUser{OrgId: testOrgID, UserId: testUserID}
|
||||
|
||||
return hs.createShortURL(c, cmd)
|
||||
return hs.createShortURL(c)
|
||||
})
|
||||
|
||||
sc.m.Post(routePattern, sc.defaultHandler)
|
||||
|
||||
@@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
// GET /api/user/signup/options
|
||||
@@ -23,7 +25,11 @@ func GetSignUpOptions(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
// POST /api/user/signup
|
||||
func SignUp(c *models.ReqContext, form dtos.SignUpForm) response.Response {
|
||||
func SignUp(c *models.ReqContext) response.Response {
|
||||
form := dtos.SignUpForm{}
|
||||
if err := web.Bind(c.Req, &form); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if !setting.AllowUserSignUp {
|
||||
return response.Error(401, "User signup is disabled", nil)
|
||||
}
|
||||
@@ -61,7 +67,11 @@ func SignUp(c *models.ReqContext, form dtos.SignUpForm) response.Response {
|
||||
return response.JSON(200, util.DynMap{"status": "SignUpCreated"})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) SignUpStep2(c *models.ReqContext, form dtos.SignUpStep2Form) response.Response {
|
||||
func (hs *HTTPServer) SignUpStep2(c *models.ReqContext) response.Response {
|
||||
form := dtos.SignUpStep2Form{}
|
||||
if err := web.Bind(c.Req, &form); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if !setting.AllowUserSignUp {
|
||||
return response.Error(401, "User signup is disabled", nil)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
@@ -10,10 +11,15 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/teamguardian"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
// POST /api/teams
|
||||
func (hs *HTTPServer) CreateTeam(c *models.ReqContext, cmd models.CreateTeamCommand) response.Response {
|
||||
func (hs *HTTPServer) CreateTeam(c *models.ReqContext) response.Response {
|
||||
cmd := models.CreateTeamCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if c.OrgRole == models.ROLE_VIEWER {
|
||||
return response.Error(403, "Not allowed to create team.", nil)
|
||||
}
|
||||
@@ -47,7 +53,11 @@ func (hs *HTTPServer) CreateTeam(c *models.ReqContext, cmd models.CreateTeamComm
|
||||
}
|
||||
|
||||
// PUT /api/teams/:teamId
|
||||
func (hs *HTTPServer) UpdateTeam(c *models.ReqContext, cmd models.UpdateTeamCommand) response.Response {
|
||||
func (hs *HTTPServer) UpdateTeam(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateTeamCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.Id = c.ParamsInt64(":teamId")
|
||||
|
||||
@@ -159,7 +169,11 @@ func (hs *HTTPServer) GetTeamPreferences(c *models.ReqContext) response.Response
|
||||
}
|
||||
|
||||
// PUT /api/teams/:teamId/preferences
|
||||
func (hs *HTTPServer) UpdateTeamPreferences(c *models.ReqContext, dtoCmd dtos.UpdatePrefsCmd) response.Response {
|
||||
func (hs *HTTPServer) UpdateTeamPreferences(c *models.ReqContext) response.Response {
|
||||
dtoCmd := dtos.UpdatePrefsCmd{}
|
||||
if err := web.Bind(c.Req, &dtoCmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
teamId := c.ParamsInt64(":teamId")
|
||||
orgId := c.OrgId
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/teamguardian"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
// GET /api/teams/:teamId/members
|
||||
@@ -41,7 +43,11 @@ func (hs *HTTPServer) GetTeamMembers(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
// POST /api/teams/:teamId/members
|
||||
func (hs *HTTPServer) AddTeamMember(c *models.ReqContext, cmd models.AddTeamMemberCommand) response.Response {
|
||||
func (hs *HTTPServer) AddTeamMember(c *models.ReqContext) response.Response {
|
||||
cmd := models.AddTeamMemberCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.TeamId = c.ParamsInt64(":teamId")
|
||||
|
||||
@@ -68,7 +74,11 @@ func (hs *HTTPServer) AddTeamMember(c *models.ReqContext, cmd models.AddTeamMemb
|
||||
}
|
||||
|
||||
// PUT /:teamId/members/:userId
|
||||
func (hs *HTTPServer) UpdateTeamMember(c *models.ReqContext, cmd models.UpdateTeamMemberCommand) response.Response {
|
||||
func (hs *HTTPServer) UpdateTeamMember(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateTeamMemberCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
teamId := c.ParamsInt64(":teamId")
|
||||
orgId := c.OrgId
|
||||
|
||||
|
||||
@@ -130,8 +130,8 @@ func TestTeamAPIEndpoint(t *testing.T) {
|
||||
Logger: stub,
|
||||
}
|
||||
c.OrgRole = models.ROLE_EDITOR
|
||||
cmd := models.CreateTeamCommand{Name: teamName}
|
||||
hs.CreateTeam(c, cmd)
|
||||
c.Req.Body = mockRequestBody(models.CreateTeamCommand{Name: teamName})
|
||||
hs.CreateTeam(c)
|
||||
assert.Equal(t, createTeamCalled, 1)
|
||||
assert.Equal(t, addTeamMemberCalled, 0)
|
||||
assert.True(t, stub.warnCalled)
|
||||
@@ -146,9 +146,9 @@ func TestTeamAPIEndpoint(t *testing.T) {
|
||||
Logger: stub,
|
||||
}
|
||||
c.OrgRole = models.ROLE_EDITOR
|
||||
cmd := models.CreateTeamCommand{Name: teamName}
|
||||
c.Req.Body = mockRequestBody(models.CreateTeamCommand{Name: teamName})
|
||||
createTeamCalled, addTeamMemberCalled = 0, 0
|
||||
hs.CreateTeam(c, cmd)
|
||||
hs.CreateTeam(c)
|
||||
assert.Equal(t, createTeamCalled, 1)
|
||||
assert.Equal(t, addTeamMemberCalled, 1)
|
||||
assert.False(t, stub.warnCalled)
|
||||
|
||||
@@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
|
||||
// GET /api/user (current authenticated user)
|
||||
@@ -70,7 +72,11 @@ func GetUserByLoginOrEmail(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
// POST /api/user
|
||||
func UpdateSignedInUser(c *models.ReqContext, cmd models.UpdateUserCommand) response.Response {
|
||||
func UpdateSignedInUser(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateUserCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if setting.AuthProxyEnabled {
|
||||
if setting.AuthProxyHeaderProperty == "email" && cmd.Email != c.Email {
|
||||
return response.Error(400, "Not allowed to change email when auth proxy is using email property", nil)
|
||||
@@ -84,7 +90,11 @@ func UpdateSignedInUser(c *models.ReqContext, cmd models.UpdateUserCommand) resp
|
||||
}
|
||||
|
||||
// POST /api/users/:id
|
||||
func UpdateUser(c *models.ReqContext, cmd models.UpdateUserCommand) response.Response {
|
||||
func UpdateUser(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateUserCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
cmd.UserId = c.ParamsInt64(":id")
|
||||
return handleUpdateUser(c.Req.Context(), cmd)
|
||||
}
|
||||
@@ -217,7 +227,11 @@ func (hs *HTTPServer) ChangeActiveOrgAndRedirectToHome(c *models.ReqContext) {
|
||||
c.Redirect(hs.Cfg.AppSubURL + "/")
|
||||
}
|
||||
|
||||
func ChangeUserPassword(c *models.ReqContext, cmd models.ChangeUserPasswordCommand) response.Response {
|
||||
func ChangeUserPassword(c *models.ReqContext) response.Response {
|
||||
cmd := models.ChangeUserPasswordCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
if setting.LDAPEnabled || setting.AuthProxyEnabled {
|
||||
return response.Error(400, "Not allowed to change password when LDAP or Auth Proxy is enabled", nil)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package api
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
"github.com/ua-parser/uap-go/uaparser"
|
||||
)
|
||||
|
||||
@@ -19,7 +21,11 @@ func (hs *HTTPServer) GetUserAuthTokens(c *models.ReqContext) response.Response
|
||||
}
|
||||
|
||||
// POST /api/user/revoke-auth-token
|
||||
func (hs *HTTPServer) RevokeUserAuthToken(c *models.ReqContext, cmd models.RevokeAuthTokenCmd) response.Response {
|
||||
func (hs *HTTPServer) RevokeUserAuthToken(c *models.ReqContext) response.Response {
|
||||
cmd := models.RevokeAuthTokenCmd{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
return hs.revokeUserAuthTokenInternal(c, c.UserId, cmd)
|
||||
}
|
||||
|
||||
|
||||
@@ -184,12 +184,13 @@ func revokeUserAuthTokenScenario(t *testing.T, desc string, url string, routePat
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.userAuthTokenService = fakeAuthTokenService
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(cmd)
|
||||
sc.context = c
|
||||
sc.context.UserId = userId
|
||||
sc.context.OrgId = testOrgID
|
||||
sc.context.OrgRole = models.ROLE_ADMIN
|
||||
|
||||
return hs.RevokeUserAuthToken(c, cmd)
|
||||
return hs.RevokeUserAuthToken(c)
|
||||
})
|
||||
|
||||
sc.m.Post(routePattern, sc.defaultHandler)
|
||||
|
||||
@@ -2,8 +2,8 @@ package libraryelements
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-macaron/binding"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
@@ -13,18 +13,23 @@ import (
|
||||
|
||||
func (l *LibraryElementService) registerAPIEndpoints() {
|
||||
l.RouteRegister.Group("/api/library-elements", func(entities routing.RouteRegister) {
|
||||
entities.Post("/", middleware.ReqSignedIn, binding.Bind(CreateLibraryElementCommand{}), routing.Wrap(l.createHandler))
|
||||
entities.Post("/", middleware.ReqSignedIn, routing.Wrap(l.createHandler))
|
||||
entities.Delete("/:uid", middleware.ReqSignedIn, routing.Wrap(l.deleteHandler))
|
||||
entities.Get("/", middleware.ReqSignedIn, routing.Wrap(l.getAllHandler))
|
||||
entities.Get("/:uid", middleware.ReqSignedIn, routing.Wrap(l.getHandler))
|
||||
entities.Get("/:uid/connections/", middleware.ReqSignedIn, routing.Wrap(l.getConnectionsHandler))
|
||||
entities.Get("/name/:name", middleware.ReqSignedIn, routing.Wrap(l.getByNameHandler))
|
||||
entities.Patch("/:uid", middleware.ReqSignedIn, binding.Bind(patchLibraryElementCommand{}), routing.Wrap(l.patchHandler))
|
||||
entities.Patch("/:uid", middleware.ReqSignedIn, routing.Wrap(l.patchHandler))
|
||||
})
|
||||
}
|
||||
|
||||
// createHandler handles POST /api/library-elements.
|
||||
func (l *LibraryElementService) createHandler(c *models.ReqContext, cmd CreateLibraryElementCommand) response.Response {
|
||||
func (l *LibraryElementService) createHandler(c *models.ReqContext) response.Response {
|
||||
cmd := CreateLibraryElementCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
|
||||
element, err := l.createLibraryElement(c.Req.Context(), c.SignedInUser, cmd)
|
||||
if err != nil {
|
||||
return toLibraryElementError(err, "Failed to create library element")
|
||||
@@ -77,7 +82,12 @@ func (l *LibraryElementService) getAllHandler(c *models.ReqContext) response.Res
|
||||
}
|
||||
|
||||
// patchHandler handles PATCH /api/library-elements/:uid
|
||||
func (l *LibraryElementService) patchHandler(c *models.ReqContext, cmd patchLibraryElementCommand) response.Response {
|
||||
func (l *LibraryElementService) patchHandler(c *models.ReqContext) response.Response {
|
||||
cmd := patchLibraryElementCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
|
||||
element, err := l.patchLibraryElement(c.Req.Context(), c.SignedInUser, cmd, web.Params(c.Req)[":uid"])
|
||||
if err != nil {
|
||||
return toLibraryElementError(err, "Failed to update library element")
|
||||
|
||||
@@ -14,7 +14,8 @@ func TestCreateLibraryElement(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to create a library panel that already exists, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 400, resp.Status())
|
||||
})
|
||||
|
||||
@@ -64,7 +65,8 @@ func TestCreateLibraryElement(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Nonexistent UID")
|
||||
command.UID = util.GenerateShortUID()
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
var expected = libraryElementResult{
|
||||
Result: libraryElement{
|
||||
@@ -110,7 +112,8 @@ func TestCreateLibraryElement(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Existing UID")
|
||||
command.UID = sc.initialResult.Result.UID
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 400, resp.Status())
|
||||
})
|
||||
|
||||
@@ -118,7 +121,8 @@ func TestCreateLibraryElement(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Invalid UID")
|
||||
command.UID = "Testing an invalid UID"
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 400, resp.Status())
|
||||
})
|
||||
|
||||
@@ -126,14 +130,16 @@ func TestCreateLibraryElement(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Invalid UID")
|
||||
command.UID = "j6T00KRZzj6T00KRZzj6T00KRZzj6T00KRZzj6T00K"
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 400, resp.Status())
|
||||
})
|
||||
|
||||
testScenario(t, "When an admin tries to create a library panel where name and panel title differ, it should not update panel title",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(1, "Library Panel Name")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
var expected = libraryElementResult{
|
||||
Result: libraryElement{
|
||||
|
||||
@@ -37,7 +37,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to get all panel elements and both panels and variables exist, it should only return panels",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateVariableCommand(sc.folder.Id, "query0")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
@@ -102,7 +103,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to get all variable elements and both panels and variables exist, it should only return panels",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateVariableCommand(sc.folder.Id, "query0")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
@@ -166,7 +168,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist, it should succeed",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
resp = sc.service.getAllHandler(sc.reqContext)
|
||||
@@ -262,7 +265,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and sort desc is set, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
@@ -369,7 +373,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
"description": "Gauge description"
|
||||
}
|
||||
`))
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
command = getCreateCommandWithModel(sc.folder.Id, "BarGauge - Library Panel", models.PanelElement, []byte(`
|
||||
@@ -381,7 +386,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
"description": "BarGauge description"
|
||||
}
|
||||
`))
|
||||
resp = sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp = sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
@@ -488,7 +494,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
"description": "Gauge description"
|
||||
}
|
||||
`))
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
@@ -517,7 +524,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
newFolder := createFolderWithACL(t, sc.sqlStore, "NewFolder", sc.user, []folderACLItem{})
|
||||
command := getCreatePanelCommand(newFolder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
folderFilter := strconv.FormatInt(newFolder.Id, 10)
|
||||
|
||||
@@ -583,7 +591,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
newFolder := createFolderWithACL(t, sc.sqlStore, "NewFolder", sc.user, []folderACLItem{})
|
||||
command := getCreatePanelCommand(newFolder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
folderFilter := "2020,2021"
|
||||
|
||||
@@ -612,7 +621,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and folderFilter is set to General folder, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
folderFilter := "0"
|
||||
|
||||
@@ -712,7 +722,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and excludeUID is set, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
@@ -776,7 +787,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
@@ -840,7 +852,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 2, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
@@ -913,7 +926,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
"description": "Some other d e s c r i p t i o n"
|
||||
}
|
||||
`))
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
@@ -987,7 +1001,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
"description": "A Library Panel"
|
||||
}
|
||||
`))
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
@@ -1086,7 +1101,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 1 and searchString is panel2, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
@@ -1152,7 +1168,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 3 and searchString is panel, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
@@ -1182,7 +1199,8 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and perPage is 1 and page is 3 and searchString does not exist, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel2")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
|
||||
@@ -14,9 +14,10 @@ import (
|
||||
func TestPatchLibraryElement(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to patch a library panel that does not exist, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
cmd := patchLibraryElementCommand{Kind: int64(models.PanelElement)}
|
||||
cmd := patchLibraryElementCommand{Kind: int64(models.PanelElement), Version: 1}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": "unknown"})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, 404, resp.Status())
|
||||
})
|
||||
|
||||
@@ -39,7 +40,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Version: 1,
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
var expected = libraryElementResult{
|
||||
@@ -91,7 +93,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Version: 1,
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
sc.initialResult.Result.FolderID = newFolder.Id
|
||||
@@ -113,7 +116,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Version: 1,
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
sc.initialResult.Result.Name = "New Name"
|
||||
sc.initialResult.Result.Meta.CreatedBy.Name = userInDbName
|
||||
@@ -135,7 +139,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Version: 1,
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
sc.initialResult.Result.UID = cmd.UID
|
||||
sc.initialResult.Result.Meta.CreatedBy.Name = userInDbName
|
||||
@@ -157,7 +162,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Version: 1,
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, 400, resp.Status())
|
||||
})
|
||||
|
||||
@@ -170,7 +176,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Version: 1,
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, 400, resp.Status())
|
||||
})
|
||||
|
||||
@@ -178,7 +185,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Existing UID")
|
||||
command.UID = util.GenerateShortUID()
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
cmd := patchLibraryElementCommand{
|
||||
FolderID: -1,
|
||||
@@ -187,7 +195,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Version: 1,
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp = sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, 400, resp.Status())
|
||||
})
|
||||
|
||||
@@ -200,7 +209,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Version: 1,
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
sc.initialResult.Result.Type = "graph"
|
||||
sc.initialResult.Result.Description = "New description"
|
||||
@@ -228,7 +238,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Version: 1,
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
sc.initialResult.Result.Type = "text"
|
||||
sc.initialResult.Result.Description = "New description"
|
||||
@@ -254,7 +265,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Version: 1,
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
sc.initialResult.Result.Type = "graph"
|
||||
sc.initialResult.Result.Description = "A description"
|
||||
@@ -276,7 +288,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
cmd := patchLibraryElementCommand{FolderID: -1, Version: 1, Kind: int64(models.PanelElement)}
|
||||
sc.reqContext.UserId = 2
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
sc.initialResult.Result.Meta.UpdatedBy.ID = int64(2)
|
||||
sc.initialResult.Result.Meta.CreatedBy.Name = userInDbName
|
||||
@@ -291,7 +304,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to patch a library panel with a name that already exists, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Another Panel")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.ctx.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
cmd := patchLibraryElementCommand{
|
||||
Name: "Text - Library Panel",
|
||||
@@ -299,7 +313,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Kind: int64(models.PanelElement),
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp = sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, 400, resp.Status())
|
||||
})
|
||||
|
||||
@@ -307,7 +322,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
newFolder := createFolderWithACL(t, sc.sqlStore, "NewFolder", sc.user, []folderACLItem{})
|
||||
command := getCreatePanelCommand(newFolder.Id, "Text - Library Panel")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.ctx.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
cmd := patchLibraryElementCommand{
|
||||
FolderID: 1,
|
||||
@@ -315,7 +331,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Kind: int64(models.PanelElement),
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp = sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, 400, resp.Status())
|
||||
})
|
||||
|
||||
@@ -328,7 +345,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
}
|
||||
sc.reqContext.OrgId = 2
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, 404, resp.Status())
|
||||
})
|
||||
|
||||
@@ -340,9 +358,11 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Kind: int64(models.PanelElement),
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp = sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, 412, resp.Status())
|
||||
})
|
||||
|
||||
@@ -354,7 +374,8 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
Kind: int64(models.VariableElement),
|
||||
}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
sc.initialResult.Result.Type = "text"
|
||||
|
||||
@@ -71,7 +71,8 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
command := getCreatePanelCommand(folder.Id, "Library Panel Name")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, testCase.status, resp.Status())
|
||||
})
|
||||
|
||||
@@ -79,14 +80,16 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
fromFolder := createFolderWithACL(t, sc.sqlStore, "Everyone", sc.user, everyonePermissions)
|
||||
command := getCreatePanelCommand(fromFolder.Id, "Library Panel Name")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
toFolder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, testCase.items)
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
cmd := patchLibraryElementCommand{FolderID: toFolder.Id, Version: 1, Kind: int64(models.PanelElement)}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||
resp = sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, testCase.status, resp.Status())
|
||||
})
|
||||
|
||||
@@ -94,14 +97,16 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
fromFolder := createFolderWithACL(t, sc.sqlStore, "Everyone", sc.user, testCase.items)
|
||||
command := getCreatePanelCommand(fromFolder.Id, "Library Panel Name")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
toFolder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, everyonePermissions)
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
cmd := patchLibraryElementCommand{FolderID: toFolder.Id, Version: 1, Kind: int64(models.PanelElement)}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||
resp = sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, testCase.status, resp.Status())
|
||||
})
|
||||
|
||||
@@ -109,7 +114,8 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
folder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, testCase.items)
|
||||
cmd := getCreatePanelCommand(folder.Id, "Library Panel Name")
|
||||
resp := sc.service.createHandler(sc.reqContext, cmd)
|
||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
@@ -134,7 +140,8 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
command := getCreatePanelCommand(0, "Library Panel Name")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, testCase.status, resp.Status())
|
||||
})
|
||||
|
||||
@@ -142,13 +149,15 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
folder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, everyonePermissions)
|
||||
command := getCreatePanelCommand(folder.Id, "Library Panel Name")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
cmd := patchLibraryElementCommand{FolderID: 0, Version: 1, Kind: int64(models.PanelElement)}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp = sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, testCase.status, resp.Status())
|
||||
})
|
||||
|
||||
@@ -156,20 +165,23 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
folder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, everyonePermissions)
|
||||
command := getCreatePanelCommand(0, "Library Panel Name")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
cmd := patchLibraryElementCommand{FolderID: folder.Id, Version: 1, Kind: int64(models.PanelElement)}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.ctx.Req.Body = mockRequestBody(cmd)
|
||||
resp = sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, testCase.status, resp.Status())
|
||||
})
|
||||
|
||||
testScenario(t, fmt.Sprintf("When %s tries to delete a library panel in the General folder, it should return correct status", testCase.role),
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
cmd := getCreatePanelCommand(0, "Library Panel Name")
|
||||
resp := sc.service.createHandler(sc.reqContext, cmd)
|
||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
@@ -193,7 +205,8 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
command := getCreatePanelCommand(-100, "Library Panel Name")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 404, resp.Status())
|
||||
})
|
||||
|
||||
@@ -201,13 +214,15 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
folder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, everyonePermissions)
|
||||
command := getCreatePanelCommand(folder.Id, "Library Panel Name")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
cmd := patchLibraryElementCommand{FolderID: -100, Version: 1, Kind: int64(models.PanelElement)}
|
||||
sc.ctx.Req = web.SetURLParams(sc.ctx.Req, map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||
resp = sc.service.patchHandler(sc.reqContext)
|
||||
require.Equal(t, 404, resp.Status())
|
||||
})
|
||||
}
|
||||
@@ -228,7 +243,8 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
for i, folderCase := range folderCases {
|
||||
folder := createFolderWithACL(t, sc.sqlStore, fmt.Sprintf("Folder%v", i), sc.user, folderCase)
|
||||
cmd := getCreatePanelCommand(folder.Id, fmt.Sprintf("Library Panel in Folder%v", i))
|
||||
resp := sc.service.createHandler(sc.reqContext, cmd)
|
||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
result.Result.Meta.CreatedBy.Name = userInDbName
|
||||
result.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar
|
||||
@@ -250,7 +266,8 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
testScenario(t, fmt.Sprintf("When %s tries to get a library panel from General folder, it should return correct response", testCase.role),
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
cmd := getCreatePanelCommand(0, "Library Panel in General Folder")
|
||||
resp := sc.service.createHandler(sc.reqContext, cmd)
|
||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
result.Result.Meta.CreatedBy.Name = userInDbName
|
||||
result.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar
|
||||
@@ -289,7 +306,8 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
for i, folderCase := range folderCases {
|
||||
folder := createFolderWithACL(t, sc.sqlStore, fmt.Sprintf("Folder%v", i), sc.user, folderCase)
|
||||
cmd := getCreatePanelCommand(folder.Id, fmt.Sprintf("Library Panel in Folder%v", i))
|
||||
resp := sc.service.createHandler(sc.reqContext, cmd)
|
||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
result.Result.Meta.CreatedBy.Name = userInDbName
|
||||
result.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar
|
||||
@@ -340,7 +358,8 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
testScenario(t, fmt.Sprintf("When %s tries to get all library panels from General folder, it should return correct response", testCase.role),
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
cmd := getCreatePanelCommand(0, "Library Panel in General Folder")
|
||||
resp := sc.service.createHandler(sc.reqContext, cmd)
|
||||
sc.reqContext.Req.Body = mockRequestBody(cmd)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
result.Result.Meta.CreatedBy.Name = userInDbName
|
||||
result.Result.Meta.CreatedBy.AvatarURL = userInDbAvatar
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package libraryelements
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -68,7 +70,8 @@ func TestDeleteLibraryPanelsInFolder(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to delete a folder that contains disconnected elements, it should delete all disconnected elements too",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateVariableCommand(sc.folder.Id, "query0")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
resp = sc.service.getAllHandler(sc.reqContext)
|
||||
@@ -266,7 +269,8 @@ func scenarioWithPanel(t *testing.T, desc string, fn func(t *testing.T, sc scena
|
||||
|
||||
testScenario(t, desc, func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreatePanelCommand(sc.folder.Id, "Text - Library Panel")
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
sc.reqContext.Req.Body = mockRequestBody(command)
|
||||
resp := sc.service.createHandler(sc.reqContext)
|
||||
sc.initialResult = validateAndUnMarshalResponse(t, resp)
|
||||
|
||||
fn(t, sc)
|
||||
@@ -333,3 +337,8 @@ func getCompareOptions() []cmp.Option {
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
func mockRequestBody(v interface{}) io.ReadCloser {
|
||||
b, _ := json.Marshal(v)
|
||||
return io.NopCloser(bytes.NewReader(b))
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ type CreateLibraryElementCommand struct {
|
||||
type patchLibraryElementCommand struct {
|
||||
FolderID int64 `json:"folderId" binding:"Default(-1)"`
|
||||
Name string `json:"name"`
|
||||
Model json.RawMessage `json:"model"`
|
||||
Model json.RawMessage `json:"model,omitempty"`
|
||||
Kind int64 `json:"kind" binding:"Required"`
|
||||
Version int64 `json:"version" binding:"Required"`
|
||||
UID string `json:"uid"`
|
||||
|
||||
@@ -893,7 +893,11 @@ func (g *GrafanaLive) ClientCount(orgID int64, channel string) (int, error) {
|
||||
return len(p.Presence), nil
|
||||
}
|
||||
|
||||
func (g *GrafanaLive) HandleHTTPPublish(ctx *models.ReqContext, cmd dtos.LivePublishCmd) response.Response {
|
||||
func (g *GrafanaLive) HandleHTTPPublish(ctx *models.ReqContext) response.Response {
|
||||
cmd := dtos.LivePublishCmd{}
|
||||
if err := web.Bind(ctx.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
addr, err := live.ParseChannel(cmd.Channel)
|
||||
if err != nil {
|
||||
return response.Error(http.StatusBadRequest, "invalid channel ID", nil)
|
||||
|
||||
Reference in New Issue
Block a user