mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
refactorin api code for user routes, preparation for admin improvements, #2014
This commit is contained in:
@@ -55,15 +55,21 @@ func Register(r *macaron.Macaron) {
|
|||||||
r.Group("/api", func() {
|
r.Group("/api", func() {
|
||||||
// user
|
// user
|
||||||
r.Group("/user", func() {
|
r.Group("/user", func() {
|
||||||
r.Get("/", GetUser)
|
r.Get("/", wrap(GetSignedInUser))
|
||||||
r.Put("/", bind(m.UpdateUserCommand{}), UpdateUser)
|
r.Put("/", bind(m.UpdateUserCommand{}), UpdateUser)
|
||||||
r.Post("/using/:id", UserSetUsingOrg)
|
r.Post("/using/:id", UserSetUsingOrg)
|
||||||
r.Get("/orgs", GetUserOrgList)
|
r.Get("/orgs", wrap(GetSignedInUserOrgList))
|
||||||
r.Post("/stars/dashboard/:id", StarDashboard)
|
r.Post("/stars/dashboard/:id", StarDashboard)
|
||||||
r.Delete("/stars/dashboard/:id", UnstarDashboard)
|
r.Delete("/stars/dashboard/:id", UnstarDashboard)
|
||||||
r.Put("/password", bind(m.ChangeUserPasswordCommand{}), ChangeUserPassword)
|
r.Put("/password", bind(m.ChangeUserPasswordCommand{}), ChangeUserPassword)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// users
|
||||||
|
r.Group("/users", func() {
|
||||||
|
r.Get("/:id/", wrap(GetUserById))
|
||||||
|
r.Get("/:id/org", wrap(GetUserOrgList))
|
||||||
|
}, reqGrafanaAdmin)
|
||||||
|
|
||||||
// account
|
// account
|
||||||
r.Group("/org", func() {
|
r.Group("/org", func() {
|
||||||
r.Get("/", GetOrg)
|
r.Get("/", GetOrg)
|
||||||
@@ -127,5 +133,5 @@ func Register(r *macaron.Macaron) {
|
|||||||
// rendering
|
// rendering
|
||||||
r.Get("/render/*", reqSignedIn, RenderToPng)
|
r.Get("/render/*", reqSignedIn, RenderToPng)
|
||||||
|
|
||||||
r.NotFound(NotFound)
|
r.NotFound(NotFoundHandler)
|
||||||
}
|
}
|
||||||
|
|||||||
111
pkg/api/common.go
Normal file
111
pkg/api/common.go
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
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 func(c *middleware.Context) Response) macaron.Handler {
|
||||||
|
return func(c *middleware.Context) {
|
||||||
|
res := action(c)
|
||||||
|
if res == nil {
|
||||||
|
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 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),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,7 +59,7 @@ func Index(c *middleware.Context) {
|
|||||||
c.HTML(200, "index")
|
c.HTML(200, "index")
|
||||||
}
|
}
|
||||||
|
|
||||||
func NotFound(c *middleware.Context) {
|
func NotFoundHandler(c *middleware.Context) {
|
||||||
if c.IsApiRequest() {
|
if c.IsApiRequest() {
|
||||||
c.JsonApiErr(404, "Not found", nil)
|
c.JsonApiErr(404, "Not found", nil)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -7,15 +7,24 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/util"
|
"github.com/grafana/grafana/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetUser(c *middleware.Context) {
|
// GET /api/user (current authenticated user)
|
||||||
query := m.GetUserProfileQuery{UserId: c.UserId}
|
func GetSignedInUser(c *middleware.Context) Response {
|
||||||
|
return getUserUserProfile(c.UserId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
if err := bus.Dispatch(&query); err != nil {
|
||||||
c.JsonApiErr(500, "Failed to get user", err)
|
return ApiError(500, "Failed to get user", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(200, query.Result)
|
return Json(200, query.Result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateUser(c *middleware.Context, cmd m.UpdateUserCommand) {
|
func UpdateUser(c *middleware.Context, cmd m.UpdateUserCommand) {
|
||||||
@@ -29,22 +38,24 @@ func UpdateUser(c *middleware.Context, cmd m.UpdateUserCommand) {
|
|||||||
c.JsonOK("User updated")
|
c.JsonOK("User updated")
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUserOrgList(c *middleware.Context) {
|
// GET /api/user/orgs
|
||||||
query := m.GetUserOrgListQuery{UserId: c.UserId}
|
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 {
|
if err := bus.Dispatch(&query); err != nil {
|
||||||
c.JsonApiErr(500, "Failed to get user organizations", err)
|
return ApiError(500, "Faile to get user organziations", err)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ac := range query.Result {
|
return Json(200, query.Result)
|
||||||
if ac.OrgId == c.OrgId {
|
|
||||||
ac.IsUsing = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(200, query.Result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateUsingOrg(userId int64, orgId int64) bool {
|
func validateUsingOrg(userId int64, orgId int64) bool {
|
||||||
|
|||||||
@@ -58,8 +58,7 @@ type OrgDTO struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type UserOrgDTO struct {
|
type UserOrgDTO struct {
|
||||||
OrgId int64 `json:"orgId"`
|
OrgId int64 `json:"orgId"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Role RoleType `json:"role"`
|
Role RoleType `json:"role"`
|
||||||
IsUsing bool `json:"isUsing"`
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tight-form" style="margin-top: 5px">
|
<div class="tight-form">
|
||||||
<ul class="tight-form-list">
|
<ul class="tight-form-list">
|
||||||
<li class="tight-form-item" style="width: 100px">
|
<li class="tight-form-item" style="width: 100px">
|
||||||
<strong>Email</strong>
|
<strong>Email</strong>
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tight-form" style="margin-top: 5px">
|
<div class="tight-form">
|
||||||
<ul class="tight-form-list">
|
<ul class="tight-form-list">
|
||||||
<li class="tight-form-item" style="width: 100px">
|
<li class="tight-form-item" style="width: 100px">
|
||||||
<strong>Username</strong>
|
<strong>Username</strong>
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tight-form" style="margin-top: 5px">
|
<div class="tight-form">
|
||||||
<ul class="tight-form-list">
|
<ul class="tight-form-list">
|
||||||
<li class="tight-form-item" style="width: 100px">
|
<li class="tight-form-item" style="width: 100px">
|
||||||
<strong>Email</strong>
|
<strong>Email</strong>
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tight-form" style="margin-top: 5px">
|
<div class="tight-form">
|
||||||
<ul class="tight-form-list">
|
<ul class="tight-form-list">
|
||||||
<li class="tight-form-item" style="width: 100px">
|
<li class="tight-form-item" style="width: 100px">
|
||||||
<strong>Username</strong>
|
<strong>Username</strong>
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tight-form" style="margin-top: 5px">
|
<div class="tight-form">
|
||||||
<ul class="tight-form-list">
|
<ul class="tight-form-list">
|
||||||
<li class="tight-form-item" style="width: 100px">
|
<li class="tight-form-item" style="width: 100px">
|
||||||
<strong>Password</strong>
|
<strong>Password</strong>
|
||||||
|
|||||||
@@ -71,10 +71,10 @@
|
|||||||
<td style="width: 98%"><strong>Name: </strong> {{org.name}}</td>
|
<td style="width: 98%"><strong>Name: </strong> {{org.name}}</td>
|
||||||
<td><strong>Role: </strong> {{org.role}}</td>
|
<td><strong>Role: </strong> {{org.role}}</td>
|
||||||
<td class="nobg max-width-btns">
|
<td class="nobg max-width-btns">
|
||||||
<span class="btn btn-primary btn-mini" ng-show="org.isUsing">
|
<span class="btn btn-primary btn-mini" ng-show="org.orgId === contextSrv.user.orgId">
|
||||||
Current
|
Current
|
||||||
</span>
|
</span>
|
||||||
<a ng-click="setUsingOrg(org)" class="btn btn-inverse btn-mini" ng-show="!org.isUsing">
|
<a ng-click="setUsingOrg(org)" class="btn btn-inverse btn-mini" ng-show="org.orgId !== contextSrv.user.orgId">
|
||||||
Select
|
Select
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
Reference in New Issue
Block a user