func GetDashboard(c *middleware.Context) { metrics.M_Api_Dashboard_Get.Inc(1) slug := strings.ToLower(c.Params(":slug")) query := m.GetDashboardQuery{Slug: slug, OrgId: c.OrgId} err := bus.Dispatch(&query) if err != nil { c.JsonApiErr(404, "Dashboard not found", nil) return } isStarred, err := isDasboardStarredByUser(c, query.Result.Id) if err != nil { c.JsonApiErr(500, "Error while checking if dashboard was starred by user", err) return } dash := query.Result dto := dtos.DashboardFullWithMeta{ Dashboard: dash.Data, Meta: dtos.DashboardMeta{ IsStarred: isStarred, Slug: slug, Type: m.DashTypeDB, CanStar: c.IsSignedIn, CanSave: c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR, CanEdit: canEditDashboard(c.OrgRole), }, } c.JSON(200, dto) }
func GetDataSourceById(c *middleware.Context) { query := m.GetDataSourceByIdQuery{ Id: c.ParamsInt64(":id"), OrgId: c.OrgId, } if err := bus.Dispatch(&query); err != nil { c.JsonApiErr(500, "Failed to query datasources", err) return } ds := query.Result c.JSON(200, &dtos.DataSource{ Id: ds.Id, OrgId: ds.OrgId, Name: ds.Name, Url: ds.Url, Type: ds.Type, Access: ds.Access, Password: ds.Password, Database: ds.Database, User: ds.User, BasicAuth: ds.BasicAuth, BasicAuthUser: ds.BasicAuthUser, BasicAuthPassword: ds.BasicAuthPassword, IsDefault: ds.IsDefault, JsonData: ds.JsonData, }) }
func handleDescribeInstances(req *cwRequest, c *middleware.Context) { svc := ec2.New(&aws.Config{Region: aws.String(req.Region)}) reqParam := &struct { Parameters struct { Filters []*ec2.Filter `json:"filters"` InstanceIds []*string `json:"instanceIds"` } `json:"parameters"` }{} json.Unmarshal(req.Body, reqParam) params := &ec2.DescribeInstancesInput{} if len(reqParam.Parameters.Filters) > 0 { params.Filters = reqParam.Parameters.Filters } if len(reqParam.Parameters.InstanceIds) > 0 { params.InstanceIds = reqParam.Parameters.InstanceIds } resp, err := svc.DescribeInstances(params) if err != nil { c.JsonApiErr(500, "Unable to call AWS API", err) return } c.JSON(200, resp) }
func GetDashboardSnapshot(c *middleware.Context) { key := c.Params(":key") query := &m.GetDashboardSnapshotQuery{Key: key} err := bus.Dispatch(query) if err != nil { c.JsonApiErr(500, "Failed to get dashboard snapshot", err) return } snapshot := query.Result // expired snapshots should also be removed from db if snapshot.Expires.Before(time.Now()) { c.JsonApiErr(404, "Dashboard snapshot not found", err) return } dto := dtos.DashboardFullWithMeta{ Dashboard: snapshot.Dashboard, Meta: dtos.DashboardMeta{ Type: m.DashTypeSnapshot, IsSnapshot: true, Created: snapshot.Created, Expires: snapshot.Expires, }, } metrics.M_Api_Dashboard_Snapshot_Get.Inc(1) c.Resp.Header().Set("Cache-Control", "public, max-age=3600") c.JSON(200, dto) }
func CreateDashboardSnapshot(c *middleware.Context, cmd m.CreateDashboardSnapshotCommand) { if cmd.External { // external snapshot ref requires key and delete key if cmd.Key == "" || cmd.DeleteKey == "" { c.JsonApiErr(400, "Missing key and delete key for external snapshot", nil) return } cmd.OrgId = -1 cmd.UserId = -1 metrics.M_Api_Dashboard_Snapshot_External.Inc(1) } else { cmd.Key = util.GetRandomString(32) cmd.DeleteKey = util.GetRandomString(32) cmd.OrgId = c.OrgId cmd.UserId = c.UserId metrics.M_Api_Dashboard_Snapshot_Create.Inc(1) } if err := bus.Dispatch(&cmd); err != nil { c.JsonApiErr(500, "Failed to create snaphost", err) return } c.JSON(200, util.DynMap{ "key": cmd.Key, "deleteKey": cmd.DeleteKey, "url": setting.ToAbsUrl("dashboard/snapshot/" + cmd.Key), "deleteUrl": setting.ToAbsUrl("api/snapshots-delete/" + cmd.DeleteKey), }) }
func GetDataSources(c *middleware.Context) { log.Info("DataSource Url: %v", setting.DataSource.DataSourceUrlRoot) query := m.GetDataSourcesQuery{OrgId: c.OrgId} if err := bus.Dispatch(&query); err != nil { c.JsonApiErr(500, "Failed to query datasources", err) return } result := make([]*dtos.DataSource, len(query.Result)) for i, ds := range query.Result { result[i] = &dtos.DataSource{ Id: ds.Id, OrgId: ds.OrgId, Name: ds.Name, Url: ds.Url, Type: ds.Type, Access: ds.Access, Password: ds.Password, Database: ds.Database, User: ds.User, BasicAuth: ds.BasicAuth, IsDefault: ds.IsDefault, } } c.JSON(200, result) }
func handleListMetrics(req *cwRequest, c *middleware.Context) { creds := credentials.NewChainCredentials( []credentials.Provider{ &credentials.EnvProvider{}, &credentials.SharedCredentialsProvider{Filename: "", Profile: req.DataSource.Database}, &ec2rolecreds.EC2RoleProvider{ExpiryWindow: 5 * time.Minute}, }) svc := cloudwatch.New(&aws.Config{ Region: aws.String(req.Region), Credentials: creds, }) reqParam := &struct { Parameters struct { Namespace string `json:"namespace"` MetricName string `json:"metricName"` Dimensions []*cloudwatch.DimensionFilter `json:"dimensions"` } `json:"parameters"` }{} json.Unmarshal(req.Body, reqParam) params := &cloudwatch.ListMetricsInput{ Namespace: aws.String(reqParam.Parameters.Namespace), MetricName: aws.String(reqParam.Parameters.MetricName), Dimensions: reqParam.Parameters.Dimensions, } resp, err := svc.ListMetrics(params) if err != nil { c.JsonApiErr(500, "Unable to call AWS API", err) return } c.JSON(200, resp) }
func LoginApiPing(c *middleware.Context) { if !tryLoginUsingRememberCookie(c) { c.JsonApiErr(401, "Unauthorized", nil) return } c.JsonOK("Logged in") }
func GetFrontendSettings(c *middleware.Context) { settings, err := getFrontendSettingsMap(c) if err != nil { c.JsonApiErr(400, "Failed to get frontend settings", err) return } c.JSON(200, settings) }
func GetDashboardTags(c *middleware.Context) { query := m.GetDashboardTagsQuery{OrgId: c.OrgId} err := bus.Dispatch(&query) if err != nil { c.JsonApiErr(500, "Failed to get tags from database", err) return } c.JSON(200, query.Result) }
func AddDataSource(c *middleware.Context, cmd m.AddDataSourceCommand) { cmd.OrgId = c.OrgId if err := bus.Dispatch(&cmd); err != nil { c.JsonApiErr(500, "Failed to add datasource", err) return } c.JSON(200, util.DynMap{"message": "Datasource added", "id": cmd.Result.Id}) }
func DeleteDashboardSnapshot(c *middleware.Context) { key := c.Params(":key") cmd := &m.DeleteDashboardSnapshotCommand{DeleteKey: key} if err := bus.Dispatch(cmd); err != nil { c.JsonApiErr(500, "Failed to delete dashboard snapshot", err) return } c.JSON(200, util.DynMap{"message": "Snapshot deleted. It might take an hour before it's cleared from a CDN cache."}) }
func AdminDeleteUser(c *middleware.Context) { userId := c.ParamsInt64(":id") cmd := m.DeleteUserCommand{UserId: userId} if err := bus.Dispatch(&cmd); err != nil { c.JsonApiErr(500, "Failed to delete user", err) return } c.JsonOK("User deleted") }
func UpdateDataSource(c *middleware.Context, cmd m.UpdateDataSourceCommand) { cmd.OrgId = c.OrgId cmd.Id = c.ParamsInt64(":id") err := bus.Dispatch(&cmd) if err != nil { c.JsonApiErr(500, "Failed to update datasource", err) return } c.JsonOK("Datasource updated") }
func Search(c *middleware.Context) { query := c.Query("query") tags := c.QueryStrings("tag") starred := c.Query("starred") limit := c.QueryInt("limit") if limit == 0 { limit = 1000 } searchQuery := search.Query{ Title: query, Tags: tags, UserId: c.UserId, Limit: limit, IsStarred: starred == "true", OrgId: c.OrgId, } err := bus.Dispatch(&searchQuery) if err != nil { c.JsonApiErr(500, "Search failed", err) return } dashQuery := m.GetCurrentDashboardDashboard{} dashQuery.UserId = c.UserId err = bus.Dispatch(&dashQuery) if err != nil { c.JsonApiErr(500, "Get Dasboard Id failed", err) return } if c.OrgRole != "Admin" || !c.IsGrafanaAdmin { for index, hit := range searchQuery.Result { isDelete := true for _, dash := range dashQuery.Result { if dash.Id == hit.Id { isDelete = false } } if isDelete { last := index + 1 if last > len(searchQuery.Result) { last = len(searchQuery.Result) } searchQuery.Result = append(searchQuery.Result[:index], searchQuery.Result[last:]...) } } } c.JSON(200, searchQuery.Result) }
func NotFoundHandler(c *middleware.Context) { if c.IsApiRequest() { c.JsonApiErr(404, "Not found", nil) return } if err := setIndexViewData(c); err != nil { c.Handle(500, "Failed to get settings", err) return } c.HTML(404, "index") }
func HandleRequest(c *middleware.Context, ds *m.DataSource) { var req cwRequest req.Body, _ = ioutil.ReadAll(c.Req.Request.Body) req.DataSource = ds json.Unmarshal(req.Body, &req) if handler, found := actionHandlers[req.Action]; !found { c.JsonApiErr(500, "Unexpected AWS Action", errors.New(req.Action)) return } else { handler(&req, c) } }
func GetDashboardFromJsonFile(c *middleware.Context) { file := c.Params(":file") dashboard := search.GetDashboardFromJsonIndex(file) if dashboard == nil { c.JsonApiErr(404, "Dashboard not found", nil) return } dash := dtos.DashboardFullWithMeta{Dashboard: dashboard.Data} dash.Meta.Type = m.DashTypeJson dash.Meta.CanEdit = canEditDashboard(c.OrgRole) c.JSON(200, &dash) }
func AdminUpdateUserPermissions(c *middleware.Context, form dtos.AdminUpdateUserPermissionsForm) { userId := c.ParamsInt64(":id") cmd := m.UpdateUserPermissionsCommand{ UserId: userId, IsGrafanaAdmin: form.IsGrafanaAdmin, } if err := bus.Dispatch(&cmd); err != nil { c.JsonApiErr(500, "Failed to update user permissions", err) return } c.JsonOK("User permissions updated") }
func DeleteDataSource(c *middleware.Context) { id := c.ParamsInt64(":id") if id <= 0 { c.JsonApiErr(400, "Missing valid datasource id", nil) return } cmd := &m.DeleteDataSourceCommand{Id: id, OrgId: c.OrgId} err := bus.Dispatch(cmd) if err != nil { c.JsonApiErr(500, "Failed to delete datasource", err) return } c.JsonOK("Data source deleted") }
func DeleteDashboard(c *middleware.Context) { slug := c.Params(":slug") query := m.GetDashboardQuery{Slug: slug, OrgId: c.OrgId} if err := bus.Dispatch(&query); err != nil { c.JsonApiErr(404, "Dashboard not found", nil) return } cmd := m.DeleteDashboardCommand{Slug: slug, OrgId: c.OrgId} if err := bus.Dispatch(&cmd); err != nil { c.JsonApiErr(500, "Failed to delete dashboard", err) return } var resp = map[string]interface{}{"title": query.Result.Title} c.JSON(200, resp) }
func GetHomeDashboard(c *middleware.Context) { filePath := path.Join(setting.StaticRootPath, "dashboards/home.json") file, err := os.Open(filePath) if err != nil { c.JsonApiErr(500, "Failed to load home dashboard", err) return } dash := dtos.DashboardFullWithMeta{} dash.Meta.IsHome = true dash.Meta.CanEdit = canEditDashboard(c.OrgRole) jsonParser := json.NewDecoder(file) if err := jsonParser.Decode(&dash.Dashboard); err != nil { c.JsonApiErr(500, "Failed to load home dashboard", err) return } c.JSON(200, &dash) }
func AdminCreateUser(c *middleware.Context, form dtos.AdminCreateUserForm) { cmd := m.CreateUserCommand{ Login: form.Login, Email: form.Email, Password: form.Password, Name: form.Name, } if len(cmd.Login) == 0 { cmd.Login = cmd.Email if len(cmd.Login) == 0 { c.JsonApiErr(400, "Validation error, need specify either username or email", nil) return } } if len(cmd.Password) < 4 { c.JsonApiErr(400, "Password is missing or too short", nil) return } if err := bus.Dispatch(&cmd); err != nil { c.JsonApiErr(500, "failed to create user", err) return } metrics.M_Api_Admin_User_Create.Inc(1) c.JsonOK("User created") }
func AdminUpdateUserPassword(c *middleware.Context, form dtos.AdminUpdateUserPasswordForm) { userId := c.ParamsInt64(":id") if len(form.Password) < 4 { c.JsonApiErr(400, "New password too short", nil) return } userQuery := m.GetUserByIdQuery{Id: userId} if err := bus.Dispatch(&userQuery); err != nil { c.JsonApiErr(500, "Could not read user from database", err) return } passwordHashed := util.EncodePassword(form.Password, userQuery.Result.Salt) cmd := m.ChangeUserPasswordCommand{ UserId: userId, NewPassword: passwordHashed, } if err := bus.Dispatch(&cmd); err != nil { c.JsonApiErr(500, "Failed to update user password", err) return } c.JsonOK("User password updated") }
func handleGetMetrics(req *cwRequest, c *middleware.Context) { reqParam := &struct { Parameters struct { Namespace string `json:"namespace"` } `json:"parameters"` }{} json.Unmarshal(req.Body, reqParam) namespaceMetrics, exists := metricsMap[reqParam.Parameters.Namespace] if !exists { c.JsonApiErr(404, "Unable to find namespace "+reqParam.Parameters.Namespace, nil) return } result := []interface{}{} for _, name := range namespaceMetrics { result = append(result, util.DynMap{"text": name, "value": name}) } c.JSON(200, result) }
func ProxyDataSourceRequest(c *middleware.Context) { ds, err := getDatasource(c.ParamsInt64(":id"), c.OrgId) if err != nil { c.JsonApiErr(500, "Unable to load datasource meta data", err) return } targetUrl, _ := url.Parse(ds.Url) if len(setting.DataProxyWhiteList) > 0 { if _, exists := setting.DataProxyWhiteList[targetUrl.Host]; !exists { c.JsonApiErr(403, "Data proxy hostname and ip are not included in whitelist", nil) return } } if ds.Type == m.DS_CLOUDWATCH { cloudwatch.HandleRequest(c, ds) } else { proxyPath := c.Params("*") proxy := NewReverseProxy(ds, proxyPath, targetUrl) proxy.Transport = dataProxyTransport proxy.ServeHTTP(c.RW(), c.Req.Request) } }
func PostDashboard(c *middleware.Context, cmd m.SaveDashboardCommand) { cmd.OrgId = c.OrgId dash := cmd.GetDashboardModel() if dash.Id == 0 { limitReached, err := middleware.QuotaReached(c, "dashboard") if err != nil { c.JsonApiErr(500, "failed to get quota", err) return } if limitReached { c.JsonApiErr(403, "Quota reached", nil) return } } err := bus.Dispatch(&cmd) if err != nil { if err == m.ErrDashboardWithSameNameExists { c.JSON(412, util.DynMap{"status": "name-exists", "message": err.Error()}) return } if err == m.ErrDashboardVersionMismatch { c.JSON(412, util.DynMap{"status": "version-mismatch", "message": err.Error()}) return } if err == m.ErrDashboardNotFound { c.JSON(404, util.DynMap{"status": "not-found", "message": err.Error()}) return } c.JsonApiErr(500, "Failed to save dashboard", err) return } metrics.M_Api_Dashboard_Post.Inc(1) c.JSON(200, util.DynMap{"status": "success", "slug": cmd.Result.Slug, "version": cmd.Result.Version, "id": cmd.Result.Id}) }