mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Chore: Moves common and response into separate packages (#30298)
* Chore: moves common and response into separate packages * Chore: moves common and response into separate packages * Update pkg/api/utils/common.go Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com> * Chore: changes after PR comments * Chore: move wrap to routing package * Chore: move functions in common to response package * Chore: move functions in common to response package * Chore: formats imports Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
@@ -4,12 +4,13 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func AdminGetSettings(c *models.ReqContext) Response {
|
||||
func AdminGetSettings(c *models.ReqContext) response.Response {
|
||||
settings := make(map[string]interface{})
|
||||
|
||||
for _, section := range setting.Raw.Sections() {
|
||||
@@ -35,15 +36,15 @@ func AdminGetSettings(c *models.ReqContext) Response {
|
||||
}
|
||||
}
|
||||
|
||||
return JSON(200, settings)
|
||||
return response.JSON(200, settings)
|
||||
}
|
||||
|
||||
func AdminGetStats(c *models.ReqContext) Response {
|
||||
func AdminGetStats(c *models.ReqContext) response.Response {
|
||||
statsQuery := models.GetAdminStatsQuery{}
|
||||
|
||||
if err := bus.Dispatch(&statsQuery); err != nil {
|
||||
return Error(500, "Failed to get admin stats from database", err)
|
||||
return response.Error(500, "Failed to get admin stats from database", err)
|
||||
}
|
||||
|
||||
return JSON(200, statsQuery.Result)
|
||||
return response.JSON(200, statsQuery.Result)
|
||||
}
|
||||
|
@@ -4,37 +4,38 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func (hs *HTTPServer) AdminProvisioningReloadDashboards(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) AdminProvisioningReloadDashboards(c *models.ReqContext) response.Response {
|
||||
err := hs.ProvisioningService.ProvisionDashboards()
|
||||
if err != nil && !errors.Is(err, context.Canceled) {
|
||||
return Error(500, "", err)
|
||||
return response.Error(500, "", err)
|
||||
}
|
||||
return Success("Dashboards config reloaded")
|
||||
return response.Success("Dashboards config reloaded")
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) AdminProvisioningReloadDatasources(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) AdminProvisioningReloadDatasources(c *models.ReqContext) response.Response {
|
||||
err := hs.ProvisioningService.ProvisionDatasources()
|
||||
if err != nil {
|
||||
return Error(500, "", err)
|
||||
return response.Error(500, "", err)
|
||||
}
|
||||
return Success("Datasources config reloaded")
|
||||
return response.Success("Datasources config reloaded")
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) AdminProvisioningReloadPlugins(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) AdminProvisioningReloadPlugins(c *models.ReqContext) response.Response {
|
||||
err := hs.ProvisioningService.ProvisionPlugins()
|
||||
if err != nil {
|
||||
return Error(500, "Failed to reload plugins config", err)
|
||||
return response.Error(500, "Failed to reload plugins config", err)
|
||||
}
|
||||
return Success("Plugins config reloaded")
|
||||
return response.Success("Plugins config reloaded")
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) AdminProvisioningReloadNotifications(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) AdminProvisioningReloadNotifications(c *models.ReqContext) response.Response {
|
||||
err := hs.ProvisioningService.ProvisionNotifications()
|
||||
if err != nil {
|
||||
return Error(500, "", err)
|
||||
return response.Error(500, "", err)
|
||||
}
|
||||
return Success("Notifications config reloaded")
|
||||
return response.Success("Notifications config reloaded")
|
||||
}
|
||||
|
@@ -5,13 +5,14 @@ import (
|
||||
"fmt"
|
||||
|
||||
"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/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func AdminCreateUser(c *models.ReqContext, form dtos.AdminCreateUserForm) Response {
|
||||
func AdminCreateUser(c *models.ReqContext, form dtos.AdminCreateUserForm) response.Response {
|
||||
cmd := models.CreateUserCommand{
|
||||
Login: form.Login,
|
||||
Email: form.Email,
|
||||
@@ -23,24 +24,24 @@ func AdminCreateUser(c *models.ReqContext, form dtos.AdminCreateUserForm) Respon
|
||||
if len(cmd.Login) == 0 {
|
||||
cmd.Login = cmd.Email
|
||||
if len(cmd.Login) == 0 {
|
||||
return Error(400, "Validation error, need specify either username or email", nil)
|
||||
return response.Error(400, "Validation error, need specify either username or email", nil)
|
||||
}
|
||||
}
|
||||
|
||||
if len(cmd.Password) < 4 {
|
||||
return Error(400, "Password is missing or too short", nil)
|
||||
return response.Error(400, "Password is missing or too short", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrOrgNotFound) {
|
||||
return Error(400, err.Error(), nil)
|
||||
return response.Error(400, err.Error(), nil)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrUserAlreadyExists) {
|
||||
return Error(412, fmt.Sprintf("User with email '%s' or username '%s' already exists", form.Email, form.Login), err)
|
||||
return response.Error(412, fmt.Sprintf("User with email '%s' or username '%s' already exists", form.Email, form.Login), err)
|
||||
}
|
||||
|
||||
return Error(500, "failed to create user", err)
|
||||
return response.Error(500, "failed to create user", err)
|
||||
}
|
||||
|
||||
metrics.MApiAdminUserCreate.Inc()
|
||||
@@ -52,25 +53,25 @@ func AdminCreateUser(c *models.ReqContext, form dtos.AdminCreateUserForm) Respon
|
||||
Id: user.Id,
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
||||
func AdminUpdateUserPassword(c *models.ReqContext, form dtos.AdminUpdateUserPasswordForm) Response {
|
||||
func AdminUpdateUserPassword(c *models.ReqContext, form dtos.AdminUpdateUserPasswordForm) response.Response {
|
||||
userID := c.ParamsInt64(":id")
|
||||
|
||||
if len(form.Password) < 4 {
|
||||
return Error(400, "New password too short", nil)
|
||||
return response.Error(400, "New password too short", nil)
|
||||
}
|
||||
|
||||
userQuery := models.GetUserByIdQuery{Id: userID}
|
||||
|
||||
if err := bus.Dispatch(&userQuery); err != nil {
|
||||
return Error(500, "Could not read user from database", err)
|
||||
return response.Error(500, "Could not read user from database", err)
|
||||
}
|
||||
|
||||
passwordHashed, err := util.EncodePassword(form.Password, userQuery.Result.Salt)
|
||||
if err != nil {
|
||||
return Error(500, "Could not encode password", err)
|
||||
return response.Error(500, "Could not encode password", err)
|
||||
}
|
||||
|
||||
cmd := models.ChangeUserPasswordCommand{
|
||||
@@ -79,14 +80,14 @@ func AdminUpdateUserPassword(c *models.ReqContext, form dtos.AdminUpdateUserPass
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to update user password", err)
|
||||
return response.Error(500, "Failed to update user password", err)
|
||||
}
|
||||
|
||||
return Success("User password updated")
|
||||
return response.Success("User password updated")
|
||||
}
|
||||
|
||||
// PUT /api/admin/users/:id/permissions
|
||||
func AdminUpdateUserPermissions(c *models.ReqContext, form dtos.AdminUpdateUserPermissionsForm) Response {
|
||||
func AdminUpdateUserPermissions(c *models.ReqContext, form dtos.AdminUpdateUserPermissionsForm) response.Response {
|
||||
userID := c.ParamsInt64(":id")
|
||||
|
||||
cmd := models.UpdateUserPermissionsCommand{
|
||||
@@ -96,96 +97,96 @@ func AdminUpdateUserPermissions(c *models.ReqContext, form dtos.AdminUpdateUserP
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrLastGrafanaAdmin) {
|
||||
return Error(400, models.ErrLastGrafanaAdmin.Error(), nil)
|
||||
return response.Error(400, models.ErrLastGrafanaAdmin.Error(), nil)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to update user permissions", err)
|
||||
return response.Error(500, "Failed to update user permissions", err)
|
||||
}
|
||||
|
||||
return Success("User permissions updated")
|
||||
return response.Success("User permissions updated")
|
||||
}
|
||||
|
||||
func AdminDeleteUser(c *models.ReqContext) Response {
|
||||
func AdminDeleteUser(c *models.ReqContext) response.Response {
|
||||
userID := c.ParamsInt64(":id")
|
||||
|
||||
cmd := models.DeleteUserCommand{UserId: userID}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrUserNotFound) {
|
||||
return Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
return response.Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
}
|
||||
return Error(500, "Failed to delete user", err)
|
||||
return response.Error(500, "Failed to delete user", err)
|
||||
}
|
||||
|
||||
return Success("User deleted")
|
||||
return response.Success("User deleted")
|
||||
}
|
||||
|
||||
// POST /api/admin/users/:id/disable
|
||||
func (hs *HTTPServer) AdminDisableUser(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) AdminDisableUser(c *models.ReqContext) response.Response {
|
||||
userID := c.ParamsInt64(":id")
|
||||
|
||||
// External users shouldn't be disabled from API
|
||||
authInfoQuery := &models.GetAuthInfoQuery{UserId: userID}
|
||||
if err := bus.Dispatch(authInfoQuery); !errors.Is(err, models.ErrUserNotFound) {
|
||||
return Error(500, "Could not disable external user", nil)
|
||||
return response.Error(500, "Could not disable external user", nil)
|
||||
}
|
||||
|
||||
disableCmd := models.DisableUserCommand{UserId: userID, IsDisabled: true}
|
||||
if err := bus.Dispatch(&disableCmd); err != nil {
|
||||
if errors.Is(err, models.ErrUserNotFound) {
|
||||
return Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
return response.Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
}
|
||||
return Error(500, "Failed to disable user", err)
|
||||
return response.Error(500, "Failed to disable user", err)
|
||||
}
|
||||
|
||||
err := hs.AuthTokenService.RevokeAllUserTokens(c.Req.Context(), userID)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to disable user", err)
|
||||
return response.Error(500, "Failed to disable user", err)
|
||||
}
|
||||
|
||||
return Success("User disabled")
|
||||
return response.Success("User disabled")
|
||||
}
|
||||
|
||||
// POST /api/admin/users/:id/enable
|
||||
func AdminEnableUser(c *models.ReqContext) Response {
|
||||
func AdminEnableUser(c *models.ReqContext) response.Response {
|
||||
userID := c.ParamsInt64(":id")
|
||||
|
||||
// External users shouldn't be disabled from API
|
||||
authInfoQuery := &models.GetAuthInfoQuery{UserId: userID}
|
||||
if err := bus.Dispatch(authInfoQuery); !errors.Is(err, models.ErrUserNotFound) {
|
||||
return Error(500, "Could not enable external user", nil)
|
||||
return response.Error(500, "Could not enable external user", nil)
|
||||
}
|
||||
|
||||
disableCmd := models.DisableUserCommand{UserId: userID, IsDisabled: false}
|
||||
if err := bus.Dispatch(&disableCmd); err != nil {
|
||||
if errors.Is(err, models.ErrUserNotFound) {
|
||||
return Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
return response.Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
}
|
||||
return Error(500, "Failed to enable user", err)
|
||||
return response.Error(500, "Failed to enable user", err)
|
||||
}
|
||||
|
||||
return Success("User enabled")
|
||||
return response.Success("User enabled")
|
||||
}
|
||||
|
||||
// POST /api/admin/users/:id/logout
|
||||
func (hs *HTTPServer) AdminLogoutUser(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) AdminLogoutUser(c *models.ReqContext) response.Response {
|
||||
userID := c.ParamsInt64(":id")
|
||||
|
||||
if c.UserId == userID {
|
||||
return Error(400, "You cannot logout yourself", nil)
|
||||
return response.Error(400, "You cannot logout yourself", nil)
|
||||
}
|
||||
|
||||
return hs.logoutUserFromAllDevicesInternal(c.Req.Context(), userID)
|
||||
}
|
||||
|
||||
// GET /api/admin/users/:id/auth-tokens
|
||||
func (hs *HTTPServer) AdminGetUserAuthTokens(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) AdminGetUserAuthTokens(c *models.ReqContext) response.Response {
|
||||
userID := c.ParamsInt64(":id")
|
||||
return hs.getUserAuthTokensInternal(c, userID)
|
||||
}
|
||||
|
||||
// POST /api/admin/users/:id/revoke-auth-token
|
||||
func (hs *HTTPServer) AdminRevokeUserAuthToken(c *models.ReqContext, cmd models.RevokeAuthTokenCmd) Response {
|
||||
func (hs *HTTPServer) AdminRevokeUserAuthToken(c *models.ReqContext, cmd models.RevokeAuthTokenCmd) response.Response {
|
||||
userID := c.ParamsInt64(":id")
|
||||
return hs.revokeUserAuthTokenInternal(c, userID, cmd)
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -355,7 +357,7 @@ func putAdminScenario(t *testing.T, desc string, url string, routePattern string
|
||||
t.Cleanup(bus.ClearBusHandlers)
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
@@ -380,7 +382,7 @@ func adminLogoutUserScenario(t *testing.T, desc string, url string, routePattern
|
||||
}
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
t.Log("Route handler invoked", "url", c.Req.URL)
|
||||
|
||||
sc.context = c
|
||||
@@ -410,7 +412,7 @@ func adminRevokeUserAuthTokenScenario(t *testing.T, desc string, url string, rou
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.userAuthTokenService = fakeAuthTokenService
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
@@ -438,7 +440,7 @@ func adminGetUserAuthTokensScenario(t *testing.T, desc string, url string, route
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.userAuthTokenService = fakeAuthTokenService
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
@@ -465,7 +467,7 @@ func adminDisableUserScenario(t *testing.T, desc string, action string, url stri
|
||||
}
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
|
||||
@@ -487,7 +489,7 @@ func adminDeleteUserScenario(t *testing.T, desc string, url string, routePattern
|
||||
t.Cleanup(bus.ClearBusHandlers)
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
|
||||
@@ -505,7 +507,7 @@ func adminCreateUserScenario(t *testing.T, desc string, url string, routePattern
|
||||
t.Cleanup(bus.ClearBusHandlers)
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"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/services/alerting"
|
||||
@@ -29,11 +30,11 @@ func ValidateOrgAlert(c *models.ReqContext) {
|
||||
}
|
||||
}
|
||||
|
||||
func GetAlertStatesForDashboard(c *models.ReqContext) Response {
|
||||
func GetAlertStatesForDashboard(c *models.ReqContext) response.Response {
|
||||
dashboardID := c.QueryInt64("dashboardId")
|
||||
|
||||
if dashboardID == 0 {
|
||||
return Error(400, "Missing query parameter dashboardId", nil)
|
||||
return response.Error(400, "Missing query parameter dashboardId", nil)
|
||||
}
|
||||
|
||||
query := models.GetAlertStatesForDashboardQuery{
|
||||
@@ -42,14 +43,14 @@ func GetAlertStatesForDashboard(c *models.ReqContext) Response {
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to fetch alert states", err)
|
||||
return response.Error(500, "Failed to fetch alert states", err)
|
||||
}
|
||||
|
||||
return JSON(200, query.Result)
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
// GET /api/alerts
|
||||
func GetAlerts(c *models.ReqContext) Response {
|
||||
func GetAlerts(c *models.ReqContext) response.Response {
|
||||
dashboardQuery := c.Query("dashboardQuery")
|
||||
dashboardTags := c.QueryStrings("dashboardTag")
|
||||
stringDashboardIDs := c.QueryStrings("dashboardId")
|
||||
@@ -86,7 +87,7 @@ func GetAlerts(c *models.ReqContext) Response {
|
||||
|
||||
err := bus.Dispatch(&searchQuery)
|
||||
if err != nil {
|
||||
return Error(500, "List alerts failed", err)
|
||||
return response.Error(500, "List alerts failed", err)
|
||||
}
|
||||
|
||||
for _, d := range searchQuery.Result {
|
||||
@@ -97,7 +98,7 @@ func GetAlerts(c *models.ReqContext) Response {
|
||||
|
||||
// if we didn't find any dashboards, return empty result
|
||||
if len(dashboardIDs) == 0 {
|
||||
return JSON(200, []*models.AlertListItemDTO{})
|
||||
return response.JSON(200, []*models.AlertListItemDTO{})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,20 +117,20 @@ func GetAlerts(c *models.ReqContext) Response {
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "List alerts failed", err)
|
||||
return response.Error(500, "List alerts failed", err)
|
||||
}
|
||||
|
||||
for _, alert := range query.Result {
|
||||
alert.Url = models.GetDashboardUrl(alert.DashboardUid, alert.DashboardSlug)
|
||||
}
|
||||
|
||||
return JSON(200, query.Result)
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
// POST /api/alerts/test
|
||||
func AlertTest(c *models.ReqContext, dto dtos.AlertTestCommand) Response {
|
||||
func AlertTest(c *models.ReqContext, dto dtos.AlertTestCommand) response.Response {
|
||||
if _, idErr := dto.Dashboard.Get("id").Int64(); idErr != nil {
|
||||
return Error(400, "The dashboard needs to be saved at least once before you can test an alert rule", nil)
|
||||
return response.Error(400, "The dashboard needs to be saved at least once before you can test an alert rule", nil)
|
||||
}
|
||||
|
||||
backendCmd := alerting.AlertTestCommand{
|
||||
@@ -142,12 +143,12 @@ func AlertTest(c *models.ReqContext, dto dtos.AlertTestCommand) Response {
|
||||
if err := bus.Dispatch(&backendCmd); err != nil {
|
||||
var validationErr alerting.ValidationError
|
||||
if errors.As(err, &validationErr) {
|
||||
return Error(422, validationErr.Error(), nil)
|
||||
return response.Error(422, validationErr.Error(), nil)
|
||||
}
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
return Error(403, "Access denied to datasource", err)
|
||||
return response.Error(403, "Access denied to datasource", err)
|
||||
}
|
||||
return Error(500, "Failed to test rule", err)
|
||||
return response.Error(500, "Failed to test rule", err)
|
||||
}
|
||||
|
||||
res := backendCmd.Result
|
||||
@@ -170,29 +171,29 @@ func AlertTest(c *models.ReqContext, dto dtos.AlertTestCommand) Response {
|
||||
|
||||
dtoRes.TimeMs = fmt.Sprintf("%1.3fms", res.GetDurationMs())
|
||||
|
||||
return JSON(200, dtoRes)
|
||||
return response.JSON(200, dtoRes)
|
||||
}
|
||||
|
||||
// GET /api/alerts/:id
|
||||
func GetAlert(c *models.ReqContext) Response {
|
||||
func GetAlert(c *models.ReqContext) response.Response {
|
||||
id := c.ParamsInt64(":alertId")
|
||||
query := models.GetAlertByIdQuery{Id: id}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "List alerts failed", err)
|
||||
return response.Error(500, "List alerts failed", err)
|
||||
}
|
||||
|
||||
return JSON(200, &query.Result)
|
||||
return response.JSON(200, &query.Result)
|
||||
}
|
||||
|
||||
func GetAlertNotifiers(c *models.ReqContext) Response {
|
||||
return JSON(200, alerting.GetNotifiers())
|
||||
func GetAlertNotifiers(c *models.ReqContext) response.Response {
|
||||
return response.JSON(200, alerting.GetNotifiers())
|
||||
}
|
||||
|
||||
func GetAlertNotificationLookup(c *models.ReqContext) Response {
|
||||
func GetAlertNotificationLookup(c *models.ReqContext) response.Response {
|
||||
alertNotifications, err := getAlertNotificationsInternal(c)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get alert notifications", err)
|
||||
return response.Error(500, "Failed to get alert notifications", err)
|
||||
}
|
||||
|
||||
result := make([]*dtos.AlertNotificationLookup, 0)
|
||||
@@ -201,13 +202,13 @@ func GetAlertNotificationLookup(c *models.ReqContext) Response {
|
||||
result = append(result, dtos.NewAlertNotificationLookup(notification))
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
||||
func GetAlertNotifications(c *models.ReqContext) Response {
|
||||
func GetAlertNotifications(c *models.ReqContext) response.Response {
|
||||
alertNotifications, err := getAlertNotificationsInternal(c)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get alert notifications", err)
|
||||
return response.Error(500, "Failed to get alert notifications", err)
|
||||
}
|
||||
|
||||
result := make([]*dtos.AlertNotification, 0)
|
||||
@@ -216,7 +217,7 @@ func GetAlertNotifications(c *models.ReqContext) Response {
|
||||
result = append(result, dtos.NewAlertNotification(notification))
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
||||
func getAlertNotificationsInternal(c *models.ReqContext) ([]*models.AlertNotification, error) {
|
||||
@@ -229,74 +230,74 @@ func getAlertNotificationsInternal(c *models.ReqContext) ([]*models.AlertNotific
|
||||
return query.Result, nil
|
||||
}
|
||||
|
||||
func GetAlertNotificationByID(c *models.ReqContext) Response {
|
||||
func GetAlertNotificationByID(c *models.ReqContext) response.Response {
|
||||
query := &models.GetAlertNotificationsQuery{
|
||||
OrgId: c.OrgId,
|
||||
Id: c.ParamsInt64("notificationId"),
|
||||
}
|
||||
|
||||
if query.Id == 0 {
|
||||
return Error(404, "Alert notification not found", nil)
|
||||
return response.Error(404, "Alert notification not found", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(query); err != nil {
|
||||
return Error(500, "Failed to get alert notifications", err)
|
||||
return response.Error(500, "Failed to get alert notifications", err)
|
||||
}
|
||||
|
||||
if query.Result == nil {
|
||||
return Error(404, "Alert notification not found", nil)
|
||||
return response.Error(404, "Alert notification not found", nil)
|
||||
}
|
||||
|
||||
return JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
return response.JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func GetAlertNotificationByUID(c *models.ReqContext) Response {
|
||||
func GetAlertNotificationByUID(c *models.ReqContext) response.Response {
|
||||
query := &models.GetAlertNotificationsWithUidQuery{
|
||||
OrgId: c.OrgId,
|
||||
Uid: c.Params("uid"),
|
||||
}
|
||||
|
||||
if query.Uid == "" {
|
||||
return Error(404, "Alert notification not found", nil)
|
||||
return response.Error(404, "Alert notification not found", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(query); err != nil {
|
||||
return Error(500, "Failed to get alert notifications", err)
|
||||
return response.Error(500, "Failed to get alert notifications", err)
|
||||
}
|
||||
|
||||
if query.Result == nil {
|
||||
return Error(404, "Alert notification not found", nil)
|
||||
return response.Error(404, "Alert notification not found", nil)
|
||||
}
|
||||
|
||||
return JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
return response.JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func CreateAlertNotification(c *models.ReqContext, cmd models.CreateAlertNotificationCommand) Response {
|
||||
func CreateAlertNotification(c *models.ReqContext, cmd models.CreateAlertNotificationCommand) response.Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrAlertNotificationWithSameNameExists) || errors.Is(err, models.ErrAlertNotificationWithSameUIDExists) {
|
||||
return Error(409, "Failed to create alert notification", err)
|
||||
return response.Error(409, "Failed to create alert notification", err)
|
||||
}
|
||||
return Error(500, "Failed to create alert notification", err)
|
||||
return response.Error(500, "Failed to create alert notification", err)
|
||||
}
|
||||
|
||||
return JSON(200, dtos.NewAlertNotification(cmd.Result))
|
||||
return response.JSON(200, dtos.NewAlertNotification(cmd.Result))
|
||||
}
|
||||
|
||||
func UpdateAlertNotification(c *models.ReqContext, cmd models.UpdateAlertNotificationCommand) Response {
|
||||
func UpdateAlertNotification(c *models.ReqContext, cmd models.UpdateAlertNotificationCommand) response.Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
err := fillWithSecureSettingsData(&cmd)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to update alert notification", err)
|
||||
return response.Error(500, "Failed to update alert notification", err)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrAlertNotificationNotFound) {
|
||||
return Error(404, err.Error(), err)
|
||||
return response.Error(404, err.Error(), err)
|
||||
}
|
||||
return Error(500, "Failed to update alert notification", err)
|
||||
return response.Error(500, "Failed to update alert notification", err)
|
||||
}
|
||||
|
||||
query := models.GetAlertNotificationsQuery{
|
||||
@@ -305,26 +306,26 @@ func UpdateAlertNotification(c *models.ReqContext, cmd models.UpdateAlertNotific
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to get alert notification", err)
|
||||
return response.Error(500, "Failed to get alert notification", err)
|
||||
}
|
||||
|
||||
return JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
return response.JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func UpdateAlertNotificationByUID(c *models.ReqContext, cmd models.UpdateAlertNotificationWithUidCommand) Response {
|
||||
func UpdateAlertNotificationByUID(c *models.ReqContext, cmd models.UpdateAlertNotificationWithUidCommand) response.Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.Uid = c.Params("uid")
|
||||
|
||||
err := fillWithSecureSettingsDataByUID(&cmd)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to update alert notification", err)
|
||||
return response.Error(500, "Failed to update alert notification", err)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrAlertNotificationNotFound) {
|
||||
return Error(404, err.Error(), nil)
|
||||
return response.Error(404, err.Error(), nil)
|
||||
}
|
||||
return Error(500, "Failed to update alert notification", err)
|
||||
return response.Error(500, "Failed to update alert notification", err)
|
||||
}
|
||||
|
||||
query := models.GetAlertNotificationsWithUidQuery{
|
||||
@@ -333,10 +334,10 @@ func UpdateAlertNotificationByUID(c *models.ReqContext, cmd models.UpdateAlertNo
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to get alert notification", err)
|
||||
return response.Error(500, "Failed to get alert notification", err)
|
||||
}
|
||||
|
||||
return JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
return response.JSON(200, dtos.NewAlertNotification(query.Result))
|
||||
}
|
||||
|
||||
func fillWithSecureSettingsData(cmd *models.UpdateAlertNotificationCommand) error {
|
||||
@@ -387,7 +388,7 @@ func fillWithSecureSettingsDataByUID(cmd *models.UpdateAlertNotificationWithUidC
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteAlertNotification(c *models.ReqContext) Response {
|
||||
func DeleteAlertNotification(c *models.ReqContext) response.Response {
|
||||
cmd := models.DeleteAlertNotificationCommand{
|
||||
OrgId: c.OrgId,
|
||||
Id: c.ParamsInt64("notificationId"),
|
||||
@@ -395,15 +396,15 @@ func DeleteAlertNotification(c *models.ReqContext) Response {
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrAlertNotificationNotFound) {
|
||||
return Error(404, err.Error(), nil)
|
||||
return response.Error(404, err.Error(), nil)
|
||||
}
|
||||
return Error(500, "Failed to delete alert notification", err)
|
||||
return response.Error(500, "Failed to delete alert notification", err)
|
||||
}
|
||||
|
||||
return Success("Notification deleted")
|
||||
return response.Success("Notification deleted")
|
||||
}
|
||||
|
||||
func DeleteAlertNotificationByUID(c *models.ReqContext) Response {
|
||||
func DeleteAlertNotificationByUID(c *models.ReqContext) response.Response {
|
||||
cmd := models.DeleteAlertNotificationWithUidCommand{
|
||||
OrgId: c.OrgId,
|
||||
Uid: c.Params("uid"),
|
||||
@@ -411,19 +412,19 @@ func DeleteAlertNotificationByUID(c *models.ReqContext) Response {
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrAlertNotificationNotFound) {
|
||||
return Error(404, err.Error(), nil)
|
||||
return response.Error(404, err.Error(), nil)
|
||||
}
|
||||
return Error(500, "Failed to delete alert notification", err)
|
||||
return response.Error(500, "Failed to delete alert notification", err)
|
||||
}
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": "Notification deleted",
|
||||
"id": cmd.DeletedAlertNotificationId,
|
||||
})
|
||||
}
|
||||
|
||||
// POST /api/alert-notifications/test
|
||||
func NotificationTest(c *models.ReqContext, dto dtos.NotificationTestCommand) Response {
|
||||
func NotificationTest(c *models.ReqContext, dto dtos.NotificationTestCommand) response.Response {
|
||||
cmd := &alerting.NotificationTestCommand{
|
||||
OrgID: c.OrgId,
|
||||
ID: dto.ID,
|
||||
@@ -435,43 +436,43 @@ func NotificationTest(c *models.ReqContext, dto dtos.NotificationTestCommand) Re
|
||||
|
||||
if err := bus.DispatchCtx(c.Req.Context(), cmd); err != nil {
|
||||
if errors.Is(err, models.ErrSmtpNotEnabled) {
|
||||
return Error(412, err.Error(), err)
|
||||
return response.Error(412, err.Error(), err)
|
||||
}
|
||||
return Error(500, "Failed to send alert notifications", err)
|
||||
return response.Error(500, "Failed to send alert notifications", err)
|
||||
}
|
||||
|
||||
return Success("Test notification sent")
|
||||
return response.Success("Test notification sent")
|
||||
}
|
||||
|
||||
// POST /api/alerts/:alertId/pause
|
||||
func PauseAlert(c *models.ReqContext, dto dtos.PauseAlertCommand) Response {
|
||||
func PauseAlert(c *models.ReqContext, dto dtos.PauseAlertCommand) response.Response {
|
||||
alertID := c.ParamsInt64("alertId")
|
||||
result := make(map[string]interface{})
|
||||
result["alertId"] = alertID
|
||||
|
||||
query := models.GetAlertByIdQuery{Id: alertID}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Get Alert failed", err)
|
||||
return response.Error(500, "Get Alert failed", err)
|
||||
}
|
||||
|
||||
guardian := guardian.New(query.Result.DashboardId, c.OrgId, c.SignedInUser)
|
||||
if canEdit, err := guardian.CanEdit(); err != nil || !canEdit {
|
||||
if err != nil {
|
||||
return Error(500, "Error while checking permissions for Alert", err)
|
||||
return response.Error(500, "Error while checking permissions for Alert", err)
|
||||
}
|
||||
|
||||
return Error(403, "Access denied to this dashboard and alert", nil)
|
||||
return response.Error(403, "Access denied to this dashboard and alert", nil)
|
||||
}
|
||||
|
||||
// Alert state validation
|
||||
if query.Result.State != models.AlertStatePaused && !dto.Paused {
|
||||
result["state"] = "un-paused"
|
||||
result["message"] = "Alert is already un-paused"
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
} else if query.Result.State == models.AlertStatePaused && dto.Paused {
|
||||
result["state"] = models.AlertStatePaused
|
||||
result["message"] = "Alert is already paused"
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
||||
cmd := models.PauseAlertCommand{
|
||||
@@ -481,43 +482,43 @@ func PauseAlert(c *models.ReqContext, dto dtos.PauseAlertCommand) Response {
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "", err)
|
||||
return response.Error(500, "", err)
|
||||
}
|
||||
|
||||
var response models.AlertStateType = models.AlertStateUnknown
|
||||
var resp models.AlertStateType = models.AlertStateUnknown
|
||||
pausedState := "un-paused"
|
||||
if cmd.Paused {
|
||||
response = models.AlertStatePaused
|
||||
resp = models.AlertStatePaused
|
||||
pausedState = "paused"
|
||||
}
|
||||
|
||||
result["state"] = response
|
||||
result["state"] = resp
|
||||
result["message"] = "Alert " + pausedState
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
||||
// POST /api/admin/pause-all-alerts
|
||||
func PauseAllAlerts(c *models.ReqContext, dto dtos.PauseAllAlertsCommand) Response {
|
||||
func PauseAllAlerts(c *models.ReqContext, dto dtos.PauseAllAlertsCommand) response.Response {
|
||||
updateCmd := models.PauseAllAlertCommand{
|
||||
Paused: dto.Paused,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&updateCmd); err != nil {
|
||||
return Error(500, "Failed to pause alerts", err)
|
||||
return response.Error(500, "Failed to pause alerts", err)
|
||||
}
|
||||
|
||||
var response models.AlertStateType = models.AlertStatePending
|
||||
var resp models.AlertStateType = models.AlertStatePending
|
||||
pausedState := "un paused"
|
||||
if updateCmd.Paused {
|
||||
response = models.AlertStatePaused
|
||||
resp = models.AlertStatePaused
|
||||
pausedState = "paused"
|
||||
}
|
||||
|
||||
result := map[string]interface{}{
|
||||
"state": response,
|
||||
"state": resp,
|
||||
"message": "alerts " + pausedState,
|
||||
"alertsAffected": updateCmd.ResultCount,
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
@@ -4,7 +4,10 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
|
||||
"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/services/search"
|
||||
@@ -162,7 +165,7 @@ func postAlertScenario(t *testing.T, desc string, url string, routePattern strin
|
||||
defer bus.ClearBusHandlers()
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
|
@@ -4,13 +4,14 @@ import (
|
||||
"strings"
|
||||
|
||||
"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/annotations"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func GetAnnotations(c *models.ReqContext) Response {
|
||||
func GetAnnotations(c *models.ReqContext) response.Response {
|
||||
query := &annotations.ItemQuery{
|
||||
From: c.QueryInt64("from"),
|
||||
To: c.QueryInt64("to"),
|
||||
@@ -29,7 +30,7 @@ func GetAnnotations(c *models.ReqContext) Response {
|
||||
|
||||
items, err := repo.Find(query)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get annotations", err)
|
||||
return response.Error(500, "Failed to get annotations", err)
|
||||
}
|
||||
|
||||
for _, item := range items {
|
||||
@@ -38,7 +39,7 @@ func GetAnnotations(c *models.ReqContext) Response {
|
||||
}
|
||||
}
|
||||
|
||||
return JSON(200, items)
|
||||
return response.JSON(200, items)
|
||||
}
|
||||
|
||||
type CreateAnnotationError struct {
|
||||
@@ -49,7 +50,7 @@ func (e *CreateAnnotationError) Error() string {
|
||||
return e.message
|
||||
}
|
||||
|
||||
func PostAnnotation(c *models.ReqContext, cmd dtos.PostAnnotationsCmd) Response {
|
||||
func PostAnnotation(c *models.ReqContext, cmd dtos.PostAnnotationsCmd) response.Response {
|
||||
if canSave, err := canSaveByDashboardID(c, cmd.DashboardId); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
}
|
||||
@@ -58,7 +59,7 @@ func PostAnnotation(c *models.ReqContext, cmd dtos.PostAnnotationsCmd) Response
|
||||
|
||||
if cmd.Text == "" {
|
||||
err := &CreateAnnotationError{"text field should not be empty"}
|
||||
return Error(500, "Failed to save annotation", err)
|
||||
return response.Error(500, "Failed to save annotation", err)
|
||||
}
|
||||
|
||||
item := annotations.Item{
|
||||
@@ -74,12 +75,12 @@ func PostAnnotation(c *models.ReqContext, cmd dtos.PostAnnotationsCmd) Response
|
||||
}
|
||||
|
||||
if err := repo.Save(&item); err != nil {
|
||||
return Error(500, "Failed to save annotation", err)
|
||||
return response.Error(500, "Failed to save annotation", err)
|
||||
}
|
||||
|
||||
startID := item.Id
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": "Annotation added",
|
||||
"id": startID,
|
||||
})
|
||||
@@ -93,12 +94,12 @@ func formatGraphiteAnnotation(what string, data string) string {
|
||||
return text
|
||||
}
|
||||
|
||||
func PostGraphiteAnnotation(c *models.ReqContext, cmd dtos.PostGraphiteAnnotationsCmd) Response {
|
||||
func PostGraphiteAnnotation(c *models.ReqContext, cmd dtos.PostGraphiteAnnotationsCmd) response.Response {
|
||||
repo := annotations.GetRepository()
|
||||
|
||||
if cmd.What == "" {
|
||||
err := &CreateAnnotationError{"what field should not be empty"}
|
||||
return Error(500, "Failed to save Graphite annotation", err)
|
||||
return response.Error(500, "Failed to save Graphite annotation", err)
|
||||
}
|
||||
|
||||
text := formatGraphiteAnnotation(cmd.What, cmd.Data)
|
||||
@@ -118,12 +119,12 @@ func PostGraphiteAnnotation(c *models.ReqContext, cmd dtos.PostGraphiteAnnotatio
|
||||
tagsArray = append(tagsArray, tagStr)
|
||||
} else {
|
||||
err := &CreateAnnotationError{"tag should be a string"}
|
||||
return Error(500, "Failed to save Graphite annotation", err)
|
||||
return response.Error(500, "Failed to save Graphite annotation", err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
err := &CreateAnnotationError{"unsupported tags format"}
|
||||
return Error(500, "Failed to save Graphite annotation", err)
|
||||
return response.Error(500, "Failed to save Graphite annotation", err)
|
||||
}
|
||||
|
||||
item := annotations.Item{
|
||||
@@ -135,16 +136,16 @@ func PostGraphiteAnnotation(c *models.ReqContext, cmd dtos.PostGraphiteAnnotatio
|
||||
}
|
||||
|
||||
if err := repo.Save(&item); err != nil {
|
||||
return Error(500, "Failed to save Graphite annotation", err)
|
||||
return response.Error(500, "Failed to save Graphite annotation", err)
|
||||
}
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": "Graphite annotation added",
|
||||
"id": item.Id,
|
||||
})
|
||||
}
|
||||
|
||||
func UpdateAnnotation(c *models.ReqContext, cmd dtos.UpdateAnnotationsCmd) Response {
|
||||
func UpdateAnnotation(c *models.ReqContext, cmd dtos.UpdateAnnotationsCmd) response.Response {
|
||||
annotationID := c.ParamsInt64(":annotationId")
|
||||
|
||||
repo := annotations.GetRepository()
|
||||
@@ -164,13 +165,13 @@ func UpdateAnnotation(c *models.ReqContext, cmd dtos.UpdateAnnotationsCmd) Respo
|
||||
}
|
||||
|
||||
if err := repo.Update(&item); err != nil {
|
||||
return Error(500, "Failed to update annotation", err)
|
||||
return response.Error(500, "Failed to update annotation", err)
|
||||
}
|
||||
|
||||
return Success("Annotation updated")
|
||||
return response.Success("Annotation updated")
|
||||
}
|
||||
|
||||
func PatchAnnotation(c *models.ReqContext, cmd dtos.PatchAnnotationsCmd) Response {
|
||||
func PatchAnnotation(c *models.ReqContext, cmd dtos.PatchAnnotationsCmd) response.Response {
|
||||
annotationID := c.ParamsInt64(":annotationId")
|
||||
|
||||
repo := annotations.GetRepository()
|
||||
@@ -182,7 +183,7 @@ func PatchAnnotation(c *models.ReqContext, cmd dtos.PatchAnnotationsCmd) Respons
|
||||
items, err := repo.Find(&annotations.ItemQuery{AnnotationId: annotationID, OrgId: c.OrgId})
|
||||
|
||||
if err != nil || len(items) == 0 {
|
||||
return Error(404, "Could not find annotation to update", err)
|
||||
return response.Error(404, "Could not find annotation to update", err)
|
||||
}
|
||||
|
||||
existing := annotations.Item{
|
||||
@@ -212,13 +213,13 @@ func PatchAnnotation(c *models.ReqContext, cmd dtos.PatchAnnotationsCmd) Respons
|
||||
}
|
||||
|
||||
if err := repo.Update(&existing); err != nil {
|
||||
return Error(500, "Failed to update annotation", err)
|
||||
return response.Error(500, "Failed to update annotation", err)
|
||||
}
|
||||
|
||||
return Success("Annotation patched")
|
||||
return response.Success("Annotation patched")
|
||||
}
|
||||
|
||||
func DeleteAnnotations(c *models.ReqContext, cmd dtos.DeleteAnnotationsCmd) Response {
|
||||
func DeleteAnnotations(c *models.ReqContext, cmd dtos.DeleteAnnotationsCmd) response.Response {
|
||||
repo := annotations.GetRepository()
|
||||
|
||||
err := repo.Delete(&annotations.DeleteParams{
|
||||
@@ -229,13 +230,13 @@ func DeleteAnnotations(c *models.ReqContext, cmd dtos.DeleteAnnotationsCmd) Resp
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return Error(500, "Failed to delete annotations", err)
|
||||
return response.Error(500, "Failed to delete annotations", err)
|
||||
}
|
||||
|
||||
return Success("Annotations deleted")
|
||||
return response.Success("Annotations deleted")
|
||||
}
|
||||
|
||||
func DeleteAnnotationByID(c *models.ReqContext) Response {
|
||||
func DeleteAnnotationByID(c *models.ReqContext) response.Response {
|
||||
repo := annotations.GetRepository()
|
||||
annotationID := c.ParamsInt64(":annotationId")
|
||||
|
||||
@@ -248,10 +249,10 @@ func DeleteAnnotationByID(c *models.ReqContext) Response {
|
||||
Id: annotationID,
|
||||
})
|
||||
if err != nil {
|
||||
return Error(500, "Failed to delete annotation", err)
|
||||
return response.Error(500, "Failed to delete annotation", err)
|
||||
}
|
||||
|
||||
return Success("Annotation deleted")
|
||||
return response.Success("Annotation deleted")
|
||||
}
|
||||
|
||||
func canSaveByDashboardID(c *models.ReqContext, dashboardID int64) (bool, error) {
|
||||
@@ -269,10 +270,10 @@ func canSaveByDashboardID(c *models.ReqContext, dashboardID int64) (bool, error)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func canSave(c *models.ReqContext, repo annotations.Repository, annotationID int64) Response {
|
||||
func canSave(c *models.ReqContext, repo annotations.Repository, annotationID int64) response.Response {
|
||||
items, err := repo.Find(&annotations.ItemQuery{AnnotationId: annotationID, OrgId: c.OrgId})
|
||||
if err != nil || len(items) == 0 {
|
||||
return Error(500, "Could not find annotation to update", err)
|
||||
return response.Error(500, "Could not find annotation to update", err)
|
||||
}
|
||||
|
||||
dashboardID := items[0].DashboardId
|
||||
|
@@ -5,6 +5,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/annotations"
|
||||
@@ -266,7 +268,7 @@ func postAnnotationScenario(t *testing.T, desc string, url string, routePattern
|
||||
t.Cleanup(bus.ClearBusHandlers)
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
@@ -290,7 +292,7 @@ func putAnnotationScenario(t *testing.T, desc string, url string, routePattern s
|
||||
t.Cleanup(bus.ClearBusHandlers)
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
@@ -313,7 +315,7 @@ func patchAnnotationScenario(t *testing.T, desc string, url string, routePattern
|
||||
defer bus.ClearBusHandlers()
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
@@ -337,7 +339,7 @@ func deleteAnnotationsScenario(t *testing.T, desc string, url string, routePatte
|
||||
defer bus.ClearBusHandlers()
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
|
360
pkg/api/api.go
360
pkg/api/api.go
@@ -33,7 +33,7 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
|
||||
// not logged in views
|
||||
r.Get("/logout", hs.Logout)
|
||||
r.Post("/login", quota("session"), bind(dtos.LoginCommand{}), Wrap(hs.LoginPost))
|
||||
r.Post("/login", quota("session"), bind(dtos.LoginCommand{}), routing.Wrap(hs.LoginPost))
|
||||
r.Get("/login/:name", quota("session"), hs.OAuthLogin)
|
||||
r.Get("/login", hs.LoginView)
|
||||
r.Get("/invite/:code", hs.Index)
|
||||
@@ -100,180 +100,180 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
// sign up
|
||||
r.Get("/verify", hs.Index)
|
||||
r.Get("/signup", hs.Index)
|
||||
r.Get("/api/user/signup/options", Wrap(GetSignUpOptions))
|
||||
r.Post("/api/user/signup", quota("user"), bind(dtos.SignUpForm{}), Wrap(SignUp))
|
||||
r.Post("/api/user/signup/step2", bind(dtos.SignUpStep2Form{}), Wrap(hs.SignUpStep2))
|
||||
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))
|
||||
|
||||
// invited
|
||||
r.Get("/api/user/invite/:code", Wrap(GetInviteInfoByCode))
|
||||
r.Post("/api/user/invite/complete", bind(dtos.CompleteInviteForm{}), Wrap(hs.CompleteInvite))
|
||||
r.Get("/api/user/invite/:code", routing.Wrap(GetInviteInfoByCode))
|
||||
r.Post("/api/user/invite/complete", bind(dtos.CompleteInviteForm{}), routing.Wrap(hs.CompleteInvite))
|
||||
|
||||
// reset password
|
||||
r.Get("/user/password/send-reset-email", hs.Index)
|
||||
r.Get("/user/password/reset", hs.Index)
|
||||
|
||||
r.Post("/api/user/password/send-reset-email", bind(dtos.SendResetPasswordEmailForm{}), Wrap(SendResetPasswordEmail))
|
||||
r.Post("/api/user/password/reset", bind(dtos.ResetUserPasswordForm{}), Wrap(ResetPassword))
|
||||
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))
|
||||
|
||||
// dashboard snapshots
|
||||
r.Get("/dashboard/snapshot/*", hs.Index)
|
||||
r.Get("/dashboard/snapshots/", reqSignedIn, hs.Index)
|
||||
|
||||
// api renew session based on cookie
|
||||
r.Get("/api/login/ping", quota("session"), Wrap(hs.LoginAPIPing))
|
||||
r.Get("/api/login/ping", quota("session"), routing.Wrap(hs.LoginAPIPing))
|
||||
|
||||
// authed api
|
||||
r.Group("/api", func(apiRoute routing.RouteRegister) {
|
||||
// user (signed in)
|
||||
apiRoute.Group("/user", func(userRoute routing.RouteRegister) {
|
||||
userRoute.Get("/", Wrap(GetSignedInUser))
|
||||
userRoute.Put("/", bind(models.UpdateUserCommand{}), Wrap(UpdateSignedInUser))
|
||||
userRoute.Post("/using/:id", Wrap(UserSetUsingOrg))
|
||||
userRoute.Get("/orgs", Wrap(GetSignedInUserOrgList))
|
||||
userRoute.Get("/teams", Wrap(GetSignedInUserTeamList))
|
||||
userRoute.Get("/", routing.Wrap(GetSignedInUser))
|
||||
userRoute.Put("/", bind(models.UpdateUserCommand{}), routing.Wrap(UpdateSignedInUser))
|
||||
userRoute.Post("/using/:id", routing.Wrap(UserSetUsingOrg))
|
||||
userRoute.Get("/orgs", routing.Wrap(GetSignedInUserOrgList))
|
||||
userRoute.Get("/teams", routing.Wrap(GetSignedInUserTeamList))
|
||||
|
||||
userRoute.Post("/stars/dashboard/:id", Wrap(StarDashboard))
|
||||
userRoute.Delete("/stars/dashboard/:id", Wrap(UnstarDashboard))
|
||||
userRoute.Post("/stars/dashboard/:id", routing.Wrap(StarDashboard))
|
||||
userRoute.Delete("/stars/dashboard/:id", routing.Wrap(UnstarDashboard))
|
||||
|
||||
userRoute.Put("/password", bind(models.ChangeUserPasswordCommand{}), Wrap(ChangeUserPassword))
|
||||
userRoute.Get("/quotas", Wrap(GetUserQuotas))
|
||||
userRoute.Put("/helpflags/:id", Wrap(SetHelpFlag))
|
||||
userRoute.Put("/password", bind(models.ChangeUserPasswordCommand{}), routing.Wrap(ChangeUserPassword))
|
||||
userRoute.Get("/quotas", routing.Wrap(GetUserQuotas))
|
||||
userRoute.Put("/helpflags/:id", routing.Wrap(SetHelpFlag))
|
||||
// For dev purpose
|
||||
userRoute.Get("/helpflags/clear", Wrap(ClearHelpFlags))
|
||||
userRoute.Get("/helpflags/clear", routing.Wrap(ClearHelpFlags))
|
||||
|
||||
userRoute.Get("/preferences", Wrap(GetUserPreferences))
|
||||
userRoute.Put("/preferences", bind(dtos.UpdatePrefsCmd{}), Wrap(UpdateUserPreferences))
|
||||
userRoute.Get("/preferences", routing.Wrap(GetUserPreferences))
|
||||
userRoute.Put("/preferences", bind(dtos.UpdatePrefsCmd{}), routing.Wrap(UpdateUserPreferences))
|
||||
|
||||
userRoute.Get("/auth-tokens", Wrap(hs.GetUserAuthTokens))
|
||||
userRoute.Post("/revoke-auth-token", bind(models.RevokeAuthTokenCmd{}), Wrap(hs.RevokeUserAuthToken))
|
||||
userRoute.Get("/auth-tokens", routing.Wrap(hs.GetUserAuthTokens))
|
||||
userRoute.Post("/revoke-auth-token", bind(models.RevokeAuthTokenCmd{}), routing.Wrap(hs.RevokeUserAuthToken))
|
||||
})
|
||||
|
||||
// users (admin permission required)
|
||||
apiRoute.Group("/users", func(usersRoute routing.RouteRegister) {
|
||||
usersRoute.Get("/", Wrap(SearchUsers))
|
||||
usersRoute.Get("/search", Wrap(SearchUsersWithPaging))
|
||||
usersRoute.Get("/:id", Wrap(GetUserByID))
|
||||
usersRoute.Get("/:id/teams", Wrap(GetUserTeams))
|
||||
usersRoute.Get("/:id/orgs", Wrap(GetUserOrgList))
|
||||
usersRoute.Get("/", routing.Wrap(SearchUsers))
|
||||
usersRoute.Get("/search", routing.Wrap(SearchUsersWithPaging))
|
||||
usersRoute.Get("/:id", routing.Wrap(GetUserByID))
|
||||
usersRoute.Get("/:id/teams", routing.Wrap(GetUserTeams))
|
||||
usersRoute.Get("/:id/orgs", routing.Wrap(GetUserOrgList))
|
||||
// query parameters /users/lookup?loginOrEmail=admin@example.com
|
||||
usersRoute.Get("/lookup", Wrap(GetUserByLoginOrEmail))
|
||||
usersRoute.Put("/:id", bind(models.UpdateUserCommand{}), Wrap(UpdateUser))
|
||||
usersRoute.Post("/:id/using/:orgId", Wrap(UpdateUserActiveOrg))
|
||||
usersRoute.Get("/lookup", routing.Wrap(GetUserByLoginOrEmail))
|
||||
usersRoute.Put("/:id", bind(models.UpdateUserCommand{}), routing.Wrap(UpdateUser))
|
||||
usersRoute.Post("/:id/using/:orgId", routing.Wrap(UpdateUserActiveOrg))
|
||||
}, reqGrafanaAdmin)
|
||||
|
||||
// team (admin permission required)
|
||||
apiRoute.Group("/teams", func(teamsRoute routing.RouteRegister) {
|
||||
teamsRoute.Post("/", bind(models.CreateTeamCommand{}), Wrap(hs.CreateTeam))
|
||||
teamsRoute.Put("/:teamId", bind(models.UpdateTeamCommand{}), Wrap(hs.UpdateTeam))
|
||||
teamsRoute.Delete("/:teamId", Wrap(hs.DeleteTeamByID))
|
||||
teamsRoute.Get("/:teamId/members", Wrap(hs.GetTeamMembers))
|
||||
teamsRoute.Post("/:teamId/members", bind(models.AddTeamMemberCommand{}), Wrap(hs.AddTeamMember))
|
||||
teamsRoute.Put("/:teamId/members/:userId", bind(models.UpdateTeamMemberCommand{}), Wrap(hs.UpdateTeamMember))
|
||||
teamsRoute.Delete("/:teamId/members/:userId", Wrap(hs.RemoveTeamMember))
|
||||
teamsRoute.Get("/:teamId/preferences", Wrap(hs.GetTeamPreferences))
|
||||
teamsRoute.Put("/:teamId/preferences", bind(dtos.UpdatePrefsCmd{}), Wrap(hs.UpdateTeamPreferences))
|
||||
teamsRoute.Post("/", bind(models.CreateTeamCommand{}), routing.Wrap(hs.CreateTeam))
|
||||
teamsRoute.Put("/:teamId", bind(models.UpdateTeamCommand{}), 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.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))
|
||||
}, reqCanAccessTeams)
|
||||
|
||||
// team without requirement of user to be org admin
|
||||
apiRoute.Group("/teams", func(teamsRoute routing.RouteRegister) {
|
||||
teamsRoute.Get("/:teamId", Wrap(hs.GetTeamByID))
|
||||
teamsRoute.Get("/search", Wrap(hs.SearchTeams))
|
||||
teamsRoute.Get("/:teamId", routing.Wrap(hs.GetTeamByID))
|
||||
teamsRoute.Get("/search", routing.Wrap(hs.SearchTeams))
|
||||
})
|
||||
|
||||
// org information available to all users.
|
||||
apiRoute.Group("/org", func(orgRoute routing.RouteRegister) {
|
||||
orgRoute.Get("/", Wrap(GetOrgCurrent))
|
||||
orgRoute.Get("/quotas", Wrap(GetOrgQuotas))
|
||||
orgRoute.Get("/", routing.Wrap(GetOrgCurrent))
|
||||
orgRoute.Get("/quotas", routing.Wrap(GetOrgQuotas))
|
||||
})
|
||||
|
||||
// current org
|
||||
apiRoute.Group("/org", func(orgRoute routing.RouteRegister) {
|
||||
orgRoute.Put("/", bind(dtos.UpdateOrgForm{}), Wrap(UpdateOrgCurrent))
|
||||
orgRoute.Put("/address", bind(dtos.UpdateOrgAddressForm{}), Wrap(UpdateOrgAddressCurrent))
|
||||
orgRoute.Get("/users", Wrap(hs.GetOrgUsersForCurrentOrg))
|
||||
orgRoute.Post("/users", quota("user"), bind(models.AddOrgUserCommand{}), Wrap(AddOrgUserToCurrentOrg))
|
||||
orgRoute.Patch("/users/:userId", bind(models.UpdateOrgUserCommand{}), Wrap(UpdateOrgUserForCurrentOrg))
|
||||
orgRoute.Delete("/users/:userId", Wrap(RemoveOrgUserForCurrentOrg))
|
||||
orgRoute.Put("/", bind(dtos.UpdateOrgForm{}), routing.Wrap(UpdateOrgCurrent))
|
||||
orgRoute.Put("/address", bind(dtos.UpdateOrgAddressForm{}), routing.Wrap(UpdateOrgAddressCurrent))
|
||||
orgRoute.Get("/users", routing.Wrap(hs.GetOrgUsersForCurrentOrg))
|
||||
orgRoute.Post("/users", quota("user"), bind(models.AddOrgUserCommand{}), routing.Wrap(AddOrgUserToCurrentOrg))
|
||||
orgRoute.Patch("/users/:userId", bind(models.UpdateOrgUserCommand{}), routing.Wrap(UpdateOrgUserForCurrentOrg))
|
||||
orgRoute.Delete("/users/:userId", routing.Wrap(RemoveOrgUserForCurrentOrg))
|
||||
|
||||
// invites
|
||||
orgRoute.Get("/invites", Wrap(GetPendingOrgInvites))
|
||||
orgRoute.Post("/invites", quota("user"), bind(dtos.AddInviteForm{}), Wrap(AddOrgInvite))
|
||||
orgRoute.Patch("/invites/:code/revoke", Wrap(RevokeInvite))
|
||||
orgRoute.Get("/invites", routing.Wrap(GetPendingOrgInvites))
|
||||
orgRoute.Post("/invites", quota("user"), bind(dtos.AddInviteForm{}), routing.Wrap(AddOrgInvite))
|
||||
orgRoute.Patch("/invites/:code/revoke", routing.Wrap(RevokeInvite))
|
||||
|
||||
// prefs
|
||||
orgRoute.Get("/preferences", Wrap(GetOrgPreferences))
|
||||
orgRoute.Put("/preferences", bind(dtos.UpdatePrefsCmd{}), Wrap(UpdateOrgPreferences))
|
||||
orgRoute.Get("/preferences", routing.Wrap(GetOrgPreferences))
|
||||
orgRoute.Put("/preferences", bind(dtos.UpdatePrefsCmd{}), routing.Wrap(UpdateOrgPreferences))
|
||||
}, reqOrgAdmin)
|
||||
|
||||
// current org without requirement of user to be org admin
|
||||
apiRoute.Group("/org", func(orgRoute routing.RouteRegister) {
|
||||
orgRoute.Get("/users/lookup", Wrap(hs.GetOrgUsersForCurrentOrgLookup))
|
||||
orgRoute.Get("/users/lookup", routing.Wrap(hs.GetOrgUsersForCurrentOrgLookup))
|
||||
})
|
||||
|
||||
// create new org
|
||||
apiRoute.Post("/orgs", quota("org"), bind(models.CreateOrgCommand{}), Wrap(CreateOrg))
|
||||
apiRoute.Post("/orgs", quota("org"), bind(models.CreateOrgCommand{}), routing.Wrap(CreateOrg))
|
||||
|
||||
// search all orgs
|
||||
apiRoute.Get("/orgs", reqGrafanaAdmin, Wrap(SearchOrgs))
|
||||
apiRoute.Get("/orgs", reqGrafanaAdmin, routing.Wrap(SearchOrgs))
|
||||
|
||||
// orgs (admin routes)
|
||||
apiRoute.Group("/orgs/:orgId", func(orgsRoute routing.RouteRegister) {
|
||||
orgsRoute.Get("/", Wrap(GetOrgByID))
|
||||
orgsRoute.Put("/", bind(dtos.UpdateOrgForm{}), Wrap(UpdateOrg))
|
||||
orgsRoute.Put("/address", bind(dtos.UpdateOrgAddressForm{}), Wrap(UpdateOrgAddress))
|
||||
orgsRoute.Delete("/", Wrap(DeleteOrgByID))
|
||||
orgsRoute.Get("/users", Wrap(hs.GetOrgUsers))
|
||||
orgsRoute.Post("/users", bind(models.AddOrgUserCommand{}), Wrap(AddOrgUser))
|
||||
orgsRoute.Patch("/users/:userId", bind(models.UpdateOrgUserCommand{}), Wrap(UpdateOrgUser))
|
||||
orgsRoute.Delete("/users/:userId", Wrap(RemoveOrgUser))
|
||||
orgsRoute.Get("/quotas", Wrap(GetOrgQuotas))
|
||||
orgsRoute.Put("/quotas/:target", bind(models.UpdateOrgQuotaCmd{}), Wrap(UpdateOrgQuota))
|
||||
orgsRoute.Get("/", routing.Wrap(GetOrgByID))
|
||||
orgsRoute.Put("/", bind(dtos.UpdateOrgForm{}), routing.Wrap(UpdateOrg))
|
||||
orgsRoute.Put("/address", bind(dtos.UpdateOrgAddressForm{}), routing.Wrap(UpdateOrgAddress))
|
||||
orgsRoute.Delete("/", routing.Wrap(DeleteOrgByID))
|
||||
orgsRoute.Get("/users", routing.Wrap(hs.GetOrgUsers))
|
||||
orgsRoute.Post("/users", bind(models.AddOrgUserCommand{}), routing.Wrap(AddOrgUser))
|
||||
orgsRoute.Patch("/users/:userId", bind(models.UpdateOrgUserCommand{}), routing.Wrap(UpdateOrgUser))
|
||||
orgsRoute.Delete("/users/:userId", routing.Wrap(RemoveOrgUser))
|
||||
orgsRoute.Get("/quotas", routing.Wrap(GetOrgQuotas))
|
||||
orgsRoute.Put("/quotas/:target", bind(models.UpdateOrgQuotaCmd{}), routing.Wrap(UpdateOrgQuota))
|
||||
}, reqGrafanaAdmin)
|
||||
|
||||
// orgs (admin routes)
|
||||
apiRoute.Group("/orgs/name/:name", func(orgsRoute routing.RouteRegister) {
|
||||
orgsRoute.Get("/", Wrap(hs.GetOrgByName))
|
||||
orgsRoute.Get("/", routing.Wrap(hs.GetOrgByName))
|
||||
}, reqGrafanaAdmin)
|
||||
|
||||
// auth api keys
|
||||
apiRoute.Group("/auth/keys", func(keysRoute routing.RouteRegister) {
|
||||
keysRoute.Get("/", Wrap(GetAPIKeys))
|
||||
keysRoute.Post("/", quota("api_key"), bind(models.AddApiKeyCommand{}), Wrap(hs.AddAPIKey))
|
||||
keysRoute.Delete("/:id", Wrap(DeleteAPIKey))
|
||||
keysRoute.Get("/", routing.Wrap(GetAPIKeys))
|
||||
keysRoute.Post("/", quota("api_key"), bind(models.AddApiKeyCommand{}), routing.Wrap(hs.AddAPIKey))
|
||||
keysRoute.Delete("/:id", routing.Wrap(DeleteAPIKey))
|
||||
}, reqOrgAdmin)
|
||||
|
||||
// Preferences
|
||||
apiRoute.Group("/preferences", func(prefRoute routing.RouteRegister) {
|
||||
prefRoute.Post("/set-home-dash", bind(models.SavePreferencesCommand{}), Wrap(SetHomeDashboard))
|
||||
prefRoute.Post("/set-home-dash", bind(models.SavePreferencesCommand{}), routing.Wrap(SetHomeDashboard))
|
||||
})
|
||||
|
||||
// Data sources
|
||||
apiRoute.Group("/datasources", func(datasourceRoute routing.RouteRegister) {
|
||||
datasourceRoute.Get("/", Wrap(hs.GetDataSources))
|
||||
datasourceRoute.Post("/", quota("data_source"), bind(models.AddDataSourceCommand{}), Wrap(AddDataSource))
|
||||
datasourceRoute.Put("/:id", bind(models.UpdateDataSourceCommand{}), Wrap(UpdateDataSource))
|
||||
datasourceRoute.Delete("/:id", Wrap(DeleteDataSourceById))
|
||||
datasourceRoute.Delete("/uid/:uid", Wrap(DeleteDataSourceByUID))
|
||||
datasourceRoute.Delete("/name/:name", Wrap(DeleteDataSourceByName))
|
||||
datasourceRoute.Get("/:id", Wrap(GetDataSourceById))
|
||||
datasourceRoute.Get("/uid/:uid", Wrap(GetDataSourceByUID))
|
||||
datasourceRoute.Get("/name/:name", Wrap(GetDataSourceByName))
|
||||
datasourceRoute.Get("/", routing.Wrap(hs.GetDataSources))
|
||||
datasourceRoute.Post("/", quota("data_source"), bind(models.AddDataSourceCommand{}), routing.Wrap(AddDataSource))
|
||||
datasourceRoute.Put("/:id", bind(models.UpdateDataSourceCommand{}), routing.Wrap(UpdateDataSource))
|
||||
datasourceRoute.Delete("/:id", routing.Wrap(DeleteDataSourceById))
|
||||
datasourceRoute.Delete("/uid/:uid", routing.Wrap(DeleteDataSourceByUID))
|
||||
datasourceRoute.Delete("/name/:name", routing.Wrap(DeleteDataSourceByName))
|
||||
datasourceRoute.Get("/:id", routing.Wrap(GetDataSourceById))
|
||||
datasourceRoute.Get("/uid/:uid", routing.Wrap(GetDataSourceByUID))
|
||||
datasourceRoute.Get("/name/:name", routing.Wrap(GetDataSourceByName))
|
||||
}, reqOrgAdmin)
|
||||
|
||||
apiRoute.Get("/datasources/id/:name", Wrap(GetDataSourceIdByName), reqSignedIn)
|
||||
apiRoute.Get("/datasources/id/:name", routing.Wrap(GetDataSourceIdByName), reqSignedIn)
|
||||
|
||||
apiRoute.Get("/plugins", Wrap(hs.GetPluginList))
|
||||
apiRoute.Get("/plugins/:pluginId/settings", Wrap(GetPluginSettingByID))
|
||||
apiRoute.Get("/plugins/:pluginId/markdown/:name", Wrap(GetPluginMarkdown))
|
||||
apiRoute.Get("/plugins/:pluginId/health", Wrap(hs.CheckHealth))
|
||||
apiRoute.Get("/plugins", routing.Wrap(hs.GetPluginList))
|
||||
apiRoute.Get("/plugins/:pluginId/settings", routing.Wrap(GetPluginSettingByID))
|
||||
apiRoute.Get("/plugins/:pluginId/markdown/:name", routing.Wrap(GetPluginMarkdown))
|
||||
apiRoute.Get("/plugins/:pluginId/health", routing.Wrap(hs.CheckHealth))
|
||||
apiRoute.Any("/plugins/:pluginId/resources", hs.CallResource)
|
||||
apiRoute.Any("/plugins/:pluginId/resources/*", hs.CallResource)
|
||||
apiRoute.Any("/plugins/errors", Wrap(hs.GetPluginErrorsList))
|
||||
apiRoute.Any("/plugins/errors", routing.Wrap(hs.GetPluginErrorsList))
|
||||
|
||||
apiRoute.Group("/plugins", func(pluginRoute routing.RouteRegister) {
|
||||
pluginRoute.Get("/:pluginId/dashboards/", Wrap(GetPluginDashboards))
|
||||
pluginRoute.Post("/:pluginId/settings", bind(models.UpdatePluginSettingCmd{}), Wrap(UpdatePluginSetting))
|
||||
pluginRoute.Get("/:pluginId/metrics", Wrap(hs.CollectPluginMetrics))
|
||||
pluginRoute.Get("/:pluginId/dashboards/", routing.Wrap(GetPluginDashboards))
|
||||
pluginRoute.Post("/:pluginId/settings", bind(models.UpdatePluginSettingCmd{}), routing.Wrap(UpdatePluginSetting))
|
||||
pluginRoute.Get("/:pluginId/metrics", routing.Wrap(hs.CollectPluginMetrics))
|
||||
}, reqOrgAdmin)
|
||||
|
||||
apiRoute.Get("/frontend/settings/", hs.GetFrontendSettings)
|
||||
@@ -281,153 +281,153 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
apiRoute.Any("/datasources/proxy/:id", reqSignedIn, hs.ProxyDataSourceRequest)
|
||||
apiRoute.Any("/datasources/:id/resources", hs.CallDatasourceResource)
|
||||
apiRoute.Any("/datasources/:id/resources/*", hs.CallDatasourceResource)
|
||||
apiRoute.Any("/datasources/:id/health", Wrap(hs.CheckDatasourceHealth))
|
||||
apiRoute.Any("/datasources/:id/health", routing.Wrap(hs.CheckDatasourceHealth))
|
||||
|
||||
// Folders
|
||||
apiRoute.Group("/folders", func(folderRoute routing.RouteRegister) {
|
||||
folderRoute.Get("/", Wrap(GetFolders))
|
||||
folderRoute.Get("/id/:id", Wrap(GetFolderByID))
|
||||
folderRoute.Post("/", bind(models.CreateFolderCommand{}), Wrap(hs.CreateFolder))
|
||||
folderRoute.Get("/", routing.Wrap(GetFolders))
|
||||
folderRoute.Get("/id/:id", routing.Wrap(GetFolderByID))
|
||||
folderRoute.Post("/", bind(models.CreateFolderCommand{}), routing.Wrap(hs.CreateFolder))
|
||||
|
||||
folderRoute.Group("/:uid", func(folderUidRoute routing.RouteRegister) {
|
||||
folderUidRoute.Get("/", Wrap(GetFolderByUID))
|
||||
folderUidRoute.Put("/", bind(models.UpdateFolderCommand{}), Wrap(UpdateFolder))
|
||||
folderUidRoute.Delete("/", Wrap(DeleteFolder))
|
||||
folderUidRoute.Get("/", routing.Wrap(GetFolderByUID))
|
||||
folderUidRoute.Put("/", bind(models.UpdateFolderCommand{}), routing.Wrap(UpdateFolder))
|
||||
folderUidRoute.Delete("/", routing.Wrap(DeleteFolder))
|
||||
|
||||
folderUidRoute.Group("/permissions", func(folderPermissionRoute routing.RouteRegister) {
|
||||
folderPermissionRoute.Get("/", Wrap(hs.GetFolderPermissionList))
|
||||
folderPermissionRoute.Post("/", bind(dtos.UpdateDashboardAclCommand{}), Wrap(hs.UpdateFolderPermissions))
|
||||
folderPermissionRoute.Get("/", routing.Wrap(hs.GetFolderPermissionList))
|
||||
folderPermissionRoute.Post("/", bind(dtos.UpdateDashboardAclCommand{}), routing.Wrap(hs.UpdateFolderPermissions))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Dashboard
|
||||
apiRoute.Group("/dashboards", func(dashboardRoute routing.RouteRegister) {
|
||||
dashboardRoute.Get("/uid/:uid", Wrap(hs.GetDashboard))
|
||||
dashboardRoute.Delete("/uid/:uid", Wrap(DeleteDashboardByUID))
|
||||
dashboardRoute.Get("/uid/:uid", routing.Wrap(hs.GetDashboard))
|
||||
dashboardRoute.Delete("/uid/:uid", routing.Wrap(DeleteDashboardByUID))
|
||||
|
||||
dashboardRoute.Get("/db/:slug", Wrap(hs.GetDashboard))
|
||||
dashboardRoute.Delete("/db/:slug", Wrap(DeleteDashboardBySlug))
|
||||
dashboardRoute.Get("/db/:slug", routing.Wrap(hs.GetDashboard))
|
||||
dashboardRoute.Delete("/db/:slug", routing.Wrap(DeleteDashboardBySlug))
|
||||
|
||||
dashboardRoute.Post("/calculate-diff", bind(dtos.CalculateDiffOptions{}), Wrap(CalculateDashboardDiff))
|
||||
dashboardRoute.Post("/calculate-diff", bind(dtos.CalculateDiffOptions{}), routing.Wrap(CalculateDashboardDiff))
|
||||
|
||||
dashboardRoute.Post("/db", bind(models.SaveDashboardCommand{}), Wrap(hs.PostDashboard))
|
||||
dashboardRoute.Get("/home", Wrap(hs.GetHomeDashboard))
|
||||
dashboardRoute.Post("/db", bind(models.SaveDashboardCommand{}), routing.Wrap(hs.PostDashboard))
|
||||
dashboardRoute.Get("/home", routing.Wrap(hs.GetHomeDashboard))
|
||||
dashboardRoute.Get("/tags", GetDashboardTags)
|
||||
dashboardRoute.Post("/import", bind(dtos.ImportDashboardCommand{}), Wrap(ImportDashboard))
|
||||
dashboardRoute.Post("/import", bind(dtos.ImportDashboardCommand{}), routing.Wrap(ImportDashboard))
|
||||
|
||||
dashboardRoute.Group("/id/:dashboardId", func(dashIdRoute routing.RouteRegister) {
|
||||
dashIdRoute.Get("/versions", Wrap(GetDashboardVersions))
|
||||
dashIdRoute.Get("/versions/:id", Wrap(GetDashboardVersion))
|
||||
dashIdRoute.Post("/restore", bind(dtos.RestoreDashboardVersionCommand{}), Wrap(hs.RestoreDashboardVersion))
|
||||
dashIdRoute.Get("/versions", routing.Wrap(GetDashboardVersions))
|
||||
dashIdRoute.Get("/versions/:id", routing.Wrap(GetDashboardVersion))
|
||||
dashIdRoute.Post("/restore", bind(dtos.RestoreDashboardVersionCommand{}), routing.Wrap(hs.RestoreDashboardVersion))
|
||||
|
||||
dashIdRoute.Group("/permissions", func(dashboardPermissionRoute routing.RouteRegister) {
|
||||
dashboardPermissionRoute.Get("/", Wrap(hs.GetDashboardPermissionList))
|
||||
dashboardPermissionRoute.Post("/", bind(dtos.UpdateDashboardAclCommand{}), Wrap(hs.UpdateDashboardPermissions))
|
||||
dashboardPermissionRoute.Get("/", routing.Wrap(hs.GetDashboardPermissionList))
|
||||
dashboardPermissionRoute.Post("/", bind(dtos.UpdateDashboardAclCommand{}), routing.Wrap(hs.UpdateDashboardPermissions))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// Dashboard snapshots
|
||||
apiRoute.Group("/dashboard/snapshots", func(dashboardRoute routing.RouteRegister) {
|
||||
dashboardRoute.Get("/", Wrap(SearchDashboardSnapshots))
|
||||
dashboardRoute.Get("/", routing.Wrap(SearchDashboardSnapshots))
|
||||
})
|
||||
|
||||
// Playlist
|
||||
apiRoute.Group("/playlists", func(playlistRoute routing.RouteRegister) {
|
||||
playlistRoute.Get("/", Wrap(SearchPlaylists))
|
||||
playlistRoute.Get("/:id", ValidateOrgPlaylist, Wrap(GetPlaylist))
|
||||
playlistRoute.Get("/:id/items", ValidateOrgPlaylist, Wrap(GetPlaylistItems))
|
||||
playlistRoute.Get("/:id/dashboards", ValidateOrgPlaylist, Wrap(GetPlaylistDashboards))
|
||||
playlistRoute.Delete("/:id", reqEditorRole, ValidateOrgPlaylist, Wrap(DeletePlaylist))
|
||||
playlistRoute.Put("/:id", reqEditorRole, bind(models.UpdatePlaylistCommand{}), ValidateOrgPlaylist, Wrap(UpdatePlaylist))
|
||||
playlistRoute.Post("/", reqEditorRole, bind(models.CreatePlaylistCommand{}), Wrap(CreatePlaylist))
|
||||
playlistRoute.Get("/", routing.Wrap(SearchPlaylists))
|
||||
playlistRoute.Get("/:id", ValidateOrgPlaylist, routing.Wrap(GetPlaylist))
|
||||
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))
|
||||
})
|
||||
|
||||
// Search
|
||||
apiRoute.Get("/search/sorting", Wrap(hs.ListSortOptions))
|
||||
apiRoute.Get("/search/", Wrap(Search))
|
||||
apiRoute.Get("/search/sorting", routing.Wrap(hs.ListSortOptions))
|
||||
apiRoute.Get("/search/", routing.Wrap(Search))
|
||||
|
||||
// metrics
|
||||
apiRoute.Post("/tsdb/query", bind(dtos.MetricRequest{}), Wrap(hs.QueryMetrics))
|
||||
apiRoute.Get("/tsdb/testdata/scenarios", Wrap(GetTestDataScenarios))
|
||||
apiRoute.Get("/tsdb/testdata/gensql", reqGrafanaAdmin, Wrap(GenerateSQLTestData))
|
||||
apiRoute.Get("/tsdb/testdata/random-walk", Wrap(GetTestDataRandomWalk))
|
||||
apiRoute.Post("/tsdb/query", bind(dtos.MetricRequest{}), routing.Wrap(hs.QueryMetrics))
|
||||
apiRoute.Get("/tsdb/testdata/scenarios", routing.Wrap(GetTestDataScenarios))
|
||||
apiRoute.Get("/tsdb/testdata/gensql", reqGrafanaAdmin, routing.Wrap(GenerateSQLTestData))
|
||||
apiRoute.Get("/tsdb/testdata/random-walk", routing.Wrap(GetTestDataRandomWalk))
|
||||
|
||||
// DataSource w/ expressions
|
||||
apiRoute.Post("/ds/query", bind(dtos.MetricRequest{}), Wrap(hs.QueryMetricsV2))
|
||||
apiRoute.Post("/ds/query", bind(dtos.MetricRequest{}), routing.Wrap(hs.QueryMetricsV2))
|
||||
|
||||
apiRoute.Group("/alerts", func(alertsRoute routing.RouteRegister) {
|
||||
alertsRoute.Post("/test", bind(dtos.AlertTestCommand{}), Wrap(AlertTest))
|
||||
alertsRoute.Post("/:alertId/pause", reqEditorRole, bind(dtos.PauseAlertCommand{}), Wrap(PauseAlert))
|
||||
alertsRoute.Get("/:alertId", ValidateOrgAlert, Wrap(GetAlert))
|
||||
alertsRoute.Get("/", Wrap(GetAlerts))
|
||||
alertsRoute.Get("/states-for-dashboard", Wrap(GetAlertStatesForDashboard))
|
||||
alertsRoute.Post("/test", bind(dtos.AlertTestCommand{}), routing.Wrap(AlertTest))
|
||||
alertsRoute.Post("/:alertId/pause", reqEditorRole, bind(dtos.PauseAlertCommand{}), routing.Wrap(PauseAlert))
|
||||
alertsRoute.Get("/:alertId", ValidateOrgAlert, routing.Wrap(GetAlert))
|
||||
alertsRoute.Get("/", routing.Wrap(GetAlerts))
|
||||
alertsRoute.Get("/states-for-dashboard", routing.Wrap(GetAlertStatesForDashboard))
|
||||
})
|
||||
|
||||
apiRoute.Get("/alert-notifiers", reqEditorRole, Wrap(GetAlertNotifiers))
|
||||
apiRoute.Get("/alert-notifiers", reqEditorRole, routing.Wrap(GetAlertNotifiers))
|
||||
|
||||
apiRoute.Group("/alert-notifications", func(alertNotifications routing.RouteRegister) {
|
||||
alertNotifications.Get("/", Wrap(GetAlertNotifications))
|
||||
alertNotifications.Post("/test", bind(dtos.NotificationTestCommand{}), Wrap(NotificationTest))
|
||||
alertNotifications.Post("/", bind(models.CreateAlertNotificationCommand{}), Wrap(CreateAlertNotification))
|
||||
alertNotifications.Put("/:notificationId", bind(models.UpdateAlertNotificationCommand{}), Wrap(UpdateAlertNotification))
|
||||
alertNotifications.Get("/:notificationId", Wrap(GetAlertNotificationByID))
|
||||
alertNotifications.Delete("/:notificationId", Wrap(DeleteAlertNotification))
|
||||
alertNotifications.Get("/uid/:uid", Wrap(GetAlertNotificationByUID))
|
||||
alertNotifications.Put("/uid/:uid", bind(models.UpdateAlertNotificationWithUidCommand{}), Wrap(UpdateAlertNotificationByUID))
|
||||
alertNotifications.Delete("/uid/:uid", Wrap(DeleteAlertNotificationByUID))
|
||||
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(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(UpdateAlertNotificationByUID))
|
||||
alertNotifications.Delete("/uid/:uid", routing.Wrap(DeleteAlertNotificationByUID))
|
||||
}, reqEditorRole)
|
||||
|
||||
// alert notifications without requirement of user to be org editor
|
||||
apiRoute.Group("/alert-notifications", func(orgRoute routing.RouteRegister) {
|
||||
orgRoute.Get("/lookup", Wrap(GetAlertNotificationLookup))
|
||||
orgRoute.Get("/lookup", routing.Wrap(GetAlertNotificationLookup))
|
||||
})
|
||||
|
||||
apiRoute.Get("/annotations", Wrap(GetAnnotations))
|
||||
apiRoute.Post("/annotations/mass-delete", reqOrgAdmin, bind(dtos.DeleteAnnotationsCmd{}), Wrap(DeleteAnnotations))
|
||||
apiRoute.Get("/annotations", routing.Wrap(GetAnnotations))
|
||||
apiRoute.Post("/annotations/mass-delete", reqOrgAdmin, bind(dtos.DeleteAnnotationsCmd{}), routing.Wrap(DeleteAnnotations))
|
||||
|
||||
apiRoute.Group("/annotations", func(annotationsRoute routing.RouteRegister) {
|
||||
annotationsRoute.Post("/", bind(dtos.PostAnnotationsCmd{}), Wrap(PostAnnotation))
|
||||
annotationsRoute.Delete("/:annotationId", Wrap(DeleteAnnotationByID))
|
||||
annotationsRoute.Put("/:annotationId", bind(dtos.UpdateAnnotationsCmd{}), Wrap(UpdateAnnotation))
|
||||
annotationsRoute.Patch("/:annotationId", bind(dtos.PatchAnnotationsCmd{}), Wrap(PatchAnnotation))
|
||||
annotationsRoute.Post("/graphite", reqEditorRole, bind(dtos.PostGraphiteAnnotationsCmd{}), Wrap(PostGraphiteAnnotation))
|
||||
annotationsRoute.Post("/", bind(dtos.PostAnnotationsCmd{}), 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))
|
||||
})
|
||||
|
||||
// error test
|
||||
r.Get("/metrics/error", Wrap(GenerateError))
|
||||
r.Get("/metrics/error", routing.Wrap(GenerateError))
|
||||
|
||||
// short urls
|
||||
apiRoute.Post("/short-urls", bind(dtos.CreateShortURLCmd{}), Wrap(hs.createShortURL))
|
||||
apiRoute.Post("/short-urls", bind(dtos.CreateShortURLCmd{}), routing.Wrap(hs.createShortURL))
|
||||
}, reqSignedIn)
|
||||
|
||||
// admin api
|
||||
r.Group("/api/admin", func(adminRoute routing.RouteRegister) {
|
||||
adminRoute.Get("/settings", Wrap(AdminGetSettings))
|
||||
adminRoute.Post("/users", bind(dtos.AdminCreateUserForm{}), Wrap(AdminCreateUser))
|
||||
adminRoute.Put("/users/:id/password", bind(dtos.AdminUpdateUserPasswordForm{}), Wrap(AdminUpdateUserPassword))
|
||||
adminRoute.Put("/users/:id/permissions", bind(dtos.AdminUpdateUserPermissionsForm{}), Wrap(AdminUpdateUserPermissions))
|
||||
adminRoute.Delete("/users/:id", Wrap(AdminDeleteUser))
|
||||
adminRoute.Post("/users/:id/disable", Wrap(hs.AdminDisableUser))
|
||||
adminRoute.Post("/users/:id/enable", Wrap(AdminEnableUser))
|
||||
adminRoute.Get("/users/:id/quotas", Wrap(GetUserQuotas))
|
||||
adminRoute.Put("/users/:id/quotas/:target", bind(models.UpdateUserQuotaCmd{}), Wrap(UpdateUserQuota))
|
||||
adminRoute.Get("/stats", Wrap(AdminGetStats))
|
||||
adminRoute.Post("/pause-all-alerts", bind(dtos.PauseAllAlertsCommand{}), Wrap(PauseAllAlerts))
|
||||
adminRoute.Get("/settings", routing.Wrap(AdminGetSettings))
|
||||
adminRoute.Post("/users", bind(dtos.AdminCreateUserForm{}), routing.Wrap(AdminCreateUser))
|
||||
adminRoute.Put("/users/:id/password", bind(dtos.AdminUpdateUserPasswordForm{}), routing.Wrap(AdminUpdateUserPassword))
|
||||
adminRoute.Put("/users/:id/permissions", bind(dtos.AdminUpdateUserPermissionsForm{}), routing.Wrap(AdminUpdateUserPermissions))
|
||||
adminRoute.Delete("/users/:id", routing.Wrap(AdminDeleteUser))
|
||||
adminRoute.Post("/users/:id/disable", routing.Wrap(hs.AdminDisableUser))
|
||||
adminRoute.Post("/users/:id/enable", routing.Wrap(AdminEnableUser))
|
||||
adminRoute.Get("/users/:id/quotas", routing.Wrap(GetUserQuotas))
|
||||
adminRoute.Put("/users/:id/quotas/:target", bind(models.UpdateUserQuotaCmd{}), routing.Wrap(UpdateUserQuota))
|
||||
adminRoute.Get("/stats", routing.Wrap(AdminGetStats))
|
||||
adminRoute.Post("/pause-all-alerts", bind(dtos.PauseAllAlertsCommand{}), routing.Wrap(PauseAllAlerts))
|
||||
|
||||
adminRoute.Post("/users/:id/logout", Wrap(hs.AdminLogoutUser))
|
||||
adminRoute.Get("/users/:id/auth-tokens", Wrap(hs.AdminGetUserAuthTokens))
|
||||
adminRoute.Post("/users/:id/revoke-auth-token", bind(models.RevokeAuthTokenCmd{}), Wrap(hs.AdminRevokeUserAuthToken))
|
||||
adminRoute.Post("/users/:id/logout", routing.Wrap(hs.AdminLogoutUser))
|
||||
adminRoute.Get("/users/:id/auth-tokens", routing.Wrap(hs.AdminGetUserAuthTokens))
|
||||
adminRoute.Post("/users/:id/revoke-auth-token", bind(models.RevokeAuthTokenCmd{}), routing.Wrap(hs.AdminRevokeUserAuthToken))
|
||||
|
||||
adminRoute.Post("/provisioning/dashboards/reload", Wrap(hs.AdminProvisioningReloadDashboards))
|
||||
adminRoute.Post("/provisioning/plugins/reload", Wrap(hs.AdminProvisioningReloadPlugins))
|
||||
adminRoute.Post("/provisioning/datasources/reload", Wrap(hs.AdminProvisioningReloadDatasources))
|
||||
adminRoute.Post("/provisioning/notifications/reload", Wrap(hs.AdminProvisioningReloadNotifications))
|
||||
adminRoute.Post("/ldap/reload", Wrap(hs.ReloadLDAPCfg))
|
||||
adminRoute.Post("/ldap/sync/:id", Wrap(hs.PostSyncUserWithLDAP))
|
||||
adminRoute.Get("/ldap/:username", Wrap(hs.GetUserFromLDAP))
|
||||
adminRoute.Get("/ldap/status", Wrap(hs.GetLDAPStatus))
|
||||
adminRoute.Post("/provisioning/dashboards/reload", routing.Wrap(hs.AdminProvisioningReloadDashboards))
|
||||
adminRoute.Post("/provisioning/plugins/reload", routing.Wrap(hs.AdminProvisioningReloadPlugins))
|
||||
adminRoute.Post("/provisioning/datasources/reload", routing.Wrap(hs.AdminProvisioningReloadDatasources))
|
||||
adminRoute.Post("/provisioning/notifications/reload", routing.Wrap(hs.AdminProvisioningReloadNotifications))
|
||||
adminRoute.Post("/ldap/reload", routing.Wrap(hs.ReloadLDAPCfg))
|
||||
adminRoute.Post("/ldap/sync/:id", routing.Wrap(hs.PostSyncUserWithLDAP))
|
||||
adminRoute.Get("/ldap/:username", routing.Wrap(hs.GetUserFromLDAP))
|
||||
adminRoute.Get("/ldap/status", routing.Wrap(hs.GetLDAPStatus))
|
||||
}, reqGrafanaAdmin)
|
||||
|
||||
// rendering
|
||||
@@ -443,10 +443,10 @@ func (hs *HTTPServer) registerRoutes() {
|
||||
// Snapshots
|
||||
r.Post("/api/snapshots/", reqSnapshotPublicModeOrSignedIn, bind(models.CreateDashboardSnapshotCommand{}), CreateDashboardSnapshot)
|
||||
r.Get("/api/snapshot/shared-options/", reqSignedIn, GetSharingOptions)
|
||||
r.Get("/api/snapshots/:key", Wrap(GetDashboardSnapshot))
|
||||
r.Get("/api/snapshots-delete/:deleteKey", reqSnapshotPublicModeOrSignedIn, Wrap(DeleteDashboardSnapshotByDeleteKey))
|
||||
r.Delete("/api/snapshots/:key", reqEditorRole, Wrap(DeleteDashboardSnapshot))
|
||||
r.Get("/api/snapshots/:key", routing.Wrap(GetDashboardSnapshot))
|
||||
r.Get("/api/snapshots-delete/:deleteKey", reqSnapshotPublicModeOrSignedIn, routing.Wrap(DeleteDashboardSnapshotByDeleteKey))
|
||||
r.Delete("/api/snapshots/:key", reqEditorRole, routing.Wrap(DeleteDashboardSnapshot))
|
||||
|
||||
// Frontend logs
|
||||
r.Post("/log", middleware.RateLimit(hs.Cfg.Sentry.EndpointRPS, hs.Cfg.Sentry.EndpointBurst, time.Now), bind(frontendSentryEvent{}), Wrap(hs.logFrontendMessage))
|
||||
r.Post("/log", middleware.RateLimit(hs.Cfg.Sentry.EndpointRPS, hs.Cfg.Sentry.EndpointBurst, time.Now), bind(frontendSentryEvent{}), routing.Wrap(hs.logFrontendMessage))
|
||||
}
|
||||
|
@@ -5,16 +5,17 @@ import (
|
||||
"time"
|
||||
|
||||
"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/components/apikeygen"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func GetAPIKeys(c *models.ReqContext) Response {
|
||||
func GetAPIKeys(c *models.ReqContext) response.Response {
|
||||
query := models.GetApiKeysQuery{OrgId: c.OrgId, IncludeExpired: c.QueryBool("includeExpired")}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to list api keys", err)
|
||||
return response.Error(500, "Failed to list api keys", err)
|
||||
}
|
||||
|
||||
result := make([]*models.ApiKeyDTO, len(query.Result))
|
||||
@@ -32,52 +33,52 @@ func GetAPIKeys(c *models.ReqContext) Response {
|
||||
}
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
||||
func DeleteAPIKey(c *models.ReqContext) Response {
|
||||
func DeleteAPIKey(c *models.ReqContext) response.Response {
|
||||
id := c.ParamsInt64(":id")
|
||||
|
||||
cmd := &models.DeleteApiKeyCommand{Id: id, OrgId: c.OrgId}
|
||||
|
||||
err := bus.Dispatch(cmd)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to delete API key", err)
|
||||
return response.Error(500, "Failed to delete API key", err)
|
||||
}
|
||||
|
||||
return Success("API key deleted")
|
||||
return response.Success("API key deleted")
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) AddAPIKey(c *models.ReqContext, cmd models.AddApiKeyCommand) Response {
|
||||
func (hs *HTTPServer) AddAPIKey(c *models.ReqContext, cmd models.AddApiKeyCommand) response.Response {
|
||||
if !cmd.Role.IsValid() {
|
||||
return Error(400, "Invalid role specified", nil)
|
||||
return response.Error(400, "Invalid role specified", nil)
|
||||
}
|
||||
|
||||
if hs.Cfg.ApiKeyMaxSecondsToLive != -1 {
|
||||
if cmd.SecondsToLive == 0 {
|
||||
return Error(400, "Number of seconds before expiration should be set", nil)
|
||||
return response.Error(400, "Number of seconds before expiration should be set", nil)
|
||||
}
|
||||
if cmd.SecondsToLive > hs.Cfg.ApiKeyMaxSecondsToLive {
|
||||
return Error(400, "Number of seconds before expiration is greater than the global limit", nil)
|
||||
return response.Error(400, "Number of seconds before expiration is greater than the global limit", nil)
|
||||
}
|
||||
}
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
newKeyInfo, err := apikeygen.New(cmd.OrgId, cmd.Name)
|
||||
if err != nil {
|
||||
return Error(500, "Generating API key failed", err)
|
||||
return response.Error(500, "Generating API key failed", err)
|
||||
}
|
||||
|
||||
cmd.Key = newKeyInfo.HashedKey
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrInvalidApiKeyExpiration) {
|
||||
return Error(400, err.Error(), nil)
|
||||
return response.Error(400, err.Error(), nil)
|
||||
}
|
||||
if errors.Is(err, models.ErrDuplicateApiKey) {
|
||||
return Error(409, err.Error(), nil)
|
||||
return response.Error(409, err.Error(), nil)
|
||||
}
|
||||
return Error(500, "Failed to add API Key", err)
|
||||
return response.Error(500, "Failed to add API Key", err)
|
||||
}
|
||||
|
||||
result := &dtos.NewApiKeyResult{
|
||||
@@ -86,5 +87,5 @@ func (hs *HTTPServer) AddAPIKey(c *models.ReqContext, cmd models.AddApiKeyComman
|
||||
Key: newKeyInfo.ClientSecret,
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
@@ -1,109 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
ServerError = func(err error) Response {
|
||||
return Error(500, "Server error", err)
|
||||
}
|
||||
)
|
||||
|
||||
func Wrap(action interface{}) macaron.Handler {
|
||||
return func(c *models.ReqContext) {
|
||||
var res Response
|
||||
val, err := c.Invoke(action)
|
||||
if err == nil && val != nil && len(val) > 0 {
|
||||
res = val[0].Interface().(Response)
|
||||
} else {
|
||||
res = ServerError(err)
|
||||
}
|
||||
|
||||
res.WriteTo(c)
|
||||
}
|
||||
}
|
||||
|
||||
// JSON creates a JSON response.
|
||||
func JSON(status int, body interface{}) *NormalResponse {
|
||||
return Respond(status, body).Header("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
// jsonStreaming creates a streaming JSON response.
|
||||
func jsonStreaming(status int, body interface{}) streamingResponse {
|
||||
header := make(http.Header)
|
||||
header.Set("Content-Type", "application/json")
|
||||
return streamingResponse{
|
||||
status: status,
|
||||
body: body,
|
||||
header: header,
|
||||
}
|
||||
}
|
||||
|
||||
// Success create a successful response
|
||||
func Success(message string) *NormalResponse {
|
||||
resp := make(map[string]interface{})
|
||||
resp["message"] = message
|
||||
return JSON(200, resp)
|
||||
}
|
||||
|
||||
// Error creates an error response.
|
||||
func Error(status int, message string, err error) *NormalResponse {
|
||||
data := make(map[string]interface{})
|
||||
|
||||
switch status {
|
||||
case 404:
|
||||
data["message"] = "Not Found"
|
||||
case 500:
|
||||
data["message"] = "Internal Server Error"
|
||||
}
|
||||
|
||||
if message != "" {
|
||||
data["message"] = message
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if setting.Env != setting.Prod {
|
||||
data["error"] = err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
resp := JSON(status, data)
|
||||
|
||||
if err != nil {
|
||||
resp.errMessage = message
|
||||
resp.err = err
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
// Respond creates a response.
|
||||
func Respond(status int, body interface{}) *NormalResponse {
|
||||
var b []byte
|
||||
switch t := body.(type) {
|
||||
case []byte:
|
||||
b = t
|
||||
case string:
|
||||
b = []byte(t)
|
||||
default:
|
||||
var err error
|
||||
if b, err = json.Marshal(body); err != nil {
|
||||
return Error(500, "body json marshal", err)
|
||||
}
|
||||
}
|
||||
return &NormalResponse{
|
||||
body: b,
|
||||
status: status,
|
||||
header: make(http.Header),
|
||||
}
|
||||
}
|
||||
|
||||
func Redirect(location string) *RedirectResponse {
|
||||
return &RedirectResponse{location: location}
|
||||
}
|
@@ -7,6 +7,8 @@ import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/fs"
|
||||
"github.com/grafana/grafana/pkg/infra/remotecache"
|
||||
@@ -30,7 +32,7 @@ func loggedInUserScenarioWithRole(t *testing.T, desc string, method string, url
|
||||
t.Cleanup(bus.ClearBusHandlers)
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
@@ -59,7 +61,7 @@ func anonymousUserScenario(t *testing.T, desc string, method string, url string,
|
||||
defer bus.ClearBusHandlers()
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
if sc.handlerFunc != nil {
|
||||
return sc.handlerFunc(sc.context)
|
||||
@@ -146,7 +148,7 @@ func (sc *scenarioContext) exec() {
|
||||
}
|
||||
|
||||
type scenarioFunc func(c *scenarioContext)
|
||||
type handlerFunc func(c *models.ReqContext) Response
|
||||
type handlerFunc func(c *models.ReqContext) response.Response
|
||||
|
||||
func getContextHandler(t *testing.T, cfg *setting.Cfg) *contexthandler.ContextHandler {
|
||||
t.Helper()
|
||||
|
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
|
||||
"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/components/dashdiffs"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
@@ -38,15 +39,15 @@ func isDashboardStarredByUser(c *models.ReqContext, dashID int64) (bool, error)
|
||||
return query.Result, nil
|
||||
}
|
||||
|
||||
func dashboardGuardianResponse(err error) Response {
|
||||
func dashboardGuardianResponse(err error) response.Response {
|
||||
if err != nil {
|
||||
return Error(500, "Error while checking dashboard permissions", err)
|
||||
return response.Error(500, "Error while checking dashboard permissions", err)
|
||||
}
|
||||
|
||||
return Error(403, "Access denied to this dashboard", nil)
|
||||
return response.Error(403, "Access denied to this dashboard", nil)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) GetDashboard(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetDashboard(c *models.ReqContext) response.Response {
|
||||
slug := c.Params(":slug")
|
||||
uid := c.Params(":uid")
|
||||
dash, rsp := getDashboardHelper(c.OrgId, slug, 0, uid)
|
||||
@@ -64,7 +65,7 @@ func (hs *HTTPServer) GetDashboard(c *models.ReqContext) Response {
|
||||
}
|
||||
}
|
||||
if isEmptyData {
|
||||
return Error(500, "Error while loading dashboard, dashboard data is invalid", nil)
|
||||
return response.Error(500, "Error while loading dashboard, dashboard data is invalid", nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +80,7 @@ func (hs *HTTPServer) GetDashboard(c *models.ReqContext) Response {
|
||||
|
||||
isStarred, err := isDashboardStarredByUser(c, dash.Id)
|
||||
if err != nil {
|
||||
return Error(500, "Error while checking if dashboard was starred by user", err)
|
||||
return response.Error(500, "Error while checking if dashboard was starred by user", err)
|
||||
}
|
||||
|
||||
// Finding creator and last updater of the dashboard
|
||||
@@ -115,7 +116,7 @@ func (hs *HTTPServer) GetDashboard(c *models.ReqContext) Response {
|
||||
if dash.FolderId > 0 {
|
||||
query := models.GetDashboardQuery{Id: dash.FolderId, OrgId: c.OrgId}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Dashboard folder could not be read", err)
|
||||
return response.Error(500, "Dashboard folder could not be read", err)
|
||||
}
|
||||
meta.FolderTitle = query.Result.Title
|
||||
meta.FolderUrl = query.Result.GetUrl()
|
||||
@@ -123,7 +124,7 @@ func (hs *HTTPServer) GetDashboard(c *models.ReqContext) Response {
|
||||
|
||||
provisioningData, err := dashboards.NewProvisioningService().GetProvisionedDashboardDataByDashboardID(dash.Id)
|
||||
if err != nil {
|
||||
return Error(500, "Error while checking if dashboard is provisioned", err)
|
||||
return response.Error(500, "Error while checking if dashboard is provisioned", err)
|
||||
}
|
||||
|
||||
if provisioningData != nil {
|
||||
@@ -152,7 +153,7 @@ func (hs *HTTPServer) GetDashboard(c *models.ReqContext) Response {
|
||||
}
|
||||
|
||||
c.TimeRequest(metrics.MApiDashboardGet)
|
||||
return JSON(200, dto)
|
||||
return response.JSON(200, dto)
|
||||
}
|
||||
|
||||
func getUserLogin(userID int64) string {
|
||||
@@ -164,7 +165,7 @@ func getUserLogin(userID int64) string {
|
||||
return query.Result.Login
|
||||
}
|
||||
|
||||
func getDashboardHelper(orgID int64, slug string, id int64, uid string) (*models.Dashboard, Response) {
|
||||
func getDashboardHelper(orgID int64, slug string, id int64, uid string) (*models.Dashboard, response.Response) {
|
||||
var query models.GetDashboardQuery
|
||||
|
||||
if len(uid) > 0 {
|
||||
@@ -174,31 +175,31 @@ func getDashboardHelper(orgID int64, slug string, id int64, uid string) (*models
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return nil, Error(404, "Dashboard not found", err)
|
||||
return nil, response.Error(404, "Dashboard not found", err)
|
||||
}
|
||||
|
||||
return query.Result, nil
|
||||
}
|
||||
|
||||
func DeleteDashboardBySlug(c *models.ReqContext) Response {
|
||||
func DeleteDashboardBySlug(c *models.ReqContext) response.Response {
|
||||
query := models.GetDashboardsBySlugQuery{OrgId: c.OrgId, Slug: c.Params(":slug")}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to retrieve dashboards by slug", err)
|
||||
return response.Error(500, "Failed to retrieve dashboards by slug", err)
|
||||
}
|
||||
|
||||
if len(query.Result) > 1 {
|
||||
return JSON(412, util.DynMap{"status": "multiple-slugs-exists", "message": models.ErrDashboardsWithSameSlugExists.Error()})
|
||||
return response.JSON(412, util.DynMap{"status": "multiple-slugs-exists", "message": models.ErrDashboardsWithSameSlugExists.Error()})
|
||||
}
|
||||
|
||||
return deleteDashboard(c)
|
||||
}
|
||||
|
||||
func DeleteDashboardByUID(c *models.ReqContext) Response {
|
||||
func DeleteDashboardByUID(c *models.ReqContext) response.Response {
|
||||
return deleteDashboard(c)
|
||||
}
|
||||
|
||||
func deleteDashboard(c *models.ReqContext) Response {
|
||||
func deleteDashboard(c *models.ReqContext) response.Response {
|
||||
dash, rsp := getDashboardHelper(c.OrgId, c.Params(":slug"), 0, c.Params(":uid"))
|
||||
if rsp != nil {
|
||||
return rsp
|
||||
@@ -214,21 +215,21 @@ func deleteDashboard(c *models.ReqContext) Response {
|
||||
var dashboardErr models.DashboardErr
|
||||
if ok := errors.As(err, &dashboardErr); ok {
|
||||
if errors.Is(err, models.ErrDashboardCannotDeleteProvisionedDashboard) {
|
||||
return Error(dashboardErr.StatusCode, dashboardErr.Error(), err)
|
||||
return response.Error(dashboardErr.StatusCode, dashboardErr.Error(), err)
|
||||
}
|
||||
}
|
||||
|
||||
return Error(500, "Failed to delete dashboard", err)
|
||||
return response.Error(500, "Failed to delete dashboard", err)
|
||||
}
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"title": dash.Title,
|
||||
"message": fmt.Sprintf("Dashboard %s deleted", dash.Title),
|
||||
"id": dash.Id,
|
||||
})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) PostDashboard(c *models.ReqContext, cmd models.SaveDashboardCommand) Response {
|
||||
func (hs *HTTPServer) PostDashboard(c *models.ReqContext, cmd models.SaveDashboardCommand) response.Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.UserId = c.UserId
|
||||
|
||||
@@ -238,16 +239,16 @@ func (hs *HTTPServer) PostDashboard(c *models.ReqContext, cmd models.SaveDashboa
|
||||
if newDashboard {
|
||||
limitReached, err := hs.QuotaService.QuotaReached(c, "dashboard")
|
||||
if err != nil {
|
||||
return Error(500, "failed to get quota", err)
|
||||
return response.Error(500, "failed to get quota", err)
|
||||
}
|
||||
if limitReached {
|
||||
return Error(403, "Quota reached", nil)
|
||||
return response.Error(403, "Quota reached", nil)
|
||||
}
|
||||
}
|
||||
|
||||
provisioningData, err := dashboards.NewProvisioningService().GetProvisionedDashboardDataByDashboardID(dash.Id)
|
||||
if err != nil {
|
||||
return Error(500, "Error while checking if dashboard is provisioned", err)
|
||||
return response.Error(500, "Error while checking if dashboard is provisioned", err)
|
||||
}
|
||||
|
||||
allowUiUpdate := true
|
||||
@@ -288,7 +289,7 @@ func (hs *HTTPServer) PostDashboard(c *models.ReqContext, cmd models.SaveDashboa
|
||||
}
|
||||
|
||||
c.TimeRequest(metrics.MApiDashboardSave)
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"status": "success",
|
||||
"slug": dashboard.Slug,
|
||||
"version": dashboard.Version,
|
||||
@@ -298,25 +299,25 @@ func (hs *HTTPServer) PostDashboard(c *models.ReqContext, cmd models.SaveDashboa
|
||||
})
|
||||
}
|
||||
|
||||
func dashboardSaveErrorToApiResponse(err error) Response {
|
||||
func dashboardSaveErrorToApiResponse(err error) response.Response {
|
||||
var dashboardErr models.DashboardErr
|
||||
if ok := errors.As(err, &dashboardErr); ok {
|
||||
if body := dashboardErr.Body(); body != nil {
|
||||
return JSON(dashboardErr.StatusCode, body)
|
||||
return response.JSON(dashboardErr.StatusCode, body)
|
||||
}
|
||||
if errors.Is(dashboardErr, models.ErrDashboardUpdateAccessDenied) {
|
||||
return Error(dashboardErr.StatusCode, dashboardErr.Error(), err)
|
||||
return response.Error(dashboardErr.StatusCode, dashboardErr.Error(), err)
|
||||
}
|
||||
return Error(dashboardErr.StatusCode, dashboardErr.Error(), nil)
|
||||
return response.Error(dashboardErr.StatusCode, dashboardErr.Error(), nil)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderNotFound) {
|
||||
return Error(400, err.Error(), nil)
|
||||
return response.Error(400, err.Error(), nil)
|
||||
}
|
||||
|
||||
var validationErr alerting.ValidationError
|
||||
if ok := errors.As(err, &validationErr); ok {
|
||||
return Error(422, validationErr.Error(), nil)
|
||||
return response.Error(422, validationErr.Error(), nil)
|
||||
}
|
||||
|
||||
var pluginErr models.UpdatePluginDashboardError
|
||||
@@ -326,17 +327,17 @@ func dashboardSaveErrorToApiResponse(err error) Response {
|
||||
if pluginDef, exist := plugins.Plugins[pluginErr.PluginId]; exist {
|
||||
message = fmt.Sprintf("The dashboard belongs to plugin %s.", pluginDef.Name)
|
||||
}
|
||||
return JSON(412, util.DynMap{"status": "plugin-dashboard", "message": message})
|
||||
return response.JSON(412, util.DynMap{"status": "plugin-dashboard", "message": message})
|
||||
}
|
||||
|
||||
return Error(500, "Failed to save dashboard", err)
|
||||
return response.Error(500, "Failed to save dashboard", err)
|
||||
}
|
||||
|
||||
// GetHomeDashboard returns the home dashboard.
|
||||
func (hs *HTTPServer) GetHomeDashboard(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetHomeDashboard(c *models.ReqContext) response.Response {
|
||||
prefsQuery := models.GetPreferencesWithDefaultsQuery{User: c.SignedInUser}
|
||||
if err := hs.Bus.Dispatch(&prefsQuery); err != nil {
|
||||
return Error(500, "Failed to get preferences", err)
|
||||
return response.Error(500, "Failed to get preferences", err)
|
||||
}
|
||||
|
||||
if prefsQuery.Result.HomeDashboardId != 0 {
|
||||
@@ -345,7 +346,7 @@ func (hs *HTTPServer) GetHomeDashboard(c *models.ReqContext) Response {
|
||||
if err == nil {
|
||||
url := models.GetDashboardUrl(slugQuery.Result.Uid, slugQuery.Result.Slug)
|
||||
dashRedirect := dtos.DashboardRedirect{RedirectUri: url}
|
||||
return JSON(200, &dashRedirect)
|
||||
return response.JSON(200, &dashRedirect)
|
||||
}
|
||||
hs.log.Warn("Failed to get slug from database", "err", err)
|
||||
}
|
||||
@@ -360,7 +361,7 @@ func (hs *HTTPServer) GetHomeDashboard(c *models.ReqContext) Response {
|
||||
// nolint:gosec
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to load home dashboard", err)
|
||||
return response.Error(500, "Failed to load home dashboard", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := file.Close(); err != nil {
|
||||
@@ -375,12 +376,12 @@ func (hs *HTTPServer) GetHomeDashboard(c *models.ReqContext) Response {
|
||||
|
||||
jsonParser := json.NewDecoder(file)
|
||||
if err := jsonParser.Decode(&dash.Dashboard); err != nil {
|
||||
return Error(500, "Failed to load home dashboard", err)
|
||||
return response.Error(500, "Failed to load home dashboard", err)
|
||||
}
|
||||
|
||||
hs.addGettingStartedPanelToHomeDashboard(c, dash.Dashboard)
|
||||
|
||||
return JSON(200, &dash)
|
||||
return response.JSON(200, &dash)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) addGettingStartedPanelToHomeDashboard(c *models.ReqContext, dash *simplejson.Json) {
|
||||
@@ -410,7 +411,7 @@ func (hs *HTTPServer) addGettingStartedPanelToHomeDashboard(c *models.ReqContext
|
||||
}
|
||||
|
||||
// GetDashboardVersions returns all dashboard versions as JSON
|
||||
func GetDashboardVersions(c *models.ReqContext) Response {
|
||||
func GetDashboardVersions(c *models.ReqContext) response.Response {
|
||||
dashID := c.ParamsInt64(":dashboardId")
|
||||
|
||||
guardian := guardian.New(dashID, c.OrgId, c.SignedInUser)
|
||||
@@ -426,7 +427,7 @@ func GetDashboardVersions(c *models.ReqContext) Response {
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(404, fmt.Sprintf("No versions found for dashboardId %d", dashID), err)
|
||||
return response.Error(404, fmt.Sprintf("No versions found for dashboardId %d", dashID), err)
|
||||
}
|
||||
|
||||
for _, version := range query.Result {
|
||||
@@ -445,11 +446,11 @@ func GetDashboardVersions(c *models.ReqContext) Response {
|
||||
}
|
||||
}
|
||||
|
||||
return JSON(200, query.Result)
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
// GetDashboardVersion returns the dashboard version with the given ID.
|
||||
func GetDashboardVersion(c *models.ReqContext) Response {
|
||||
func GetDashboardVersion(c *models.ReqContext) response.Response {
|
||||
dashID := c.ParamsInt64(":dashboardId")
|
||||
|
||||
guardian := guardian.New(dashID, c.OrgId, c.SignedInUser)
|
||||
@@ -464,7 +465,7 @@ func GetDashboardVersion(c *models.ReqContext) Response {
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, fmt.Sprintf("Dashboard version %d not found for dashboardId %d", query.Version, dashID), err)
|
||||
return response.Error(500, fmt.Sprintf("Dashboard version %d not found for dashboardId %d", query.Version, dashID), err)
|
||||
}
|
||||
|
||||
creator := anonString
|
||||
@@ -484,11 +485,11 @@ func GetDashboardVersion(c *models.ReqContext) Response {
|
||||
CreatedBy: creator,
|
||||
}
|
||||
|
||||
return JSON(200, dashVersionMeta)
|
||||
return response.JSON(200, dashVersionMeta)
|
||||
}
|
||||
|
||||
// POST /api/dashboards/calculate-diff performs diffs on two dashboards
|
||||
func CalculateDashboardDiff(c *models.ReqContext, apiOptions dtos.CalculateDiffOptions) Response {
|
||||
func CalculateDashboardDiff(c *models.ReqContext, apiOptions dtos.CalculateDiffOptions) response.Response {
|
||||
guardianBase := guardian.New(apiOptions.Base.DashboardId, c.OrgId, c.SignedInUser)
|
||||
if canSave, err := guardianBase.CanSave(); err != nil || !canSave {
|
||||
return dashboardGuardianResponse(err)
|
||||
@@ -519,20 +520,20 @@ func CalculateDashboardDiff(c *models.ReqContext, apiOptions dtos.CalculateDiffO
|
||||
result, err := dashdiffs.CalculateDiff(&options)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDashboardVersionNotFound) {
|
||||
return Error(404, "Dashboard version not found", err)
|
||||
return response.Error(404, "Dashboard version not found", err)
|
||||
}
|
||||
return Error(500, "Unable to compute diff", err)
|
||||
return response.Error(500, "Unable to compute diff", err)
|
||||
}
|
||||
|
||||
if options.DiffType == dashdiffs.DiffDelta {
|
||||
return Respond(200, result.Delta).Header("Content-Type", "application/json")
|
||||
return response.Respond(200, result.Delta).Header("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
return Respond(200, result.Delta).Header("Content-Type", "text/html")
|
||||
return response.Respond(200, result.Delta).Header("Content-Type", "text/html")
|
||||
}
|
||||
|
||||
// RestoreDashboardVersion restores a dashboard to the given version.
|
||||
func (hs *HTTPServer) RestoreDashboardVersion(c *models.ReqContext, apiCmd dtos.RestoreDashboardVersionCommand) Response {
|
||||
func (hs *HTTPServer) RestoreDashboardVersion(c *models.ReqContext, apiCmd dtos.RestoreDashboardVersionCommand) response.Response {
|
||||
dash, rsp := getDashboardHelper(c.OrgId, "", c.ParamsInt64(":dashboardId"), "")
|
||||
if rsp != nil {
|
||||
return rsp
|
||||
@@ -545,7 +546,7 @@ func (hs *HTTPServer) RestoreDashboardVersion(c *models.ReqContext, apiCmd dtos.
|
||||
|
||||
versionQuery := models.GetDashboardVersionQuery{DashboardId: dash.Id, Version: apiCmd.Version, OrgId: c.OrgId}
|
||||
if err := bus.Dispatch(&versionQuery); err != nil {
|
||||
return Error(404, "Dashboard version not found", nil)
|
||||
return response.Error(404, "Dashboard version not found", nil)
|
||||
}
|
||||
|
||||
version := versionQuery.Result
|
||||
|
@@ -5,12 +5,13 @@ import (
|
||||
"time"
|
||||
|
||||
"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/services/guardian"
|
||||
)
|
||||
|
||||
func (hs *HTTPServer) GetDashboardPermissionList(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetDashboardPermissionList(c *models.ReqContext) response.Response {
|
||||
dashID := c.ParamsInt64(":dashboardId")
|
||||
|
||||
_, rsp := getDashboardHelper(c.OrgId, "", dashID, "")
|
||||
@@ -26,7 +27,7 @@ func (hs *HTTPServer) GetDashboardPermissionList(c *models.ReqContext) Response
|
||||
|
||||
acl, err := g.GetAcl()
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get dashboard permissions", err)
|
||||
return response.Error(500, "Failed to get dashboard permissions", err)
|
||||
}
|
||||
|
||||
filteredAcls := make([]*models.DashboardAclInfoDTO, 0, len(acl))
|
||||
@@ -47,12 +48,12 @@ func (hs *HTTPServer) GetDashboardPermissionList(c *models.ReqContext) Response
|
||||
filteredAcls = append(filteredAcls, perm)
|
||||
}
|
||||
|
||||
return JSON(200, filteredAcls)
|
||||
return response.JSON(200, filteredAcls)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateDashboardPermissions(c *models.ReqContext, apiCmd dtos.UpdateDashboardAclCommand) Response {
|
||||
func (hs *HTTPServer) UpdateDashboardPermissions(c *models.ReqContext, apiCmd dtos.UpdateDashboardAclCommand) response.Response {
|
||||
if err := validatePermissionsUpdate(apiCmd); err != nil {
|
||||
return Error(400, err.Error(), err)
|
||||
return response.Error(400, err.Error(), err)
|
||||
}
|
||||
|
||||
dashID := c.ParamsInt64(":dashboardId")
|
||||
@@ -85,31 +86,31 @@ func (hs *HTTPServer) UpdateDashboardPermissions(c *models.ReqContext, apiCmd dt
|
||||
|
||||
hiddenACL, err := g.GetHiddenACL(hs.Cfg)
|
||||
if err != nil {
|
||||
return Error(500, "Error while retrieving hidden permissions", err)
|
||||
return response.Error(500, "Error while retrieving hidden permissions", err)
|
||||
}
|
||||
cmd.Items = append(cmd.Items, hiddenACL...)
|
||||
|
||||
if okToUpdate, err := g.CheckPermissionBeforeUpdate(models.PERMISSION_ADMIN, cmd.Items); err != nil || !okToUpdate {
|
||||
if err != nil {
|
||||
if errors.Is(err, guardian.ErrGuardianPermissionExists) || errors.Is(err, guardian.ErrGuardianOverride) {
|
||||
return Error(400, err.Error(), err)
|
||||
return response.Error(400, err.Error(), err)
|
||||
}
|
||||
|
||||
return Error(500, "Error while checking dashboard permissions", err)
|
||||
return response.Error(500, "Error while checking dashboard permissions", err)
|
||||
}
|
||||
|
||||
return Error(403, "Cannot remove own admin permission for a folder", nil)
|
||||
return response.Error(403, "Cannot remove own admin permission for a folder", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrDashboardAclInfoMissing) ||
|
||||
errors.Is(err, models.ErrDashboardPermissionDashboardEmpty) {
|
||||
return Error(409, err.Error(), err)
|
||||
return response.Error(409, err.Error(), err)
|
||||
}
|
||||
return Error(500, "Failed to create permission", err)
|
||||
return response.Error(500, "Failed to create permission", err)
|
||||
}
|
||||
|
||||
return Success("Dashboard permissions updated")
|
||||
return response.Success("Dashboard permissions updated")
|
||||
}
|
||||
|
||||
func validatePermissionsUpdate(apiCmd dtos.UpdateDashboardAclCommand) error {
|
||||
|
@@ -6,6 +6,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
@@ -373,7 +375,7 @@ func updateDashboardPermissionScenario(t *testing.T, ctx updatePermissionContext
|
||||
|
||||
sc := setupScenarioContext(t, ctx.url)
|
||||
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.OrgId = testOrgID
|
||||
sc.context.UserId = testUserID
|
||||
|
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"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/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
@@ -141,25 +142,25 @@ func CreateDashboardSnapshot(c *models.ReqContext, cmd models.CreateDashboardSna
|
||||
}
|
||||
|
||||
// GET /api/snapshots/:key
|
||||
func GetDashboardSnapshot(c *models.ReqContext) Response {
|
||||
func GetDashboardSnapshot(c *models.ReqContext) response.Response {
|
||||
key := c.Params(":key")
|
||||
query := &models.GetDashboardSnapshotQuery{Key: key}
|
||||
|
||||
err := bus.Dispatch(query)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get dashboard snapshot", err)
|
||||
return response.Error(500, "Failed to get dashboard snapshot", err)
|
||||
}
|
||||
|
||||
snapshot := query.Result
|
||||
|
||||
// expired snapshots should also be removed from db
|
||||
if snapshot.Expires.Before(time.Now()) {
|
||||
return Error(404, "Dashboard snapshot not found", err)
|
||||
return response.Error(404, "Dashboard snapshot not found", err)
|
||||
}
|
||||
|
||||
dashboard, err := snapshot.DashboardJSON()
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get dashboard data for dashboard snapshot", err)
|
||||
return response.Error(500, "Failed to get dashboard data for dashboard snapshot", err)
|
||||
}
|
||||
|
||||
dto := dtos.DashboardFullWithMeta{
|
||||
@@ -174,7 +175,7 @@ func GetDashboardSnapshot(c *models.ReqContext) Response {
|
||||
|
||||
metrics.MApiDashboardSnapshotGet.Inc()
|
||||
|
||||
return JSON(200, dto).Header("Cache-Control", "public, max-age=3600")
|
||||
return response.JSON(200, dto).Header("Cache-Control", "public, max-age=3600")
|
||||
}
|
||||
|
||||
func deleteExternalDashboardSnapshot(externalUrl string) error {
|
||||
@@ -207,86 +208,86 @@ func deleteExternalDashboardSnapshot(externalUrl string) error {
|
||||
}
|
||||
|
||||
// GET /api/snapshots-delete/:deleteKey
|
||||
func DeleteDashboardSnapshotByDeleteKey(c *models.ReqContext) Response {
|
||||
func DeleteDashboardSnapshotByDeleteKey(c *models.ReqContext) response.Response {
|
||||
key := c.Params(":deleteKey")
|
||||
|
||||
query := &models.GetDashboardSnapshotQuery{DeleteKey: key}
|
||||
|
||||
err := bus.Dispatch(query)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get dashboard snapshot", err)
|
||||
return response.Error(500, "Failed to get dashboard snapshot", err)
|
||||
}
|
||||
|
||||
if query.Result.External {
|
||||
err := deleteExternalDashboardSnapshot(query.Result.ExternalDeleteUrl)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to delete external dashboard", err)
|
||||
return response.Error(500, "Failed to delete external dashboard", err)
|
||||
}
|
||||
}
|
||||
|
||||
cmd := &models.DeleteDashboardSnapshotCommand{DeleteKey: query.Result.DeleteKey}
|
||||
|
||||
if err := bus.Dispatch(cmd); err != nil {
|
||||
return Error(500, "Failed to delete dashboard snapshot", err)
|
||||
return response.Error(500, "Failed to delete dashboard snapshot", err)
|
||||
}
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": "Snapshot deleted. It might take an hour before it's cleared from any CDN caches.",
|
||||
"id": query.Result.Id,
|
||||
})
|
||||
}
|
||||
|
||||
// DELETE /api/snapshots/:key
|
||||
func DeleteDashboardSnapshot(c *models.ReqContext) Response {
|
||||
func DeleteDashboardSnapshot(c *models.ReqContext) response.Response {
|
||||
key := c.Params(":key")
|
||||
|
||||
query := &models.GetDashboardSnapshotQuery{Key: key}
|
||||
|
||||
err := bus.Dispatch(query)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get dashboard snapshot", err)
|
||||
return response.Error(500, "Failed to get dashboard snapshot", err)
|
||||
}
|
||||
if query.Result == nil {
|
||||
return Error(404, "Failed to get dashboard snapshot", nil)
|
||||
return response.Error(404, "Failed to get dashboard snapshot", nil)
|
||||
}
|
||||
|
||||
dashboard, err := query.Result.DashboardJSON()
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get dashboard data for dashboard snapshot", err)
|
||||
return response.Error(500, "Failed to get dashboard data for dashboard snapshot", err)
|
||||
}
|
||||
dashboardID := dashboard.Get("id").MustInt64()
|
||||
|
||||
guardian := guardian.New(dashboardID, c.OrgId, c.SignedInUser)
|
||||
canEdit, err := guardian.CanEdit()
|
||||
if err != nil {
|
||||
return Error(500, "Error while checking permissions for snapshot", err)
|
||||
return response.Error(500, "Error while checking permissions for snapshot", err)
|
||||
}
|
||||
|
||||
if !canEdit && query.Result.UserId != c.SignedInUser.UserId {
|
||||
return Error(403, "Access denied to this snapshot", nil)
|
||||
return response.Error(403, "Access denied to this snapshot", nil)
|
||||
}
|
||||
|
||||
if query.Result.External {
|
||||
err := deleteExternalDashboardSnapshot(query.Result.ExternalDeleteUrl)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to delete external dashboard", err)
|
||||
return response.Error(500, "Failed to delete external dashboard", err)
|
||||
}
|
||||
}
|
||||
|
||||
cmd := &models.DeleteDashboardSnapshotCommand{DeleteKey: query.Result.DeleteKey}
|
||||
|
||||
if err := bus.Dispatch(cmd); err != nil {
|
||||
return Error(500, "Failed to delete dashboard snapshot", err)
|
||||
return response.Error(500, "Failed to delete dashboard snapshot", err)
|
||||
}
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": "Snapshot deleted. It might take an hour before it's cleared from any CDN caches.",
|
||||
"id": query.Result.Id,
|
||||
})
|
||||
}
|
||||
|
||||
// GET /api/dashboard/snapshots
|
||||
func SearchDashboardSnapshots(c *models.ReqContext) Response {
|
||||
func SearchDashboardSnapshots(c *models.ReqContext) response.Response {
|
||||
query := c.Query("query")
|
||||
limit := c.QueryInt("limit")
|
||||
|
||||
@@ -303,7 +304,7 @@ func SearchDashboardSnapshots(c *models.ReqContext) Response {
|
||||
|
||||
err := bus.Dispatch(&searchQuery)
|
||||
if err != nil {
|
||||
return Error(500, "Search failed", err)
|
||||
return response.Error(500, "Search failed", err)
|
||||
}
|
||||
|
||||
dtos := make([]*models.DashboardSnapshotDTO, len(searchQuery.Result))
|
||||
@@ -322,5 +323,5 @@ func SearchDashboardSnapshots(c *models.ReqContext) Response {
|
||||
}
|
||||
}
|
||||
|
||||
return JSON(200, dtos)
|
||||
return response.JSON(200, dtos)
|
||||
}
|
||||
|
@@ -8,6 +8,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -61,9 +63,9 @@ func TestGetHomeDashboard(t *testing.T) {
|
||||
require.NoError(t, err, "must be able to marshal object to JSON")
|
||||
|
||||
res := hs.GetHomeDashboard(req)
|
||||
nr, ok := res.(*NormalResponse)
|
||||
nr, ok := res.(*response.NormalResponse)
|
||||
require.True(t, ok, "should return *NormalResponse")
|
||||
require.Equal(t, b, nr.body, "default home dashboard should equal content on disk")
|
||||
require.Equal(t, b, nr.Body(), "default home dashboard should equal content on disk")
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1192,7 +1194,7 @@ func postDashboardScenario(t *testing.T, desc string, url string, routePattern s
|
||||
}
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.SignedInUser = &models.SignedInUser{OrgId: cmd.OrgId, UserId: cmd.UserId}
|
||||
|
||||
@@ -1223,7 +1225,7 @@ func postDiffScenario(t *testing.T, desc string, url string, routePattern string
|
||||
defer bus.ClearBusHandlers()
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.SignedInUser = &models.SignedInUser{
|
||||
OrgId: testOrgID,
|
||||
@@ -1255,7 +1257,7 @@ func restoreDashboardVersionScenario(t *testing.T, desc string, url string, rout
|
||||
}
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.SignedInUser = &models.SignedInUser{
|
||||
OrgId: testOrgID,
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana/pkg/api/datasource"
|
||||
"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/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -19,11 +20,11 @@ import (
|
||||
|
||||
var datasourcesLogger = log.New("datasources")
|
||||
|
||||
func (hs *HTTPServer) GetDataSources(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetDataSources(c *models.ReqContext) response.Response {
|
||||
query := models.GetDataSourcesQuery{OrgId: c.OrgId, DataSourceLimit: hs.Cfg.DataSourceLimit}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to query datasources", err)
|
||||
return response.Error(500, "Failed to query datasources", err)
|
||||
}
|
||||
|
||||
result := make(dtos.DataSourceList, 0)
|
||||
@@ -56,10 +57,10 @@ func (hs *HTTPServer) GetDataSources(c *models.ReqContext) Response {
|
||||
|
||||
sort.Sort(result)
|
||||
|
||||
return JSON(200, &result)
|
||||
return response.JSON(200, &result)
|
||||
}
|
||||
|
||||
func GetDataSourceById(c *models.ReqContext) Response {
|
||||
func GetDataSourceById(c *models.ReqContext) response.Response {
|
||||
query := models.GetDataSourceQuery{
|
||||
Id: c.ParamsInt64(":id"),
|
||||
OrgId: c.OrgId,
|
||||
@@ -67,135 +68,135 @@ func GetDataSourceById(c *models.ReqContext) Response {
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
return Error(404, "Data source not found", nil)
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return Error(500, "Failed to query datasources", err)
|
||||
return response.Error(500, "Failed to query datasources", err)
|
||||
}
|
||||
|
||||
ds := query.Result
|
||||
dtos := convertModelToDtos(ds)
|
||||
|
||||
return JSON(200, &dtos)
|
||||
return response.JSON(200, &dtos)
|
||||
}
|
||||
|
||||
func DeleteDataSourceById(c *models.ReqContext) Response {
|
||||
func DeleteDataSourceById(c *models.ReqContext) response.Response {
|
||||
id := c.ParamsInt64(":id")
|
||||
|
||||
if id <= 0 {
|
||||
return Error(400, "Missing valid datasource id", nil)
|
||||
return response.Error(400, "Missing valid datasource id", nil)
|
||||
}
|
||||
|
||||
ds, err := getRawDataSourceById(id, c.OrgId)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
return Error(404, "Data source not found", nil)
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return Error(400, "Failed to delete datasource", nil)
|
||||
return response.Error(400, "Failed to delete datasource", nil)
|
||||
}
|
||||
|
||||
if ds.ReadOnly {
|
||||
return Error(403, "Cannot delete read-only data source", nil)
|
||||
return response.Error(403, "Cannot delete read-only data source", nil)
|
||||
}
|
||||
|
||||
cmd := &models.DeleteDataSourceCommand{ID: id, OrgID: c.OrgId}
|
||||
|
||||
err = bus.Dispatch(cmd)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to delete datasource", err)
|
||||
return response.Error(500, "Failed to delete datasource", err)
|
||||
}
|
||||
|
||||
return Success("Data source deleted")
|
||||
return response.Success("Data source deleted")
|
||||
}
|
||||
|
||||
// GET /api/datasources/uid/:uid
|
||||
func GetDataSourceByUID(c *models.ReqContext) Response {
|
||||
func GetDataSourceByUID(c *models.ReqContext) response.Response {
|
||||
ds, err := getRawDataSourceByUID(c.Params(":uid"), c.OrgId)
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
return Error(404, "Data source not found", nil)
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return Error(500, "Failed to query datasources", err)
|
||||
return response.Error(500, "Failed to query datasources", err)
|
||||
}
|
||||
|
||||
dtos := convertModelToDtos(ds)
|
||||
return JSON(200, &dtos)
|
||||
return response.JSON(200, &dtos)
|
||||
}
|
||||
|
||||
// DELETE /api/datasources/uid/:uid
|
||||
func DeleteDataSourceByUID(c *models.ReqContext) Response {
|
||||
func DeleteDataSourceByUID(c *models.ReqContext) response.Response {
|
||||
uid := c.Params(":uid")
|
||||
|
||||
if uid == "" {
|
||||
return Error(400, "Missing datasource uid", nil)
|
||||
return response.Error(400, "Missing datasource uid", nil)
|
||||
}
|
||||
|
||||
ds, err := getRawDataSourceByUID(uid, c.OrgId)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
return Error(404, "Data source not found", nil)
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return Error(400, "Failed to delete datasource", nil)
|
||||
return response.Error(400, "Failed to delete datasource", nil)
|
||||
}
|
||||
|
||||
if ds.ReadOnly {
|
||||
return Error(403, "Cannot delete read-only data source", nil)
|
||||
return response.Error(403, "Cannot delete read-only data source", nil)
|
||||
}
|
||||
|
||||
cmd := &models.DeleteDataSourceCommand{UID: uid, OrgID: c.OrgId}
|
||||
|
||||
err = bus.Dispatch(cmd)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to delete datasource", err)
|
||||
return response.Error(500, "Failed to delete datasource", err)
|
||||
}
|
||||
|
||||
return Success("Data source deleted")
|
||||
return response.Success("Data source deleted")
|
||||
}
|
||||
|
||||
func DeleteDataSourceByName(c *models.ReqContext) Response {
|
||||
func DeleteDataSourceByName(c *models.ReqContext) response.Response {
|
||||
name := c.Params(":name")
|
||||
|
||||
if name == "" {
|
||||
return Error(400, "Missing valid datasource name", nil)
|
||||
return response.Error(400, "Missing valid datasource name", nil)
|
||||
}
|
||||
|
||||
getCmd := &models.GetDataSourceQuery{Name: name, OrgId: c.OrgId}
|
||||
if err := bus.Dispatch(getCmd); err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
return Error(404, "Data source not found", nil)
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return Error(500, "Failed to delete datasource", err)
|
||||
return response.Error(500, "Failed to delete datasource", err)
|
||||
}
|
||||
|
||||
if getCmd.Result.ReadOnly {
|
||||
return Error(403, "Cannot delete read-only data source", nil)
|
||||
return response.Error(403, "Cannot delete read-only data source", nil)
|
||||
}
|
||||
|
||||
cmd := &models.DeleteDataSourceCommand{Name: name, OrgID: c.OrgId}
|
||||
err := bus.Dispatch(cmd)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to delete datasource", err)
|
||||
return response.Error(500, "Failed to delete datasource", err)
|
||||
}
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": "Data source deleted",
|
||||
"id": getCmd.Result.Id,
|
||||
})
|
||||
}
|
||||
|
||||
func validateURL(tp string, u string) Response {
|
||||
func validateURL(tp string, u string) response.Response {
|
||||
if u != "" {
|
||||
if _, err := datasource.ValidateURL(tp, u); err != nil {
|
||||
datasourcesLogger.Error("Received invalid data source URL as part of data source command",
|
||||
"url", u)
|
||||
return Error(400, fmt.Sprintf("Validation error, invalid URL: %q", u), err)
|
||||
return response.Error(400, fmt.Sprintf("Validation error, invalid URL: %q", u), err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func AddDataSource(c *models.ReqContext, cmd models.AddDataSourceCommand) Response {
|
||||
func AddDataSource(c *models.ReqContext, cmd models.AddDataSourceCommand) response.Response {
|
||||
datasourcesLogger.Debug("Received command to add data source", "url", cmd.Url)
|
||||
cmd.OrgId = c.OrgId
|
||||
if resp := validateURL(cmd.Type, cmd.Url); resp != nil {
|
||||
@@ -204,14 +205,14 @@ func AddDataSource(c *models.ReqContext, cmd models.AddDataSourceCommand) Respon
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNameExists) || errors.Is(err, models.ErrDataSourceUidExists) {
|
||||
return Error(409, err.Error(), err)
|
||||
return response.Error(409, err.Error(), err)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to add datasource", err)
|
||||
return response.Error(500, "Failed to add datasource", err)
|
||||
}
|
||||
|
||||
ds := convertModelToDtos(cmd.Result)
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": "Datasource added",
|
||||
"id": cmd.Result.Id,
|
||||
"name": cmd.Result.Name,
|
||||
@@ -219,7 +220,7 @@ func AddDataSource(c *models.ReqContext, cmd models.AddDataSourceCommand) Respon
|
||||
})
|
||||
}
|
||||
|
||||
func UpdateDataSource(c *models.ReqContext, cmd models.UpdateDataSourceCommand) Response {
|
||||
func UpdateDataSource(c *models.ReqContext, cmd models.UpdateDataSourceCommand) response.Response {
|
||||
datasourcesLogger.Debug("Received command to update data source", "url", cmd.Url)
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.Id = c.ParamsInt64(":id")
|
||||
@@ -229,15 +230,15 @@ func UpdateDataSource(c *models.ReqContext, cmd models.UpdateDataSourceCommand)
|
||||
|
||||
err := fillWithSecureJSONData(&cmd)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to update datasource", err)
|
||||
return response.Error(500, "Failed to update datasource", err)
|
||||
}
|
||||
|
||||
err = bus.Dispatch(&cmd)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceUpdatingOldVersion) {
|
||||
return Error(500, "Failed to update datasource. Reload new version and try again", err)
|
||||
return response.Error(500, "Failed to update datasource. Reload new version and try again", err)
|
||||
}
|
||||
return Error(500, "Failed to update datasource", err)
|
||||
return response.Error(500, "Failed to update datasource", err)
|
||||
}
|
||||
|
||||
query := models.GetDataSourceQuery{
|
||||
@@ -247,14 +248,14 @@ func UpdateDataSource(c *models.ReqContext, cmd models.UpdateDataSourceCommand)
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
return Error(404, "Data source not found", nil)
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return Error(500, "Failed to query datasources", err)
|
||||
return response.Error(500, "Failed to query datasources", err)
|
||||
}
|
||||
|
||||
dtos := convertModelToDtos(query.Result)
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": "Datasource updated",
|
||||
"id": cmd.Id,
|
||||
"name": cmd.Name,
|
||||
@@ -313,29 +314,29 @@ func getRawDataSourceByUID(uid string, orgID int64) (*models.DataSource, error)
|
||||
}
|
||||
|
||||
// Get /api/datasources/name/:name
|
||||
func GetDataSourceByName(c *models.ReqContext) Response {
|
||||
func GetDataSourceByName(c *models.ReqContext) response.Response {
|
||||
query := models.GetDataSourceQuery{Name: c.Params(":name"), OrgId: c.OrgId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
return Error(404, "Data source not found", nil)
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return Error(500, "Failed to query datasources", err)
|
||||
return response.Error(500, "Failed to query datasources", err)
|
||||
}
|
||||
|
||||
dtos := convertModelToDtos(query.Result)
|
||||
return JSON(200, &dtos)
|
||||
return response.JSON(200, &dtos)
|
||||
}
|
||||
|
||||
// Get /api/datasources/id/:name
|
||||
func GetDataSourceIdByName(c *models.ReqContext) Response {
|
||||
func GetDataSourceIdByName(c *models.ReqContext) response.Response {
|
||||
query := models.GetDataSourceQuery{Name: c.Params(":name"), OrgId: c.OrgId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
return Error(404, "Data source not found", nil)
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return Error(500, "Failed to query datasources", err)
|
||||
return response.Error(500, "Failed to query datasources", err)
|
||||
}
|
||||
|
||||
ds := query.Result
|
||||
@@ -343,7 +344,7 @@ func GetDataSourceIdByName(c *models.ReqContext) Response {
|
||||
Id: ds.Id,
|
||||
}
|
||||
|
||||
return JSON(200, &dtos)
|
||||
return response.JSON(200, &dtos)
|
||||
}
|
||||
|
||||
// /api/datasources/:id/resources/*
|
||||
@@ -414,25 +415,25 @@ func convertModelToDtos(ds *models.DataSource) dtos.DataSource {
|
||||
|
||||
// CheckDatasourceHealth sends a health check request to the plugin datasource
|
||||
// /api/datasource/:id/health
|
||||
func (hs *HTTPServer) CheckDatasourceHealth(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) CheckDatasourceHealth(c *models.ReqContext) response.Response {
|
||||
datasourceID := c.ParamsInt64("id")
|
||||
|
||||
ds, err := hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
return Error(403, "Access denied to datasource", err)
|
||||
return response.Error(403, "Access denied to datasource", err)
|
||||
}
|
||||
return Error(500, "Unable to load datasource metadata", err)
|
||||
return response.Error(500, "Unable to load datasource metadata", err)
|
||||
}
|
||||
|
||||
plugin, ok := hs.PluginManager.GetDatasource(ds.Type)
|
||||
if !ok {
|
||||
return Error(500, "Unable to find datasource plugin", err)
|
||||
return response.Error(500, "Unable to find datasource plugin", err)
|
||||
}
|
||||
|
||||
dsInstanceSettings, err := wrapper.ModelToInstanceSettings(ds)
|
||||
if err != nil {
|
||||
return Error(500, "Unable to get datasource model", err)
|
||||
return response.Error(500, "Unable to get datasource model", err)
|
||||
}
|
||||
pCtx := backend.PluginContext{
|
||||
User: wrapper.BackendUserFromSignedInUser(c.SignedInUser),
|
||||
@@ -456,15 +457,15 @@ func (hs *HTTPServer) CheckDatasourceHealth(c *models.ReqContext) Response {
|
||||
var jsonDetails map[string]interface{}
|
||||
err = json.Unmarshal(resp.JSONDetails, &jsonDetails)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to unmarshal detailed response from backend plugin", err)
|
||||
return response.Error(500, "Failed to unmarshal detailed response from backend plugin", err)
|
||||
}
|
||||
|
||||
payload["details"] = jsonDetails
|
||||
}
|
||||
|
||||
if resp.Status != backend.HealthStatusOk {
|
||||
return JSON(503, payload)
|
||||
return response.JSON(503, payload)
|
||||
}
|
||||
|
||||
return JSON(200, payload)
|
||||
return response.JSON(200, payload)
|
||||
}
|
||||
|
@@ -4,6 +4,8 @@ import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -61,7 +63,7 @@ func TestAddDataSource_InvalidURL(t *testing.T) {
|
||||
|
||||
sc := setupScenarioContext(t, "/api/datasources")
|
||||
|
||||
sc.m.Post(sc.url, Wrap(func(c *models.ReqContext) Response {
|
||||
sc.m.Post(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
return AddDataSource(c, models.AddDataSourceCommand{
|
||||
Name: "Test",
|
||||
Url: "invalid:url",
|
||||
@@ -91,7 +93,7 @@ func TestAddDataSource_URLWithoutProtocol(t *testing.T) {
|
||||
|
||||
sc := setupScenarioContext(t, "/api/datasources")
|
||||
|
||||
sc.m.Post(sc.url, Wrap(func(c *models.ReqContext) Response {
|
||||
sc.m.Post(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
return AddDataSource(c, models.AddDataSourceCommand{
|
||||
Name: name,
|
||||
Url: url,
|
||||
@@ -109,7 +111,7 @@ func TestUpdateDataSource_InvalidURL(t *testing.T) {
|
||||
|
||||
sc := setupScenarioContext(t, "/api/datasources/1234")
|
||||
|
||||
sc.m.Put(sc.url, Wrap(func(c *models.ReqContext) Response {
|
||||
sc.m.Put(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
return AddDataSource(c, models.AddDataSourceCommand{
|
||||
Name: "Test",
|
||||
Url: "invalid:url",
|
||||
@@ -139,7 +141,7 @@ func TestUpdateDataSource_URLWithoutProtocol(t *testing.T) {
|
||||
|
||||
sc := setupScenarioContext(t, "/api/datasources/1234")
|
||||
|
||||
sc.m.Put(sc.url, Wrap(func(c *models.ReqContext) Response {
|
||||
sc.m.Put(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
return AddDataSource(c, models.AddDataSourceCommand{
|
||||
Name: name,
|
||||
Url: url,
|
||||
|
@@ -5,13 +5,14 @@ import (
|
||||
"fmt"
|
||||
|
||||
"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/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func GetFolders(c *models.ReqContext) Response {
|
||||
func GetFolders(c *models.ReqContext) response.Response {
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser)
|
||||
folders, err := s.GetFolders(c.QueryInt64("limit"))
|
||||
|
||||
@@ -29,10 +30,10 @@ func GetFolders(c *models.ReqContext) Response {
|
||||
})
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
||||
func GetFolderByUID(c *models.ReqContext) Response {
|
||||
func GetFolderByUID(c *models.ReqContext) response.Response {
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser)
|
||||
folder, err := s.GetFolderByUID(c.Params(":uid"))
|
||||
|
||||
@@ -41,10 +42,10 @@ func GetFolderByUID(c *models.ReqContext) Response {
|
||||
}
|
||||
|
||||
g := guardian.New(folder.Id, c.OrgId, c.SignedInUser)
|
||||
return JSON(200, toFolderDto(g, folder))
|
||||
return response.JSON(200, toFolderDto(g, folder))
|
||||
}
|
||||
|
||||
func GetFolderByID(c *models.ReqContext) Response {
|
||||
func GetFolderByID(c *models.ReqContext) response.Response {
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser)
|
||||
folder, err := s.GetFolderByID(c.ParamsInt64(":id"))
|
||||
if err != nil {
|
||||
@@ -52,10 +53,10 @@ func GetFolderByID(c *models.ReqContext) Response {
|
||||
}
|
||||
|
||||
g := guardian.New(folder.Id, c.OrgId, c.SignedInUser)
|
||||
return JSON(200, toFolderDto(g, folder))
|
||||
return response.JSON(200, toFolderDto(g, folder))
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) CreateFolder(c *models.ReqContext, cmd models.CreateFolderCommand) Response {
|
||||
func (hs *HTTPServer) CreateFolder(c *models.ReqContext, cmd models.CreateFolderCommand) response.Response {
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser)
|
||||
err := s.CreateFolder(&cmd)
|
||||
if err != nil {
|
||||
@@ -69,10 +70,10 @@ func (hs *HTTPServer) CreateFolder(c *models.ReqContext, cmd models.CreateFolder
|
||||
}
|
||||
|
||||
g := guardian.New(cmd.Result.Id, c.OrgId, c.SignedInUser)
|
||||
return JSON(200, toFolderDto(g, cmd.Result))
|
||||
return response.JSON(200, toFolderDto(g, cmd.Result))
|
||||
}
|
||||
|
||||
func UpdateFolder(c *models.ReqContext, cmd models.UpdateFolderCommand) Response {
|
||||
func UpdateFolder(c *models.ReqContext, cmd models.UpdateFolderCommand) response.Response {
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser)
|
||||
err := s.UpdateFolder(c.Params(":uid"), &cmd)
|
||||
if err != nil {
|
||||
@@ -80,17 +81,17 @@ func UpdateFolder(c *models.ReqContext, cmd models.UpdateFolderCommand) Response
|
||||
}
|
||||
|
||||
g := guardian.New(cmd.Result.Id, c.OrgId, c.SignedInUser)
|
||||
return JSON(200, toFolderDto(g, cmd.Result))
|
||||
return response.JSON(200, toFolderDto(g, cmd.Result))
|
||||
}
|
||||
|
||||
func DeleteFolder(c *models.ReqContext) Response {
|
||||
func DeleteFolder(c *models.ReqContext) response.Response {
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser)
|
||||
f, err := s.DeleteFolder(c.Params(":uid"))
|
||||
if err != nil {
|
||||
return toFolderError(err)
|
||||
}
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"title": f.Title,
|
||||
"message": fmt.Sprintf("Folder %s deleted", f.Title),
|
||||
"id": f.Id,
|
||||
@@ -128,10 +129,10 @@ func toFolderDto(g guardian.DashboardGuardian, folder *models.Folder) dtos.Folde
|
||||
}
|
||||
}
|
||||
|
||||
func toFolderError(err error) Response {
|
||||
func toFolderError(err error) response.Response {
|
||||
var dashboardErr models.DashboardErr
|
||||
if ok := errors.As(err, &dashboardErr); ok {
|
||||
return Error(dashboardErr.StatusCode, err.Error(), err)
|
||||
return response.Error(dashboardErr.StatusCode, err.Error(), err)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderTitleEmpty) ||
|
||||
@@ -140,20 +141,20 @@ func toFolderError(err error) Response {
|
||||
errors.Is(err, models.ErrDashboardTypeMismatch) ||
|
||||
errors.Is(err, models.ErrDashboardInvalidUid) ||
|
||||
errors.Is(err, models.ErrDashboardUidTooLong) {
|
||||
return Error(400, err.Error(), nil)
|
||||
return response.Error(400, err.Error(), nil)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderAccessDenied) {
|
||||
return Error(403, "Access denied", err)
|
||||
return response.Error(403, "Access denied", err)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderNotFound) {
|
||||
return JSON(404, util.DynMap{"status": "not-found", "message": models.ErrFolderNotFound.Error()})
|
||||
return response.JSON(404, util.DynMap{"status": "not-found", "message": models.ErrFolderNotFound.Error()})
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderVersionMismatch) {
|
||||
return JSON(412, util.DynMap{"status": "version-mismatch", "message": models.ErrFolderVersionMismatch.Error()})
|
||||
return response.JSON(412, util.DynMap{"status": "version-mismatch", "message": models.ErrFolderVersionMismatch.Error()})
|
||||
}
|
||||
|
||||
return Error(500, "Folder API error", err)
|
||||
return response.Error(500, "Folder API error", err)
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
"time"
|
||||
|
||||
"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/services/dashboards"
|
||||
@@ -12,7 +13,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Response {
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser)
|
||||
folder, err := s.GetFolderByUID(c.Params(":uid"))
|
||||
|
||||
@@ -28,7 +29,7 @@ func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) Response {
|
||||
|
||||
acl, err := g.GetAcl()
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get folder permissions", err)
|
||||
return response.Error(500, "Failed to get folder permissions", err)
|
||||
}
|
||||
|
||||
filteredAcls := make([]*models.DashboardAclInfoDTO, 0, len(acl))
|
||||
@@ -53,12 +54,12 @@ func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) Response {
|
||||
filteredAcls = append(filteredAcls, perm)
|
||||
}
|
||||
|
||||
return JSON(200, filteredAcls)
|
||||
return response.JSON(200, filteredAcls)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext, apiCmd dtos.UpdateDashboardAclCommand) Response {
|
||||
func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext, apiCmd dtos.UpdateDashboardAclCommand) response.Response {
|
||||
if err := validatePermissionsUpdate(apiCmd); err != nil {
|
||||
return Error(400, err.Error(), err)
|
||||
return response.Error(400, err.Error(), err)
|
||||
}
|
||||
|
||||
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser)
|
||||
@@ -96,7 +97,7 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext, apiCmd dtos.
|
||||
|
||||
hiddenACL, err := g.GetHiddenACL(hs.Cfg)
|
||||
if err != nil {
|
||||
return Error(500, "Error while retrieving hidden permissions", err)
|
||||
return response.Error(500, "Error while retrieving hidden permissions", err)
|
||||
}
|
||||
cmd.Items = append(cmd.Items, hiddenACL...)
|
||||
|
||||
@@ -104,13 +105,13 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext, apiCmd dtos.
|
||||
if err != nil {
|
||||
if errors.Is(err, guardian.ErrGuardianPermissionExists) ||
|
||||
errors.Is(err, guardian.ErrGuardianOverride) {
|
||||
return Error(400, err.Error(), err)
|
||||
return response.Error(400, err.Error(), err)
|
||||
}
|
||||
|
||||
return Error(500, "Error while checking folder permissions", err)
|
||||
return response.Error(500, "Error while checking folder permissions", err)
|
||||
}
|
||||
|
||||
return Error(403, "Cannot remove own admin permission for a folder", nil)
|
||||
return response.Error(403, "Cannot remove own admin permission for a folder", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
@@ -122,13 +123,13 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext, apiCmd dtos.
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrFolderAclInfoMissing) || errors.Is(err, models.ErrFolderPermissionFolderEmpty) {
|
||||
return Error(409, err.Error(), err)
|
||||
return response.Error(409, err.Error(), err)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to create permission", err)
|
||||
return response.Error(500, "Failed to create permission", err)
|
||||
}
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": "Folder permissions updated",
|
||||
"id": folder.Id,
|
||||
"title": folder.Title,
|
||||
|
@@ -6,6 +6,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
@@ -384,7 +386,7 @@ func updateFolderPermissionScenario(t *testing.T, ctx updatePermissionContext, h
|
||||
|
||||
sc := setupScenarioContext(t, ctx.url)
|
||||
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.OrgId = testOrgID
|
||||
sc.context.UserId = testUserID
|
||||
|
@@ -6,6 +6,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
@@ -143,7 +145,7 @@ func createFolderScenario(t *testing.T, desc string, url string, routePattern st
|
||||
}
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.SignedInUser = &models.SignedInUser{OrgId: testOrgID, UserId: testUserID}
|
||||
|
||||
@@ -173,7 +175,7 @@ func updateFolderScenario(t *testing.T, desc string, url string, routePattern st
|
||||
defer bus.ClearBusHandlers()
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.SignedInUser = &models.SignedInUser{OrgId: testOrgID, UserId: testUserID}
|
||||
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/getsentry/sentry-go"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/inconshreveable/log15"
|
||||
@@ -77,7 +78,7 @@ func (event *frontendSentryEvent) ToLogContext() log15.Ctx {
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) logFrontendMessage(c *models.ReqContext, event frontendSentryEvent) Response {
|
||||
func (hs *HTTPServer) logFrontendMessage(c *models.ReqContext, event frontendSentryEvent) response.Response {
|
||||
var msg = "unknown"
|
||||
|
||||
if len(event.Message) > 0 {
|
||||
@@ -99,5 +100,5 @@ func (hs *HTTPServer) logFrontendMessage(c *models.ReqContext, event frontendSen
|
||||
frontendLogger.Info(msg, ctx)
|
||||
}
|
||||
|
||||
return Success("ok")
|
||||
return response.Success("ok")
|
||||
}
|
||||
|
@@ -6,6 +6,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/getsentry/sentry-go"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
log "github.com/inconshreveable/log15"
|
||||
|
||||
@@ -30,7 +32,7 @@ func logSentryEventScenario(t *testing.T, desc string, event frontendSentryEvent
|
||||
sc := setupScenarioContext(t, "/log")
|
||||
hs := HTTPServer{}
|
||||
|
||||
handler := Wrap(func(w http.ResponseWriter, c *models.ReqContext) Response {
|
||||
handler := routing.Wrap(func(w http.ResponseWriter, c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
return hs.logFrontendMessage(c, event)
|
||||
})
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"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/login"
|
||||
@@ -97,38 +98,38 @@ func (user *LDAPUserDTO) FetchOrgs() error {
|
||||
}
|
||||
|
||||
// ReloadLDAPCfg reloads the LDAP configuration
|
||||
func (hs *HTTPServer) ReloadLDAPCfg() Response {
|
||||
func (hs *HTTPServer) ReloadLDAPCfg() response.Response {
|
||||
if !ldap.IsEnabled() {
|
||||
return Error(http.StatusBadRequest, "LDAP is not enabled", nil)
|
||||
return response.Error(http.StatusBadRequest, "LDAP is not enabled", nil)
|
||||
}
|
||||
|
||||
err := ldap.ReloadConfig()
|
||||
if err != nil {
|
||||
return Error(http.StatusInternalServerError, "Failed to reload LDAP config", err)
|
||||
return response.Error(http.StatusInternalServerError, "Failed to reload LDAP config", err)
|
||||
}
|
||||
return Success("LDAP config reloaded")
|
||||
return response.Success("LDAP config reloaded")
|
||||
}
|
||||
|
||||
// GetLDAPStatus attempts to connect to all the configured LDAP servers and returns information on whenever they're available or not.
|
||||
func (hs *HTTPServer) GetLDAPStatus(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetLDAPStatus(c *models.ReqContext) response.Response {
|
||||
if !ldap.IsEnabled() {
|
||||
return Error(http.StatusBadRequest, "LDAP is not enabled", nil)
|
||||
return response.Error(http.StatusBadRequest, "LDAP is not enabled", nil)
|
||||
}
|
||||
|
||||
ldapConfig, err := getLDAPConfig(hs.Cfg)
|
||||
if err != nil {
|
||||
return Error(http.StatusBadRequest, "Failed to obtain the LDAP configuration. Please verify the configuration and try again", err)
|
||||
return response.Error(http.StatusBadRequest, "Failed to obtain the LDAP configuration. Please verify the configuration and try again", err)
|
||||
}
|
||||
|
||||
ldap := newLDAP(ldapConfig.Servers)
|
||||
|
||||
if ldap == nil {
|
||||
return Error(http.StatusInternalServerError, "Failed to find the LDAP server", nil)
|
||||
return response.Error(http.StatusInternalServerError, "Failed to find the LDAP server", nil)
|
||||
}
|
||||
|
||||
statuses, err := ldap.Ping()
|
||||
if err != nil {
|
||||
return Error(http.StatusBadRequest, "Failed to connect to the LDAP server(s)", err)
|
||||
return response.Error(http.StatusBadRequest, "Failed to connect to the LDAP server(s)", err)
|
||||
}
|
||||
|
||||
serverDTOs := []*LDAPServerDTO{}
|
||||
@@ -146,18 +147,18 @@ func (hs *HTTPServer) GetLDAPStatus(c *models.ReqContext) Response {
|
||||
serverDTOs = append(serverDTOs, s)
|
||||
}
|
||||
|
||||
return JSON(http.StatusOK, serverDTOs)
|
||||
return response.JSON(http.StatusOK, serverDTOs)
|
||||
}
|
||||
|
||||
// PostSyncUserWithLDAP enables a single Grafana user to be synchronized against LDAP
|
||||
func (hs *HTTPServer) PostSyncUserWithLDAP(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) PostSyncUserWithLDAP(c *models.ReqContext) response.Response {
|
||||
if !ldap.IsEnabled() {
|
||||
return Error(http.StatusBadRequest, "LDAP is not enabled", nil)
|
||||
return response.Error(http.StatusBadRequest, "LDAP is not enabled", nil)
|
||||
}
|
||||
|
||||
ldapConfig, err := getLDAPConfig(hs.Cfg)
|
||||
if err != nil {
|
||||
return Error(http.StatusBadRequest, "Failed to obtain the LDAP configuration. Please verify the configuration and try again", err)
|
||||
return response.Error(http.StatusBadRequest, "Failed to obtain the LDAP configuration. Please verify the configuration and try again", err)
|
||||
}
|
||||
|
||||
userId := c.ParamsInt64(":id")
|
||||
@@ -166,20 +167,20 @@ func (hs *HTTPServer) PostSyncUserWithLDAP(c *models.ReqContext) Response {
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil { // validate the userId exists
|
||||
if errors.Is(err, models.ErrUserNotFound) {
|
||||
return Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
return response.Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to get user", err)
|
||||
return response.Error(500, "Failed to get user", err)
|
||||
}
|
||||
|
||||
authModuleQuery := &models.GetAuthInfoQuery{UserId: query.Result.Id, AuthModule: models.AuthModuleLDAP}
|
||||
|
||||
if err := bus.Dispatch(authModuleQuery); err != nil { // validate the userId comes from LDAP
|
||||
if errors.Is(err, models.ErrUserNotFound) {
|
||||
return Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
return response.Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to get user", err)
|
||||
return response.Error(500, "Failed to get user", err)
|
||||
}
|
||||
|
||||
ldapServer := newLDAP(ldapConfig.Servers)
|
||||
@@ -189,25 +190,25 @@ func (hs *HTTPServer) PostSyncUserWithLDAP(c *models.ReqContext) Response {
|
||||
if hs.Cfg.AdminUser == query.Result.Login { // User is *the* Grafana Admin. We cannot disable it.
|
||||
errMsg := fmt.Sprintf(`Refusing to sync grafana super admin "%s" - it would be disabled`, query.Result.Login)
|
||||
ldapLogger.Error(errMsg)
|
||||
return Error(http.StatusBadRequest, errMsg, err)
|
||||
return response.Error(http.StatusBadRequest, errMsg, err)
|
||||
}
|
||||
|
||||
// Since the user was not in the LDAP server. Let's disable it.
|
||||
err := login.DisableExternalUser(query.Result.Login)
|
||||
if err != nil {
|
||||
return Error(http.StatusInternalServerError, "Failed to disable the user", err)
|
||||
return response.Error(http.StatusInternalServerError, "Failed to disable the user", err)
|
||||
}
|
||||
|
||||
err = hs.AuthTokenService.RevokeAllUserTokens(c.Req.Context(), userId)
|
||||
if err != nil {
|
||||
return Error(http.StatusInternalServerError, "Failed to remove session tokens for the user", err)
|
||||
return response.Error(http.StatusInternalServerError, "Failed to remove session tokens for the user", err)
|
||||
}
|
||||
|
||||
return Error(http.StatusBadRequest, "User not found in LDAP. Disabled the user without updating information", nil) // should this be a success?
|
||||
return response.Error(http.StatusBadRequest, "User not found in LDAP. Disabled the user without updating information", nil) // should this be a success?
|
||||
}
|
||||
|
||||
ldapLogger.Debug("Failed to sync the user with LDAP", "err", err)
|
||||
return Error(http.StatusBadRequest, "Something went wrong while finding the user in LDAP", err)
|
||||
return response.Error(http.StatusBadRequest, "Something went wrong while finding the user in LDAP", err)
|
||||
}
|
||||
|
||||
upsertCmd := &models.UpsertUserCommand{
|
||||
@@ -218,21 +219,21 @@ func (hs *HTTPServer) PostSyncUserWithLDAP(c *models.ReqContext) Response {
|
||||
|
||||
err = bus.Dispatch(upsertCmd)
|
||||
if err != nil {
|
||||
return Error(http.StatusInternalServerError, "Failed to update the user", err)
|
||||
return response.Error(http.StatusInternalServerError, "Failed to update the user", err)
|
||||
}
|
||||
|
||||
return Success("User synced successfully")
|
||||
return response.Success("User synced successfully")
|
||||
}
|
||||
|
||||
// GetUserFromLDAP finds an user based on a username in LDAP. This helps illustrate how would the particular user be mapped in Grafana when synced.
|
||||
func (hs *HTTPServer) GetUserFromLDAP(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetUserFromLDAP(c *models.ReqContext) response.Response {
|
||||
if !ldap.IsEnabled() {
|
||||
return Error(http.StatusBadRequest, "LDAP is not enabled", nil)
|
||||
return response.Error(http.StatusBadRequest, "LDAP is not enabled", nil)
|
||||
}
|
||||
|
||||
ldapConfig, err := getLDAPConfig(hs.Cfg)
|
||||
if err != nil {
|
||||
return Error(http.StatusBadRequest, "Failed to obtain the LDAP configuration", err)
|
||||
return response.Error(http.StatusBadRequest, "Failed to obtain the LDAP configuration", err)
|
||||
}
|
||||
|
||||
ldap := newLDAP(ldapConfig.Servers)
|
||||
@@ -240,13 +241,13 @@ func (hs *HTTPServer) GetUserFromLDAP(c *models.ReqContext) Response {
|
||||
username := c.Params(":username")
|
||||
|
||||
if len(username) == 0 {
|
||||
return Error(http.StatusBadRequest, "Validation error. You must specify an username", nil)
|
||||
return response.Error(http.StatusBadRequest, "Validation error. You must specify an username", nil)
|
||||
}
|
||||
|
||||
user, serverConfig, err := ldap.User(username)
|
||||
|
||||
if user == nil {
|
||||
return Error(http.StatusNotFound, "No user was found in the LDAP server(s) with that username", err)
|
||||
return response.Error(http.StatusNotFound, "No user was found in the LDAP server(s) with that username", err)
|
||||
}
|
||||
|
||||
ldapLogger.Debug("user found", "user", user)
|
||||
@@ -301,18 +302,18 @@ func (hs *HTTPServer) GetUserFromLDAP(c *models.ReqContext) Response {
|
||||
ldapLogger.Debug("mapping org roles", "orgsRoles", u.OrgRoles)
|
||||
err = u.FetchOrgs()
|
||||
if err != nil {
|
||||
return Error(http.StatusBadRequest, "An organization was not found - Please verify your LDAP configuration", err)
|
||||
return response.Error(http.StatusBadRequest, "An organization was not found - Please verify your LDAP configuration", err)
|
||||
}
|
||||
|
||||
cmd := &models.GetTeamsForLDAPGroupCommand{Groups: user.Groups}
|
||||
err = bus.Dispatch(cmd)
|
||||
if err != nil && !errors.Is(err, bus.ErrHandlerNotFound) {
|
||||
return Error(http.StatusBadRequest, "Unable to find the teams for this user", err)
|
||||
return response.Error(http.StatusBadRequest, "Unable to find the teams for this user", err)
|
||||
}
|
||||
|
||||
u.Teams = cmd.Result
|
||||
|
||||
return JSON(200, u)
|
||||
return response.JSON(200, u)
|
||||
}
|
||||
|
||||
// splitName receives the full name of a user and splits it into two parts: A name and a surname.
|
||||
|
@@ -6,6 +6,8 @@ import (
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
@@ -58,7 +60,7 @@ func getUserFromLDAPContext(t *testing.T, requestURL string) *scenarioContext {
|
||||
|
||||
hs := &HTTPServer{Cfg: setting.NewCfg()}
|
||||
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
return hs.GetUserFromLDAP(c)
|
||||
})
|
||||
@@ -327,7 +329,7 @@ func getLDAPStatusContext(t *testing.T) *scenarioContext {
|
||||
|
||||
hs := &HTTPServer{Cfg: setting.NewCfg()}
|
||||
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
return hs.GetLDAPStatus(c)
|
||||
})
|
||||
@@ -391,7 +393,7 @@ func postSyncUserWithLDAPContext(t *testing.T, requestURL string, preHook func(*
|
||||
AuthTokenService: auth.NewFakeUserAuthTokenService(),
|
||||
}
|
||||
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
return hs.PostSyncUserWithLDAP(c)
|
||||
})
|
||||
|
@@ -8,6 +8,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"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/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
@@ -159,36 +160,36 @@ func tryOAuthAutoLogin(c *models.ReqContext) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) LoginAPIPing(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) LoginAPIPing(c *models.ReqContext) response.Response {
|
||||
if c.IsSignedIn || c.IsAnonymous {
|
||||
return JSON(200, "Logged in")
|
||||
return response.JSON(200, "Logged in")
|
||||
}
|
||||
|
||||
return Error(401, "Unauthorized", nil)
|
||||
return response.Error(401, "Unauthorized", nil)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) LoginPost(c *models.ReqContext, cmd dtos.LoginCommand) Response {
|
||||
func (hs *HTTPServer) LoginPost(c *models.ReqContext, cmd dtos.LoginCommand) response.Response {
|
||||
authModule := ""
|
||||
var user *models.User
|
||||
var response *NormalResponse
|
||||
var resp *response.NormalResponse
|
||||
|
||||
defer func() {
|
||||
err := response.err
|
||||
if err == nil && response.errMessage != "" {
|
||||
err = errors.New(response.errMessage)
|
||||
err := resp.Err()
|
||||
if err == nil && resp.ErrMessage() != "" {
|
||||
err = errors.New(resp.ErrMessage())
|
||||
}
|
||||
hs.HooksService.RunLoginHook(&models.LoginInfo{
|
||||
AuthModule: authModule,
|
||||
User: user,
|
||||
LoginUsername: cmd.User,
|
||||
HTTPStatus: response.status,
|
||||
HTTPStatus: resp.Status(),
|
||||
Error: err,
|
||||
}, c)
|
||||
}()
|
||||
|
||||
if setting.DisableLoginForm {
|
||||
response = Error(http.StatusUnauthorized, "Login is disabled", nil)
|
||||
return response
|
||||
resp = response.Error(http.StatusUnauthorized, "Login is disabled", nil)
|
||||
return resp
|
||||
}
|
||||
|
||||
authQuery := &models.LoginUserQuery{
|
||||
@@ -202,29 +203,29 @@ func (hs *HTTPServer) LoginPost(c *models.ReqContext, cmd dtos.LoginCommand) Res
|
||||
err := bus.Dispatch(authQuery)
|
||||
authModule = authQuery.AuthModule
|
||||
if err != nil {
|
||||
response = Error(401, "Invalid username or password", err)
|
||||
resp = response.Error(401, "Invalid username or password", err)
|
||||
if errors.Is(err, login.ErrInvalidCredentials) || errors.Is(err, login.ErrTooManyLoginAttempts) || errors.Is(err,
|
||||
models.ErrUserNotFound) {
|
||||
return response
|
||||
return resp
|
||||
}
|
||||
|
||||
// Do not expose disabled status,
|
||||
// just show incorrect user credentials error (see #17947)
|
||||
if errors.Is(err, login.ErrUserDisabled) {
|
||||
hs.log.Warn("User is disabled", "user", cmd.User)
|
||||
return response
|
||||
return resp
|
||||
}
|
||||
|
||||
response = Error(500, "Error while trying to authenticate user", err)
|
||||
return response
|
||||
resp = response.Error(500, "Error while trying to authenticate user", err)
|
||||
return resp
|
||||
}
|
||||
|
||||
user = authQuery.User
|
||||
|
||||
err = hs.loginUserWithUser(user, c)
|
||||
if err != nil {
|
||||
response = Error(http.StatusInternalServerError, "Error while signing in user", err)
|
||||
return response
|
||||
resp = response.Error(http.StatusInternalServerError, "Error while signing in user", err)
|
||||
return resp
|
||||
}
|
||||
|
||||
result := map[string]interface{}{
|
||||
@@ -241,8 +242,8 @@ func (hs *HTTPServer) LoginPost(c *models.ReqContext, cmd dtos.LoginCommand) Res
|
||||
}
|
||||
|
||||
metrics.MApiLoginPost.Inc()
|
||||
response = JSON(http.StatusOK, result)
|
||||
return response
|
||||
resp = response.JSON(http.StatusOK, result)
|
||||
return resp
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) loginUserWithUser(user *models.User, c *models.ReqContext) error {
|
||||
@@ -324,11 +325,11 @@ func (hs *HTTPServer) redirectWithError(ctx *models.ReqContext, err error, v ...
|
||||
ctx.Redirect(setting.AppSubUrl + "/login")
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) RedirectResponseWithError(ctx *models.ReqContext, err error, v ...interface{}) *RedirectResponse {
|
||||
func (hs *HTTPServer) RedirectResponseWithError(ctx *models.ReqContext, err error, v ...interface{}) *response.RedirectResponse {
|
||||
ctx.Logger.Error(err.Error(), v...)
|
||||
if err := hs.trySetEncryptedCookie(ctx, loginErrorCookieName, err.Error(), 60); err != nil {
|
||||
hs.log.Error("Failed to set encrypted cookie", "err", err)
|
||||
}
|
||||
|
||||
return Redirect(setting.AppSubUrl + "/login")
|
||||
return response.Redirect(setting.AppSubUrl + "/login")
|
||||
}
|
||||
|
@@ -11,6 +11,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
@@ -96,7 +98,7 @@ func TestLoginErrorCookieAPIEndpoint(t *testing.T) {
|
||||
License: &licensing.OSSLicensingService{},
|
||||
}
|
||||
|
||||
sc.defaultHandler = Wrap(func(w http.ResponseWriter, c *models.ReqContext) {
|
||||
sc.defaultHandler = routing.Wrap(func(w http.ResponseWriter, c *models.ReqContext) {
|
||||
hs.LoginView(c)
|
||||
})
|
||||
|
||||
@@ -158,7 +160,7 @@ func TestLoginViewRedirect(t *testing.T) {
|
||||
}
|
||||
hs.Cfg.CookieSecure = true
|
||||
|
||||
sc.defaultHandler = Wrap(func(w http.ResponseWriter, c *models.ReqContext) {
|
||||
sc.defaultHandler = routing.Wrap(func(w http.ResponseWriter, c *models.ReqContext) {
|
||||
c.IsSignedIn = true
|
||||
c.SignedInUser = &models.SignedInUser{
|
||||
UserId: 10,
|
||||
@@ -335,7 +337,7 @@ func TestLoginPostRedirect(t *testing.T) {
|
||||
}
|
||||
hs.Cfg.CookieSecure = true
|
||||
|
||||
sc.defaultHandler = Wrap(func(w http.ResponseWriter, c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(w http.ResponseWriter, c *models.ReqContext) response.Response {
|
||||
cmd := dtos.LoginCommand{
|
||||
User: "admin",
|
||||
Password: "admin",
|
||||
@@ -488,7 +490,7 @@ func TestLoginOAuthRedirect(t *testing.T) {
|
||||
License: &licensing.OSSLicensingService{},
|
||||
}
|
||||
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) {
|
||||
hs.LoginView(c)
|
||||
})
|
||||
|
||||
@@ -522,7 +524,7 @@ func TestLoginInternal(t *testing.T) {
|
||||
log: log.New("test"),
|
||||
}
|
||||
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) {
|
||||
c.Req.URL.RawQuery = "disableAutoLogin=true"
|
||||
hs.LoginView(c)
|
||||
})
|
||||
@@ -580,7 +582,7 @@ func setupAuthProxyLoginTest(t *testing.T, enableLoginToken bool) *scenarioConte
|
||||
log: log.New("hello"),
|
||||
}
|
||||
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) {
|
||||
c.IsSignedIn = true
|
||||
c.SignedInUser = &models.SignedInUser{
|
||||
UserId: 10,
|
||||
@@ -618,7 +620,7 @@ func TestLoginPostRunLokingHook(t *testing.T) {
|
||||
HooksService: hookService,
|
||||
}
|
||||
|
||||
sc.defaultHandler = Wrap(func(w http.ResponseWriter, c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(w http.ResponseWriter, c *models.ReqContext) response.Response {
|
||||
cmd := dtos.LoginCommand{
|
||||
User: "admin",
|
||||
Password: "admin",
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
|
||||
"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/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/tsdb"
|
||||
@@ -18,9 +19,9 @@ import (
|
||||
|
||||
// QueryMetricsV2 returns query metrics.
|
||||
// POST /api/ds/query DataSource query w/ expressions
|
||||
func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext, reqDTO dtos.MetricRequest) Response {
|
||||
func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext, reqDTO dtos.MetricRequest) response.Response {
|
||||
if len(reqDTO.Queries) == 0 {
|
||||
return Error(400, "No queries found in query", nil)
|
||||
return response.Error(400, "No queries found in query", nil)
|
||||
}
|
||||
|
||||
request := &tsdb.TsdbQuery{
|
||||
@@ -41,7 +42,7 @@ func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext, reqDTO dtos.MetricReq
|
||||
datasourceID, err := query.Get("datasourceId").Int64()
|
||||
if err != nil {
|
||||
hs.log.Debug("Can't process query since it's missing data source ID")
|
||||
return Error(400, "Query missing data source ID", nil)
|
||||
return response.Error(400, "Query missing data source ID", nil)
|
||||
}
|
||||
|
||||
if i == 0 && !hasExpr {
|
||||
@@ -49,12 +50,12 @@ func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext, reqDTO dtos.MetricReq
|
||||
if err != nil {
|
||||
hs.log.Debug("Encountered error getting data source", "err", err, "id", datasourceID)
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
return Error(403, "Access denied to data source", err)
|
||||
return response.Error(403, "Access denied to data source", err)
|
||||
}
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
return Error(400, "Invalid data source ID", err)
|
||||
return response.Error(400, "Invalid data source ID", err)
|
||||
}
|
||||
return Error(500, "Unable to load data source metadata", err)
|
||||
return response.Error(500, "Unable to load data source metadata", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,16 +74,16 @@ func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext, reqDTO dtos.MetricReq
|
||||
if !hasExpr {
|
||||
resp, err = tsdb.HandleRequest(c.Req.Context(), ds, request)
|
||||
if err != nil {
|
||||
return Error(500, "Metric request error", err)
|
||||
return response.Error(500, "Metric request error", err)
|
||||
}
|
||||
} else {
|
||||
if !hs.Cfg.IsExpressionsEnabled() {
|
||||
return Error(404, "Expressions feature toggle is not enabled", nil)
|
||||
return response.Error(404, "Expressions feature toggle is not enabled", nil)
|
||||
}
|
||||
|
||||
resp, err = expr.WrapTransformData(c.Req.Context(), request)
|
||||
if err != nil {
|
||||
return Error(500, "Transform request error", err)
|
||||
return response.Error(500, "Transform request error", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,29 +96,29 @@ func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext, reqDTO dtos.MetricReq
|
||||
}
|
||||
}
|
||||
|
||||
return jsonStreaming(statusCode, resp)
|
||||
return response.JSONStreaming(statusCode, resp)
|
||||
}
|
||||
|
||||
// QueryMetrics returns query metrics
|
||||
// POST /api/tsdb/query
|
||||
func (hs *HTTPServer) QueryMetrics(c *models.ReqContext, reqDto dtos.MetricRequest) Response {
|
||||
func (hs *HTTPServer) QueryMetrics(c *models.ReqContext, reqDto dtos.MetricRequest) response.Response {
|
||||
timeRange := tsdb.NewTimeRange(reqDto.From, reqDto.To)
|
||||
|
||||
if len(reqDto.Queries) == 0 {
|
||||
return Error(400, "No queries found in query", nil)
|
||||
return response.Error(400, "No queries found in query", nil)
|
||||
}
|
||||
|
||||
datasourceId, err := reqDto.Queries[0].Get("datasourceId").Int64()
|
||||
if err != nil {
|
||||
return Error(400, "Query missing datasourceId", nil)
|
||||
return response.Error(400, "Query missing datasourceId", nil)
|
||||
}
|
||||
|
||||
ds, err := hs.DatasourceCache.GetDatasource(datasourceId, c.SignedInUser, c.SkipCache)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
return Error(403, "Access denied to datasource", err)
|
||||
return response.Error(403, "Access denied to datasource", err)
|
||||
}
|
||||
return Error(500, "Unable to load datasource meta data", err)
|
||||
return response.Error(500, "Unable to load datasource meta data", err)
|
||||
}
|
||||
|
||||
request := &tsdb.TsdbQuery{
|
||||
@@ -138,7 +139,7 @@ func (hs *HTTPServer) QueryMetrics(c *models.ReqContext, reqDto dtos.MetricReque
|
||||
|
||||
resp, err := tsdb.HandleRequest(c.Req.Context(), ds, request)
|
||||
if err != nil {
|
||||
return Error(500, "Metric request error", err)
|
||||
return response.Error(500, "Metric request error", err)
|
||||
}
|
||||
|
||||
statusCode := 200
|
||||
@@ -150,11 +151,11 @@ func (hs *HTTPServer) QueryMetrics(c *models.ReqContext, reqDto dtos.MetricReque
|
||||
}
|
||||
}
|
||||
|
||||
return JSON(statusCode, &resp)
|
||||
return response.JSON(statusCode, &resp)
|
||||
}
|
||||
|
||||
// GET /api/tsdb/testdata/scenarios
|
||||
func GetTestDataScenarios(c *models.ReqContext) Response {
|
||||
func GetTestDataScenarios(c *models.ReqContext) response.Response {
|
||||
result := make([]interface{}, 0)
|
||||
|
||||
scenarioIds := make([]string, 0)
|
||||
@@ -173,27 +174,27 @@ func GetTestDataScenarios(c *models.ReqContext) Response {
|
||||
})
|
||||
}
|
||||
|
||||
return JSON(200, &result)
|
||||
return response.JSON(200, &result)
|
||||
}
|
||||
|
||||
// GenerateError generates a index out of range error
|
||||
func GenerateError(c *models.ReqContext) Response {
|
||||
func GenerateError(c *models.ReqContext) response.Response {
|
||||
var array []string
|
||||
// nolint: govet
|
||||
return JSON(200, array[20])
|
||||
return response.JSON(200, array[20])
|
||||
}
|
||||
|
||||
// GET /api/tsdb/testdata/gensql
|
||||
func GenerateSQLTestData(c *models.ReqContext) Response {
|
||||
func GenerateSQLTestData(c *models.ReqContext) response.Response {
|
||||
if err := bus.Dispatch(&models.InsertSQLTestDataCommand{}); err != nil {
|
||||
return Error(500, "Failed to insert test data", err)
|
||||
return response.Error(500, "Failed to insert test data", err)
|
||||
}
|
||||
|
||||
return JSON(200, &util.DynMap{"message": "OK"})
|
||||
return response.JSON(200, &util.DynMap{"message": "OK"})
|
||||
}
|
||||
|
||||
// GET /api/tsdb/testdata/random-walk
|
||||
func GetTestDataRandomWalk(c *models.ReqContext) Response {
|
||||
func GetTestDataRandomWalk(c *models.ReqContext) response.Response {
|
||||
from := c.Query("from")
|
||||
to := c.Query("to")
|
||||
intervalMs := c.QueryInt64("intervalMs")
|
||||
@@ -213,8 +214,8 @@ func GetTestDataRandomWalk(c *models.ReqContext) Response {
|
||||
|
||||
resp, err := tsdb.HandleRequest(context.Background(), dsInfo, request)
|
||||
if err != nil {
|
||||
return Error(500, "Metric request error", err)
|
||||
return response.Error(500, "Metric request error", err)
|
||||
}
|
||||
|
||||
return JSON(200, &resp)
|
||||
return response.JSON(200, &resp)
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"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/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -12,24 +13,24 @@ import (
|
||||
)
|
||||
|
||||
// GET /api/org
|
||||
func GetOrgCurrent(c *models.ReqContext) Response {
|
||||
func GetOrgCurrent(c *models.ReqContext) response.Response {
|
||||
return getOrgHelper(c.OrgId)
|
||||
}
|
||||
|
||||
// GET /api/orgs/:orgId
|
||||
func GetOrgByID(c *models.ReqContext) Response {
|
||||
func GetOrgByID(c *models.ReqContext) response.Response {
|
||||
return getOrgHelper(c.ParamsInt64(":orgId"))
|
||||
}
|
||||
|
||||
// Get /api/orgs/name/:name
|
||||
func (hs *HTTPServer) GetOrgByName(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetOrgByName(c *models.ReqContext) response.Response {
|
||||
org, err := hs.SQLStore.GetOrgByName(c.Params(":name"))
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrOrgNotFound) {
|
||||
return Error(404, "Organization not found", err)
|
||||
return response.Error(404, "Organization not found", err)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to get organization", err)
|
||||
return response.Error(500, "Failed to get organization", err)
|
||||
}
|
||||
result := models.OrgDetailsDTO{
|
||||
Id: org.Id,
|
||||
@@ -44,18 +45,18 @@ func (hs *HTTPServer) GetOrgByName(c *models.ReqContext) Response {
|
||||
},
|
||||
}
|
||||
|
||||
return JSON(200, &result)
|
||||
return response.JSON(200, &result)
|
||||
}
|
||||
|
||||
func getOrgHelper(orgID int64) Response {
|
||||
func getOrgHelper(orgID int64) response.Response {
|
||||
query := models.GetOrgByIdQuery{Id: orgID}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if errors.Is(err, models.ErrOrgNotFound) {
|
||||
return Error(404, "Organization not found", err)
|
||||
return response.Error(404, "Organization not found", err)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to get organization", err)
|
||||
return response.Error(500, "Failed to get organization", err)
|
||||
}
|
||||
|
||||
org := query.Result
|
||||
@@ -72,64 +73,64 @@ func getOrgHelper(orgID int64) Response {
|
||||
},
|
||||
}
|
||||
|
||||
return JSON(200, &result)
|
||||
return response.JSON(200, &result)
|
||||
}
|
||||
|
||||
// POST /api/orgs
|
||||
func CreateOrg(c *models.ReqContext, cmd models.CreateOrgCommand) Response {
|
||||
func CreateOrg(c *models.ReqContext, cmd models.CreateOrgCommand) response.Response {
|
||||
if !c.IsSignedIn || (!setting.AllowUserOrgCreate && !c.IsGrafanaAdmin) {
|
||||
return Error(403, "Access denied", nil)
|
||||
return response.Error(403, "Access denied", nil)
|
||||
}
|
||||
|
||||
cmd.UserId = c.UserId
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrOrgNameTaken) {
|
||||
return Error(409, "Organization name taken", err)
|
||||
return response.Error(409, "Organization name taken", err)
|
||||
}
|
||||
return Error(500, "Failed to create organization", err)
|
||||
return response.Error(500, "Failed to create organization", err)
|
||||
}
|
||||
|
||||
metrics.MApiOrgCreate.Inc()
|
||||
|
||||
return JSON(200, &util.DynMap{
|
||||
return response.JSON(200, &util.DynMap{
|
||||
"orgId": cmd.Result.Id,
|
||||
"message": "Organization created",
|
||||
})
|
||||
}
|
||||
|
||||
// PUT /api/org
|
||||
func UpdateOrgCurrent(c *models.ReqContext, form dtos.UpdateOrgForm) Response {
|
||||
func UpdateOrgCurrent(c *models.ReqContext, form dtos.UpdateOrgForm) response.Response {
|
||||
return updateOrgHelper(form, c.OrgId)
|
||||
}
|
||||
|
||||
// PUT /api/orgs/:orgId
|
||||
func UpdateOrg(c *models.ReqContext, form dtos.UpdateOrgForm) Response {
|
||||
func UpdateOrg(c *models.ReqContext, form dtos.UpdateOrgForm) response.Response {
|
||||
return updateOrgHelper(form, c.ParamsInt64(":orgId"))
|
||||
}
|
||||
|
||||
func updateOrgHelper(form dtos.UpdateOrgForm, orgID int64) Response {
|
||||
func updateOrgHelper(form dtos.UpdateOrgForm, orgID int64) response.Response {
|
||||
cmd := models.UpdateOrgCommand{Name: form.Name, OrgId: orgID}
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrOrgNameTaken) {
|
||||
return Error(400, "Organization name taken", err)
|
||||
return response.Error(400, "Organization name taken", err)
|
||||
}
|
||||
return Error(500, "Failed to update organization", err)
|
||||
return response.Error(500, "Failed to update organization", err)
|
||||
}
|
||||
|
||||
return Success("Organization updated")
|
||||
return response.Success("Organization updated")
|
||||
}
|
||||
|
||||
// PUT /api/org/address
|
||||
func UpdateOrgAddressCurrent(c *models.ReqContext, form dtos.UpdateOrgAddressForm) Response {
|
||||
func UpdateOrgAddressCurrent(c *models.ReqContext, form dtos.UpdateOrgAddressForm) response.Response {
|
||||
return updateOrgAddressHelper(form, c.OrgId)
|
||||
}
|
||||
|
||||
// PUT /api/orgs/:orgId/address
|
||||
func UpdateOrgAddress(c *models.ReqContext, form dtos.UpdateOrgAddressForm) Response {
|
||||
func UpdateOrgAddress(c *models.ReqContext, form dtos.UpdateOrgAddressForm) response.Response {
|
||||
return updateOrgAddressHelper(form, c.ParamsInt64(":orgId"))
|
||||
}
|
||||
|
||||
func updateOrgAddressHelper(form dtos.UpdateOrgAddressForm, orgID int64) Response {
|
||||
func updateOrgAddressHelper(form dtos.UpdateOrgAddressForm, orgID int64) response.Response {
|
||||
cmd := models.UpdateOrgAddressCommand{
|
||||
OrgId: orgID,
|
||||
Address: models.Address{
|
||||
@@ -143,24 +144,24 @@ func updateOrgAddressHelper(form dtos.UpdateOrgAddressForm, orgID int64) Respons
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to update org address", err)
|
||||
return response.Error(500, "Failed to update org address", err)
|
||||
}
|
||||
|
||||
return Success("Address updated")
|
||||
return response.Success("Address updated")
|
||||
}
|
||||
|
||||
// GET /api/orgs/:orgId
|
||||
func DeleteOrgByID(c *models.ReqContext) Response {
|
||||
func DeleteOrgByID(c *models.ReqContext) response.Response {
|
||||
if err := bus.Dispatch(&models.DeleteOrgCommand{Id: c.ParamsInt64(":orgId")}); err != nil {
|
||||
if errors.Is(err, models.ErrOrgNotFound) {
|
||||
return Error(404, "Failed to delete organization. ID not found", nil)
|
||||
return response.Error(404, "Failed to delete organization. ID not found", nil)
|
||||
}
|
||||
return Error(500, "Failed to update organization", err)
|
||||
return response.Error(500, "Failed to update organization", err)
|
||||
}
|
||||
return Success("Organization deleted")
|
||||
return response.Success("Organization deleted")
|
||||
}
|
||||
|
||||
func SearchOrgs(c *models.ReqContext) Response {
|
||||
func SearchOrgs(c *models.ReqContext) response.Response {
|
||||
perPage := c.QueryInt("perpage")
|
||||
if perPage <= 0 {
|
||||
perPage = 1000
|
||||
@@ -176,8 +177,8 @@ func SearchOrgs(c *models.ReqContext) Response {
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to search orgs", err)
|
||||
return response.Error(500, "Failed to search orgs", err)
|
||||
}
|
||||
|
||||
return JSON(200, query.Result)
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"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/events"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
@@ -13,37 +14,37 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func GetPendingOrgInvites(c *models.ReqContext) Response {
|
||||
func GetPendingOrgInvites(c *models.ReqContext) response.Response {
|
||||
query := models.GetTempUsersQuery{OrgId: c.OrgId, Status: models.TmpUserInvitePending}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to get invites from db", err)
|
||||
return response.Error(500, "Failed to get invites from db", err)
|
||||
}
|
||||
|
||||
for _, invite := range query.Result {
|
||||
invite.Url = setting.ToAbsUrl("invite/" + invite.Code)
|
||||
}
|
||||
|
||||
return JSON(200, query.Result)
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
func AddOrgInvite(c *models.ReqContext, inviteDto dtos.AddInviteForm) Response {
|
||||
func AddOrgInvite(c *models.ReqContext, inviteDto dtos.AddInviteForm) response.Response {
|
||||
if !inviteDto.Role.IsValid() {
|
||||
return Error(400, "Invalid role specified", nil)
|
||||
return response.Error(400, "Invalid role specified", nil)
|
||||
}
|
||||
|
||||
// first try get existing user
|
||||
userQuery := models.GetUserByLoginQuery{LoginOrEmail: inviteDto.LoginOrEmail}
|
||||
if err := bus.Dispatch(&userQuery); err != nil {
|
||||
if !errors.Is(err, models.ErrUserNotFound) {
|
||||
return Error(500, "Failed to query db for existing user check", err)
|
||||
return response.Error(500, "Failed to query db for existing user check", err)
|
||||
}
|
||||
} else {
|
||||
return inviteExistingUserToOrg(c, userQuery.Result, &inviteDto)
|
||||
}
|
||||
|
||||
if setting.DisableLoginForm {
|
||||
return Error(400, "Cannot invite when login is disabled.", nil)
|
||||
return response.Error(400, "Cannot invite when login is disabled.", nil)
|
||||
}
|
||||
|
||||
cmd := models.CreateTempUserCommand{}
|
||||
@@ -55,13 +56,13 @@ func AddOrgInvite(c *models.ReqContext, inviteDto dtos.AddInviteForm) Response {
|
||||
var err error
|
||||
cmd.Code, err = util.GetRandomString(30)
|
||||
if err != nil {
|
||||
return Error(500, "Could not generate random string", err)
|
||||
return response.Error(500, "Could not generate random string", err)
|
||||
}
|
||||
cmd.Role = inviteDto.Role
|
||||
cmd.RemoteAddr = c.Req.RemoteAddr
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to save invite to database", err)
|
||||
return response.Error(500, "Failed to save invite to database", err)
|
||||
}
|
||||
|
||||
// send invite email
|
||||
@@ -80,31 +81,31 @@ func AddOrgInvite(c *models.ReqContext, inviteDto dtos.AddInviteForm) Response {
|
||||
|
||||
if err := bus.Dispatch(&emailCmd); err != nil {
|
||||
if errors.Is(err, models.ErrSmtpNotEnabled) {
|
||||
return Error(412, err.Error(), err)
|
||||
return response.Error(412, err.Error(), err)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to send email invite", err)
|
||||
return response.Error(500, "Failed to send email invite", err)
|
||||
}
|
||||
|
||||
emailSentCmd := models.UpdateTempUserWithEmailSentCommand{Code: cmd.Result.Code}
|
||||
if err := bus.Dispatch(&emailSentCmd); err != nil {
|
||||
return Error(500, "Failed to update invite with email sent info", err)
|
||||
return response.Error(500, "Failed to update invite with email sent info", err)
|
||||
}
|
||||
|
||||
return Success(fmt.Sprintf("Sent invite to %s", inviteDto.LoginOrEmail))
|
||||
return response.Success(fmt.Sprintf("Sent invite to %s", inviteDto.LoginOrEmail))
|
||||
}
|
||||
|
||||
return Success(fmt.Sprintf("Created invite for %s", inviteDto.LoginOrEmail))
|
||||
return response.Success(fmt.Sprintf("Created invite for %s", inviteDto.LoginOrEmail))
|
||||
}
|
||||
|
||||
func inviteExistingUserToOrg(c *models.ReqContext, user *models.User, inviteDto *dtos.AddInviteForm) Response {
|
||||
func inviteExistingUserToOrg(c *models.ReqContext, user *models.User, inviteDto *dtos.AddInviteForm) response.Response {
|
||||
// user exists, add org role
|
||||
createOrgUserCmd := models.AddOrgUserCommand{OrgId: c.OrgId, UserId: user.Id, Role: inviteDto.Role}
|
||||
if err := bus.Dispatch(&createOrgUserCmd); err != nil {
|
||||
if errors.Is(err, models.ErrOrgUserAlreadyAdded) {
|
||||
return Error(412, fmt.Sprintf("User %s is already added to organization", inviteDto.LoginOrEmail), err)
|
||||
return response.Error(412, fmt.Sprintf("User %s is already added to organization", inviteDto.LoginOrEmail), err)
|
||||
}
|
||||
return Error(500, "Error while trying to create org user", err)
|
||||
return response.Error(500, "Error while trying to create org user", err)
|
||||
}
|
||||
|
||||
if inviteDto.SendEmail && util.IsEmail(user.Email) {
|
||||
@@ -119,42 +120,42 @@ func inviteExistingUserToOrg(c *models.ReqContext, user *models.User, inviteDto
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&emailCmd); err != nil {
|
||||
return Error(500, "Failed to send email invited_to_org", err)
|
||||
return response.Error(500, "Failed to send email invited_to_org", err)
|
||||
}
|
||||
}
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": fmt.Sprintf("Existing Grafana user %s added to org %s", user.NameOrFallback(), c.OrgName),
|
||||
"userId": user.Id,
|
||||
})
|
||||
}
|
||||
|
||||
func RevokeInvite(c *models.ReqContext) Response {
|
||||
func RevokeInvite(c *models.ReqContext) response.Response {
|
||||
if ok, rsp := updateTempUserStatus(c.Params(":code"), models.TmpUserRevoked); !ok {
|
||||
return rsp
|
||||
}
|
||||
|
||||
return Success("Invite revoked")
|
||||
return response.Success("Invite revoked")
|
||||
}
|
||||
|
||||
// GetInviteInfoByCode gets a pending user invite corresponding to a certain code.
|
||||
// A response containing an InviteInfo object is returned if the invite is found.
|
||||
// If a (pending) invite is not found, 404 is returned.
|
||||
func GetInviteInfoByCode(c *models.ReqContext) Response {
|
||||
func GetInviteInfoByCode(c *models.ReqContext) response.Response {
|
||||
query := models.GetTempUserByCodeQuery{Code: c.Params(":code")}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if errors.Is(err, models.ErrTempUserNotFound) {
|
||||
return Error(404, "Invite not found", nil)
|
||||
return response.Error(404, "Invite not found", nil)
|
||||
}
|
||||
return Error(500, "Failed to get invite", err)
|
||||
return response.Error(500, "Failed to get invite", err)
|
||||
}
|
||||
|
||||
invite := query.Result
|
||||
if invite.Status != models.TmpUserInvitePending {
|
||||
return Error(404, "Invite not found", nil)
|
||||
return response.Error(404, "Invite not found", nil)
|
||||
}
|
||||
|
||||
return JSON(200, dtos.InviteInfo{
|
||||
return response.JSON(200, dtos.InviteInfo{
|
||||
Email: invite.Email,
|
||||
Name: invite.Name,
|
||||
Username: invite.Email,
|
||||
@@ -162,19 +163,19 @@ func GetInviteInfoByCode(c *models.ReqContext) Response {
|
||||
})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) CompleteInvite(c *models.ReqContext, completeInvite dtos.CompleteInviteForm) Response {
|
||||
func (hs *HTTPServer) CompleteInvite(c *models.ReqContext, completeInvite dtos.CompleteInviteForm) response.Response {
|
||||
query := models.GetTempUserByCodeQuery{Code: completeInvite.InviteCode}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if errors.Is(err, models.ErrTempUserNotFound) {
|
||||
return Error(404, "Invite not found", nil)
|
||||
return response.Error(404, "Invite not found", nil)
|
||||
}
|
||||
return Error(500, "Failed to get invite", err)
|
||||
return response.Error(500, "Failed to get invite", err)
|
||||
}
|
||||
|
||||
invite := query.Result
|
||||
if invite.Status != models.TmpUserInvitePending {
|
||||
return Error(412, fmt.Sprintf("Invite cannot be used in status %s", invite.Status), nil)
|
||||
return response.Error(412, fmt.Sprintf("Invite cannot be used in status %s", invite.Status), nil)
|
||||
}
|
||||
|
||||
cmd := models.CreateUserCommand{
|
||||
@@ -187,10 +188,10 @@ func (hs *HTTPServer) CompleteInvite(c *models.ReqContext, completeInvite dtos.C
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrUserAlreadyExists) {
|
||||
return Error(412, fmt.Sprintf("User with email '%s' or username '%s' already exists", completeInvite.Email, completeInvite.Username), err)
|
||||
return response.Error(412, fmt.Sprintf("User with email '%s' or username '%s' already exists", completeInvite.Email, completeInvite.Username), err)
|
||||
}
|
||||
|
||||
return Error(500, "failed to create user", err)
|
||||
return response.Error(500, "failed to create user", err)
|
||||
}
|
||||
|
||||
user := &cmd.Result
|
||||
@@ -199,7 +200,7 @@ func (hs *HTTPServer) CompleteInvite(c *models.ReqContext, completeInvite dtos.C
|
||||
Name: user.NameOrFallback(),
|
||||
Email: user.Email,
|
||||
}); err != nil {
|
||||
return Error(500, "failed to publish event", err)
|
||||
return response.Error(500, "failed to publish event", err)
|
||||
}
|
||||
|
||||
if ok, rsp := applyUserInvite(user, invite, true); !ok {
|
||||
@@ -208,34 +209,34 @@ func (hs *HTTPServer) CompleteInvite(c *models.ReqContext, completeInvite dtos.C
|
||||
|
||||
err := hs.loginUserWithUser(user, c)
|
||||
if err != nil {
|
||||
return Error(500, "failed to accept invite", err)
|
||||
return response.Error(500, "failed to accept invite", err)
|
||||
}
|
||||
|
||||
metrics.MApiUserSignUpCompleted.Inc()
|
||||
metrics.MApiUserSignUpInvite.Inc()
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": "User created and logged in",
|
||||
"id": user.Id,
|
||||
})
|
||||
}
|
||||
|
||||
func updateTempUserStatus(code string, status models.TempUserStatus) (bool, Response) {
|
||||
func updateTempUserStatus(code string, status models.TempUserStatus) (bool, response.Response) {
|
||||
// update temp user status
|
||||
updateTmpUserCmd := models.UpdateTempUserStatusCommand{Code: code, Status: status}
|
||||
if err := bus.Dispatch(&updateTmpUserCmd); err != nil {
|
||||
return false, Error(500, "Failed to update invite status", err)
|
||||
return false, response.Error(500, "Failed to update invite status", err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func applyUserInvite(user *models.User, invite *models.TempUserDTO, setActive bool) (bool, Response) {
|
||||
func applyUserInvite(user *models.User, invite *models.TempUserDTO, setActive bool) (bool, response.Response) {
|
||||
// add to org
|
||||
addOrgUserCmd := models.AddOrgUserCommand{OrgId: invite.OrgId, UserId: user.Id, Role: invite.Role}
|
||||
if err := bus.Dispatch(&addOrgUserCmd); err != nil {
|
||||
if !errors.Is(err, models.ErrOrgUserAlreadyAdded) {
|
||||
return false, Error(500, "Error while trying to create org user", err)
|
||||
return false, response.Error(500, "Error while trying to create org user", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +248,7 @@ func applyUserInvite(user *models.User, invite *models.TempUserDTO, setActive bo
|
||||
if setActive {
|
||||
// set org to active
|
||||
if err := bus.Dispatch(&models.SetUsingOrgCommand{OrgId: invite.OrgId, UserId: user.Id}); err != nil {
|
||||
return false, Error(500, "Failed to set org as active", err)
|
||||
return false, response.Error(500, "Failed to set org as active", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -4,32 +4,33 @@ import (
|
||||
"errors"
|
||||
|
||||
"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/util"
|
||||
)
|
||||
|
||||
// POST /api/org/users
|
||||
func AddOrgUserToCurrentOrg(c *models.ReqContext, cmd models.AddOrgUserCommand) Response {
|
||||
func AddOrgUserToCurrentOrg(c *models.ReqContext, cmd models.AddOrgUserCommand) response.Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
return addOrgUserHelper(cmd)
|
||||
}
|
||||
|
||||
// POST /api/orgs/:orgId/users
|
||||
func AddOrgUser(c *models.ReqContext, cmd models.AddOrgUserCommand) Response {
|
||||
func AddOrgUser(c *models.ReqContext, cmd models.AddOrgUserCommand) response.Response {
|
||||
cmd.OrgId = c.ParamsInt64(":orgId")
|
||||
return addOrgUserHelper(cmd)
|
||||
}
|
||||
|
||||
func addOrgUserHelper(cmd models.AddOrgUserCommand) Response {
|
||||
func addOrgUserHelper(cmd models.AddOrgUserCommand) response.Response {
|
||||
if !cmd.Role.IsValid() {
|
||||
return Error(400, "Invalid role specified", nil)
|
||||
return response.Error(400, "Invalid role specified", nil)
|
||||
}
|
||||
|
||||
userQuery := models.GetUserByLoginQuery{LoginOrEmail: cmd.LoginOrEmail}
|
||||
err := bus.Dispatch(&userQuery)
|
||||
if err != nil {
|
||||
return Error(404, "User not found", nil)
|
||||
return response.Error(404, "User not found", nil)
|
||||
}
|
||||
|
||||
userToAdd := userQuery.Result
|
||||
@@ -38,22 +39,22 @@ func addOrgUserHelper(cmd models.AddOrgUserCommand) Response {
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrOrgUserAlreadyAdded) {
|
||||
return JSON(409, util.DynMap{
|
||||
return response.JSON(409, util.DynMap{
|
||||
"message": "User is already member of this organization",
|
||||
"userId": cmd.UserId,
|
||||
})
|
||||
}
|
||||
return Error(500, "Could not add user to organization", err)
|
||||
return response.Error(500, "Could not add user to organization", err)
|
||||
}
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": "User added to organization",
|
||||
"userId": cmd.UserId,
|
||||
})
|
||||
}
|
||||
|
||||
// GET /api/org/users
|
||||
func (hs *HTTPServer) GetOrgUsersForCurrentOrg(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetOrgUsersForCurrentOrg(c *models.ReqContext) response.Response {
|
||||
result, err := hs.getOrgUsersHelper(&models.GetOrgUsersQuery{
|
||||
OrgId: c.OrgId,
|
||||
Query: c.Query("query"),
|
||||
@@ -61,21 +62,21 @@ func (hs *HTTPServer) GetOrgUsersForCurrentOrg(c *models.ReqContext) Response {
|
||||
}, c.SignedInUser)
|
||||
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get users for current organization", err)
|
||||
return response.Error(500, "Failed to get users for current organization", err)
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
||||
// GET /api/org/users/lookup
|
||||
func (hs *HTTPServer) GetOrgUsersForCurrentOrgLookup(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetOrgUsersForCurrentOrgLookup(c *models.ReqContext) response.Response {
|
||||
isAdmin, err := isOrgAdminFolderAdminOrTeamAdmin(c)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get users for current organization", err)
|
||||
return response.Error(500, "Failed to get users for current organization", err)
|
||||
}
|
||||
|
||||
if !isAdmin {
|
||||
return Error(403, "Permission denied", nil)
|
||||
return response.Error(403, "Permission denied", nil)
|
||||
}
|
||||
|
||||
orgUsers, err := hs.getOrgUsersHelper(&models.GetOrgUsersQuery{
|
||||
@@ -85,7 +86,7 @@ func (hs *HTTPServer) GetOrgUsersForCurrentOrgLookup(c *models.ReqContext) Respo
|
||||
}, c.SignedInUser)
|
||||
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get users for current organization", err)
|
||||
return response.Error(500, "Failed to get users for current organization", err)
|
||||
}
|
||||
|
||||
result := make([]*dtos.UserLookupDTO, 0)
|
||||
@@ -98,7 +99,7 @@ func (hs *HTTPServer) GetOrgUsersForCurrentOrgLookup(c *models.ReqContext) Respo
|
||||
})
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
||||
func isOrgAdminFolderAdminOrTeamAdmin(c *models.ReqContext) (bool, error) {
|
||||
@@ -124,7 +125,7 @@ func isOrgAdminFolderAdminOrTeamAdmin(c *models.ReqContext) (bool, error) {
|
||||
}
|
||||
|
||||
// GET /api/orgs/:orgId/users
|
||||
func (hs *HTTPServer) GetOrgUsers(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetOrgUsers(c *models.ReqContext) response.Response {
|
||||
result, err := hs.getOrgUsersHelper(&models.GetOrgUsersQuery{
|
||||
OrgId: c.ParamsInt64(":orgId"),
|
||||
Query: "",
|
||||
@@ -132,10 +133,10 @@ func (hs *HTTPServer) GetOrgUsers(c *models.ReqContext) Response {
|
||||
}, c.SignedInUser)
|
||||
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get users for organization", err)
|
||||
return response.Error(500, "Failed to get users for organization", err)
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) getOrgUsersHelper(query *models.GetOrgUsersQuery, signedInUser *models.SignedInUser) ([]*models.OrgUserDTO, error) {
|
||||
@@ -157,36 +158,36 @@ func (hs *HTTPServer) getOrgUsersHelper(query *models.GetOrgUsersQuery, signedIn
|
||||
}
|
||||
|
||||
// PATCH /api/org/users/:userId
|
||||
func UpdateOrgUserForCurrentOrg(c *models.ReqContext, cmd models.UpdateOrgUserCommand) Response {
|
||||
func UpdateOrgUserForCurrentOrg(c *models.ReqContext, cmd models.UpdateOrgUserCommand) response.Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.UserId = c.ParamsInt64(":userId")
|
||||
return updateOrgUserHelper(cmd)
|
||||
}
|
||||
|
||||
// PATCH /api/orgs/:orgId/users/:userId
|
||||
func UpdateOrgUser(c *models.ReqContext, cmd models.UpdateOrgUserCommand) Response {
|
||||
func UpdateOrgUser(c *models.ReqContext, cmd models.UpdateOrgUserCommand) response.Response {
|
||||
cmd.OrgId = c.ParamsInt64(":orgId")
|
||||
cmd.UserId = c.ParamsInt64(":userId")
|
||||
return updateOrgUserHelper(cmd)
|
||||
}
|
||||
|
||||
func updateOrgUserHelper(cmd models.UpdateOrgUserCommand) Response {
|
||||
func updateOrgUserHelper(cmd models.UpdateOrgUserCommand) response.Response {
|
||||
if !cmd.Role.IsValid() {
|
||||
return Error(400, "Invalid role specified", nil)
|
||||
return response.Error(400, "Invalid role specified", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrLastOrgAdmin) {
|
||||
return Error(400, "Cannot change role so that there is no organization admin left", nil)
|
||||
return response.Error(400, "Cannot change role so that there is no organization admin left", nil)
|
||||
}
|
||||
return Error(500, "Failed update org user", err)
|
||||
return response.Error(500, "Failed update org user", err)
|
||||
}
|
||||
|
||||
return Success("Organization user updated")
|
||||
return response.Success("Organization user updated")
|
||||
}
|
||||
|
||||
// DELETE /api/org/users/:userId
|
||||
func RemoveOrgUserForCurrentOrg(c *models.ReqContext) Response {
|
||||
func RemoveOrgUserForCurrentOrg(c *models.ReqContext) response.Response {
|
||||
return removeOrgUserHelper(&models.RemoveOrgUserCommand{
|
||||
UserId: c.ParamsInt64(":userId"),
|
||||
OrgId: c.OrgId,
|
||||
@@ -195,24 +196,24 @@ func RemoveOrgUserForCurrentOrg(c *models.ReqContext) Response {
|
||||
}
|
||||
|
||||
// DELETE /api/orgs/:orgId/users/:userId
|
||||
func RemoveOrgUser(c *models.ReqContext) Response {
|
||||
func RemoveOrgUser(c *models.ReqContext) response.Response {
|
||||
return removeOrgUserHelper(&models.RemoveOrgUserCommand{
|
||||
UserId: c.ParamsInt64(":userId"),
|
||||
OrgId: c.ParamsInt64(":orgId"),
|
||||
})
|
||||
}
|
||||
|
||||
func removeOrgUserHelper(cmd *models.RemoveOrgUserCommand) Response {
|
||||
func removeOrgUserHelper(cmd *models.RemoveOrgUserCommand) response.Response {
|
||||
if err := bus.Dispatch(cmd); err != nil {
|
||||
if errors.Is(err, models.ErrLastOrgAdmin) {
|
||||
return Error(400, "Cannot remove last organization admin", nil)
|
||||
return response.Error(400, "Cannot remove last organization admin", nil)
|
||||
}
|
||||
return Error(500, "Failed to remove user from organization", err)
|
||||
return response.Error(500, "Failed to remove user from organization", err)
|
||||
}
|
||||
|
||||
if cmd.UserWasDeleted {
|
||||
return Success("User deleted")
|
||||
return response.Success("User deleted")
|
||||
}
|
||||
|
||||
return Success("User removed from organization")
|
||||
return response.Success("User removed from organization")
|
||||
}
|
||||
|
@@ -4,47 +4,48 @@ import (
|
||||
"errors"
|
||||
|
||||
"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/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func SendResetPasswordEmail(c *models.ReqContext, form dtos.SendResetPasswordEmailForm) Response {
|
||||
func SendResetPasswordEmail(c *models.ReqContext, form dtos.SendResetPasswordEmailForm) response.Response {
|
||||
if setting.LDAPEnabled || setting.AuthProxyEnabled {
|
||||
return Error(401, "Not allowed to reset password when LDAP or Auth Proxy is enabled", nil)
|
||||
return response.Error(401, "Not allowed to reset password when LDAP or Auth Proxy is enabled", nil)
|
||||
}
|
||||
if setting.DisableLoginForm {
|
||||
return Error(401, "Not allowed to reset password when login form is disabled", nil)
|
||||
return response.Error(401, "Not allowed to reset password when login form is disabled", nil)
|
||||
}
|
||||
|
||||
userQuery := models.GetUserByLoginQuery{LoginOrEmail: form.UserOrEmail}
|
||||
|
||||
if err := bus.Dispatch(&userQuery); err != nil {
|
||||
c.Logger.Info("Requested password reset for user that was not found", "user", userQuery.LoginOrEmail)
|
||||
return Error(200, "Email sent", err)
|
||||
return response.Error(200, "Email sent", err)
|
||||
}
|
||||
|
||||
emailCmd := models.SendResetPasswordEmailCommand{User: userQuery.Result}
|
||||
if err := bus.Dispatch(&emailCmd); err != nil {
|
||||
return Error(500, "Failed to send email", err)
|
||||
return response.Error(500, "Failed to send email", err)
|
||||
}
|
||||
|
||||
return Success("Email sent")
|
||||
return response.Success("Email sent")
|
||||
}
|
||||
|
||||
func ResetPassword(c *models.ReqContext, form dtos.ResetUserPasswordForm) Response {
|
||||
func ResetPassword(c *models.ReqContext, form dtos.ResetUserPasswordForm) response.Response {
|
||||
query := models.ValidateResetPasswordCodeQuery{Code: form.Code}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if errors.Is(err, models.ErrInvalidEmailCode) {
|
||||
return Error(400, "Invalid or expired reset password code", nil)
|
||||
return response.Error(400, "Invalid or expired reset password code", nil)
|
||||
}
|
||||
return Error(500, "Unknown error validating email code", err)
|
||||
return response.Error(500, "Unknown error validating email code", err)
|
||||
}
|
||||
|
||||
if form.NewPassword != form.ConfirmPassword {
|
||||
return Error(400, "Passwords do not match", nil)
|
||||
return response.Error(400, "Passwords do not match", nil)
|
||||
}
|
||||
|
||||
cmd := models.ChangeUserPasswordCommand{}
|
||||
@@ -52,12 +53,12 @@ func ResetPassword(c *models.ReqContext, form dtos.ResetUserPasswordForm) Respon
|
||||
var err error
|
||||
cmd.NewPassword, err = util.EncodePassword(form.NewPassword, query.Result.Salt)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to encode password", err)
|
||||
return response.Error(500, "Failed to encode password", err)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to change user password", err)
|
||||
return response.Error(500, "Failed to change user password", err)
|
||||
}
|
||||
|
||||
return Success("User password changed")
|
||||
return response.Success("User password changed")
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
@@ -26,7 +27,7 @@ func ValidateOrgPlaylist(c *models.ReqContext) {
|
||||
}
|
||||
}
|
||||
|
||||
func SearchPlaylists(c *models.ReqContext) Response {
|
||||
func SearchPlaylists(c *models.ReqContext) response.Response {
|
||||
query := c.Query("query")
|
||||
limit := c.QueryInt("limit")
|
||||
|
||||
@@ -42,18 +43,18 @@ func SearchPlaylists(c *models.ReqContext) Response {
|
||||
|
||||
err := bus.Dispatch(&searchQuery)
|
||||
if err != nil {
|
||||
return Error(500, "Search failed", err)
|
||||
return response.Error(500, "Search failed", err)
|
||||
}
|
||||
|
||||
return JSON(200, searchQuery.Result)
|
||||
return response.JSON(200, searchQuery.Result)
|
||||
}
|
||||
|
||||
func GetPlaylist(c *models.ReqContext) Response {
|
||||
func GetPlaylist(c *models.ReqContext) response.Response {
|
||||
id := c.ParamsInt64(":id")
|
||||
cmd := models.GetPlaylistByIdQuery{Id: id}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Playlist not found", err)
|
||||
return response.Error(500, "Playlist not found", err)
|
||||
}
|
||||
|
||||
playlistDTOs, _ := LoadPlaylistItemDTOs(id)
|
||||
@@ -66,7 +67,7 @@ func GetPlaylist(c *models.ReqContext) Response {
|
||||
Items: playlistDTOs,
|
||||
}
|
||||
|
||||
return JSON(200, dto)
|
||||
return response.JSON(200, dto)
|
||||
}
|
||||
|
||||
func LoadPlaylistItemDTOs(id int64) ([]models.PlaylistItemDTO, error) {
|
||||
@@ -101,63 +102,63 @@ func LoadPlaylistItems(id int64) ([]models.PlaylistItem, error) {
|
||||
return *itemQuery.Result, nil
|
||||
}
|
||||
|
||||
func GetPlaylistItems(c *models.ReqContext) Response {
|
||||
func GetPlaylistItems(c *models.ReqContext) response.Response {
|
||||
id := c.ParamsInt64(":id")
|
||||
|
||||
playlistDTOs, err := LoadPlaylistItemDTOs(id)
|
||||
|
||||
if err != nil {
|
||||
return Error(500, "Could not load playlist items", err)
|
||||
return response.Error(500, "Could not load playlist items", err)
|
||||
}
|
||||
|
||||
return JSON(200, playlistDTOs)
|
||||
return response.JSON(200, playlistDTOs)
|
||||
}
|
||||
|
||||
func GetPlaylistDashboards(c *models.ReqContext) Response {
|
||||
func GetPlaylistDashboards(c *models.ReqContext) response.Response {
|
||||
playlistID := c.ParamsInt64(":id")
|
||||
|
||||
playlists, err := LoadPlaylistDashboards(c.OrgId, c.SignedInUser, playlistID)
|
||||
if err != nil {
|
||||
return Error(500, "Could not load dashboards", err)
|
||||
return response.Error(500, "Could not load dashboards", err)
|
||||
}
|
||||
|
||||
return JSON(200, playlists)
|
||||
return response.JSON(200, playlists)
|
||||
}
|
||||
|
||||
func DeletePlaylist(c *models.ReqContext) Response {
|
||||
func DeletePlaylist(c *models.ReqContext) response.Response {
|
||||
id := c.ParamsInt64(":id")
|
||||
|
||||
cmd := models.DeletePlaylistCommand{Id: id, OrgId: c.OrgId}
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to delete playlist", err)
|
||||
return response.Error(500, "Failed to delete playlist", err)
|
||||
}
|
||||
|
||||
return JSON(200, "")
|
||||
return response.JSON(200, "")
|
||||
}
|
||||
|
||||
func CreatePlaylist(c *models.ReqContext, cmd models.CreatePlaylistCommand) Response {
|
||||
func CreatePlaylist(c *models.ReqContext, cmd models.CreatePlaylistCommand) response.Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to create playlist", err)
|
||||
return response.Error(500, "Failed to create playlist", err)
|
||||
}
|
||||
|
||||
return JSON(200, cmd.Result)
|
||||
return response.JSON(200, cmd.Result)
|
||||
}
|
||||
|
||||
func UpdatePlaylist(c *models.ReqContext, cmd models.UpdatePlaylistCommand) Response {
|
||||
func UpdatePlaylist(c *models.ReqContext, cmd models.UpdatePlaylistCommand) response.Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.Id = c.ParamsInt64(":id")
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to save playlist", err)
|
||||
return response.Error(500, "Failed to save playlist", err)
|
||||
}
|
||||
|
||||
playlistDTOs, err := LoadPlaylistItemDTOs(cmd.Id)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to save playlist", err)
|
||||
return response.Error(500, "Failed to save playlist", err)
|
||||
}
|
||||
|
||||
cmd.Result.Items = playlistDTOs
|
||||
return JSON(200, cmd.Result)
|
||||
return response.JSON(200, cmd.Result)
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
"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/plugins"
|
||||
@@ -61,7 +62,7 @@ func (hs *HTTPServer) getPluginContext(pluginID string, user *models.SignedInUse
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) GetPluginList(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetPluginList(c *models.ReqContext) response.Response {
|
||||
typeFilter := c.Query("type")
|
||||
enabledFilter := c.Query("enabled")
|
||||
embeddedFilter := c.Query("embedded")
|
||||
@@ -75,7 +76,7 @@ func (hs *HTTPServer) GetPluginList(c *models.ReqContext) Response {
|
||||
pluginSettingsMap, err := plugins.GetPluginSettings(c.OrgId)
|
||||
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get list of plugins", err)
|
||||
return response.Error(500, "Failed to get list of plugins", err)
|
||||
}
|
||||
|
||||
result := make(dtos.PluginList, 0)
|
||||
@@ -139,15 +140,15 @@ func (hs *HTTPServer) GetPluginList(c *models.ReqContext) Response {
|
||||
}
|
||||
|
||||
sort.Sort(result)
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
||||
func GetPluginSettingByID(c *models.ReqContext) Response {
|
||||
func GetPluginSettingByID(c *models.ReqContext) response.Response {
|
||||
pluginID := c.Params(":pluginId")
|
||||
|
||||
def, exists := plugins.Plugins[pluginID]
|
||||
if !exists {
|
||||
return Error(404, "Plugin not found, no installed plugin with that id", nil)
|
||||
return response.Error(404, "Plugin not found, no installed plugin with that id", nil)
|
||||
}
|
||||
|
||||
dto := &dtos.PluginSetting{
|
||||
@@ -171,7 +172,7 @@ func GetPluginSettingByID(c *models.ReqContext) Response {
|
||||
query := models.GetPluginSettingByIdQuery{PluginId: pluginID, OrgId: c.OrgId}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if !errors.Is(err, models.ErrPluginSettingNotFound) {
|
||||
return Error(500, "Failed to get login settings", nil)
|
||||
return response.Error(500, "Failed to get login settings", nil)
|
||||
}
|
||||
} else {
|
||||
dto.Enabled = query.Result.Enabled
|
||||
@@ -179,43 +180,43 @@ func GetPluginSettingByID(c *models.ReqContext) Response {
|
||||
dto.JsonData = query.Result.JsonData
|
||||
}
|
||||
|
||||
return JSON(200, dto)
|
||||
return response.JSON(200, dto)
|
||||
}
|
||||
|
||||
func UpdatePluginSetting(c *models.ReqContext, cmd models.UpdatePluginSettingCmd) Response {
|
||||
func UpdatePluginSetting(c *models.ReqContext, cmd models.UpdatePluginSettingCmd) response.Response {
|
||||
pluginID := c.Params(":pluginId")
|
||||
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.PluginId = pluginID
|
||||
|
||||
if _, ok := plugins.Apps[cmd.PluginId]; !ok {
|
||||
return Error(404, "Plugin not installed.", nil)
|
||||
return response.Error(404, "Plugin not installed.", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to update plugin setting", err)
|
||||
return response.Error(500, "Failed to update plugin setting", err)
|
||||
}
|
||||
|
||||
return Success("Plugin settings updated")
|
||||
return response.Success("Plugin settings updated")
|
||||
}
|
||||
|
||||
func GetPluginDashboards(c *models.ReqContext) Response {
|
||||
func GetPluginDashboards(c *models.ReqContext) response.Response {
|
||||
pluginID := c.Params(":pluginId")
|
||||
|
||||
list, err := plugins.GetPluginDashboards(c.OrgId, pluginID)
|
||||
if err != nil {
|
||||
var notFound plugins.PluginNotFoundError
|
||||
if errors.As(err, ¬Found) {
|
||||
return Error(404, notFound.Error(), nil)
|
||||
return response.Error(404, notFound.Error(), nil)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to get plugin dashboards", err)
|
||||
return response.Error(500, "Failed to get plugin dashboards", err)
|
||||
}
|
||||
|
||||
return JSON(200, list)
|
||||
return response.JSON(200, list)
|
||||
}
|
||||
|
||||
func GetPluginMarkdown(c *models.ReqContext) Response {
|
||||
func GetPluginMarkdown(c *models.ReqContext) response.Response {
|
||||
pluginID := c.Params(":pluginId")
|
||||
name := c.Params(":name")
|
||||
|
||||
@@ -223,28 +224,28 @@ func GetPluginMarkdown(c *models.ReqContext) Response {
|
||||
if err != nil {
|
||||
var notFound plugins.PluginNotFoundError
|
||||
if errors.As(err, ¬Found) {
|
||||
return Error(404, notFound.Error(), nil)
|
||||
return response.Error(404, notFound.Error(), nil)
|
||||
}
|
||||
|
||||
return Error(500, "Could not get markdown file", err)
|
||||
return response.Error(500, "Could not get markdown file", err)
|
||||
}
|
||||
|
||||
// fallback try readme
|
||||
if len(content) == 0 {
|
||||
content, err = plugins.GetPluginMarkdown(pluginID, "readme")
|
||||
if err != nil {
|
||||
return Error(501, "Could not get markdown file", err)
|
||||
return response.Error(501, "Could not get markdown file", err)
|
||||
}
|
||||
}
|
||||
|
||||
resp := Respond(200, content)
|
||||
resp := response.Respond(200, content)
|
||||
resp.Header("Content-Type", "text/plain; charset=utf-8")
|
||||
return resp
|
||||
}
|
||||
|
||||
func ImportDashboard(c *models.ReqContext, apiCmd dtos.ImportDashboardCommand) Response {
|
||||
func ImportDashboard(c *models.ReqContext, apiCmd dtos.ImportDashboardCommand) response.Response {
|
||||
if apiCmd.PluginId == "" && apiCmd.Dashboard == nil {
|
||||
return Error(422, "Dashboard must be set", nil)
|
||||
return response.Error(422, "Dashboard must be set", nil)
|
||||
}
|
||||
|
||||
cmd := plugins.ImportDashboardCommand{
|
||||
@@ -262,17 +263,17 @@ func ImportDashboard(c *models.ReqContext, apiCmd dtos.ImportDashboardCommand) R
|
||||
return dashboardSaveErrorToApiResponse(err)
|
||||
}
|
||||
|
||||
return JSON(200, cmd.Result)
|
||||
return response.JSON(200, cmd.Result)
|
||||
}
|
||||
|
||||
// CollectPluginMetrics collect metrics from a plugin.
|
||||
//
|
||||
// /api/plugins/:pluginId/metrics
|
||||
func (hs *HTTPServer) CollectPluginMetrics(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) CollectPluginMetrics(c *models.ReqContext) response.Response {
|
||||
pluginID := c.Params("pluginId")
|
||||
plugin, exists := plugins.Plugins[pluginID]
|
||||
if !exists {
|
||||
return Error(404, "Plugin not found", nil)
|
||||
return response.Error(404, "Plugin not found", nil)
|
||||
}
|
||||
|
||||
resp, err := hs.BackendPluginManager.CollectMetrics(c.Req.Context(), plugin.Id)
|
||||
@@ -283,25 +284,21 @@ func (hs *HTTPServer) CollectPluginMetrics(c *models.ReqContext) Response {
|
||||
headers := make(http.Header)
|
||||
headers.Set("Content-Type", "text/plain")
|
||||
|
||||
return &NormalResponse{
|
||||
header: headers,
|
||||
body: resp.PrometheusMetrics,
|
||||
status: http.StatusOK,
|
||||
}
|
||||
return response.CreateNormalResponse(headers, resp.PrometheusMetrics, http.StatusOK)
|
||||
}
|
||||
|
||||
// CheckHealth returns the health of a plugin.
|
||||
// /api/plugins/:pluginId/health
|
||||
func (hs *HTTPServer) CheckHealth(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) CheckHealth(c *models.ReqContext) response.Response {
|
||||
pluginID := c.Params("pluginId")
|
||||
|
||||
pCtx, err := hs.getPluginContext(pluginID, c.SignedInUser)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrPluginNotFound) {
|
||||
return Error(404, "Plugin not found", nil)
|
||||
return response.Error(404, "Plugin not found", nil)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to get plugin settings", err)
|
||||
return response.Error(500, "Failed to get plugin settings", err)
|
||||
}
|
||||
|
||||
resp, err := hs.BackendPluginManager.CheckHealth(c.Req.Context(), pCtx)
|
||||
@@ -319,17 +316,17 @@ func (hs *HTTPServer) CheckHealth(c *models.ReqContext) Response {
|
||||
var jsonDetails map[string]interface{}
|
||||
err = json.Unmarshal(resp.JSONDetails, &jsonDetails)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to unmarshal detailed response from backend plugin", err)
|
||||
return response.Error(500, "Failed to unmarshal detailed response from backend plugin", err)
|
||||
}
|
||||
|
||||
payload["details"] = jsonDetails
|
||||
}
|
||||
|
||||
if resp.Status != backend.HealthStatusOk {
|
||||
return JSON(503, payload)
|
||||
return response.JSON(503, payload)
|
||||
}
|
||||
|
||||
return JSON(200, payload)
|
||||
return response.JSON(200, payload)
|
||||
}
|
||||
|
||||
// CallResource passes a resource call from a plugin to the backend plugin.
|
||||
@@ -370,26 +367,26 @@ func (hs *HTTPServer) getCachedPluginSettings(pluginID string, user *models.Sign
|
||||
return query.Result, nil
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) GetPluginErrorsList(c *models.ReqContext) Response {
|
||||
return JSON(200, plugins.ScanningErrors())
|
||||
func (hs *HTTPServer) GetPluginErrorsList(c *models.ReqContext) response.Response {
|
||||
return response.JSON(200, plugins.ScanningErrors())
|
||||
}
|
||||
|
||||
func translatePluginRequestErrorToAPIError(err error) Response {
|
||||
func translatePluginRequestErrorToAPIError(err error) response.Response {
|
||||
if errors.Is(err, backendplugin.ErrPluginNotRegistered) {
|
||||
return Error(404, "Plugin not found", err)
|
||||
return response.Error(404, "Plugin not found", err)
|
||||
}
|
||||
|
||||
if errors.Is(err, backendplugin.ErrMethodNotImplemented) {
|
||||
return Error(404, "Not found", err)
|
||||
return response.Error(404, "Not found", err)
|
||||
}
|
||||
|
||||
if errors.Is(err, backendplugin.ErrHealthCheckFailed) {
|
||||
return Error(500, "Plugin health check failed", err)
|
||||
return response.Error(500, "Plugin health check failed", err)
|
||||
}
|
||||
|
||||
if errors.Is(err, backendplugin.ErrPluginUnavailable) {
|
||||
return Error(503, "Plugin unavailable", err)
|
||||
return response.Error(503, "Plugin unavailable", err)
|
||||
}
|
||||
|
||||
return Error(500, "Plugin request failed", err)
|
||||
return response.Error(500, "Plugin request failed", err)
|
||||
}
|
||||
|
@@ -2,32 +2,33 @@ package api
|
||||
|
||||
import (
|
||||
"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"
|
||||
)
|
||||
|
||||
// POST /api/preferences/set-home-dash
|
||||
func SetHomeDashboard(c *models.ReqContext, cmd models.SavePreferencesCommand) Response {
|
||||
func SetHomeDashboard(c *models.ReqContext, cmd models.SavePreferencesCommand) response.Response {
|
||||
cmd.UserId = c.UserId
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to set home dashboard", err)
|
||||
return response.Error(500, "Failed to set home dashboard", err)
|
||||
}
|
||||
|
||||
return Success("Home dashboard set")
|
||||
return response.Success("Home dashboard set")
|
||||
}
|
||||
|
||||
// GET /api/user/preferences
|
||||
func GetUserPreferences(c *models.ReqContext) Response {
|
||||
func GetUserPreferences(c *models.ReqContext) response.Response {
|
||||
return getPreferencesFor(c.OrgId, c.UserId, 0)
|
||||
}
|
||||
|
||||
func getPreferencesFor(orgID, userID, teamID int64) Response {
|
||||
func getPreferencesFor(orgID, userID, teamID int64) response.Response {
|
||||
prefsQuery := models.GetPreferencesQuery{UserId: userID, OrgId: orgID, TeamId: teamID}
|
||||
|
||||
if err := bus.Dispatch(&prefsQuery); err != nil {
|
||||
return Error(500, "Failed to get preferences", err)
|
||||
return response.Error(500, "Failed to get preferences", err)
|
||||
}
|
||||
|
||||
dto := dtos.Prefs{
|
||||
@@ -36,15 +37,15 @@ func getPreferencesFor(orgID, userID, teamID int64) Response {
|
||||
Timezone: prefsQuery.Result.Timezone,
|
||||
}
|
||||
|
||||
return JSON(200, &dto)
|
||||
return response.JSON(200, &dto)
|
||||
}
|
||||
|
||||
// PUT /api/user/preferences
|
||||
func UpdateUserPreferences(c *models.ReqContext, dtoCmd dtos.UpdatePrefsCmd) Response {
|
||||
func UpdateUserPreferences(c *models.ReqContext, dtoCmd dtos.UpdatePrefsCmd) response.Response {
|
||||
return updatePreferencesFor(c.OrgId, c.UserId, 0, &dtoCmd)
|
||||
}
|
||||
|
||||
func updatePreferencesFor(orgID, userID, teamId int64, dtoCmd *dtos.UpdatePrefsCmd) Response {
|
||||
func updatePreferencesFor(orgID, userID, teamId int64, dtoCmd *dtos.UpdatePrefsCmd) response.Response {
|
||||
saveCmd := models.SavePreferencesCommand{
|
||||
UserId: userID,
|
||||
OrgId: orgID,
|
||||
@@ -55,18 +56,18 @@ func updatePreferencesFor(orgID, userID, teamId int64, dtoCmd *dtos.UpdatePrefsC
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&saveCmd); err != nil {
|
||||
return Error(500, "Failed to save preferences", err)
|
||||
return response.Error(500, "Failed to save preferences", err)
|
||||
}
|
||||
|
||||
return Success("Preferences updated")
|
||||
return response.Success("Preferences updated")
|
||||
}
|
||||
|
||||
// GET /api/org/preferences
|
||||
func GetOrgPreferences(c *models.ReqContext) Response {
|
||||
func GetOrgPreferences(c *models.ReqContext) response.Response {
|
||||
return getPreferencesFor(c.OrgId, 0, 0)
|
||||
}
|
||||
|
||||
// PUT /api/org/preferences
|
||||
func UpdateOrgPreferences(c *models.ReqContext, dtoCmd dtos.UpdatePrefsCmd) Response {
|
||||
func UpdateOrgPreferences(c *models.ReqContext, dtoCmd dtos.UpdatePrefsCmd) response.Response {
|
||||
return updatePreferencesFor(c.OrgId, 0, 0, &dtoCmd)
|
||||
}
|
||||
|
@@ -1,67 +1,68 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func GetOrgQuotas(c *models.ReqContext) Response {
|
||||
func GetOrgQuotas(c *models.ReqContext) response.Response {
|
||||
if !setting.Quota.Enabled {
|
||||
return Error(404, "Quotas not enabled", nil)
|
||||
return response.Error(404, "Quotas not enabled", nil)
|
||||
}
|
||||
query := models.GetOrgQuotasQuery{OrgId: c.ParamsInt64(":orgId")}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to get org quotas", err)
|
||||
return response.Error(500, "Failed to get org quotas", err)
|
||||
}
|
||||
|
||||
return JSON(200, query.Result)
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
func UpdateOrgQuota(c *models.ReqContext, cmd models.UpdateOrgQuotaCmd) Response {
|
||||
func UpdateOrgQuota(c *models.ReqContext, cmd models.UpdateOrgQuotaCmd) response.Response {
|
||||
if !setting.Quota.Enabled {
|
||||
return Error(404, "Quotas not enabled", nil)
|
||||
return response.Error(404, "Quotas not enabled", nil)
|
||||
}
|
||||
cmd.OrgId = c.ParamsInt64(":orgId")
|
||||
cmd.Target = c.Params(":target")
|
||||
|
||||
if _, ok := setting.Quota.Org.ToMap()[cmd.Target]; !ok {
|
||||
return Error(404, "Invalid quota target", nil)
|
||||
return response.Error(404, "Invalid quota target", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to update org quotas", err)
|
||||
return response.Error(500, "Failed to update org quotas", err)
|
||||
}
|
||||
return Success("Organization quota updated")
|
||||
return response.Success("Organization quota updated")
|
||||
}
|
||||
|
||||
func GetUserQuotas(c *models.ReqContext) Response {
|
||||
func GetUserQuotas(c *models.ReqContext) response.Response {
|
||||
if !setting.Quota.Enabled {
|
||||
return Error(404, "Quotas not enabled", nil)
|
||||
return response.Error(404, "Quotas not enabled", nil)
|
||||
}
|
||||
query := models.GetUserQuotasQuery{UserId: c.ParamsInt64(":id")}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to get org quotas", err)
|
||||
return response.Error(500, "Failed to get org quotas", err)
|
||||
}
|
||||
|
||||
return JSON(200, query.Result)
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
func UpdateUserQuota(c *models.ReqContext, cmd models.UpdateUserQuotaCmd) Response {
|
||||
func UpdateUserQuota(c *models.ReqContext, cmd models.UpdateUserQuotaCmd) response.Response {
|
||||
if !setting.Quota.Enabled {
|
||||
return Error(404, "Quotas not enabled", nil)
|
||||
return response.Error(404, "Quotas not enabled", nil)
|
||||
}
|
||||
cmd.UserId = c.ParamsInt64(":id")
|
||||
cmd.Target = c.Params(":target")
|
||||
|
||||
if _, ok := setting.Quota.User.ToMap()[cmd.Target]; !ok {
|
||||
return Error(404, "Invalid quota target", nil)
|
||||
return response.Error(404, "Invalid quota target", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to update org quotas", err)
|
||||
return response.Error(500, "Failed to update org quotas", err)
|
||||
}
|
||||
return Success("Organization quota updated")
|
||||
return response.Success("Organization quota updated")
|
||||
}
|
||||
|
@@ -1,9 +1,11 @@
|
||||
package api
|
||||
package response
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
|
||||
@@ -17,6 +19,14 @@ type Response interface {
|
||||
Status() int
|
||||
}
|
||||
|
||||
func CreateNormalResponse(header http.Header, body []byte, status int) *NormalResponse {
|
||||
return &NormalResponse{
|
||||
header: header,
|
||||
body: body,
|
||||
status: status,
|
||||
}
|
||||
}
|
||||
|
||||
type NormalResponse struct {
|
||||
status int
|
||||
body []byte
|
||||
@@ -35,6 +45,16 @@ func (r *NormalResponse) Body() []byte {
|
||||
return r.body
|
||||
}
|
||||
|
||||
// Err gets the response's err.
|
||||
func (r *NormalResponse) Err() error {
|
||||
return r.err
|
||||
}
|
||||
|
||||
// ErrMessage gets the response's errMessage.
|
||||
func (r *NormalResponse) ErrMessage() string {
|
||||
return r.errMessage
|
||||
}
|
||||
|
||||
func (r *NormalResponse) WriteTo(ctx *models.ReqContext) {
|
||||
if r.err != nil {
|
||||
ctx.Logger.Error(r.errMessage, "error", r.err, "remote_addr", ctx.RemoteAddr())
|
||||
@@ -55,13 +75,8 @@ func (r *NormalResponse) Header(key, value string) *NormalResponse {
|
||||
return r
|
||||
}
|
||||
|
||||
// Empty creates an empty NormalResponse.
|
||||
func Empty(status int) *NormalResponse {
|
||||
return Respond(status, nil)
|
||||
}
|
||||
|
||||
// streamingResponse is a response that streams itself back to the client.
|
||||
type streamingResponse struct {
|
||||
// StreamingResponse is a response that streams itself back to the client.
|
||||
type StreamingResponse struct {
|
||||
body interface{}
|
||||
status int
|
||||
header http.Header
|
||||
@@ -69,19 +84,19 @@ type streamingResponse struct {
|
||||
|
||||
// Status gets the response's status.
|
||||
// Required to implement api.Response.
|
||||
func (r streamingResponse) Status() int {
|
||||
func (r StreamingResponse) Status() int {
|
||||
return r.status
|
||||
}
|
||||
|
||||
// Body gets the response's body.
|
||||
// Required to implement api.Response.
|
||||
func (r streamingResponse) Body() []byte {
|
||||
func (r StreamingResponse) Body() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteTo writes the response to the provided context.
|
||||
// Required to implement api.Response.
|
||||
func (r streamingResponse) WriteTo(ctx *models.ReqContext) {
|
||||
func (r StreamingResponse) WriteTo(ctx *models.ReqContext) {
|
||||
header := ctx.Resp.Header()
|
||||
for k, v := range r.header {
|
||||
header[k] = v
|
||||
@@ -114,3 +129,88 @@ func (*RedirectResponse) Status() int {
|
||||
func (r *RedirectResponse) Body() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
// JSON creates a JSON response.
|
||||
func JSON(status int, body interface{}) *NormalResponse {
|
||||
return Respond(status, body).Header("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
// JSONStreaming creates a streaming JSON response.
|
||||
func JSONStreaming(status int, body interface{}) StreamingResponse {
|
||||
header := make(http.Header)
|
||||
header.Set("Content-Type", "application/json")
|
||||
return StreamingResponse{
|
||||
body: body,
|
||||
status: status,
|
||||
header: header,
|
||||
}
|
||||
}
|
||||
|
||||
// Success create a successful response
|
||||
func Success(message string) *NormalResponse {
|
||||
resp := make(map[string]interface{})
|
||||
resp["message"] = message
|
||||
return JSON(200, resp)
|
||||
}
|
||||
|
||||
// Error creates an error response.
|
||||
func Error(status int, message string, err error) *NormalResponse {
|
||||
data := make(map[string]interface{})
|
||||
|
||||
switch status {
|
||||
case 404:
|
||||
data["message"] = "Not Found"
|
||||
case 500:
|
||||
data["message"] = "Internal Server Error"
|
||||
}
|
||||
|
||||
if message != "" {
|
||||
data["message"] = message
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if setting.Env != setting.Prod {
|
||||
data["error"] = err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
resp := JSON(status, data)
|
||||
|
||||
if err != nil {
|
||||
resp.errMessage = message
|
||||
resp.err = err
|
||||
}
|
||||
|
||||
return resp
|
||||
}
|
||||
|
||||
// Empty creates an empty NormalResponse.
|
||||
func Empty(status int) *NormalResponse {
|
||||
return Respond(status, nil)
|
||||
}
|
||||
|
||||
// Respond creates a response.
|
||||
func Respond(status int, body interface{}) *NormalResponse {
|
||||
var b []byte
|
||||
switch t := body.(type) {
|
||||
case []byte:
|
||||
b = t
|
||||
case string:
|
||||
b = []byte(t)
|
||||
default:
|
||||
var err error
|
||||
if b, err = json.Marshal(body); err != nil {
|
||||
return Error(500, "body json marshal", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &NormalResponse{
|
||||
status: status,
|
||||
body: b,
|
||||
header: make(http.Header),
|
||||
}
|
||||
}
|
||||
|
||||
func Redirect(location string) *RedirectResponse {
|
||||
return &RedirectResponse{location: location}
|
||||
}
|
27
pkg/api/routing/routing.go
Normal file
27
pkg/api/routing/routing.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package routing
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"gopkg.in/macaron.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
ServerError = func(err error) response.Response {
|
||||
return response.Error(500, "Server error", err)
|
||||
}
|
||||
)
|
||||
|
||||
func Wrap(action interface{}) macaron.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)
|
||||
}
|
||||
|
||||
res.WriteTo(c)
|
||||
}
|
||||
}
|
@@ -6,13 +6,14 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
)
|
||||
|
||||
func Search(c *models.ReqContext) Response {
|
||||
func Search(c *models.ReqContext) response.Response {
|
||||
query := c.Query("query")
|
||||
tags := c.QueryStrings("tag")
|
||||
starred := c.Query("starred")
|
||||
@@ -23,7 +24,7 @@ func Search(c *models.ReqContext) Response {
|
||||
permission := models.PERMISSION_VIEW
|
||||
|
||||
if limit > 5000 {
|
||||
return Error(422, "Limit is above maximum allowed (5000), use page parameter to access hits beyond limit", nil)
|
||||
return response.Error(422, "Limit is above maximum allowed (5000), use page parameter to access hits beyond limit", nil)
|
||||
}
|
||||
|
||||
if c.Query("permission") == "Edit" {
|
||||
@@ -63,14 +64,14 @@ func Search(c *models.ReqContext) Response {
|
||||
|
||||
err := bus.Dispatch(&searchQuery)
|
||||
if err != nil {
|
||||
return Error(500, "Search failed", err)
|
||||
return response.Error(500, "Search failed", err)
|
||||
}
|
||||
|
||||
c.TimeRequest(metrics.MApiDashboardSearch)
|
||||
return JSON(200, searchQuery.Result)
|
||||
return response.JSON(200, searchQuery.Result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) ListSortOptions(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) ListSortOptions(c *models.ReqContext) response.Response {
|
||||
opts := hs.SearchService.SortOptions()
|
||||
|
||||
res := []util.DynMap{}
|
||||
@@ -82,7 +83,7 @@ func (hs *HTTPServer) ListSortOptions(c *models.ReqContext) Response {
|
||||
})
|
||||
}
|
||||
|
||||
return JSON(http.StatusOK, util.DynMap{
|
||||
return response.JSON(http.StatusOK, util.DynMap{
|
||||
"sortOptions": res,
|
||||
})
|
||||
}
|
||||
|
@@ -7,25 +7,26 @@ import (
|
||||
"strings"
|
||||
|
||||
"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/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
// createShortURL handles requests to create short URLs.
|
||||
func (hs *HTTPServer) createShortURL(c *models.ReqContext, cmd dtos.CreateShortURLCmd) Response {
|
||||
func (hs *HTTPServer) createShortURL(c *models.ReqContext, cmd dtos.CreateShortURLCmd) response.Response {
|
||||
hs.log.Debug("Received request to create short URL", "path", cmd.Path)
|
||||
|
||||
cmd.Path = strings.TrimSpace(cmd.Path)
|
||||
|
||||
if path.IsAbs(cmd.Path) {
|
||||
hs.log.Error("Invalid short URL path", "path", cmd.Path)
|
||||
return Error(400, "Path should be relative", nil)
|
||||
return response.Error(400, "Path should be relative", nil)
|
||||
}
|
||||
|
||||
shortURL, err := hs.ShortURLService.CreateShortURL(c.Req.Context(), c.SignedInUser, cmd.Path)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to create short URL", err)
|
||||
return response.Error(500, "Failed to create short URL", err)
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/goto/%s", strings.TrimSuffix(setting.AppUrl, "/"), shortURL.Uid)
|
||||
@@ -36,7 +37,7 @@ func (hs *HTTPServer) createShortURL(c *models.ReqContext, cmd dtos.CreateShortU
|
||||
URL: url,
|
||||
}
|
||||
|
||||
return JSON(200, dto)
|
||||
return response.JSON(200, dto)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) redirectFromShortURL(c *models.ReqContext) {
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"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/events"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
@@ -13,22 +14,22 @@ import (
|
||||
)
|
||||
|
||||
// GET /api/user/signup/options
|
||||
func GetSignUpOptions(c *models.ReqContext) Response {
|
||||
return JSON(200, util.DynMap{
|
||||
func GetSignUpOptions(c *models.ReqContext) response.Response {
|
||||
return response.JSON(200, util.DynMap{
|
||||
"verifyEmailEnabled": setting.VerifyEmailEnabled,
|
||||
"autoAssignOrg": setting.AutoAssignOrg,
|
||||
})
|
||||
}
|
||||
|
||||
// POST /api/user/signup
|
||||
func SignUp(c *models.ReqContext, form dtos.SignUpForm) Response {
|
||||
func SignUp(c *models.ReqContext, form dtos.SignUpForm) response.Response {
|
||||
if !setting.AllowUserSignUp {
|
||||
return Error(401, "User signup is disabled", nil)
|
||||
return response.Error(401, "User signup is disabled", nil)
|
||||
}
|
||||
|
||||
existing := models.GetUserByLoginQuery{LoginOrEmail: form.Email}
|
||||
if err := bus.Dispatch(&existing); err == nil {
|
||||
return Error(422, "User with same email address already exists", nil)
|
||||
return response.Error(422, "User with same email address already exists", nil)
|
||||
}
|
||||
|
||||
cmd := models.CreateTempUserCommand{}
|
||||
@@ -39,29 +40,29 @@ func SignUp(c *models.ReqContext, form dtos.SignUpForm) Response {
|
||||
var err error
|
||||
cmd.Code, err = util.GetRandomString(20)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to generate random string", err)
|
||||
return response.Error(500, "Failed to generate random string", err)
|
||||
}
|
||||
cmd.RemoteAddr = c.Req.RemoteAddr
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to create signup", err)
|
||||
return response.Error(500, "Failed to create signup", err)
|
||||
}
|
||||
|
||||
if err := bus.Publish(&events.SignUpStarted{
|
||||
Email: form.Email,
|
||||
Code: cmd.Code,
|
||||
}); err != nil {
|
||||
return Error(500, "Failed to publish event", err)
|
||||
return response.Error(500, "Failed to publish event", err)
|
||||
}
|
||||
|
||||
metrics.MApiUserSignUpStarted.Inc()
|
||||
|
||||
return JSON(200, util.DynMap{"status": "SignUpCreated"})
|
||||
return response.JSON(200, util.DynMap{"status": "SignUpCreated"})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) SignUpStep2(c *models.ReqContext, form dtos.SignUpStep2Form) Response {
|
||||
func (hs *HTTPServer) SignUpStep2(c *models.ReqContext, form dtos.SignUpStep2Form) response.Response {
|
||||
if !setting.AllowUserSignUp {
|
||||
return Error(401, "User signup is disabled", nil)
|
||||
return response.Error(401, "User signup is disabled", nil)
|
||||
}
|
||||
|
||||
createUserCmd := models.CreateUserCommand{
|
||||
@@ -83,10 +84,10 @@ func (hs *HTTPServer) SignUpStep2(c *models.ReqContext, form dtos.SignUpStep2For
|
||||
// dispatch create command
|
||||
if err := bus.Dispatch(&createUserCmd); err != nil {
|
||||
if errors.Is(err, models.ErrUserAlreadyExists) {
|
||||
return Error(401, "User with same email address already exists", nil)
|
||||
return response.Error(401, "User with same email address already exists", nil)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to create user", err)
|
||||
return response.Error(500, "Failed to create user", err)
|
||||
}
|
||||
|
||||
// publish signup event
|
||||
@@ -95,7 +96,7 @@ func (hs *HTTPServer) SignUpStep2(c *models.ReqContext, form dtos.SignUpStep2For
|
||||
Email: user.Email,
|
||||
Name: user.NameOrFallback(),
|
||||
}); err != nil {
|
||||
return Error(500, "Failed to publish event", err)
|
||||
return response.Error(500, "Failed to publish event", err)
|
||||
}
|
||||
|
||||
// mark temp user as completed
|
||||
@@ -106,7 +107,7 @@ func (hs *HTTPServer) SignUpStep2(c *models.ReqContext, form dtos.SignUpStep2For
|
||||
// check for pending invites
|
||||
invitesQuery := models.GetTempUsersQuery{Email: form.Email, Status: models.TmpUserInvitePending}
|
||||
if err := bus.Dispatch(&invitesQuery); err != nil {
|
||||
return Error(500, "Failed to query database for invites", err)
|
||||
return response.Error(500, "Failed to query database for invites", err)
|
||||
}
|
||||
|
||||
apiResponse := util.DynMap{"message": "User sign up completed successfully", "code": "redirect-to-landing-page"}
|
||||
@@ -119,27 +120,27 @@ func (hs *HTTPServer) SignUpStep2(c *models.ReqContext, form dtos.SignUpStep2For
|
||||
|
||||
err := hs.loginUserWithUser(user, c)
|
||||
if err != nil {
|
||||
return Error(500, "failed to login user", err)
|
||||
return response.Error(500, "failed to login user", err)
|
||||
}
|
||||
|
||||
metrics.MApiUserSignUpCompleted.Inc()
|
||||
|
||||
return JSON(200, apiResponse)
|
||||
return response.JSON(200, apiResponse)
|
||||
}
|
||||
|
||||
func verifyUserSignUpEmail(email string, code string) (bool, Response) {
|
||||
func verifyUserSignUpEmail(email string, code string) (bool, response.Response) {
|
||||
query := models.GetTempUserByCodeQuery{Code: code}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if errors.Is(err, models.ErrTempUserNotFound) {
|
||||
return false, Error(404, "Invalid email verification code", nil)
|
||||
return false, response.Error(404, "Invalid email verification code", nil)
|
||||
}
|
||||
return false, Error(500, "Failed to read temp user", err)
|
||||
return false, response.Error(500, "Failed to read temp user", err)
|
||||
}
|
||||
|
||||
tempUser := query.Result
|
||||
if tempUser.Email != email {
|
||||
return false, Error(404, "Email verification code does not match email", nil)
|
||||
return false, response.Error(404, "Email verification code does not match email", nil)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
|
@@ -1,38 +1,39 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func StarDashboard(c *models.ReqContext) Response {
|
||||
func StarDashboard(c *models.ReqContext) response.Response {
|
||||
if !c.IsSignedIn {
|
||||
return Error(412, "You need to sign in to star dashboards", nil)
|
||||
return response.Error(412, "You need to sign in to star dashboards", nil)
|
||||
}
|
||||
|
||||
cmd := models.StarDashboardCommand{UserId: c.UserId, DashboardId: c.ParamsInt64(":id")}
|
||||
|
||||
if cmd.DashboardId <= 0 {
|
||||
return Error(400, "Missing dashboard id", nil)
|
||||
return response.Error(400, "Missing dashboard id", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to star dashboard", err)
|
||||
return response.Error(500, "Failed to star dashboard", err)
|
||||
}
|
||||
|
||||
return Success("Dashboard starred!")
|
||||
return response.Success("Dashboard starred!")
|
||||
}
|
||||
|
||||
func UnstarDashboard(c *models.ReqContext) Response {
|
||||
func UnstarDashboard(c *models.ReqContext) response.Response {
|
||||
cmd := models.UnstarDashboardCommand{UserId: c.UserId, DashboardId: c.ParamsInt64(":id")}
|
||||
|
||||
if cmd.DashboardId <= 0 {
|
||||
return Error(400, "Missing dashboard id", nil)
|
||||
return response.Error(400, "Missing dashboard id", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to unstar dashboard", err)
|
||||
return response.Error(500, "Failed to unstar dashboard", err)
|
||||
}
|
||||
|
||||
return Success("Dashboard unstarred")
|
||||
return response.Success("Dashboard unstarred")
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"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/services/teamguardian"
|
||||
@@ -11,18 +12,18 @@ import (
|
||||
)
|
||||
|
||||
// POST /api/teams
|
||||
func (hs *HTTPServer) CreateTeam(c *models.ReqContext, cmd models.CreateTeamCommand) Response {
|
||||
func (hs *HTTPServer) CreateTeam(c *models.ReqContext, cmd models.CreateTeamCommand) response.Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
if c.OrgRole == models.ROLE_VIEWER {
|
||||
return Error(403, "Not allowed to create team.", nil)
|
||||
return response.Error(403, "Not allowed to create team.", nil)
|
||||
}
|
||||
|
||||
if err := hs.Bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrTeamNameTaken) {
|
||||
return Error(409, "Team name taken", err)
|
||||
return response.Error(409, "Team name taken", err)
|
||||
}
|
||||
return Error(500, "Failed to create Team", err)
|
||||
return response.Error(500, "Failed to create Team", err)
|
||||
}
|
||||
|
||||
if c.OrgRole == models.ROLE_EDITOR && hs.Cfg.EditorsCanAdmin {
|
||||
@@ -45,52 +46,52 @@ func (hs *HTTPServer) CreateTeam(c *models.ReqContext, cmd models.CreateTeamComm
|
||||
}
|
||||
}
|
||||
|
||||
return JSON(200, &util.DynMap{
|
||||
return response.JSON(200, &util.DynMap{
|
||||
"teamId": cmd.Result.Id,
|
||||
"message": "Team created",
|
||||
})
|
||||
}
|
||||
|
||||
// PUT /api/teams/:teamId
|
||||
func (hs *HTTPServer) UpdateTeam(c *models.ReqContext, cmd models.UpdateTeamCommand) Response {
|
||||
func (hs *HTTPServer) UpdateTeam(c *models.ReqContext, cmd models.UpdateTeamCommand) response.Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.Id = c.ParamsInt64(":teamId")
|
||||
|
||||
if err := teamguardian.CanAdmin(hs.Bus, cmd.OrgId, cmd.Id, c.SignedInUser); err != nil {
|
||||
return Error(403, "Not allowed to update team", err)
|
||||
return response.Error(403, "Not allowed to update team", err)
|
||||
}
|
||||
|
||||
if err := hs.Bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrTeamNameTaken) {
|
||||
return Error(400, "Team name taken", err)
|
||||
return response.Error(400, "Team name taken", err)
|
||||
}
|
||||
return Error(500, "Failed to update Team", err)
|
||||
return response.Error(500, "Failed to update Team", err)
|
||||
}
|
||||
|
||||
return Success("Team updated")
|
||||
return response.Success("Team updated")
|
||||
}
|
||||
|
||||
// DELETE /api/teams/:teamId
|
||||
func (hs *HTTPServer) DeleteTeamByID(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) DeleteTeamByID(c *models.ReqContext) response.Response {
|
||||
orgId := c.OrgId
|
||||
teamId := c.ParamsInt64(":teamId")
|
||||
user := c.SignedInUser
|
||||
|
||||
if err := teamguardian.CanAdmin(hs.Bus, orgId, teamId, user); err != nil {
|
||||
return Error(403, "Not allowed to delete team", err)
|
||||
return response.Error(403, "Not allowed to delete team", err)
|
||||
}
|
||||
|
||||
if err := hs.Bus.Dispatch(&models.DeleteTeamCommand{OrgId: orgId, Id: teamId}); err != nil {
|
||||
if errors.Is(err, models.ErrTeamNotFound) {
|
||||
return Error(404, "Failed to delete Team. ID not found", nil)
|
||||
return response.Error(404, "Failed to delete Team. ID not found", nil)
|
||||
}
|
||||
return Error(500, "Failed to delete Team", err)
|
||||
return response.Error(500, "Failed to delete Team", err)
|
||||
}
|
||||
return Success("Team deleted")
|
||||
return response.Success("Team deleted")
|
||||
}
|
||||
|
||||
// GET /api/teams/search
|
||||
func (hs *HTTPServer) SearchTeams(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) SearchTeams(c *models.ReqContext) response.Response {
|
||||
perPage := c.QueryInt("perpage")
|
||||
if perPage <= 0 {
|
||||
perPage = 1000
|
||||
@@ -117,7 +118,7 @@ func (hs *HTTPServer) SearchTeams(c *models.ReqContext) Response {
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to search Teams", err)
|
||||
return response.Error(500, "Failed to search Teams", err)
|
||||
}
|
||||
|
||||
for _, team := range query.Result.Teams {
|
||||
@@ -127,11 +128,11 @@ func (hs *HTTPServer) SearchTeams(c *models.ReqContext) Response {
|
||||
query.Result.Page = page
|
||||
query.Result.PerPage = perPage
|
||||
|
||||
return JSON(200, query.Result)
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
// GET /api/teams/:teamId
|
||||
func (hs *HTTPServer) GetTeamByID(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetTeamByID(c *models.ReqContext) response.Response {
|
||||
query := models.GetTeamByIdQuery{
|
||||
OrgId: c.OrgId,
|
||||
Id: c.ParamsInt64(":teamId"),
|
||||
@@ -141,35 +142,35 @@ func (hs *HTTPServer) GetTeamByID(c *models.ReqContext) Response {
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if errors.Is(err, models.ErrTeamNotFound) {
|
||||
return Error(404, "Team not found", err)
|
||||
return response.Error(404, "Team not found", err)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to get Team", err)
|
||||
return response.Error(500, "Failed to get Team", err)
|
||||
}
|
||||
|
||||
query.Result.AvatarUrl = dtos.GetGravatarUrlWithDefault(query.Result.Email, query.Result.Name)
|
||||
return JSON(200, &query.Result)
|
||||
return response.JSON(200, &query.Result)
|
||||
}
|
||||
|
||||
// GET /api/teams/:teamId/preferences
|
||||
func (hs *HTTPServer) GetTeamPreferences(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetTeamPreferences(c *models.ReqContext) response.Response {
|
||||
teamId := c.ParamsInt64(":teamId")
|
||||
orgId := c.OrgId
|
||||
|
||||
if err := teamguardian.CanAdmin(hs.Bus, orgId, teamId, c.SignedInUser); err != nil {
|
||||
return Error(403, "Not allowed to view team preferences.", err)
|
||||
return response.Error(403, "Not allowed to view team preferences.", err)
|
||||
}
|
||||
|
||||
return getPreferencesFor(orgId, 0, teamId)
|
||||
}
|
||||
|
||||
// PUT /api/teams/:teamId/preferences
|
||||
func (hs *HTTPServer) UpdateTeamPreferences(c *models.ReqContext, dtoCmd dtos.UpdatePrefsCmd) Response {
|
||||
func (hs *HTTPServer) UpdateTeamPreferences(c *models.ReqContext, dtoCmd dtos.UpdatePrefsCmd) response.Response {
|
||||
teamId := c.ParamsInt64(":teamId")
|
||||
orgId := c.OrgId
|
||||
|
||||
if err := teamguardian.CanAdmin(hs.Bus, orgId, teamId, c.SignedInUser); err != nil {
|
||||
return Error(403, "Not allowed to update team preferences.", err)
|
||||
return response.Error(403, "Not allowed to update team preferences.", err)
|
||||
}
|
||||
|
||||
return updatePreferencesFor(orgId, 0, teamId, &dtoCmd)
|
||||
|
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"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/services/teamguardian"
|
||||
@@ -11,11 +12,11 @@ import (
|
||||
)
|
||||
|
||||
// GET /api/teams/:teamId/members
|
||||
func (hs *HTTPServer) GetTeamMembers(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetTeamMembers(c *models.ReqContext) response.Response {
|
||||
query := models.GetTeamMembersQuery{OrgId: c.OrgId, TeamId: c.ParamsInt64(":teamId")}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to get Team Members", err)
|
||||
return response.Error(500, "Failed to get Team Members", err)
|
||||
}
|
||||
|
||||
filteredMembers := make([]*models.TeamMemberDTO, 0, len(query.Result))
|
||||
@@ -35,42 +36,42 @@ func (hs *HTTPServer) GetTeamMembers(c *models.ReqContext) Response {
|
||||
filteredMembers = append(filteredMembers, member)
|
||||
}
|
||||
|
||||
return JSON(200, filteredMembers)
|
||||
return response.JSON(200, filteredMembers)
|
||||
}
|
||||
|
||||
// POST /api/teams/:teamId/members
|
||||
func (hs *HTTPServer) AddTeamMember(c *models.ReqContext, cmd models.AddTeamMemberCommand) Response {
|
||||
func (hs *HTTPServer) AddTeamMember(c *models.ReqContext, cmd models.AddTeamMemberCommand) response.Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.TeamId = c.ParamsInt64(":teamId")
|
||||
|
||||
if err := teamguardian.CanAdmin(hs.Bus, cmd.OrgId, cmd.TeamId, c.SignedInUser); err != nil {
|
||||
return Error(403, "Not allowed to add team member", err)
|
||||
return response.Error(403, "Not allowed to add team member", err)
|
||||
}
|
||||
|
||||
if err := hs.Bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrTeamNotFound) {
|
||||
return Error(404, "Team not found", nil)
|
||||
return response.Error(404, "Team not found", nil)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrTeamMemberAlreadyAdded) {
|
||||
return Error(400, "User is already added to this team", nil)
|
||||
return response.Error(400, "User is already added to this team", nil)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to add Member to Team", err)
|
||||
return response.Error(500, "Failed to add Member to Team", err)
|
||||
}
|
||||
|
||||
return JSON(200, &util.DynMap{
|
||||
return response.JSON(200, &util.DynMap{
|
||||
"message": "Member added to Team",
|
||||
})
|
||||
}
|
||||
|
||||
// PUT /:teamId/members/:userId
|
||||
func (hs *HTTPServer) UpdateTeamMember(c *models.ReqContext, cmd models.UpdateTeamMemberCommand) Response {
|
||||
func (hs *HTTPServer) UpdateTeamMember(c *models.ReqContext, cmd models.UpdateTeamMemberCommand) response.Response {
|
||||
teamId := c.ParamsInt64(":teamId")
|
||||
orgId := c.OrgId
|
||||
|
||||
if err := teamguardian.CanAdmin(hs.Bus, orgId, teamId, c.SignedInUser); err != nil {
|
||||
return Error(403, "Not allowed to update team member", err)
|
||||
return response.Error(403, "Not allowed to update team member", err)
|
||||
}
|
||||
|
||||
if c.OrgRole != models.ROLE_ADMIN {
|
||||
@@ -83,21 +84,21 @@ func (hs *HTTPServer) UpdateTeamMember(c *models.ReqContext, cmd models.UpdateTe
|
||||
|
||||
if err := hs.Bus.Dispatch(&cmd); err != nil {
|
||||
if errors.Is(err, models.ErrTeamMemberNotFound) {
|
||||
return Error(404, "Team member not found.", nil)
|
||||
return response.Error(404, "Team member not found.", nil)
|
||||
}
|
||||
return Error(500, "Failed to update team member.", err)
|
||||
return response.Error(500, "Failed to update team member.", err)
|
||||
}
|
||||
return Success("Team member updated")
|
||||
return response.Success("Team member updated")
|
||||
}
|
||||
|
||||
// DELETE /api/teams/:teamId/members/:userId
|
||||
func (hs *HTTPServer) RemoveTeamMember(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) RemoveTeamMember(c *models.ReqContext) response.Response {
|
||||
orgId := c.OrgId
|
||||
teamId := c.ParamsInt64(":teamId")
|
||||
userId := c.ParamsInt64(":userId")
|
||||
|
||||
if err := teamguardian.CanAdmin(hs.Bus, orgId, teamId, c.SignedInUser); err != nil {
|
||||
return Error(403, "Not allowed to remove team member", err)
|
||||
return response.Error(403, "Not allowed to remove team member", err)
|
||||
}
|
||||
|
||||
protectLastAdmin := false
|
||||
@@ -107,14 +108,14 @@ func (hs *HTTPServer) RemoveTeamMember(c *models.ReqContext) Response {
|
||||
|
||||
if err := hs.Bus.Dispatch(&models.RemoveTeamMemberCommand{OrgId: orgId, TeamId: teamId, UserId: userId, ProtectLastAdmin: protectLastAdmin}); err != nil {
|
||||
if errors.Is(err, models.ErrTeamNotFound) {
|
||||
return Error(404, "Team not found", nil)
|
||||
return response.Error(404, "Team not found", nil)
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrTeamMemberNotFound) {
|
||||
return Error(404, "Team member not found", nil)
|
||||
return response.Error(404, "Team member not found", nil)
|
||||
}
|
||||
|
||||
return Error(500, "Failed to remove Member from Team", err)
|
||||
return response.Error(500, "Failed to remove Member from Team", err)
|
||||
}
|
||||
return Success("Team Member removed")
|
||||
return response.Success("Team Member removed")
|
||||
}
|
||||
|
115
pkg/api/user.go
115
pkg/api/user.go
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"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/setting"
|
||||
@@ -11,23 +12,23 @@ import (
|
||||
)
|
||||
|
||||
// GET /api/user (current authenticated user)
|
||||
func GetSignedInUser(c *models.ReqContext) Response {
|
||||
func GetSignedInUser(c *models.ReqContext) response.Response {
|
||||
return getUserUserProfile(c.UserId)
|
||||
}
|
||||
|
||||
// GET /api/users/:id
|
||||
func GetUserByID(c *models.ReqContext) Response {
|
||||
func GetUserByID(c *models.ReqContext) response.Response {
|
||||
return getUserUserProfile(c.ParamsInt64(":id"))
|
||||
}
|
||||
|
||||
func getUserUserProfile(userID int64) Response {
|
||||
func getUserUserProfile(userID int64) response.Response {
|
||||
query := models.GetUserProfileQuery{UserId: userID}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if errors.Is(err, models.ErrUserNotFound) {
|
||||
return Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
return response.Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
}
|
||||
return Error(500, "Failed to get user", err)
|
||||
return response.Error(500, "Failed to get user", err)
|
||||
}
|
||||
|
||||
getAuthQuery := models.GetAuthInfoQuery{UserId: userID}
|
||||
@@ -40,17 +41,17 @@ func getUserUserProfile(userID int64) Response {
|
||||
|
||||
query.Result.AvatarUrl = dtos.GetGravatarUrl(query.Result.Email)
|
||||
|
||||
return JSON(200, query.Result)
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
// GET /api/users/lookup
|
||||
func GetUserByLoginOrEmail(c *models.ReqContext) Response {
|
||||
func GetUserByLoginOrEmail(c *models.ReqContext) response.Response {
|
||||
query := models.GetUserByLoginQuery{LoginOrEmail: c.Query("loginOrEmail")}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if errors.Is(err, models.ErrUserNotFound) {
|
||||
return Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
return response.Error(404, models.ErrUserNotFound.Error(), nil)
|
||||
}
|
||||
return Error(500, "Failed to get user", err)
|
||||
return response.Error(500, "Failed to get user", err)
|
||||
}
|
||||
user := query.Result
|
||||
result := models.UserProfileDTO{
|
||||
@@ -64,17 +65,17 @@ func GetUserByLoginOrEmail(c *models.ReqContext) Response {
|
||||
UpdatedAt: user.Updated,
|
||||
CreatedAt: user.Created,
|
||||
}
|
||||
return JSON(200, &result)
|
||||
return response.JSON(200, &result)
|
||||
}
|
||||
|
||||
// POST /api/user
|
||||
func UpdateSignedInUser(c *models.ReqContext, cmd models.UpdateUserCommand) Response {
|
||||
func UpdateSignedInUser(c *models.ReqContext, cmd models.UpdateUserCommand) response.Response {
|
||||
if setting.AuthProxyEnabled {
|
||||
if setting.AuthProxyHeaderProperty == "email" && cmd.Email != c.Email {
|
||||
return Error(400, "Not allowed to change email when auth proxy is using email property", nil)
|
||||
return response.Error(400, "Not allowed to change email when auth proxy is using email property", nil)
|
||||
}
|
||||
if setting.AuthProxyHeaderProperty == "username" && cmd.Login != c.Login {
|
||||
return Error(400, "Not allowed to change username when auth proxy is using username property", nil)
|
||||
return response.Error(400, "Not allowed to change username when auth proxy is using username property", nil)
|
||||
}
|
||||
}
|
||||
cmd.UserId = c.UserId
|
||||
@@ -82,85 +83,85 @@ func UpdateSignedInUser(c *models.ReqContext, cmd models.UpdateUserCommand) Resp
|
||||
}
|
||||
|
||||
// POST /api/users/:id
|
||||
func UpdateUser(c *models.ReqContext, cmd models.UpdateUserCommand) Response {
|
||||
func UpdateUser(c *models.ReqContext, cmd models.UpdateUserCommand) response.Response {
|
||||
cmd.UserId = c.ParamsInt64(":id")
|
||||
return handleUpdateUser(cmd)
|
||||
}
|
||||
|
||||
// POST /api/users/:id/using/:orgId
|
||||
func UpdateUserActiveOrg(c *models.ReqContext) Response {
|
||||
func UpdateUserActiveOrg(c *models.ReqContext) response.Response {
|
||||
userID := c.ParamsInt64(":id")
|
||||
orgID := c.ParamsInt64(":orgId")
|
||||
|
||||
if !validateUsingOrg(userID, orgID) {
|
||||
return Error(401, "Not a valid organization", nil)
|
||||
return response.Error(401, "Not a valid organization", nil)
|
||||
}
|
||||
|
||||
cmd := models.SetUsingOrgCommand{UserId: userID, OrgId: orgID}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to change active organization", err)
|
||||
return response.Error(500, "Failed to change active organization", err)
|
||||
}
|
||||
|
||||
return Success("Active organization changed")
|
||||
return response.Success("Active organization changed")
|
||||
}
|
||||
|
||||
func handleUpdateUser(cmd models.UpdateUserCommand) Response {
|
||||
func handleUpdateUser(cmd models.UpdateUserCommand) response.Response {
|
||||
if len(cmd.Login) == 0 {
|
||||
cmd.Login = cmd.Email
|
||||
if len(cmd.Login) == 0 {
|
||||
return Error(400, "Validation error, need to specify either username or email", nil)
|
||||
return response.Error(400, "Validation error, need to specify either username or email", nil)
|
||||
}
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to update user", err)
|
||||
return response.Error(500, "Failed to update user", err)
|
||||
}
|
||||
|
||||
return Success("User updated")
|
||||
return response.Success("User updated")
|
||||
}
|
||||
|
||||
// GET /api/user/orgs
|
||||
func GetSignedInUserOrgList(c *models.ReqContext) Response {
|
||||
func GetSignedInUserOrgList(c *models.ReqContext) response.Response {
|
||||
return getUserOrgList(c.UserId)
|
||||
}
|
||||
|
||||
// GET /api/user/teams
|
||||
func GetSignedInUserTeamList(c *models.ReqContext) Response {
|
||||
func GetSignedInUserTeamList(c *models.ReqContext) response.Response {
|
||||
return getUserTeamList(c.OrgId, c.UserId)
|
||||
}
|
||||
|
||||
// GET /api/users/:id/teams
|
||||
func GetUserTeams(c *models.ReqContext) Response {
|
||||
func GetUserTeams(c *models.ReqContext) response.Response {
|
||||
return getUserTeamList(c.OrgId, c.ParamsInt64(":id"))
|
||||
}
|
||||
|
||||
func getUserTeamList(orgID int64, userID int64) Response {
|
||||
func getUserTeamList(orgID int64, userID int64) response.Response {
|
||||
query := models.GetTeamsByUserQuery{OrgId: orgID, UserId: userID}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to get user teams", err)
|
||||
return response.Error(500, "Failed to get user teams", err)
|
||||
}
|
||||
|
||||
for _, team := range query.Result {
|
||||
team.AvatarUrl = dtos.GetGravatarUrlWithDefault(team.Email, team.Name)
|
||||
}
|
||||
return JSON(200, query.Result)
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
// GET /api/users/:id/orgs
|
||||
func GetUserOrgList(c *models.ReqContext) Response {
|
||||
func GetUserOrgList(c *models.ReqContext) response.Response {
|
||||
return getUserOrgList(c.ParamsInt64(":id"))
|
||||
}
|
||||
|
||||
func getUserOrgList(userID int64) Response {
|
||||
func getUserOrgList(userID int64) response.Response {
|
||||
query := models.GetUserOrgListQuery{UserId: userID}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return Error(500, "Failed to get user organizations", err)
|
||||
return response.Error(500, "Failed to get user organizations", err)
|
||||
}
|
||||
|
||||
return JSON(200, query.Result)
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
func validateUsingOrg(userID int64, orgID int64) bool {
|
||||
@@ -182,20 +183,20 @@ func validateUsingOrg(userID int64, orgID int64) bool {
|
||||
}
|
||||
|
||||
// POST /api/user/using/:id
|
||||
func UserSetUsingOrg(c *models.ReqContext) Response {
|
||||
func UserSetUsingOrg(c *models.ReqContext) response.Response {
|
||||
orgID := c.ParamsInt64(":id")
|
||||
|
||||
if !validateUsingOrg(c.UserId, orgID) {
|
||||
return Error(401, "Not a valid organization", nil)
|
||||
return response.Error(401, "Not a valid organization", nil)
|
||||
}
|
||||
|
||||
cmd := models.SetUsingOrgCommand{UserId: c.UserId, OrgId: orgID}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to change active organization", err)
|
||||
return response.Error(500, "Failed to change active organization", err)
|
||||
}
|
||||
|
||||
return Success("Active organization changed")
|
||||
return response.Success("Active organization changed")
|
||||
}
|
||||
|
||||
// GET /profile/switch-org/:id
|
||||
@@ -215,41 +216,41 @@ func (hs *HTTPServer) ChangeActiveOrgAndRedirectToHome(c *models.ReqContext) {
|
||||
c.Redirect(setting.AppSubUrl + "/")
|
||||
}
|
||||
|
||||
func ChangeUserPassword(c *models.ReqContext, cmd models.ChangeUserPasswordCommand) Response {
|
||||
func ChangeUserPassword(c *models.ReqContext, cmd models.ChangeUserPasswordCommand) response.Response {
|
||||
if setting.LDAPEnabled || setting.AuthProxyEnabled {
|
||||
return Error(400, "Not allowed to change password when LDAP or Auth Proxy is enabled", nil)
|
||||
return response.Error(400, "Not allowed to change password when LDAP or Auth Proxy is enabled", nil)
|
||||
}
|
||||
|
||||
userQuery := models.GetUserByIdQuery{Id: c.UserId}
|
||||
|
||||
if err := bus.Dispatch(&userQuery); err != nil {
|
||||
return Error(500, "Could not read user from database", err)
|
||||
return response.Error(500, "Could not read user from database", err)
|
||||
}
|
||||
|
||||
passwordHashed, err := util.EncodePassword(cmd.OldPassword, userQuery.Result.Salt)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to encode password", err)
|
||||
return response.Error(500, "Failed to encode password", err)
|
||||
}
|
||||
if passwordHashed != userQuery.Result.Password {
|
||||
return Error(401, "Invalid old password", nil)
|
||||
return response.Error(401, "Invalid old password", nil)
|
||||
}
|
||||
|
||||
password := models.Password(cmd.NewPassword)
|
||||
if password.IsWeak() {
|
||||
return Error(400, "New password is too short", nil)
|
||||
return response.Error(400, "New password is too short", nil)
|
||||
}
|
||||
|
||||
cmd.UserId = c.UserId
|
||||
cmd.NewPassword, err = util.EncodePassword(cmd.NewPassword, userQuery.Result.Salt)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to encode password", err)
|
||||
return response.Error(500, "Failed to encode password", err)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to change user password", err)
|
||||
return response.Error(500, "Failed to change user password", err)
|
||||
}
|
||||
|
||||
return Success("User password changed")
|
||||
return response.Success("User password changed")
|
||||
}
|
||||
|
||||
// redirectToChangePassword handles GET /.well-known/change-password.
|
||||
@@ -258,23 +259,23 @@ func redirectToChangePassword(c *models.ReqContext) {
|
||||
}
|
||||
|
||||
// GET /api/users
|
||||
func SearchUsers(c *models.ReqContext) Response {
|
||||
func SearchUsers(c *models.ReqContext) response.Response {
|
||||
query, err := searchUser(c)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to fetch users", err)
|
||||
return response.Error(500, "Failed to fetch users", err)
|
||||
}
|
||||
|
||||
return JSON(200, query.Result.Users)
|
||||
return response.JSON(200, query.Result.Users)
|
||||
}
|
||||
|
||||
// GET /api/users/search
|
||||
func SearchUsersWithPaging(c *models.ReqContext) Response {
|
||||
func SearchUsersWithPaging(c *models.ReqContext) response.Response {
|
||||
query, err := searchUser(c)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to fetch users", err)
|
||||
return response.Error(500, "Failed to fetch users", err)
|
||||
}
|
||||
|
||||
return JSON(200, query.Result)
|
||||
return response.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
func searchUser(c *models.ReqContext) (*models.SearchUsersQuery, error) {
|
||||
@@ -311,7 +312,7 @@ func searchUser(c *models.ReqContext) (*models.SearchUsersQuery, error) {
|
||||
return query, nil
|
||||
}
|
||||
|
||||
func SetHelpFlag(c *models.ReqContext) Response {
|
||||
func SetHelpFlag(c *models.ReqContext) response.Response {
|
||||
flag := c.ParamsInt64(":id")
|
||||
|
||||
bitmask := &c.HelpFlags1
|
||||
@@ -323,23 +324,23 @@ func SetHelpFlag(c *models.ReqContext) Response {
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to update help flag", err)
|
||||
return response.Error(500, "Failed to update help flag", err)
|
||||
}
|
||||
|
||||
return JSON(200, &util.DynMap{"message": "Help flag set", "helpFlags1": cmd.HelpFlags1})
|
||||
return response.JSON(200, &util.DynMap{"message": "Help flag set", "helpFlags1": cmd.HelpFlags1})
|
||||
}
|
||||
|
||||
func ClearHelpFlags(c *models.ReqContext) Response {
|
||||
func ClearHelpFlags(c *models.ReqContext) response.Response {
|
||||
cmd := models.SetUserHelpFlagCommand{
|
||||
UserId: c.UserId,
|
||||
HelpFlags1: models.HelpFlags1(0),
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return Error(500, "Failed to update help flag", err)
|
||||
return response.Error(500, "Failed to update help flag", err)
|
||||
}
|
||||
|
||||
return JSON(200, &util.DynMap{"message": "Help flag set", "helpFlags1": cmd.HelpFlags1})
|
||||
return response.JSON(200, &util.DynMap{"message": "Help flag set", "helpFlags1": cmd.HelpFlags1})
|
||||
}
|
||||
|
||||
func GetAuthProviderLabel(authModule string) string {
|
||||
|
@@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"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/util"
|
||||
@@ -13,48 +14,48 @@ import (
|
||||
)
|
||||
|
||||
// GET /api/user/auth-tokens
|
||||
func (hs *HTTPServer) GetUserAuthTokens(c *models.ReqContext) Response {
|
||||
func (hs *HTTPServer) GetUserAuthTokens(c *models.ReqContext) response.Response {
|
||||
return hs.getUserAuthTokensInternal(c, c.UserId)
|
||||
}
|
||||
|
||||
// POST /api/user/revoke-auth-token
|
||||
func (hs *HTTPServer) RevokeUserAuthToken(c *models.ReqContext, cmd models.RevokeAuthTokenCmd) Response {
|
||||
func (hs *HTTPServer) RevokeUserAuthToken(c *models.ReqContext, cmd models.RevokeAuthTokenCmd) response.Response {
|
||||
return hs.revokeUserAuthTokenInternal(c, c.UserId, cmd)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) logoutUserFromAllDevicesInternal(ctx context.Context, userID int64) Response {
|
||||
func (hs *HTTPServer) logoutUserFromAllDevicesInternal(ctx context.Context, userID int64) response.Response {
|
||||
userQuery := models.GetUserByIdQuery{Id: userID}
|
||||
|
||||
if err := bus.Dispatch(&userQuery); err != nil {
|
||||
if errors.Is(err, models.ErrUserNotFound) {
|
||||
return Error(404, "User not found", err)
|
||||
return response.Error(404, "User not found", err)
|
||||
}
|
||||
return Error(500, "Could not read user from database", err)
|
||||
return response.Error(500, "Could not read user from database", err)
|
||||
}
|
||||
|
||||
err := hs.AuthTokenService.RevokeAllUserTokens(ctx, userID)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to logout user", err)
|
||||
return response.Error(500, "Failed to logout user", err)
|
||||
}
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": "User logged out",
|
||||
})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) getUserAuthTokensInternal(c *models.ReqContext, userID int64) Response {
|
||||
func (hs *HTTPServer) getUserAuthTokensInternal(c *models.ReqContext, userID int64) response.Response {
|
||||
userQuery := models.GetUserByIdQuery{Id: userID}
|
||||
|
||||
if err := bus.Dispatch(&userQuery); err != nil {
|
||||
if errors.Is(err, models.ErrUserNotFound) {
|
||||
return Error(404, "User not found", err)
|
||||
return response.Error(404, "User not found", err)
|
||||
}
|
||||
return Error(500, "Failed to get user", err)
|
||||
return response.Error(500, "Failed to get user", err)
|
||||
}
|
||||
|
||||
tokens, err := hs.AuthTokenService.GetUserTokens(c.Req.Context(), userID)
|
||||
if err != nil {
|
||||
return Error(500, "Failed to get user auth tokens", err)
|
||||
return response.Error(500, "Failed to get user auth tokens", err)
|
||||
}
|
||||
|
||||
result := []*dtos.UserToken{}
|
||||
@@ -106,40 +107,40 @@ func (hs *HTTPServer) getUserAuthTokensInternal(c *models.ReqContext, userID int
|
||||
})
|
||||
}
|
||||
|
||||
return JSON(200, result)
|
||||
return response.JSON(200, result)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) revokeUserAuthTokenInternal(c *models.ReqContext, userID int64, cmd models.RevokeAuthTokenCmd) Response {
|
||||
func (hs *HTTPServer) revokeUserAuthTokenInternal(c *models.ReqContext, userID int64, cmd models.RevokeAuthTokenCmd) response.Response {
|
||||
userQuery := models.GetUserByIdQuery{Id: userID}
|
||||
|
||||
if err := bus.Dispatch(&userQuery); err != nil {
|
||||
if errors.Is(err, models.ErrUserNotFound) {
|
||||
return Error(404, "User not found", err)
|
||||
return response.Error(404, "User not found", err)
|
||||
}
|
||||
return Error(500, "Failed to get user", err)
|
||||
return response.Error(500, "Failed to get user", err)
|
||||
}
|
||||
|
||||
token, err := hs.AuthTokenService.GetUserToken(c.Req.Context(), userID, cmd.AuthTokenId)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrUserTokenNotFound) {
|
||||
return Error(404, "User auth token not found", err)
|
||||
return response.Error(404, "User auth token not found", err)
|
||||
}
|
||||
return Error(500, "Failed to get user auth token", err)
|
||||
return response.Error(500, "Failed to get user auth token", err)
|
||||
}
|
||||
|
||||
if c.UserToken != nil && c.UserToken.Id == token.Id {
|
||||
return Error(400, "Cannot revoke active user auth token", nil)
|
||||
return response.Error(400, "Cannot revoke active user auth token", nil)
|
||||
}
|
||||
|
||||
err = hs.AuthTokenService.RevokeToken(c.Req.Context(), token)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrUserTokenNotFound) {
|
||||
return Error(404, "User auth token not found", err)
|
||||
return response.Error(404, "User auth token not found", err)
|
||||
}
|
||||
return Error(500, "Failed to revoke user auth token", err)
|
||||
return response.Error(500, "Failed to revoke user auth token", err)
|
||||
}
|
||||
|
||||
return JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"message": "User auth token revoked",
|
||||
})
|
||||
}
|
||||
|
@@ -6,6 +6,8 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/auth"
|
||||
@@ -181,7 +183,7 @@ func revokeUserAuthTokenScenario(t *testing.T, desc string, url string, routePat
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.userAuthTokenService = fakeAuthTokenService
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = userId
|
||||
sc.context.OrgId = testOrgID
|
||||
@@ -209,7 +211,7 @@ func getUserAuthTokensScenario(t *testing.T, desc string, url string, routePatte
|
||||
|
||||
sc := setupScenarioContext(t, url)
|
||||
sc.userAuthTokenService = fakeAuthTokenService
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = userId
|
||||
sc.context.OrgId = testOrgID
|
||||
@@ -234,7 +236,7 @@ func logoutUserFromAllDevicesInternalScenario(t *testing.T, desc string, userId
|
||||
}
|
||||
|
||||
sc := setupScenarioContext(t, "/")
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
@@ -263,7 +265,7 @@ func revokeUserAuthTokenInternalScenario(t *testing.T, desc string, cmd models.R
|
||||
|
||||
sc := setupScenarioContext(t, "/")
|
||||
sc.userAuthTokenService = fakeAuthTokenService
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
@@ -292,7 +294,7 @@ func getUserAuthTokensInternalScenario(t *testing.T, desc string, token *models.
|
||||
|
||||
sc := setupScenarioContext(t, "/")
|
||||
sc.userAuthTokenService = fakeAuthTokenService
|
||||
sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
|
||||
sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
sc.context = c
|
||||
sc.context.UserId = testUserID
|
||||
sc.context.OrgId = testOrgID
|
||||
|
@@ -4,7 +4,7 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/go-macaron/binding"
|
||||
"github.com/grafana/grafana/pkg/api"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -17,119 +17,119 @@ func (lps *LibraryPanelService) registerAPIEndpoints() {
|
||||
}
|
||||
|
||||
lps.RouteRegister.Group("/api/library-panels", func(libraryPanels routing.RouteRegister) {
|
||||
libraryPanels.Post("/", middleware.ReqSignedIn, binding.Bind(createLibraryPanelCommand{}), api.Wrap(lps.createHandler))
|
||||
libraryPanels.Post("/:uid/dashboards/:dashboardId", middleware.ReqSignedIn, api.Wrap(lps.connectHandler))
|
||||
libraryPanels.Delete("/:uid", middleware.ReqSignedIn, api.Wrap(lps.deleteHandler))
|
||||
libraryPanels.Delete("/:uid/dashboards/:dashboardId", middleware.ReqSignedIn, api.Wrap(lps.disconnectHandler))
|
||||
libraryPanels.Get("/", middleware.ReqSignedIn, api.Wrap(lps.getAllHandler))
|
||||
libraryPanels.Get("/:uid", middleware.ReqSignedIn, api.Wrap(lps.getHandler))
|
||||
libraryPanels.Get("/:uid/dashboards/", middleware.ReqSignedIn, api.Wrap(lps.getConnectedDashboardsHandler))
|
||||
libraryPanels.Patch("/:uid", middleware.ReqSignedIn, binding.Bind(patchLibraryPanelCommand{}), api.Wrap(lps.patchHandler))
|
||||
libraryPanels.Post("/", middleware.ReqSignedIn, binding.Bind(createLibraryPanelCommand{}), routing.Wrap(lps.createHandler))
|
||||
libraryPanels.Post("/:uid/dashboards/:dashboardId", middleware.ReqSignedIn, routing.Wrap(lps.connectHandler))
|
||||
libraryPanels.Delete("/:uid", middleware.ReqSignedIn, routing.Wrap(lps.deleteHandler))
|
||||
libraryPanels.Delete("/:uid/dashboards/:dashboardId", middleware.ReqSignedIn, routing.Wrap(lps.disconnectHandler))
|
||||
libraryPanels.Get("/", middleware.ReqSignedIn, routing.Wrap(lps.getAllHandler))
|
||||
libraryPanels.Get("/:uid", middleware.ReqSignedIn, routing.Wrap(lps.getHandler))
|
||||
libraryPanels.Get("/:uid/dashboards/", middleware.ReqSignedIn, routing.Wrap(lps.getConnectedDashboardsHandler))
|
||||
libraryPanels.Patch("/:uid", middleware.ReqSignedIn, binding.Bind(patchLibraryPanelCommand{}), routing.Wrap(lps.patchHandler))
|
||||
})
|
||||
}
|
||||
|
||||
// createHandler handles POST /api/library-panels.
|
||||
func (lps *LibraryPanelService) createHandler(c *models.ReqContext, cmd createLibraryPanelCommand) api.Response {
|
||||
func (lps *LibraryPanelService) createHandler(c *models.ReqContext, cmd createLibraryPanelCommand) response.Response {
|
||||
panel, err := lps.createLibraryPanel(c, cmd)
|
||||
if err != nil {
|
||||
if errors.Is(err, errLibraryPanelAlreadyExists) {
|
||||
return api.Error(400, errLibraryPanelAlreadyExists.Error(), err)
|
||||
return response.Error(400, errLibraryPanelAlreadyExists.Error(), err)
|
||||
}
|
||||
return api.Error(500, "Failed to create library panel", err)
|
||||
return response.Error(500, "Failed to create library panel", err)
|
||||
}
|
||||
|
||||
return api.JSON(200, util.DynMap{"result": panel})
|
||||
return response.JSON(200, util.DynMap{"result": panel})
|
||||
}
|
||||
|
||||
// connectHandler handles POST /api/library-panels/:uid/dashboards/:dashboardId.
|
||||
func (lps *LibraryPanelService) connectHandler(c *models.ReqContext) api.Response {
|
||||
func (lps *LibraryPanelService) connectHandler(c *models.ReqContext) response.Response {
|
||||
if err := lps.connectDashboard(c, c.Params(":uid"), c.ParamsInt64(":dashboardId")); err != nil {
|
||||
if errors.Is(err, errLibraryPanelNotFound) {
|
||||
return api.Error(404, errLibraryPanelNotFound.Error(), err)
|
||||
return response.Error(404, errLibraryPanelNotFound.Error(), err)
|
||||
}
|
||||
return api.Error(500, "Failed to connect library panel", err)
|
||||
return response.Error(500, "Failed to connect library panel", err)
|
||||
}
|
||||
|
||||
return api.Success("Library panel connected")
|
||||
return response.Success("Library panel connected")
|
||||
}
|
||||
|
||||
// deleteHandler handles DELETE /api/library-panels/:uid.
|
||||
func (lps *LibraryPanelService) deleteHandler(c *models.ReqContext) api.Response {
|
||||
func (lps *LibraryPanelService) deleteHandler(c *models.ReqContext) response.Response {
|
||||
err := lps.deleteLibraryPanel(c, c.Params(":uid"))
|
||||
if err != nil {
|
||||
if errors.Is(err, errLibraryPanelNotFound) {
|
||||
return api.Error(404, errLibraryPanelNotFound.Error(), err)
|
||||
return response.Error(404, errLibraryPanelNotFound.Error(), err)
|
||||
}
|
||||
return api.Error(500, "Failed to delete library panel", err)
|
||||
return response.Error(500, "Failed to delete library panel", err)
|
||||
}
|
||||
|
||||
return api.Success("Library panel deleted")
|
||||
return response.Success("Library panel deleted")
|
||||
}
|
||||
|
||||
// disconnectHandler handles DELETE /api/library-panels/:uid/dashboards/:dashboardId.
|
||||
func (lps *LibraryPanelService) disconnectHandler(c *models.ReqContext) api.Response {
|
||||
func (lps *LibraryPanelService) disconnectHandler(c *models.ReqContext) response.Response {
|
||||
err := lps.disconnectDashboard(c, c.Params(":uid"), c.ParamsInt64(":dashboardId"))
|
||||
if err != nil {
|
||||
if errors.Is(err, errLibraryPanelNotFound) {
|
||||
return api.Error(404, errLibraryPanelNotFound.Error(), err)
|
||||
return response.Error(404, errLibraryPanelNotFound.Error(), err)
|
||||
}
|
||||
if errors.Is(err, errLibraryPanelDashboardNotFound) {
|
||||
return api.Error(404, errLibraryPanelDashboardNotFound.Error(), err)
|
||||
return response.Error(404, errLibraryPanelDashboardNotFound.Error(), err)
|
||||
}
|
||||
return api.Error(500, "Failed to disconnect library panel", err)
|
||||
return response.Error(500, "Failed to disconnect library panel", err)
|
||||
}
|
||||
|
||||
return api.Success("Library panel disconnected")
|
||||
return response.Success("Library panel disconnected")
|
||||
}
|
||||
|
||||
// getHandler handles GET /api/library-panels/:uid.
|
||||
func (lps *LibraryPanelService) getHandler(c *models.ReqContext) api.Response {
|
||||
func (lps *LibraryPanelService) getHandler(c *models.ReqContext) response.Response {
|
||||
libraryPanel, err := lps.getLibraryPanel(c, c.Params(":uid"))
|
||||
if err != nil {
|
||||
if errors.Is(err, errLibraryPanelNotFound) {
|
||||
return api.Error(404, errLibraryPanelNotFound.Error(), err)
|
||||
return response.Error(404, errLibraryPanelNotFound.Error(), err)
|
||||
}
|
||||
return api.Error(500, "Failed to get library panel", err)
|
||||
return response.Error(500, "Failed to get library panel", err)
|
||||
}
|
||||
|
||||
return api.JSON(200, util.DynMap{"result": libraryPanel})
|
||||
return response.JSON(200, util.DynMap{"result": libraryPanel})
|
||||
}
|
||||
|
||||
// getAllHandler handles GET /api/library-panels/.
|
||||
func (lps *LibraryPanelService) getAllHandler(c *models.ReqContext) api.Response {
|
||||
func (lps *LibraryPanelService) getAllHandler(c *models.ReqContext) response.Response {
|
||||
libraryPanels, err := lps.getAllLibraryPanels(c)
|
||||
if err != nil {
|
||||
return api.Error(500, "Failed to get library panels", err)
|
||||
return response.Error(500, "Failed to get library panels", err)
|
||||
}
|
||||
|
||||
return api.JSON(200, util.DynMap{"result": libraryPanels})
|
||||
return response.JSON(200, util.DynMap{"result": libraryPanels})
|
||||
}
|
||||
|
||||
// getConnectedDashboardsHandler handles GET /api/library-panels/:uid/dashboards/.
|
||||
func (lps *LibraryPanelService) getConnectedDashboardsHandler(c *models.ReqContext) api.Response {
|
||||
func (lps *LibraryPanelService) getConnectedDashboardsHandler(c *models.ReqContext) response.Response {
|
||||
dashboardIDs, err := lps.getConnectedDashboards(c, c.Params(":uid"))
|
||||
if err != nil {
|
||||
if errors.Is(err, errLibraryPanelNotFound) {
|
||||
return api.Error(404, errLibraryPanelNotFound.Error(), err)
|
||||
return response.Error(404, errLibraryPanelNotFound.Error(), err)
|
||||
}
|
||||
return api.Error(500, "Failed to get connected dashboards", err)
|
||||
return response.Error(500, "Failed to get connected dashboards", err)
|
||||
}
|
||||
|
||||
return api.JSON(200, util.DynMap{"result": dashboardIDs})
|
||||
return response.JSON(200, util.DynMap{"result": dashboardIDs})
|
||||
}
|
||||
|
||||
// patchHandler handles PATCH /api/library-panels/:uid
|
||||
func (lps *LibraryPanelService) patchHandler(c *models.ReqContext, cmd patchLibraryPanelCommand) api.Response {
|
||||
func (lps *LibraryPanelService) patchHandler(c *models.ReqContext, cmd patchLibraryPanelCommand) response.Response {
|
||||
libraryPanel, err := lps.patchLibraryPanel(c, cmd, c.Params(":uid"))
|
||||
if err != nil {
|
||||
if errors.Is(err, errLibraryPanelAlreadyExists) {
|
||||
return api.Error(400, errLibraryPanelAlreadyExists.Error(), err)
|
||||
return response.Error(400, errLibraryPanelAlreadyExists.Error(), err)
|
||||
}
|
||||
if errors.Is(err, errLibraryPanelNotFound) {
|
||||
return api.Error(404, errLibraryPanelNotFound.Error(), err)
|
||||
return response.Error(404, errLibraryPanelNotFound.Error(), err)
|
||||
}
|
||||
return api.Error(500, "Failed to update library panel", err)
|
||||
return response.Error(500, "Failed to update library panel", err)
|
||||
}
|
||||
|
||||
return api.JSON(200, util.DynMap{"result": libraryPanel})
|
||||
return response.JSON(200, util.DynMap{"result": libraryPanel})
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@ package ngalert
|
||||
import (
|
||||
"github.com/go-macaron/binding"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana/pkg/api"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/api/routing"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
@@ -14,79 +14,79 @@ import (
|
||||
|
||||
func (ng *AlertNG) registerAPIEndpoints() {
|
||||
ng.RouteRegister.Group("/api/alert-definitions", func(alertDefinitions routing.RouteRegister) {
|
||||
alertDefinitions.Get("", middleware.ReqSignedIn, api.Wrap(ng.listAlertDefinitions))
|
||||
alertDefinitions.Get("/eval/:alertDefinitionUID", ng.validateOrgAlertDefinition, api.Wrap(ng.alertDefinitionEvalEndpoint))
|
||||
alertDefinitions.Post("/eval", middleware.ReqSignedIn, binding.Bind(evalAlertConditionCommand{}), api.Wrap(ng.conditionEvalEndpoint))
|
||||
alertDefinitions.Get("/:alertDefinitionUID", ng.validateOrgAlertDefinition, api.Wrap(ng.getAlertDefinitionEndpoint))
|
||||
alertDefinitions.Delete("/:alertDefinitionUID", ng.validateOrgAlertDefinition, api.Wrap(ng.deleteAlertDefinitionEndpoint))
|
||||
alertDefinitions.Post("/", middleware.ReqSignedIn, binding.Bind(saveAlertDefinitionCommand{}), api.Wrap(ng.createAlertDefinitionEndpoint))
|
||||
alertDefinitions.Put("/:alertDefinitionUID", ng.validateOrgAlertDefinition, binding.Bind(updateAlertDefinitionCommand{}), api.Wrap(ng.updateAlertDefinitionEndpoint))
|
||||
alertDefinitions.Get("", middleware.ReqSignedIn, routing.Wrap(ng.listAlertDefinitions))
|
||||
alertDefinitions.Get("/eval/:alertDefinitionUID", ng.validateOrgAlertDefinition, routing.Wrap(ng.alertDefinitionEvalEndpoint))
|
||||
alertDefinitions.Post("/eval", middleware.ReqSignedIn, binding.Bind(evalAlertConditionCommand{}), routing.Wrap(ng.conditionEvalEndpoint))
|
||||
alertDefinitions.Get("/:alertDefinitionUID", ng.validateOrgAlertDefinition, routing.Wrap(ng.getAlertDefinitionEndpoint))
|
||||
alertDefinitions.Delete("/:alertDefinitionUID", ng.validateOrgAlertDefinition, routing.Wrap(ng.deleteAlertDefinitionEndpoint))
|
||||
alertDefinitions.Post("/", middleware.ReqSignedIn, binding.Bind(saveAlertDefinitionCommand{}), routing.Wrap(ng.createAlertDefinitionEndpoint))
|
||||
alertDefinitions.Put("/:alertDefinitionUID", ng.validateOrgAlertDefinition, binding.Bind(updateAlertDefinitionCommand{}), routing.Wrap(ng.updateAlertDefinitionEndpoint))
|
||||
})
|
||||
|
||||
ng.RouteRegister.Group("/api/ngalert/", func(schedulerRouter routing.RouteRegister) {
|
||||
schedulerRouter.Post("/pause", api.Wrap(ng.pauseScheduler))
|
||||
schedulerRouter.Post("/unpause", api.Wrap(ng.unpauseScheduler))
|
||||
schedulerRouter.Post("/pause", routing.Wrap(ng.pauseScheduler))
|
||||
schedulerRouter.Post("/unpause", routing.Wrap(ng.unpauseScheduler))
|
||||
}, middleware.ReqOrgAdmin)
|
||||
}
|
||||
|
||||
// conditionEvalEndpoint handles POST /api/alert-definitions/eval.
|
||||
func (ng *AlertNG) conditionEvalEndpoint(c *models.ReqContext, dto evalAlertConditionCommand) api.Response {
|
||||
func (ng *AlertNG) conditionEvalEndpoint(c *models.ReqContext, dto evalAlertConditionCommand) response.Response {
|
||||
if err := ng.validateCondition(dto.Condition, c.SignedInUser); err != nil {
|
||||
return api.Error(400, "invalid condition", err)
|
||||
return response.Error(400, "invalid condition", err)
|
||||
}
|
||||
|
||||
evalResults, err := eval.ConditionEval(&dto.Condition, timeNow())
|
||||
if err != nil {
|
||||
return api.Error(400, "Failed to evaluate conditions", err)
|
||||
return response.Error(400, "Failed to evaluate conditions", err)
|
||||
}
|
||||
|
||||
frame := evalResults.AsDataFrame()
|
||||
df := tsdb.NewDecodedDataFrames([]*data.Frame{&frame})
|
||||
instances, err := df.Encoded()
|
||||
if err != nil {
|
||||
return api.Error(400, "Failed to encode result dataframes", err)
|
||||
return response.Error(400, "Failed to encode result dataframes", err)
|
||||
}
|
||||
|
||||
return api.JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"instances": instances,
|
||||
})
|
||||
}
|
||||
|
||||
// alertDefinitionEvalEndpoint handles GET /api/alert-definitions/eval/:alertDefinitionUID.
|
||||
func (ng *AlertNG) alertDefinitionEvalEndpoint(c *models.ReqContext) api.Response {
|
||||
func (ng *AlertNG) alertDefinitionEvalEndpoint(c *models.ReqContext) response.Response {
|
||||
alertDefinitionUID := c.ParamsEscape(":alertDefinitionUID")
|
||||
|
||||
condition, err := ng.LoadAlertCondition(alertDefinitionUID, c.SignedInUser.OrgId)
|
||||
if err != nil {
|
||||
return api.Error(400, "Failed to load alert definition conditions", err)
|
||||
return response.Error(400, "Failed to load alert definition conditions", err)
|
||||
}
|
||||
|
||||
if err := ng.validateCondition(*condition, c.SignedInUser); err != nil {
|
||||
return api.Error(400, "invalid condition", err)
|
||||
return response.Error(400, "invalid condition", err)
|
||||
}
|
||||
|
||||
evalResults, err := eval.ConditionEval(condition, timeNow())
|
||||
if err != nil {
|
||||
return api.Error(400, "Failed to evaluate alert", err)
|
||||
return response.Error(400, "Failed to evaluate alert", err)
|
||||
}
|
||||
frame := evalResults.AsDataFrame()
|
||||
|
||||
df := tsdb.NewDecodedDataFrames([]*data.Frame{&frame})
|
||||
if err != nil {
|
||||
return api.Error(400, "Failed to instantiate Dataframes from the decoded frames", err)
|
||||
return response.Error(400, "Failed to instantiate Dataframes from the decoded frames", err)
|
||||
}
|
||||
|
||||
instances, err := df.Encoded()
|
||||
if err != nil {
|
||||
return api.Error(400, "Failed to encode result dataframes", err)
|
||||
return response.Error(400, "Failed to encode result dataframes", err)
|
||||
}
|
||||
return api.JSON(200, util.DynMap{
|
||||
return response.JSON(200, util.DynMap{
|
||||
"instances": instances,
|
||||
})
|
||||
}
|
||||
|
||||
// getAlertDefinitionEndpoint handles GET /api/alert-definitions/:alertDefinitionUID.
|
||||
func (ng *AlertNG) getAlertDefinitionEndpoint(c *models.ReqContext) api.Response {
|
||||
func (ng *AlertNG) getAlertDefinitionEndpoint(c *models.ReqContext) response.Response {
|
||||
alertDefinitionUID := c.ParamsEscape(":alertDefinitionUID")
|
||||
|
||||
query := getAlertDefinitionByUIDQuery{
|
||||
@@ -95,14 +95,14 @@ func (ng *AlertNG) getAlertDefinitionEndpoint(c *models.ReqContext) api.Response
|
||||
}
|
||||
|
||||
if err := ng.getAlertDefinitionByUID(&query); err != nil {
|
||||
return api.Error(500, "Failed to get alert definition", err)
|
||||
return response.Error(500, "Failed to get alert definition", err)
|
||||
}
|
||||
|
||||
return api.JSON(200, &query.Result)
|
||||
return response.JSON(200, &query.Result)
|
||||
}
|
||||
|
||||
// deleteAlertDefinitionEndpoint handles DELETE /api/alert-definitions/:alertDefinitionUID.
|
||||
func (ng *AlertNG) deleteAlertDefinitionEndpoint(c *models.ReqContext) api.Response {
|
||||
func (ng *AlertNG) deleteAlertDefinitionEndpoint(c *models.ReqContext) response.Response {
|
||||
alertDefinitionUID := c.ParamsEscape(":alertDefinitionUID")
|
||||
|
||||
cmd := deleteAlertDefinitionByUIDCommand{
|
||||
@@ -111,66 +111,66 @@ func (ng *AlertNG) deleteAlertDefinitionEndpoint(c *models.ReqContext) api.Respo
|
||||
}
|
||||
|
||||
if err := ng.deleteAlertDefinitionByUID(&cmd); err != nil {
|
||||
return api.Error(500, "Failed to delete alert definition", err)
|
||||
return response.Error(500, "Failed to delete alert definition", err)
|
||||
}
|
||||
|
||||
return api.Success("Alert definition deleted")
|
||||
return response.Success("Alert definition deleted")
|
||||
}
|
||||
|
||||
// updateAlertDefinitionEndpoint handles PUT /api/alert-definitions/:alertDefinitionUID.
|
||||
func (ng *AlertNG) updateAlertDefinitionEndpoint(c *models.ReqContext, cmd updateAlertDefinitionCommand) api.Response {
|
||||
func (ng *AlertNG) updateAlertDefinitionEndpoint(c *models.ReqContext, cmd updateAlertDefinitionCommand) response.Response {
|
||||
cmd.UID = c.ParamsEscape(":alertDefinitionUID")
|
||||
cmd.OrgID = c.SignedInUser.OrgId
|
||||
|
||||
if err := ng.validateCondition(cmd.Condition, c.SignedInUser); err != nil {
|
||||
return api.Error(400, "invalid condition", err)
|
||||
return response.Error(400, "invalid condition", err)
|
||||
}
|
||||
|
||||
if err := ng.updateAlertDefinition(&cmd); err != nil {
|
||||
return api.Error(500, "Failed to update alert definition", err)
|
||||
return response.Error(500, "Failed to update alert definition", err)
|
||||
}
|
||||
|
||||
return api.JSON(200, cmd.Result)
|
||||
return response.JSON(200, cmd.Result)
|
||||
}
|
||||
|
||||
// createAlertDefinitionEndpoint handles POST /api/alert-definitions.
|
||||
func (ng *AlertNG) createAlertDefinitionEndpoint(c *models.ReqContext, cmd saveAlertDefinitionCommand) api.Response {
|
||||
func (ng *AlertNG) createAlertDefinitionEndpoint(c *models.ReqContext, cmd saveAlertDefinitionCommand) response.Response {
|
||||
cmd.OrgID = c.SignedInUser.OrgId
|
||||
|
||||
if err := ng.validateCondition(cmd.Condition, c.SignedInUser); err != nil {
|
||||
return api.Error(400, "invalid condition", err)
|
||||
return response.Error(400, "invalid condition", err)
|
||||
}
|
||||
|
||||
if err := ng.saveAlertDefinition(&cmd); err != nil {
|
||||
return api.Error(500, "Failed to create alert definition", err)
|
||||
return response.Error(500, "Failed to create alert definition", err)
|
||||
}
|
||||
|
||||
return api.JSON(200, cmd.Result)
|
||||
return response.JSON(200, cmd.Result)
|
||||
}
|
||||
|
||||
// listAlertDefinitions handles GET /api/alert-definitions.
|
||||
func (ng *AlertNG) listAlertDefinitions(c *models.ReqContext) api.Response {
|
||||
func (ng *AlertNG) listAlertDefinitions(c *models.ReqContext) response.Response {
|
||||
query := listAlertDefinitionsQuery{OrgID: c.SignedInUser.OrgId}
|
||||
|
||||
if err := ng.getOrgAlertDefinitions(&query); err != nil {
|
||||
return api.Error(500, "Failed to list alert definitions", err)
|
||||
return response.Error(500, "Failed to list alert definitions", err)
|
||||
}
|
||||
|
||||
return api.JSON(200, util.DynMap{"results": query.Result})
|
||||
return response.JSON(200, util.DynMap{"results": query.Result})
|
||||
}
|
||||
|
||||
func (ng *AlertNG) pauseScheduler() api.Response {
|
||||
func (ng *AlertNG) pauseScheduler() response.Response {
|
||||
err := ng.schedule.pause()
|
||||
if err != nil {
|
||||
return api.Error(500, "Failed to pause scheduler", err)
|
||||
return response.Error(500, "Failed to pause scheduler", err)
|
||||
}
|
||||
return api.JSON(200, util.DynMap{"message": "alert definition scheduler paused"})
|
||||
return response.JSON(200, util.DynMap{"message": "alert definition scheduler paused"})
|
||||
}
|
||||
|
||||
func (ng *AlertNG) unpauseScheduler() api.Response {
|
||||
func (ng *AlertNG) unpauseScheduler() response.Response {
|
||||
err := ng.schedule.unpause()
|
||||
if err != nil {
|
||||
return api.Error(500, "Failed to unpause scheduler", err)
|
||||
return response.Error(500, "Failed to unpause scheduler", err)
|
||||
}
|
||||
return api.JSON(200, util.DynMap{"message": "alert definition scheduler unpaused"})
|
||||
return response.JSON(200, util.DynMap{"message": "alert definition scheduler unpaused"})
|
||||
}
|
||||
|
Reference in New Issue
Block a user