Merge branch 'master' into ldap
This commit is contained in:
@@ -17,7 +17,7 @@ func AdminGetSettings(c *middleware.Context) {
|
||||
for _, key := range section.Keys() {
|
||||
keyName := key.Name()
|
||||
value := key.Value()
|
||||
if strings.Contains(keyName, "secret") || strings.Contains(keyName, "password") {
|
||||
if strings.Contains(keyName, "secret") || strings.Contains(keyName, "password") || (strings.Contains(keyName, "provider_config") && strings.Contains(value, "@")) {
|
||||
value = "************"
|
||||
}
|
||||
|
||||
|
||||
@@ -9,36 +9,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func AdminSearchUsers(c *middleware.Context) {
|
||||
query := m.SearchUsersQuery{Query: "", Page: 0, Limit: 1000}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
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 := dtos.AdminUserListItem{
|
||||
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,
|
||||
@@ -70,32 +40,6 @@ func AdminCreateUser(c *middleware.Context, form dtos.AdminCreateUserForm) {
|
||||
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")
|
||||
|
||||
|
||||
+51
-31
@@ -13,7 +13,7 @@ func Register(r *macaron.Macaron) {
|
||||
reqSignedIn := middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true})
|
||||
reqGrafanaAdmin := middleware.Auth(&middleware.AuthOptions{ReqSignedIn: true, ReqGrafanaAdmin: true})
|
||||
reqEditorRole := middleware.RoleAuth(m.ROLE_EDITOR, m.ROLE_ADMIN)
|
||||
reqAccountAdmin := middleware.RoleAuth(m.ROLE_ADMIN)
|
||||
regOrgAdmin := middleware.RoleAuth(m.ROLE_ADMIN)
|
||||
bind := binding.Bind
|
||||
|
||||
// not logged in views
|
||||
@@ -53,48 +53,71 @@ func Register(r *macaron.Macaron) {
|
||||
|
||||
// authed api
|
||||
r.Group("/api", func() {
|
||||
// user
|
||||
|
||||
// user (signed in)
|
||||
r.Group("/user", func() {
|
||||
r.Get("/", GetUser)
|
||||
r.Put("/", bind(m.UpdateUserCommand{}), UpdateUser)
|
||||
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)
|
||||
r.Get("/", wrap(GetSignedInUser))
|
||||
r.Put("/", bind(m.UpdateUserCommand{}), wrap(UpdateSignedInUser))
|
||||
r.Post("/using/:id", wrap(UserSetUsingOrg))
|
||||
r.Get("/orgs", wrap(GetSignedInUserOrgList))
|
||||
r.Post("/stars/dashboard/:id", wrap(StarDashboard))
|
||||
r.Delete("/stars/dashboard/:id", wrap(UnstarDashboard))
|
||||
r.Put("/password", bind(m.ChangeUserPasswordCommand{}), wrap(ChangeUserPassword))
|
||||
})
|
||||
|
||||
// account
|
||||
// users (admin permission required)
|
||||
r.Group("/users", func() {
|
||||
r.Get("/", wrap(SearchUsers))
|
||||
r.Get("/:id", wrap(GetUserById))
|
||||
r.Get("/:id/orgs", wrap(GetUserOrgList))
|
||||
r.Put("/:id", bind(m.UpdateUserCommand{}), wrap(UpdateUser))
|
||||
}, reqGrafanaAdmin)
|
||||
|
||||
// current org
|
||||
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.Patch("/users/:id", bind(m.UpdateOrgUserCommand{}), UpdateOrgUser)
|
||||
r.Delete("/users/:id", RemoveOrgUser)
|
||||
}, reqAccountAdmin)
|
||||
r.Get("/", wrap(GetOrgCurrent))
|
||||
r.Put("/", bind(m.UpdateOrgCommand{}), wrap(UpdateOrgCurrent))
|
||||
r.Post("/users", bind(m.AddOrgUserCommand{}), wrap(AddOrgUserToCurrentOrg))
|
||||
r.Get("/users", wrap(GetOrgUsersForCurrentOrg))
|
||||
r.Patch("/users/:userId", bind(m.UpdateOrgUserCommand{}), wrap(UpdateOrgUserForCurrentOrg))
|
||||
r.Delete("/users/:userId", wrap(RemoveOrgUserForCurrentOrg))
|
||||
}, regOrgAdmin)
|
||||
|
||||
// create new org
|
||||
r.Post("/orgs", bind(m.CreateOrgCommand{}), wrap(CreateOrg))
|
||||
|
||||
// search all orgs
|
||||
r.Get("/orgs", reqGrafanaAdmin, wrap(SearchOrgs))
|
||||
|
||||
// orgs (admin routes)
|
||||
r.Group("/orgs/:orgId", func() {
|
||||
r.Put("/", bind(m.UpdateOrgCommand{}), wrap(UpdateOrg))
|
||||
r.Get("/users", wrap(GetOrgUsers))
|
||||
r.Post("/users", bind(m.AddOrgUserCommand{}), wrap(AddOrgUser))
|
||||
r.Patch("/users/:userId", bind(m.UpdateOrgUserCommand{}), wrap(UpdateOrgUser))
|
||||
r.Delete("/users/:userId", wrap(RemoveOrgUser))
|
||||
}, reqGrafanaAdmin)
|
||||
|
||||
// auth api keys
|
||||
r.Group("/auth/keys", func() {
|
||||
r.Get("/", GetApiKeys)
|
||||
r.Post("/", bind(m.AddApiKeyCommand{}), AddApiKey)
|
||||
r.Delete("/:id", DeleteApiKey)
|
||||
}, reqAccountAdmin)
|
||||
r.Get("/", wrap(GetApiKeys))
|
||||
r.Post("/", bind(m.AddApiKeyCommand{}), wrap(AddApiKey))
|
||||
r.Delete("/:id", wrap(DeleteApiKey))
|
||||
}, regOrgAdmin)
|
||||
|
||||
// Data sources
|
||||
r.Group("/datasources", func() {
|
||||
r.Combo("/").
|
||||
Get(GetDataSources).
|
||||
Put(bind(m.AddDataSourceCommand{}), AddDataSource).
|
||||
Post(bind(m.UpdateDataSourceCommand{}), UpdateDataSource)
|
||||
r.Get("/", GetDataSources)
|
||||
r.Post("/", bind(m.AddDataSourceCommand{}), AddDataSource)
|
||||
r.Put("/:id", bind(m.UpdateDataSourceCommand{}), UpdateDataSource)
|
||||
r.Delete("/:id", DeleteDataSource)
|
||||
r.Get("/:id", GetDataSourceById)
|
||||
r.Get("/plugins", GetDataSourcePlugins)
|
||||
}, reqAccountAdmin)
|
||||
}, regOrgAdmin)
|
||||
|
||||
r.Get("/frontend/settings/", GetFrontendSettings)
|
||||
r.Any("/datasources/proxy/:id/*", reqSignedIn, ProxyDataSourceRequest)
|
||||
r.Any("/datasources/proxy/:id", reqSignedIn, ProxyDataSourceRequest)
|
||||
|
||||
// Dashboard
|
||||
r.Group("/dashboards", func() {
|
||||
@@ -115,10 +138,7 @@ 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)
|
||||
@@ -127,5 +147,5 @@ func Register(r *macaron.Macaron) {
|
||||
// rendering
|
||||
r.Get("/render/*", reqSignedIn, RenderToPng)
|
||||
|
||||
r.NotFound(NotFound)
|
||||
r.NotFound(NotFoundHandler)
|
||||
}
|
||||
|
||||
+12
-16
@@ -8,12 +8,11 @@ import (
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func GetApiKeys(c *middleware.Context) {
|
||||
func GetApiKeys(c *middleware.Context) Response {
|
||||
query := m.GetApiKeysQuery{OrgId: c.OrgId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(500, "Failed to list api keys", err)
|
||||
return
|
||||
return ApiError(500, "Failed to list api keys", err)
|
||||
}
|
||||
|
||||
result := make([]*m.ApiKeyDTO, len(query.Result))
|
||||
@@ -24,27 +23,26 @@ func GetApiKeys(c *middleware.Context) {
|
||||
Role: t.Role,
|
||||
}
|
||||
}
|
||||
c.JSON(200, result)
|
||||
|
||||
return Json(200, result)
|
||||
}
|
||||
|
||||
func DeleteApiKey(c *middleware.Context) {
|
||||
func DeleteApiKey(c *middleware.Context) Response {
|
||||
id := c.ParamsInt64(":id")
|
||||
|
||||
cmd := &m.DeleteApiKeyCommand{Id: id, OrgId: c.OrgId}
|
||||
|
||||
err := bus.Dispatch(cmd)
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, "Failed to delete API key", err)
|
||||
return
|
||||
return ApiError(500, "Failed to delete API key", err)
|
||||
}
|
||||
|
||||
c.JsonOK("API key deleted")
|
||||
return ApiSuccess("API key deleted")
|
||||
}
|
||||
|
||||
func AddApiKey(c *middleware.Context, cmd m.AddApiKeyCommand) {
|
||||
func AddApiKey(c *middleware.Context, cmd m.AddApiKeyCommand) Response {
|
||||
if !cmd.Role.IsValid() {
|
||||
c.JsonApiErr(400, "Invalid role specified", nil)
|
||||
return
|
||||
return ApiError(400, "Invalid role specified", nil)
|
||||
}
|
||||
|
||||
cmd.OrgId = c.OrgId
|
||||
@@ -53,14 +51,12 @@ func AddApiKey(c *middleware.Context, cmd m.AddApiKeyCommand) {
|
||||
cmd.Key = newKeyInfo.HashedKey
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed to add API key", err)
|
||||
return
|
||||
return ApiError(500, "Failed to add API key", err)
|
||||
}
|
||||
|
||||
result := &dtos.NewApiKeyResult{
|
||||
Name: cmd.Result.Name,
|
||||
Key: newKeyInfo.ClientSecret,
|
||||
}
|
||||
Key: newKeyInfo.ClientSecret}
|
||||
|
||||
c.JSON(200, result)
|
||||
return Json(200, result)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/Unknwon/macaron"
|
||||
"github.com/grafana/grafana/pkg/log"
|
||||
"github.com/grafana/grafana/pkg/metrics"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
var (
|
||||
NotFound = ApiError(404, "Not found", nil)
|
||||
ServerError = ApiError(500, "Server error", nil)
|
||||
)
|
||||
|
||||
type Response interface {
|
||||
WriteTo(out http.ResponseWriter)
|
||||
}
|
||||
|
||||
type NormalResponse struct {
|
||||
status int
|
||||
body []byte
|
||||
header http.Header
|
||||
}
|
||||
|
||||
func wrap(action interface{}) macaron.Handler {
|
||||
|
||||
return func(c *middleware.Context) {
|
||||
var res Response
|
||||
val, err := c.Invoke(action)
|
||||
if err == nil && val != nil && len(val) > 0 {
|
||||
res = val[0].Interface().(Response)
|
||||
} else {
|
||||
res = ServerError
|
||||
}
|
||||
|
||||
res.WriteTo(c.Resp)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *NormalResponse) WriteTo(out http.ResponseWriter) {
|
||||
header := out.Header()
|
||||
for k, v := range r.header {
|
||||
header[k] = v
|
||||
}
|
||||
out.WriteHeader(r.status)
|
||||
out.Write(r.body)
|
||||
}
|
||||
|
||||
func (r *NormalResponse) Cache(ttl string) *NormalResponse {
|
||||
return r.Header("Cache-Control", "public,max-age="+ttl)
|
||||
}
|
||||
|
||||
func (r *NormalResponse) Header(key, value string) *NormalResponse {
|
||||
r.header.Set(key, value)
|
||||
return r
|
||||
}
|
||||
|
||||
// functions to create responses
|
||||
|
||||
func Empty(status int) *NormalResponse {
|
||||
return Respond(status, nil)
|
||||
}
|
||||
|
||||
func Json(status int, body interface{}) *NormalResponse {
|
||||
return Respond(status, body).Header("Content-Type", "application/json")
|
||||
}
|
||||
|
||||
func ApiSuccess(message string) *NormalResponse {
|
||||
resp := make(map[string]interface{})
|
||||
resp["message"] = message
|
||||
return Respond(200, resp)
|
||||
}
|
||||
|
||||
func ApiError(status int, message string, err error) *NormalResponse {
|
||||
resp := make(map[string]interface{})
|
||||
|
||||
if err != nil {
|
||||
log.Error(4, "%s: %v", message, err)
|
||||
if setting.Env != setting.PROD {
|
||||
resp["error"] = err.Error()
|
||||
}
|
||||
}
|
||||
|
||||
switch status {
|
||||
case 404:
|
||||
resp["message"] = "Not Found"
|
||||
metrics.M_Api_Status_500.Inc(1)
|
||||
case 500:
|
||||
metrics.M_Api_Status_404.Inc(1)
|
||||
resp["message"] = "Internal Server Error"
|
||||
}
|
||||
|
||||
if message != "" {
|
||||
resp["message"] = message
|
||||
}
|
||||
|
||||
return Json(status, resp)
|
||||
}
|
||||
|
||||
func Respond(status int, body interface{}) *NormalResponse {
|
||||
var b []byte
|
||||
var err error
|
||||
switch t := body.(type) {
|
||||
case []byte:
|
||||
b = t
|
||||
case string:
|
||||
b = []byte(t)
|
||||
default:
|
||||
if b, err = json.Marshal(body); err != nil {
|
||||
return ApiError(500, "body json marshal", err)
|
||||
}
|
||||
}
|
||||
return &NormalResponse{
|
||||
body: b,
|
||||
status: status,
|
||||
header: make(http.Header),
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,7 @@ func GetDashboard(c *middleware.Context) {
|
||||
Type: m.DashTypeDB,
|
||||
CanStar: c.IsSignedIn,
|
||||
CanSave: c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR,
|
||||
CanEdit: c.OrgRole == m.ROLE_ADMIN || c.OrgRole == m.ROLE_EDITOR || c.OrgRole == m.ROLE_READ_ONLY_EDITOR,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
@@ -11,6 +14,16 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
var dataProxyTransport = &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
}
|
||||
|
||||
func NewReverseProxy(ds *m.DataSource, proxyPath string) *httputil.ReverseProxy {
|
||||
target, _ := url.Parse(ds.Url)
|
||||
|
||||
@@ -56,5 +69,6 @@ func ProxyDataSourceRequest(c *middleware.Context) {
|
||||
|
||||
proxyPath := c.Params("*")
|
||||
proxy := NewReverseProxy(&query.Result, proxyPath)
|
||||
proxy.Transport = dataProxyTransport
|
||||
proxy.ServeHTTP(c.RW(), c.Req.Request)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/middleware"
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func GetDataSources(c *middleware.Context) {
|
||||
@@ -94,11 +95,12 @@ func AddDataSource(c *middleware.Context, cmd m.AddDataSourceCommand) {
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonOK("Datasource added")
|
||||
c.JSON(200, util.DynMap{"message": "Datasource added", "id": cmd.Result.Id})
|
||||
}
|
||||
|
||||
func UpdateDataSource(c *middleware.Context, cmd m.UpdateDataSourceCommand) {
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.Id = c.ParamsInt64(":id")
|
||||
|
||||
err := bus.Dispatch(&cmd)
|
||||
if err != nil {
|
||||
|
||||
@@ -34,6 +34,7 @@ type DashboardMeta struct {
|
||||
IsSnapshot bool `json:"isSnapshot,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
CanSave bool `json:"canSave"`
|
||||
CanEdit bool `json:"canEdit"`
|
||||
CanStar bool `json:"canStar"`
|
||||
Slug string `json:"slug"`
|
||||
Expires time.Time `json:"expires"`
|
||||
|
||||
@@ -54,6 +54,10 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
|
||||
defaultDatasource = ds.Name
|
||||
}
|
||||
|
||||
if len(ds.JsonData) > 0 {
|
||||
dsMap["jsonData"] = ds.JsonData
|
||||
}
|
||||
|
||||
if ds.Access == m.DS_ACCESS_DIRECT {
|
||||
if ds.BasicAuth {
|
||||
dsMap["basicAuth"] = util.GetBasicAuthHeader(ds.BasicAuthUser, ds.BasicAuthPassword)
|
||||
@@ -95,6 +99,7 @@ func getFrontendSettingsMap(c *middleware.Context) (map[string]interface{}, erro
|
||||
"defaultDatasource": defaultDatasource,
|
||||
"datasources": datasources,
|
||||
"appSubUrl": setting.AppSubUrl,
|
||||
"viewerRoleMode": setting.ViewerRoleMode,
|
||||
"buildInfo": map[string]interface{}{
|
||||
"version": setting.BuildVersion,
|
||||
"commit": setting.BuildCommit,
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ func Index(c *middleware.Context) {
|
||||
c.HTML(200, "index")
|
||||
}
|
||||
|
||||
func NotFound(c *middleware.Context) {
|
||||
func NotFoundHandler(c *middleware.Context) {
|
||||
if c.IsApiRequest() {
|
||||
c.JsonApiErr(404, "Not found", nil)
|
||||
return
|
||||
|
||||
@@ -48,6 +48,8 @@ func OAuthLogin(ctx *middleware.Context) {
|
||||
if err != nil {
|
||||
if err == social.ErrMissingTeamMembership {
|
||||
ctx.Redirect(setting.AppSubUrl + "/login?failedMsg=" + url.QueryEscape("Required Github team membership not fulfilled"))
|
||||
} else if err == social.ErrMissingOrganizationMembership {
|
||||
ctx.Redirect(setting.AppSubUrl + "/login?failedMsg=" + url.QueryEscape("Required Github organization membership not fulfilled"))
|
||||
} else {
|
||||
ctx.Handle(500, fmt.Sprintf("login.OAuthLogin(get info from %s)", name), err)
|
||||
}
|
||||
|
||||
+48
-17
@@ -8,17 +8,25 @@ import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func GetOrg(c *middleware.Context) {
|
||||
query := m.GetOrgByIdQuery{Id: c.OrgId}
|
||||
// GET /api/org
|
||||
func GetOrgCurrent(c *middleware.Context) Response {
|
||||
return getOrgHelper(c.OrgId)
|
||||
}
|
||||
|
||||
// GET /api/orgs/:orgId
|
||||
func GetOrgById(c *middleware.Context) Response {
|
||||
return getOrgHelper(c.ParamsInt64(":orgId"))
|
||||
}
|
||||
|
||||
func getOrgHelper(orgId int64) Response {
|
||||
query := m.GetOrgByIdQuery{Id: orgId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if err == m.ErrOrgNotFound {
|
||||
c.JsonApiErr(404, "Organization not found", err)
|
||||
return
|
||||
return ApiError(404, "Organization not found", err)
|
||||
}
|
||||
|
||||
c.JsonApiErr(500, "Failed to get organization", err)
|
||||
return
|
||||
return ApiError(500, "Failed to get organization", err)
|
||||
}
|
||||
|
||||
org := m.OrgDTO{
|
||||
@@ -26,33 +34,56 @@ func GetOrg(c *middleware.Context) {
|
||||
Name: query.Result.Name,
|
||||
}
|
||||
|
||||
c.JSON(200, &org)
|
||||
return Json(200, &org)
|
||||
}
|
||||
|
||||
func CreateOrg(c *middleware.Context, cmd m.CreateOrgCommand) {
|
||||
// POST /api/orgs
|
||||
func CreateOrg(c *middleware.Context, cmd m.CreateOrgCommand) Response {
|
||||
if !setting.AllowUserOrgCreate && !c.IsGrafanaAdmin {
|
||||
c.JsonApiErr(401, "Access denied", nil)
|
||||
return
|
||||
return ApiError(401, "Access denied", nil)
|
||||
}
|
||||
|
||||
cmd.UserId = c.UserId
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed to create organization", err)
|
||||
return
|
||||
return ApiError(500, "Failed to create organization", err)
|
||||
}
|
||||
|
||||
metrics.M_Api_Org_Create.Inc(1)
|
||||
|
||||
c.JsonOK("Organization created")
|
||||
return ApiSuccess("Organization created")
|
||||
}
|
||||
|
||||
func UpdateOrg(c *middleware.Context, cmd m.UpdateOrgCommand) {
|
||||
// PUT /api/org
|
||||
func UpdateOrgCurrent(c *middleware.Context, cmd m.UpdateOrgCommand) Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
return updateOrgHelper(cmd)
|
||||
}
|
||||
|
||||
// PUT /api/orgs/:orgId
|
||||
func UpdateOrg(c *middleware.Context, cmd m.UpdateOrgCommand) Response {
|
||||
cmd.OrgId = c.ParamsInt64(":orgId")
|
||||
return updateOrgHelper(cmd)
|
||||
}
|
||||
|
||||
func updateOrgHelper(cmd m.UpdateOrgCommand) Response {
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed to update organization", err)
|
||||
return
|
||||
return ApiError(500, "Failed to update organization", err)
|
||||
}
|
||||
|
||||
c.JsonOK("Organization updated")
|
||||
return ApiSuccess("Organization updated")
|
||||
}
|
||||
|
||||
func SearchOrgs(c *middleware.Context) Response {
|
||||
query := m.SearchOrgsQuery{
|
||||
Query: c.Query("query"),
|
||||
Name: c.Query("name"),
|
||||
Page: 0,
|
||||
Limit: 1000,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return ApiError(500, "Failed to search orgs", err)
|
||||
}
|
||||
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
+77
-39
@@ -6,77 +6,115 @@ import (
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func AddOrgUser(c *middleware.Context, cmd m.AddOrgUserCommand) {
|
||||
// POST /api/org/users
|
||||
func AddOrgUserToCurrentOrg(c *middleware.Context, cmd m.AddOrgUserCommand) Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
return addOrgUserHelper(cmd)
|
||||
}
|
||||
|
||||
// POST /api/orgs/:orgId/users
|
||||
func AddOrgUser(c *middleware.Context, cmd m.AddOrgUserCommand) Response {
|
||||
cmd.OrgId = c.ParamsInt64(":orgId")
|
||||
return addOrgUserHelper(cmd)
|
||||
}
|
||||
|
||||
func addOrgUserHelper(cmd m.AddOrgUserCommand) Response {
|
||||
if !cmd.Role.IsValid() {
|
||||
c.JsonApiErr(400, "Invalid role specified", nil)
|
||||
return
|
||||
return ApiError(400, "Invalid role specified", nil)
|
||||
}
|
||||
|
||||
userQuery := m.GetUserByLoginQuery{LoginOrEmail: cmd.LoginOrEmail}
|
||||
err := bus.Dispatch(&userQuery)
|
||||
if err != nil {
|
||||
c.JsonApiErr(404, "User not found", nil)
|
||||
return
|
||||
return ApiError(404, "User not found", nil)
|
||||
}
|
||||
|
||||
userToAdd := userQuery.Result
|
||||
|
||||
if userToAdd.Id == c.UserId {
|
||||
c.JsonApiErr(400, "Cannot add yourself as user", nil)
|
||||
return
|
||||
}
|
||||
// if userToAdd.Id == c.UserId {
|
||||
// return ApiError(400, "Cannot add yourself as user", nil)
|
||||
// }
|
||||
|
||||
cmd.OrgId = c.OrgId
|
||||
cmd.UserId = userToAdd.Id
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Could not add user to organization", err)
|
||||
return
|
||||
return ApiError(500, "Could not add user to organization", err)
|
||||
}
|
||||
|
||||
c.JsonOK("User added to organization")
|
||||
return ApiSuccess("User added to organization")
|
||||
}
|
||||
|
||||
func GetOrgUsers(c *middleware.Context) {
|
||||
query := m.GetOrgUsersQuery{OrgId: c.OrgId}
|
||||
// GET /api/org/users
|
||||
func GetOrgUsersForCurrentOrg(c *middleware.Context) Response {
|
||||
return getOrgUsersHelper(c.OrgId)
|
||||
}
|
||||
|
||||
// GET /api/orgs/:orgId/users
|
||||
func GetOrgUsers(c *middleware.Context) Response {
|
||||
return getOrgUsersHelper(c.ParamsInt64(":orgId"))
|
||||
}
|
||||
|
||||
func getOrgUsersHelper(orgId int64) Response {
|
||||
query := m.GetOrgUsersQuery{OrgId: orgId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(500, "Failed to get account user", err)
|
||||
return
|
||||
return ApiError(500, "Failed to get account user", err)
|
||||
}
|
||||
|
||||
c.JSON(200, query.Result)
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
func UpdateOrgUser(c *middleware.Context, cmd m.UpdateOrgUserCommand) {
|
||||
if !cmd.Role.IsValid() {
|
||||
c.JsonApiErr(400, "Invalid role specified", nil)
|
||||
return
|
||||
}
|
||||
|
||||
cmd.UserId = c.ParamsInt64(":id")
|
||||
// PATCH /api/org/users/:userId
|
||||
func UpdateOrgUserForCurrentOrg(c *middleware.Context, cmd m.UpdateOrgUserCommand) Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed update org user", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonOK("Organization user updated")
|
||||
cmd.UserId = c.ParamsInt64(":userId")
|
||||
return updateOrgUserHelper(cmd)
|
||||
}
|
||||
|
||||
func RemoveOrgUser(c *middleware.Context) {
|
||||
userId := c.ParamsInt64(":id")
|
||||
// PATCH /api/orgs/:orgId/users/:userId
|
||||
func UpdateOrgUser(c *middleware.Context, cmd m.UpdateOrgUserCommand) Response {
|
||||
cmd.OrgId = c.ParamsInt64(":orgId")
|
||||
cmd.UserId = c.ParamsInt64(":userId")
|
||||
return updateOrgUserHelper(cmd)
|
||||
}
|
||||
|
||||
cmd := m.RemoveOrgUserCommand{OrgId: c.OrgId, UserId: userId}
|
||||
func updateOrgUserHelper(cmd m.UpdateOrgUserCommand) Response {
|
||||
if !cmd.Role.IsValid() {
|
||||
return ApiError(400, "Invalid role specified", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if err == m.ErrLastOrgAdmin {
|
||||
c.JsonApiErr(400, "Cannot remove last organization admin", nil)
|
||||
return
|
||||
return ApiError(400, "Cannot change role so that there is no organization admin left", nil)
|
||||
}
|
||||
c.JsonApiErr(500, "Failed to remove user from organization", err)
|
||||
return ApiError(500, "Failed update org user", err)
|
||||
}
|
||||
|
||||
c.JsonOK("User removed from organization")
|
||||
return ApiSuccess("Organization user updated")
|
||||
}
|
||||
|
||||
// DELETE /api/org/users/:userId
|
||||
func RemoveOrgUserForCurrentOrg(c *middleware.Context) Response {
|
||||
userId := c.ParamsInt64(":userId")
|
||||
return removeOrgUserHelper(c.OrgId, userId)
|
||||
}
|
||||
|
||||
// DELETE /api/orgs/:orgId/users/:userId
|
||||
func RemoveOrgUser(c *middleware.Context) Response {
|
||||
userId := c.ParamsInt64(":userId")
|
||||
orgId := c.ParamsInt64(":orgId")
|
||||
return removeOrgUserHelper(orgId, userId)
|
||||
}
|
||||
|
||||
func removeOrgUserHelper(orgId int64, userId int64) Response {
|
||||
cmd := m.RemoveOrgUserCommand{OrgId: orgId, UserId: userId}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if err == m.ErrLastOrgAdmin {
|
||||
return ApiError(400, "Cannot remove last organization admin", nil)
|
||||
}
|
||||
return ApiError(500, "Failed to remove user from organization", err)
|
||||
}
|
||||
|
||||
return ApiSuccess("User removed from organization")
|
||||
}
|
||||
|
||||
+3
-3
@@ -8,17 +8,17 @@ import (
|
||||
|
||||
func Search(c *middleware.Context) {
|
||||
query := c.Query("query")
|
||||
tag := c.Query("tag")
|
||||
tags := c.QueryStrings("tag")
|
||||
starred := c.Query("starred")
|
||||
limit := c.QueryInt("limit")
|
||||
|
||||
if limit == 0 {
|
||||
limit = 200
|
||||
limit = 1000
|
||||
}
|
||||
|
||||
searchQuery := search.Query{
|
||||
Title: query,
|
||||
Tag: tag,
|
||||
Tags: tags,
|
||||
UserId: c.UserId,
|
||||
Limit: limit,
|
||||
IsStarred: starred == "true",
|
||||
|
||||
+12
-22
@@ -6,45 +6,35 @@ import (
|
||||
m "github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func StarDashboard(c *middleware.Context) {
|
||||
func StarDashboard(c *middleware.Context) Response {
|
||||
if !c.IsSignedIn {
|
||||
c.JsonApiErr(412, "You need to sign in to star dashboards", nil)
|
||||
return
|
||||
return ApiError(412, "You need to sign in to star dashboards", nil)
|
||||
}
|
||||
|
||||
var cmd = m.StarDashboardCommand{
|
||||
UserId: c.UserId,
|
||||
DashboardId: c.ParamsInt64(":id"),
|
||||
}
|
||||
cmd := m.StarDashboardCommand{UserId: c.UserId, DashboardId: c.ParamsInt64(":id")}
|
||||
|
||||
if cmd.DashboardId <= 0 {
|
||||
c.JsonApiErr(400, "Missing dashboard id", nil)
|
||||
return
|
||||
return ApiError(400, "Missing dashboard id", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed to star dashboard", err)
|
||||
return
|
||||
return ApiError(500, "Failed to star dashboard", err)
|
||||
}
|
||||
|
||||
c.JsonOK("Dashboard starred!")
|
||||
return ApiSuccess("Dashboard starred!")
|
||||
}
|
||||
|
||||
func UnstarDashboard(c *middleware.Context) {
|
||||
var cmd = m.UnstarDashboardCommand{
|
||||
UserId: c.UserId,
|
||||
DashboardId: c.ParamsInt64(":id"),
|
||||
}
|
||||
func UnstarDashboard(c *middleware.Context) Response {
|
||||
|
||||
cmd := m.UnstarDashboardCommand{UserId: c.UserId, DashboardId: c.ParamsInt64(":id")}
|
||||
|
||||
if cmd.DashboardId <= 0 {
|
||||
c.JsonApiErr(400, "Missing dashboard id", nil)
|
||||
return
|
||||
return ApiError(400, "Missing dashboard id", nil)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed to unstar dashboard", err)
|
||||
return
|
||||
return ApiError(500, "Failed to unstar dashboard", err)
|
||||
}
|
||||
|
||||
c.JsonOK("Dashboard unstarred")
|
||||
return ApiSuccess("Dashboard unstarred")
|
||||
}
|
||||
|
||||
+78
-49
@@ -7,44 +7,71 @@ import (
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
func GetUser(c *middleware.Context) {
|
||||
query := m.GetUserProfileQuery{UserId: c.UserId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(500, "Failed to get user", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(200, query.Result)
|
||||
// GET /api/user (current authenticated user)
|
||||
func GetSignedInUser(c *middleware.Context) Response {
|
||||
return getUserUserProfile(c.UserId)
|
||||
}
|
||||
|
||||
func UpdateUser(c *middleware.Context, cmd m.UpdateUserCommand) {
|
||||
// GET /api/user/:id
|
||||
func GetUserById(c *middleware.Context) Response {
|
||||
return getUserUserProfile(c.ParamsInt64(":id"))
|
||||
}
|
||||
|
||||
func getUserUserProfile(userId int64) Response {
|
||||
query := m.GetUserProfileQuery{UserId: userId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return ApiError(500, "Failed to get user", err)
|
||||
}
|
||||
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
// POST /api/user
|
||||
func UpdateSignedInUser(c *middleware.Context, cmd m.UpdateUserCommand) Response {
|
||||
cmd.UserId = c.UserId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(400, "Failed to update user", err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JsonOK("User updated")
|
||||
return handleUpdateUser(cmd)
|
||||
}
|
||||
|
||||
func GetUserOrgList(c *middleware.Context) {
|
||||
query := m.GetUserOrgListQuery{UserId: c.UserId}
|
||||
// POST /api/users/:id
|
||||
func UpdateUser(c *middleware.Context, cmd m.UpdateUserCommand) Response {
|
||||
cmd.UserId = c.ParamsInt64(":id")
|
||||
return handleUpdateUser(cmd)
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
c.JsonApiErr(500, "Failed to get user organizations", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, ac := range query.Result {
|
||||
if ac.OrgId == c.OrgId {
|
||||
ac.IsUsing = true
|
||||
break
|
||||
func handleUpdateUser(cmd m.UpdateUserCommand) Response {
|
||||
if len(cmd.Login) == 0 {
|
||||
cmd.Login = cmd.Email
|
||||
if len(cmd.Login) == 0 {
|
||||
return ApiError(400, "Validation error, need specify either username or email", nil)
|
||||
}
|
||||
}
|
||||
|
||||
c.JSON(200, query.Result)
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
return ApiError(500, "failed to update user", err)
|
||||
}
|
||||
|
||||
return ApiSuccess("User updated")
|
||||
}
|
||||
|
||||
// GET /api/user/orgs
|
||||
func GetSignedInUserOrgList(c *middleware.Context) Response {
|
||||
return getUserOrgList(c.UserId)
|
||||
}
|
||||
|
||||
// GET /api/user/:id/orgs
|
||||
func GetUserOrgList(c *middleware.Context) Response {
|
||||
return getUserOrgList(c.ParamsInt64(":id"))
|
||||
}
|
||||
|
||||
func getUserOrgList(userId int64) Response {
|
||||
query := m.GetUserOrgListQuery{UserId: userId}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return ApiError(500, "Faile to get user organziations", err)
|
||||
}
|
||||
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
func validateUsingOrg(userId int64, orgId int64) bool {
|
||||
@@ -65,53 +92,55 @@ func validateUsingOrg(userId int64, orgId int64) bool {
|
||||
return valid
|
||||
}
|
||||
|
||||
func UserSetUsingOrg(c *middleware.Context) {
|
||||
// POST /api/user/using/:id
|
||||
func UserSetUsingOrg(c *middleware.Context) Response {
|
||||
orgId := c.ParamsInt64(":id")
|
||||
|
||||
if !validateUsingOrg(c.UserId, orgId) {
|
||||
c.JsonApiErr(401, "Not a valid organization", nil)
|
||||
return
|
||||
return ApiError(401, "Not a valid organization", nil)
|
||||
}
|
||||
|
||||
cmd := m.SetUsingOrgCommand{
|
||||
UserId: c.UserId,
|
||||
OrgId: orgId,
|
||||
}
|
||||
cmd := m.SetUsingOrgCommand{UserId: c.UserId, OrgId: orgId}
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
c.JsonApiErr(500, "Failed change active organization", err)
|
||||
return
|
||||
return ApiError(500, "Failed change active organization", err)
|
||||
}
|
||||
|
||||
c.JsonOK("Active organization changed")
|
||||
return ApiSuccess("Active organization changed")
|
||||
}
|
||||
|
||||
func ChangeUserPassword(c *middleware.Context, cmd m.ChangeUserPasswordCommand) {
|
||||
func ChangeUserPassword(c *middleware.Context, cmd m.ChangeUserPasswordCommand) Response {
|
||||
userQuery := m.GetUserByIdQuery{Id: c.UserId}
|
||||
|
||||
if err := bus.Dispatch(&userQuery); err != nil {
|
||||
c.JsonApiErr(500, "Could not read user from database", err)
|
||||
return
|
||||
return ApiError(500, "Could not read user from database", err)
|
||||
}
|
||||
|
||||
passwordHashed := util.EncodePassword(cmd.OldPassword, userQuery.Result.Salt)
|
||||
if passwordHashed != userQuery.Result.Password {
|
||||
c.JsonApiErr(401, "Invalid old password", nil)
|
||||
return
|
||||
return ApiError(401, "Invalid old password", nil)
|
||||
}
|
||||
|
||||
if len(cmd.NewPassword) < 4 {
|
||||
c.JsonApiErr(400, "New password too short", nil)
|
||||
return
|
||||
return ApiError(400, "New password too short", nil)
|
||||
}
|
||||
|
||||
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
|
||||
return ApiError(500, "Failed to change user password", err)
|
||||
}
|
||||
|
||||
c.JsonOK("User password changed")
|
||||
return ApiSuccess("User password changed")
|
||||
}
|
||||
|
||||
// GET /api/users
|
||||
func SearchUsers(c *middleware.Context) Response {
|
||||
query := m.SearchUsersQuery{Query: "", Page: 0, Limit: 1000}
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return ApiError(500, "Failed to fetch users", err)
|
||||
}
|
||||
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user