Merge branch 'develop' into apikey_hashed
Conflicts: pkg/api/apikey.go pkg/services/sqlstore/migrations.go
This commit is contained in:
@@ -1,50 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func GetAccount(c *middleware.Context) {
|
||||
query := m.GetAccountByIdQuery{Id: c.AccountId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if err == m.ErrAccountNotFound {
|
||||
c.JsonApiErr(404, "Account not found", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonApiErr(500, "Failed to get account", err)
|
||||
return
|
||||
}
|
||||
|
||||
account := m.AccountDTO{
|
||||
Id: query.Result.Id,
|
||||
Name: query.Result.Name,
|
||||
}
|
||||
|
||||
c.JSON(200, &account)
|
||||
}
|
||||
|
||||
func CreateAccount(c *middleware.Context, cmd m.CreateAccountCommand) {
|
||||
cmd.UserId = c.UserId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed to create account", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonOK("Account created")
|
||||
}
|
||||
|
||||
func UpdateAccount(c *middleware.Context, cmd m.UpdateAccountCommand) {
|
||||
cmd.AccountId = c.AccountId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed to update account", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonOK("Account updated")
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func AdminGetSettings(c *middleware.Context) {
|
||||
settings := make(map[string]interface{})
|
||||
|
||||
for _, section := range setting.Cfg.Sections() {
|
||||
jsonSec := make(map[string]interface{})
|
||||
settings[section.Name()] = jsonSec
|
||||
|
||||
for _, key := range section.Keys() {
|
||||
keyName := key.Name()
|
||||
value := key.Value()
|
||||
if strings.Contains(keyName, "secret") || strings.Contains(keyName, "password") {
|
||||
value = "************"
|
||||
}
|
||||
|
||||
jsonSec[keyName] = value
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(200, settings)
|
||||
}
|
||||
+138
-5
@@ -1,20 +1,153 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func AdminSearchUsers(c *middleware.Context) {
|
||||
// query := c.QueryStrings("q")
|
||||
// page := c.QueryStrings("p")
|
||||
|
||||
query := m.SearchUsersQuery{Query: "", Page: 0, Limit: 20}
|
||||
query := m.SearchUsersQuery{Query: "", Page: 0, Limit: 1000}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(500, "Failed to fetch collaboratos", err)
|
||||
c.JsonApiErr(500, "Failed to fetch users", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
func AdminGetUser(c *middleware.Context) {
|
||||
userId := c.ParamsInt64(":id")
|
||||
|
||||
query := m.GetUserByIdQuery{Id: userId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(500, "Failed to fetch user", err)
|
||||
return
|
||||
}
|
||||
|
||||
result := m.UserDTO{
|
||||
Name: query.Result.Name,
|
||||
Email: query.Result.Email,
|
||||
Login: query.Result.Login,
|
||||
IsGrafanaAdmin: query.Result.IsAdmin,
|
||||
}
|
||||
|
||||
c.JSON(200, result)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
c.JsonOK("User created")
|
||||
}
|
||||
|
||||
func AdminUpdateUser(c *middleware.Context, form dtos.AdminUpdateUserForm) {
|
||||
userId := c.ParamsInt64(":id")
|
||||
|
||||
cmd := m.UpdateUserCommand{
|
||||
UserId: userId,
|
||||
Login: form.Login,
|
||||
Email: form.Email,
|
||||
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 err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "failed to update user", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonOK("User updated")
|
||||
}
|
||||
|
||||
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 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 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")
|
||||
}
|
||||
|
||||
+29
-15
@@ -25,12 +25,15 @@ func Register(r *macaron.Macaron) {
|
||||
|
||||
// authed views
|
||||
r.Get("/profile/", reqSignedIn, Index)
|
||||
r.Get("/account/", reqSignedIn, Index)
|
||||
r.Get("/account/datasources/", reqSignedIn, Index)
|
||||
r.Get("/account/users/", reqSignedIn, Index)
|
||||
r.Get("/account/apikeys/", reqSignedIn, Index)
|
||||
r.Get("/account/import/", reqSignedIn, Index)
|
||||
r.Get("/org/", reqSignedIn, Index)
|
||||
r.Get("/datasources/", reqSignedIn, Index)
|
||||
r.Get("/org/users/", reqSignedIn, Index)
|
||||
r.Get("/org/apikeys/", reqSignedIn, Index)
|
||||
r.Get("/dashboard/import/", reqSignedIn, Index)
|
||||
r.Get("/admin/settings", reqGrafanaAdmin, Index)
|
||||
r.Get("/admin/users", reqGrafanaAdmin, Index)
|
||||
r.Get("/admin/users/create", reqGrafanaAdmin, Index)
|
||||
r.Get("/admin/users/edit/:id", reqGrafanaAdmin, Index)
|
||||
r.Get("/dashboard/*", reqSignedIn, Index)
|
||||
|
||||
// sign up
|
||||
@@ -43,20 +46,21 @@ func Register(r *macaron.Macaron) {
|
||||
r.Group("/user", func() {
|
||||
r.Get("/", GetUser)
|
||||
r.Put("/", bind(m.UpdateUserCommand{}), UpdateUser)
|
||||
r.Post("/using/:id", SetUsingAccount)
|
||||
r.Get("/accounts", GetUserAccounts)
|
||||
r.Post("/using/:id", UserSetUsingOrg)
|
||||
r.Get("/orgs", GetUserOrgList)
|
||||
r.Post("/stars/dashboard/:id", StarDashboard)
|
||||
r.Delete("/stars/dashboard/:id", UnstarDashboard)
|
||||
r.Put("/password", bind(m.ChangeUserPasswordCommand{}), ChangeUserPassword)
|
||||
})
|
||||
|
||||
// account
|
||||
r.Group("/account", func() {
|
||||
r.Get("/", GetAccount)
|
||||
r.Post("/", bind(m.CreateAccountCommand{}), CreateAccount)
|
||||
r.Put("/", bind(m.UpdateAccountCommand{}), UpdateAccount)
|
||||
r.Post("/users", bind(m.AddAccountUserCommand{}), AddAccountUser)
|
||||
r.Get("/users", GetAccountUsers)
|
||||
r.Delete("/users/:id", RemoveAccountUser)
|
||||
r.Group("/org", func() {
|
||||
r.Get("/", GetOrg)
|
||||
r.Post("/", bind(m.CreateOrgCommand{}), CreateOrg)
|
||||
r.Put("/", bind(m.UpdateOrgCommand{}), UpdateOrg)
|
||||
r.Post("/users", bind(m.AddOrgUserCommand{}), AddOrgUser)
|
||||
r.Get("/users", GetOrgUsers)
|
||||
r.Delete("/users/:id", RemoveOrgUser)
|
||||
}, reqAccountAdmin)
|
||||
|
||||
// auth api keys
|
||||
@@ -70,9 +74,12 @@ func Register(r *macaron.Macaron) {
|
||||
r.Group("/datasources", func() {
|
||||
r.Combo("/").Get(GetDataSources).Put(AddDataSource).Post(UpdateDataSource)
|
||||
r.Delete("/:id", DeleteDataSource)
|
||||
r.Any("/proxy/:id/*", reqSignedIn, ProxyDataSourceRequest)
|
||||
r.Get("/:id", GetDataSourceById)
|
||||
}, reqAccountAdmin)
|
||||
|
||||
r.Get("/frontend/settings/", GetFrontendSettings)
|
||||
r.Any("/datasources/proxy/:id/*", reqSignedIn, ProxyDataSourceRequest)
|
||||
|
||||
// Dashboard
|
||||
r.Group("/dashboards", func() {
|
||||
r.Combo("/db/:slug").Get(GetDashboard).Delete(DeleteDashboard)
|
||||
@@ -89,7 +96,14 @@ func Register(r *macaron.Macaron) {
|
||||
|
||||
// admin api
|
||||
r.Group("/api/admin", func() {
|
||||
r.Get("/settings", AdminGetSettings)
|
||||
r.Get("/users", AdminSearchUsers)
|
||||
r.Get("/users/:id", AdminGetUser)
|
||||
r.Post("/users", bind(dtos.AdminCreateUserForm{}), AdminCreateUser)
|
||||
r.Put("/users/:id/details", bind(dtos.AdminUpdateUserForm{}), AdminUpdateUser)
|
||||
r.Put("/users/:id/password", bind(dtos.AdminUpdateUserPasswordForm{}), AdminUpdateUserPassword)
|
||||
r.Put("/users/:id/permissions", bind(dtos.AdminUpdateUserPermissionsForm{}), AdminUpdateUserPermissions)
|
||||
r.Delete("/users/:id", AdminDeleteUser)
|
||||
}, reqGrafanaAdmin)
|
||||
|
||||
// rendering
|
||||
|
||||
+20
-3
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func GetApiKeys(c *middleware.Context) {
|
||||
query := m.GetApiKeysQuery{AccountId: c.AccountId}
|
||||
query := m.GetApiKeysQuery{OrgId: c.OrgId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(500, "Failed to list api keys", err)
|
||||
@@ -29,7 +29,7 @@ func GetApiKeys(c *middleware.Context) {
|
||||
func DeleteApiKey(c *middleware.Context) {
|
||||
id := c.ParamsInt64(":id")
|
||||
|
||||
cmd := &m.DeleteApiKeyCommand{Id: id, AccountId: c.AccountId}
|
||||
cmd := &m.DeleteApiKeyCommand{Id: id, OrgId: c.OrgId}
|
||||
|
||||
err := bus.Dispatch(cmd)
|
||||
if err != nil {
|
||||
@@ -46,7 +46,7 @@ func AddApiKey(c *middleware.Context, cmd m.AddApiKeyCommand) {
|
||||
return
|
||||
}
|
||||
|
||||
cmd.AccountId = c.AccountId
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.Key = util.GetRandomString(64)
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
@@ -62,3 +62,20 @@ func AddApiKey(c *middleware.Context, cmd m.AddApiKeyCommand) {
|
||||
|
||||
c.JSON(200, result)
|
||||
}
|
||||
|
||||
func UpdateApiKey(c *middleware.Context, cmd m.UpdateApiKeyCommand) {
|
||||
if !cmd.Role.IsValid() {
|
||||
c.JsonApiErr(400, "Invalid role specified", nil)
|
||||
return
|
||||
}
|
||||
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
err := bus.Dispatch(&cmd)
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, "Failed to update api key", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonOK("API key updated")
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ func isDasboardStarredByUser(c *middleware.Context, dashId int64) (bool, error)
|
||||
func GetDashboard(c *middleware.Context) {
|
||||
slug := c.Params(":slug")
|
||||
|
||||
query := m.GetDashboardQuery{Slug: slug, AccountId: c.AccountId}
|
||||
query := m.GetDashboardQuery{Slug: slug, OrgId: c.OrgId}
|
||||
err := bus.Dispatch(&query)
|
||||
if err != nil {
|
||||
c.JsonApiErr(404, "Dashboard not found", nil)
|
||||
@@ -54,13 +54,13 @@ func GetDashboard(c *middleware.Context) {
|
||||
func DeleteDashboard(c *middleware.Context) {
|
||||
slug := c.Params(":slug")
|
||||
|
||||
query := m.GetDashboardQuery{Slug: slug, AccountId: c.AccountId}
|
||||
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, AccountId: c.AccountId}
|
||||
cmd := m.DeleteDashboardCommand{Slug: slug, OrgId: c.OrgId}
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed to delete dashboard", err)
|
||||
return
|
||||
@@ -72,7 +72,7 @@ func DeleteDashboard(c *middleware.Context) {
|
||||
}
|
||||
|
||||
func PostDashboard(c *middleware.Context, cmd m.SaveDashboardCommand) {
|
||||
cmd.AccountId = c.AccountId
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
err := bus.Dispatch(&cmd)
|
||||
if err != nil {
|
||||
|
||||
@@ -17,6 +17,7 @@ func NewReverseProxy(ds *m.DataSource, proxyPath string) *httputil.ReverseProxy
|
||||
director := func(req *http.Request) {
|
||||
req.URL.Scheme = target.Scheme
|
||||
req.URL.Host = target.Host
|
||||
req.Host = target.Host
|
||||
|
||||
reqQueryVals := req.URL.Query()
|
||||
|
||||
@@ -25,6 +26,12 @@ func NewReverseProxy(ds *m.DataSource, proxyPath string) *httputil.ReverseProxy
|
||||
reqQueryVals.Add("u", ds.User)
|
||||
reqQueryVals.Add("p", ds.Password)
|
||||
req.URL.RawQuery = reqQueryVals.Encode()
|
||||
} else if ds.Type == m.DS_INFLUXDB_08 {
|
||||
req.URL.Path = util.JoinUrlFragments(target.Path, proxyPath)
|
||||
reqQueryVals.Add("db", ds.Database)
|
||||
reqQueryVals.Add("u", ds.User)
|
||||
reqQueryVals.Add("p", ds.Password)
|
||||
req.URL.RawQuery = reqQueryVals.Encode()
|
||||
} else {
|
||||
req.URL.Path = util.JoinUrlFragments(target.Path, proxyPath)
|
||||
}
|
||||
@@ -38,8 +45,8 @@ func ProxyDataSourceRequest(c *middleware.Context) {
|
||||
id := c.ParamsInt64(":id")
|
||||
|
||||
query := m.GetDataSourceByIdQuery{
|
||||
Id: id,
|
||||
AccountId: c.AccountId,
|
||||
Id: id,
|
||||
OrgId: c.OrgId,
|
||||
}
|
||||
|
||||
err := bus.Dispatch(&query)
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func TestAccountDataAccess(t *testing.T) {
|
||||
func TestDataSourceProxy(t *testing.T) {
|
||||
|
||||
Convey("When getting graphite datasource proxy", t, func() {
|
||||
ds := m.DataSource{Url: "htttp://graphite:8080", Type: m.DS_GRAPHITE}
|
||||
|
||||
+34
-7
@@ -8,10 +8,9 @@ import (
|
||||
)
|
||||
|
||||
func GetDataSources(c *middleware.Context) {
|
||||
query := m.GetDataSourcesQuery{AccountId: c.AccountId}
|
||||
err := bus.Dispatch(&query)
|
||||
query := m.GetDataSourcesQuery{OrgId: c.OrgId}
|
||||
|
||||
if err != nil {
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(500, "Failed to query datasources", err)
|
||||
return
|
||||
}
|
||||
@@ -20,7 +19,7 @@ func GetDataSources(c *middleware.Context) {
|
||||
for i, ds := range query.Result {
|
||||
result[i] = &dtos.DataSource{
|
||||
Id: ds.Id,
|
||||
AccountId: ds.AccountId,
|
||||
OrgId: ds.OrgId,
|
||||
Name: ds.Name,
|
||||
Url: ds.Url,
|
||||
Type: ds.Type,
|
||||
@@ -36,6 +35,34 @@ func GetDataSources(c *middleware.Context) {
|
||||
c.JSON(200, result)
|
||||
}
|
||||
|
||||
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,
|
||||
IsDefault: ds.IsDefault,
|
||||
})
|
||||
}
|
||||
|
||||
func DeleteDataSource(c *middleware.Context) {
|
||||
id := c.ParamsInt64(":id")
|
||||
|
||||
@@ -44,7 +71,7 @@ func DeleteDataSource(c *middleware.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
cmd := &m.DeleteDataSourceCommand{Id: id, AccountId: c.AccountId}
|
||||
cmd := &m.DeleteDataSourceCommand{Id: id, OrgId: c.OrgId}
|
||||
|
||||
err := bus.Dispatch(cmd)
|
||||
if err != nil {
|
||||
@@ -63,7 +90,7 @@ func AddDataSource(c *middleware.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
cmd.AccountId = c.AccountId
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed to add datasource", err)
|
||||
@@ -81,7 +108,7 @@ func UpdateDataSource(c *middleware.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
cmd.AccountId = c.AccountId
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
err := bus.Dispatch(&cmd)
|
||||
if err != nil {
|
||||
|
||||
@@ -19,8 +19,8 @@ type CurrentUser struct {
|
||||
Login string `json:"login"`
|
||||
Email string `json:"email"`
|
||||
Name string `json:"name"`
|
||||
AccountRole m.RoleType `json:"accountRole"`
|
||||
AccountName string `json:"acountName"`
|
||||
OrgRole m.RoleType `json:"orgRole"`
|
||||
OrgName string `json:"orgName"`
|
||||
IsGrafanaAdmin bool `json:"isGrafanaAdmin"`
|
||||
GravatarUrl string `json:"gravatarUrl"`
|
||||
}
|
||||
@@ -38,7 +38,7 @@ type Dashboard struct {
|
||||
|
||||
type DataSource struct {
|
||||
Id int64 `json:"id"`
|
||||
AccountId int64 `json:"accountId"`
|
||||
OrgId int64 `json:"orgId"`
|
||||
Name string `json:"name"`
|
||||
Type m.DsType `json:"type"`
|
||||
Access m.DsAccess `json:"access"`
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package dtos
|
||||
|
||||
type AdminCreateUserForm struct {
|
||||
Email string `json:"email"`
|
||||
Login string `json:"login"`
|
||||
Name string `json:"name"`
|
||||
Password string `json:"password" binding:"Required"`
|
||||
}
|
||||
|
||||
type AdminUpdateUserForm struct {
|
||||
Email string `json:"email"`
|
||||
Login string `json:"login"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type AdminUpdateUserPasswordForm struct {
|
||||
Password string `json:"password" binding:"Required"`
|
||||
}
|
||||
|
||||
type AdminUpdateUserPermissionsForm struct {
|
||||
IsGrafanaAdmin bool `json:"IsGrafanaAdmin" binding:"Required"`
|
||||
}
|
||||
@@ -9,23 +9,23 @@ import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func getFrontendSettings(c *middleware.Context) (map[string]interface{}, error) {
|
||||
accountDataSources := make([]*m.DataSource, 0)
|
||||
func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, error) {
|
||||
orgDataSources := make([]*m.DataSource, 0)
|
||||
|
||||
if c.IsSignedIn {
|
||||
query := m.GetDataSourcesQuery{AccountId: c.AccountId}
|
||||
query := m.GetDataSourcesQuery{OrgId: c.OrgId}
|
||||
err := bus.Dispatch(&query)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
accountDataSources = query.Result
|
||||
orgDataSources = query.Result
|
||||
}
|
||||
|
||||
datasources := make(map[string]interface{})
|
||||
|
||||
for _, ds := range accountDataSources {
|
||||
for _, ds := range orgDataSources {
|
||||
url := ds.Url
|
||||
|
||||
if ds.Access == m.DS_ACCESS_PROXY {
|
||||
@@ -38,7 +38,7 @@ func getFrontendSettings(c *middleware.Context) (map[string]interface{}, error)
|
||||
"default": ds.IsDefault,
|
||||
}
|
||||
|
||||
if ds.Type == m.DS_INFLUXDB {
|
||||
if ds.Type == m.DS_INFLUXDB_08 {
|
||||
if ds.Access == m.DS_ACCESS_DIRECT {
|
||||
dsMap["username"] = ds.User
|
||||
dsMap["password"] = ds.Password
|
||||
@@ -46,6 +46,15 @@ func getFrontendSettings(c *middleware.Context) (map[string]interface{}, error)
|
||||
}
|
||||
}
|
||||
|
||||
if ds.Type == m.DS_INFLUXDB {
|
||||
if ds.Access == m.DS_ACCESS_DIRECT {
|
||||
dsMap["username"] = ds.User
|
||||
dsMap["password"] = ds.Password
|
||||
dsMap["database"] = ds.Database
|
||||
dsMap["url"] = url
|
||||
}
|
||||
}
|
||||
|
||||
if ds.Type == m.DS_ES {
|
||||
dsMap["index"] = ds.Database
|
||||
}
|
||||
@@ -71,3 +80,13 @@ func getFrontendSettings(c *middleware.Context) (map[string]interface{}, error)
|
||||
|
||||
return jsonObj, nil
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
+3
-3
@@ -7,7 +7,7 @@ import (
|
||||
)
|
||||
|
||||
func setIndexViewData(c *middleware.Context) error {
|
||||
settings, err := getFrontendSettings(c)
|
||||
settings, err := getFrontendSettingsMap(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -17,8 +17,8 @@ func setIndexViewData(c *middleware.Context) error {
|
||||
Login: c.Login,
|
||||
Email: c.Email,
|
||||
Name: c.Name,
|
||||
AccountName: c.AccountName,
|
||||
AccountRole: c.AccountRole,
|
||||
OrgName: c.OrgName,
|
||||
OrgRole: c.OrgRole,
|
||||
GravatarUrl: dtos.GetGravatarUrl(c.Email),
|
||||
IsGrafanaAdmin: c.IsGrafanaAdmin,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func GetOrg(c *middleware.Context) {
|
||||
query := m.GetOrgByIdQuery{Id: c.OrgId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if err == m.ErrOrgNotFound {
|
||||
c.JsonApiErr(404, "Organization not found", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonApiErr(500, "Failed to get organization", err)
|
||||
return
|
||||
}
|
||||
|
||||
org := m.OrgDTO{
|
||||
Id: query.Result.Id,
|
||||
Name: query.Result.Name,
|
||||
}
|
||||
|
||||
c.JSON(200, &org)
|
||||
}
|
||||
|
||||
func CreateOrg(c *middleware.Context, cmd m.CreateOrgCommand) {
|
||||
cmd.UserId = c.UserId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed to create organization", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonOK("Organization created")
|
||||
}
|
||||
|
||||
func UpdateOrg(c *middleware.Context, cmd m.UpdateOrgCommand) {
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed to update organization", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonOK("Organization updated")
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func AddAccountUser(c *middleware.Context, cmd m.AddAccountUserCommand) {
|
||||
func AddOrgUser(c *middleware.Context, cmd m.AddOrgUserCommand) {
|
||||
if !cmd.Role.IsValid() {
|
||||
c.JsonApiErr(400, "Invalid role specified", nil)
|
||||
return
|
||||
@@ -26,19 +26,19 @@ func AddAccountUser(c *middleware.Context, cmd m.AddAccountUserCommand) {
|
||||
return
|
||||
}
|
||||
|
||||
cmd.AccountId = c.AccountId
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.UserId = userToAdd.Id
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Could not add user to account", err)
|
||||
c.JsonApiErr(500, "Could not add user to organization", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonOK("User added to account")
|
||||
c.JsonOK("User added to organization")
|
||||
}
|
||||
|
||||
func GetAccountUsers(c *middleware.Context) {
|
||||
query := m.GetAccountUsersQuery{AccountId: c.AccountId}
|
||||
func GetOrgUsers(c *middleware.Context) {
|
||||
query := m.GetOrgUsersQuery{OrgId: c.OrgId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(500, "Failed to get account user", err)
|
||||
@@ -48,18 +48,18 @@ func GetAccountUsers(c *middleware.Context) {
|
||||
c.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
func RemoveAccountUser(c *middleware.Context) {
|
||||
func RemoveOrgUser(c *middleware.Context) {
|
||||
userId := c.ParamsInt64(":id")
|
||||
|
||||
cmd := m.RemoveAccountUserCommand{AccountId: c.AccountId, UserId: userId}
|
||||
cmd := m.RemoveOrgUserCommand{OrgId: c.OrgId, UserId: userId}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if err == m.ErrLastAccountAdmin {
|
||||
c.JsonApiErr(400, "Cannot remove last account admin", nil)
|
||||
if err == m.ErrLastOrgAdmin {
|
||||
c.JsonApiErr(400, "Cannot remove last organization admin", nil)
|
||||
return
|
||||
}
|
||||
c.JsonApiErr(500, "Failed to remove user from account", err)
|
||||
c.JsonApiErr(500, "Failed to remove user from organization", err)
|
||||
}
|
||||
|
||||
c.JsonOK("User removed from account")
|
||||
c.JsonOK("User removed from organization")
|
||||
}
|
||||
+2
-6
@@ -4,7 +4,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
// TODO: this needs to be cached or improved somehow
|
||||
@@ -45,7 +44,7 @@ func Search(c *middleware.Context) {
|
||||
|
||||
if tagcloud == "true" {
|
||||
|
||||
query := m.GetDashboardTagsQuery{AccountId: c.AccountId}
|
||||
query := m.GetDashboardTagsQuery{OrgId: c.OrgId}
|
||||
err := bus.Dispatch(&query)
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, "Failed to get tags from database", err)
|
||||
@@ -61,7 +60,7 @@ func Search(c *middleware.Context) {
|
||||
UserId: c.UserId,
|
||||
Limit: limit,
|
||||
IsStarred: starred == "true",
|
||||
AccountId: c.AccountId,
|
||||
OrgId: c.OrgId,
|
||||
}
|
||||
|
||||
err := bus.Dispatch(&query)
|
||||
@@ -76,9 +75,6 @@ func Search(c *middleware.Context) {
|
||||
}
|
||||
|
||||
result.Dashboards = query.Result
|
||||
for _, dash := range result.Dashboards {
|
||||
dash.Url = setting.ToAbsUrl("dashboard/db/" + dash.Slug)
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(200, result)
|
||||
|
||||
+51
-20
@@ -4,13 +4,14 @@ import (
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func GetUser(c *middleware.Context) {
|
||||
query := m.GetUserInfoQuery{UserId: c.UserId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(500, "Failed to get account", err)
|
||||
c.JsonApiErr(500, "Failed to get user", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -21,23 +22,23 @@ func UpdateUser(c *middleware.Context, cmd m.UpdateUserCommand) {
|
||||
cmd.UserId = c.UserId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(400, "Failed to update account", err)
|
||||
c.JsonApiErr(400, "Failed to update user", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonOK("Account updated")
|
||||
c.JsonOK("User updated")
|
||||
}
|
||||
|
||||
func GetUserAccounts(c *middleware.Context) {
|
||||
query := m.GetUserAccountsQuery{UserId: c.UserId}
|
||||
func GetUserOrgList(c *middleware.Context) {
|
||||
query := m.GetUserOrgListQuery{UserId: c.UserId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(500, "Failed to get user accounts", err)
|
||||
c.JsonApiErr(500, "Failed to get user organizations", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, ac := range query.Result {
|
||||
if ac.AccountId == c.AccountId {
|
||||
if ac.OrgId == c.OrgId {
|
||||
ac.IsUsing = true
|
||||
break
|
||||
}
|
||||
@@ -46,17 +47,17 @@ func GetUserAccounts(c *middleware.Context) {
|
||||
c.JSON(200, query.Result)
|
||||
}
|
||||
|
||||
func validateUsingAccount(userId int64, accountId int64) bool {
|
||||
query := m.GetUserAccountsQuery{UserId: userId}
|
||||
func validateUsingOrg(userId int64, orgId int64) bool {
|
||||
query := m.GetUserOrgListQuery{UserId: userId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// validate that the account id in the list
|
||||
// validate that the org id in the list
|
||||
valid := false
|
||||
for _, other := range query.Result {
|
||||
if other.AccountId == accountId {
|
||||
if other.OrgId == orgId {
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
@@ -64,23 +65,53 @@ func validateUsingAccount(userId int64, accountId int64) bool {
|
||||
return valid
|
||||
}
|
||||
|
||||
func SetUsingAccount(c *middleware.Context) {
|
||||
usingAccountId := c.ParamsInt64(":id")
|
||||
func UserSetUsingOrg(c *middleware.Context) {
|
||||
orgId := c.ParamsInt64(":id")
|
||||
|
||||
if !validateUsingAccount(c.UserId, usingAccountId) {
|
||||
c.JsonApiErr(401, "Not a valid account", nil)
|
||||
if !validateUsingOrg(c.UserId, orgId) {
|
||||
c.JsonApiErr(401, "Not a valid organization", nil)
|
||||
return
|
||||
}
|
||||
|
||||
cmd := m.SetUsingAccountCommand{
|
||||
UserId: c.UserId,
|
||||
AccountId: usingAccountId,
|
||||
cmd := m.SetUsingOrgCommand{
|
||||
UserId: c.UserId,
|
||||
OrgId: orgId,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed change active account", err)
|
||||
c.JsonApiErr(500, "Failed change active organization", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonOK("Active account changed")
|
||||
c.JsonOK("Active organization changed")
|
||||
}
|
||||
|
||||
func ChangeUserPassword(c *middleware.Context, cmd m.ChangeUserPasswordCommand) {
|
||||
userQuery := m.GetUserByIdQuery{Id: c.UserId}
|
||||
|
||||
if err := bus.Dispatch(&userQuery); err != nil {
|
||||
c.JsonApiErr(500, "Could not read user from database", err)
|
||||
return
|
||||
}
|
||||
|
||||
passwordHashed := util.EncodePassword(cmd.OldPassword, userQuery.Result.Salt)
|
||||
if passwordHashed != userQuery.Result.Password {
|
||||
c.JsonApiErr(401, "Invalid old password", nil)
|
||||
return
|
||||
}
|
||||
|
||||
if len(cmd.NewPassword) < 4 {
|
||||
c.JsonApiErr(400, "New password too short", nil)
|
||||
return
|
||||
}
|
||||
|
||||
cmd.UserId = c.UserId
|
||||
cmd.NewPassword = util.EncodePassword(cmd.NewPassword, userQuery.Result.Salt)
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed to change user password", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonOK("User password changed")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user