Merge branch 'develop' into apikey_hashed

Conflicts:
	pkg/api/apikey.go
	pkg/services/sqlstore/migrations.go
This commit is contained in:
Torkel Ödegaard
2015-02-26 15:48:54 +01:00
226 changed files with 6360 additions and 5676 deletions
-50
View File
@@ -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")
}
+29
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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")
}
+4 -4
View File
@@ -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 {
+9 -2
View File
@@ -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)
+1 -1
View File
@@ -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
View File
@@ -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 {
+3 -3
View File
@@ -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"`
+22
View File
@@ -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"`
}
+25 -6
View File
@@ -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
View File
@@ -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,
}
+50
View File
@@ -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
View File
@@ -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
View File
@@ -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")
}