Merge branch 'refactor-user-group-to-team' of https://github.com/alexanderzobnin/grafana into user-group-to-team
This commit is contained in:
+10
-10
@@ -135,16 +135,16 @@ func (hs *HttpServer) registerRoutes() {
|
||||
usersRoute.Post("/:id/using/:orgId", wrap(UpdateUserActiveOrg))
|
||||
}, reqGrafanaAdmin)
|
||||
|
||||
// user group (admin permission required)
|
||||
apiRoute.Group("/user-groups", func(userGroupsRoute RouteRegister) {
|
||||
userGroupsRoute.Get("/:userGroupId", wrap(GetUserGroupById))
|
||||
userGroupsRoute.Get("/search", wrap(SearchUserGroups))
|
||||
userGroupsRoute.Post("/", quota("user-groups"), bind(m.CreateUserGroupCommand{}), wrap(CreateUserGroup))
|
||||
userGroupsRoute.Put("/:userGroupId", bind(m.UpdateUserGroupCommand{}), wrap(UpdateUserGroup))
|
||||
userGroupsRoute.Delete("/:userGroupId", wrap(DeleteUserGroupById))
|
||||
userGroupsRoute.Get("/:userGroupId/members", wrap(GetUserGroupMembers))
|
||||
userGroupsRoute.Post("/:userGroupId/members", quota("user-groups"), bind(m.AddUserGroupMemberCommand{}), wrap(AddUserGroupMember))
|
||||
userGroupsRoute.Delete("/:userGroupId/members/:userId", wrap(RemoveUserGroupMember))
|
||||
// team (admin permission required)
|
||||
apiRoute.Group("/teams", func(teamsRoute RouteRegister) {
|
||||
teamsRoute.Get("/:teamId", wrap(GetTeamById))
|
||||
teamsRoute.Get("/search", wrap(SearchTeams))
|
||||
teamsRoute.Post("/", quota("teams"), bind(m.CreateTeamCommand{}), wrap(CreateTeam))
|
||||
teamsRoute.Put("/:teamId", bind(m.UpdateTeamCommand{}), wrap(UpdateTeam))
|
||||
teamsRoute.Delete("/:teamId", wrap(DeleteTeamById))
|
||||
teamsRoute.Get("/:teamId/members", wrap(GetTeamMembers))
|
||||
teamsRoute.Post("/:teamId/members", quota("teams"), bind(m.AddTeamMemberCommand{}), wrap(AddTeamMember))
|
||||
teamsRoute.Delete("/:teamId/members/:userId", wrap(RemoveTeamMember))
|
||||
}, reqOrgAdmin)
|
||||
|
||||
// org information available to all users.
|
||||
|
||||
@@ -43,7 +43,7 @@ func UpdateDashboardAcl(c *middleware.Context, apiCmd dtos.UpdateDashboardAclCom
|
||||
OrgId: c.OrgId,
|
||||
DashboardId: dashId,
|
||||
UserId: item.UserId,
|
||||
UserGroupId: item.UserGroupId,
|
||||
TeamId: item.TeamId,
|
||||
Role: item.Role,
|
||||
Permission: item.Permission,
|
||||
Created: time.Now(),
|
||||
|
||||
@@ -16,8 +16,8 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
|
||||
{Id: 1, OrgId: 1, DashboardId: 1, UserId: 2, Permission: m.PERMISSION_VIEW},
|
||||
{Id: 2, OrgId: 1, DashboardId: 1, UserId: 3, Permission: m.PERMISSION_EDIT},
|
||||
{Id: 3, OrgId: 1, DashboardId: 1, UserId: 4, Permission: m.PERMISSION_ADMIN},
|
||||
{Id: 4, OrgId: 1, DashboardId: 1, UserGroupId: 1, Permission: m.PERMISSION_VIEW},
|
||||
{Id: 5, OrgId: 1, DashboardId: 1, UserGroupId: 2, Permission: m.PERMISSION_ADMIN},
|
||||
{Id: 4, OrgId: 1, DashboardId: 1, TeamId: 1, Permission: m.PERMISSION_VIEW},
|
||||
{Id: 5, OrgId: 1, DashboardId: 1, TeamId: 2, Permission: m.PERMISSION_ADMIN},
|
||||
}
|
||||
dtoRes := transformDashboardAclsToDTOs(mockResult)
|
||||
|
||||
@@ -31,9 +31,9 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
|
||||
userGroupResp := []*m.UserGroup{}
|
||||
bus.AddHandler("test", func(query *m.GetUserGroupsByUserQuery) error {
|
||||
query.Result = userGroupResp
|
||||
teamResp := []*m.Team{}
|
||||
bus.AddHandler("test", func(query *m.GetTeamsByUserQuery) error {
|
||||
query.Result = teamResp
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -81,9 +81,9 @@ func TestDashboardAclApiEndpoint(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When user is a member of a user group in the ACL with admin permission", func() {
|
||||
Convey("When user is a member of a team in the ACL with admin permission", func() {
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/dashboards/id/1/acl/1", "/api/dashboards/id/:dashboardsId/acl/:aclId", m.ROLE_EDITOR, func(sc *scenarioContext) {
|
||||
userGroupResp = append(userGroupResp, &m.UserGroup{Id: 2, OrgId: 1, Name: "UG2"})
|
||||
teamResp = append(teamResp, &m.Team{Id: 2, OrgId: 1, Name: "UG2"})
|
||||
|
||||
bus.AddHandler("test3", func(cmd *m.RemoveDashboardAclCommand) error {
|
||||
return nil
|
||||
@@ -165,7 +165,7 @@ func transformDashboardAclsToDTOs(acls []*m.DashboardAclInfoDTO) []*m.DashboardA
|
||||
DashboardId: acl.DashboardId,
|
||||
Permission: acl.Permission,
|
||||
UserId: acl.UserId,
|
||||
UserGroupId: acl.UserGroupId,
|
||||
TeamId: acl.TeamId,
|
||||
}
|
||||
dtos = append(dtos, dto)
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ func TestDashboardApiEndpoint(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
|
||||
bus.AddHandler("test", func(query *m.GetUserGroupsByUserQuery) error {
|
||||
query.Result = []*m.UserGroup{}
|
||||
bus.AddHandler("test", func(query *m.GetTeamsByUserQuery) error {
|
||||
query.Result = []*m.Team{}
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -217,8 +217,8 @@ func TestDashboardApiEndpoint(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
|
||||
bus.AddHandler("test", func(query *m.GetUserGroupsByUserQuery) error {
|
||||
query.Result = []*m.UserGroup{}
|
||||
bus.AddHandler("test", func(query *m.GetTeamsByUserQuery) error {
|
||||
query.Result = []*m.Team{}
|
||||
return nil
|
||||
})
|
||||
|
||||
|
||||
+4
-4
@@ -9,8 +9,8 @@ type UpdateDashboardAclCommand struct {
|
||||
}
|
||||
|
||||
type DashboardAclUpdateItem struct {
|
||||
UserId int64 `json:"userId"`
|
||||
UserGroupId int64 `json:"userGroupId"`
|
||||
Role *m.RoleType `json:"role,omitempty"`
|
||||
Permission m.PermissionType `json:"permission"`
|
||||
UserId int64 `json:"userId"`
|
||||
TeamId int64 `json:"teamId"`
|
||||
Role *m.RoleType `json:"role,omitempty"`
|
||||
Permission m.PermissionType `json:"permission"`
|
||||
}
|
||||
|
||||
+2
-2
@@ -231,8 +231,8 @@ func setIndexViewData(c *middleware.Context) (*dtos.IndexViewData, error) {
|
||||
Text: "Teams",
|
||||
Id: "teams",
|
||||
Description: "Manage org groups",
|
||||
Icon: "gicon gicon-user-group",
|
||||
Url: setting.AppSubUrl + "/org/user-groups",
|
||||
Icon: "gicon gicon-team",
|
||||
Url: setting.AppSubUrl + "/org/teams",
|
||||
},
|
||||
{
|
||||
Text: "Plugins",
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
package api
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
// POST /api/teams
|
||||
func CreateTeam(c *middleware.Context, cmd m.CreateTeamCommand) Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if err == m.ErrTeamNameTaken {
|
||||
return ApiError(409, "Team name taken", err)
|
||||
}
|
||||
return ApiError(500, "Failed to create Team", err)
|
||||
}
|
||||
|
||||
return Json(200, &util.DynMap{
|
||||
"teamId": cmd.Result.Id,
|
||||
"message": "Team created",
|
||||
})
|
||||
}
|
||||
|
||||
// PUT /api/teams/:teamId
|
||||
func UpdateTeam(c *middleware.Context, cmd m.UpdateTeamCommand) Response {
|
||||
cmd.Id = c.ParamsInt64(":teamId")
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if err == m.ErrTeamNameTaken {
|
||||
return ApiError(400, "Team name taken", err)
|
||||
}
|
||||
return ApiError(500, "Failed to update Team", err)
|
||||
}
|
||||
|
||||
return ApiSuccess("Team updated")
|
||||
}
|
||||
|
||||
// DELETE /api/teams/:teamId
|
||||
func DeleteTeamById(c *middleware.Context) Response {
|
||||
if err := bus.Dispatch(&m.DeleteTeamCommand{Id: c.ParamsInt64(":teamId")}); err != nil {
|
||||
if err == m.ErrTeamNotFound {
|
||||
return ApiError(404, "Failed to delete Team. ID not found", nil)
|
||||
}
|
||||
return ApiError(500, "Failed to update Team", err)
|
||||
}
|
||||
return ApiSuccess("Team deleted")
|
||||
}
|
||||
|
||||
// GET /api/teams/search
|
||||
func SearchTeams(c *middleware.Context) Response {
|
||||
perPage := c.QueryInt("perpage")
|
||||
if perPage <= 0 {
|
||||
perPage = 1000
|
||||
}
|
||||
page := c.QueryInt("page")
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
query := m.SearchTeamsQuery{
|
||||
Query: c.Query("query"),
|
||||
Name: c.Query("name"),
|
||||
Page: page,
|
||||
Limit: perPage,
|
||||
OrgId: c.OrgId,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return ApiError(500, "Failed to search Teams", err)
|
||||
}
|
||||
|
||||
query.Result.Page = page
|
||||
query.Result.PerPage = perPage
|
||||
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
// GET /api/teams/:teamId
|
||||
func GetTeamById(c *middleware.Context) Response {
|
||||
query := m.GetTeamByIdQuery{Id: c.ParamsInt64(":teamId")}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if err == m.ErrTeamNotFound {
|
||||
return ApiError(404, "Team not found", err)
|
||||
}
|
||||
|
||||
return ApiError(500, "Failed to get Team", err)
|
||||
}
|
||||
|
||||
return Json(200, &query.Result)
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package api
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
// GET /api/teams/:teamId/members
|
||||
func GetTeamMembers(c *middleware.Context) Response {
|
||||
query := m.GetTeamMembersQuery{TeamId: c.ParamsInt64(":teamId")}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return ApiError(500, "Failed to get Team Members", err)
|
||||
}
|
||||
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
// POST /api/teams/:teamId/members
|
||||
func AddTeamMember(c *middleware.Context, cmd m.AddTeamMemberCommand) Response {
|
||||
cmd.TeamId = c.ParamsInt64(":teamId")
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if err == m.ErrTeamMemberAlreadyAdded {
|
||||
return ApiError(400, "User is already added to this team", err)
|
||||
}
|
||||
return ApiError(500, "Failed to add Member to Team", err)
|
||||
}
|
||||
|
||||
return Json(200, &util.DynMap{
|
||||
"message": "Member added to Team",
|
||||
})
|
||||
}
|
||||
|
||||
// DELETE /api/teams/:teamId/members/:userId
|
||||
func RemoveTeamMember(c *middleware.Context) Response {
|
||||
if err := bus.Dispatch(&m.RemoveTeamMemberCommand{TeamId: c.ParamsInt64(":teamId"), UserId: c.ParamsInt64(":userId")}); err != nil {
|
||||
return ApiError(500, "Failed to remove Member from Team", err)
|
||||
}
|
||||
return ApiSuccess("Team Member removed")
|
||||
}
|
||||
@@ -10,21 +10,21 @@ import (
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestUserGroupApiEndpoint(t *testing.T) {
|
||||
Convey("Given two user groups", t, func() {
|
||||
mockResult := models.SearchUserGroupQueryResult{
|
||||
UserGroups: []*models.UserGroup{
|
||||
{Name: "userGroup1"},
|
||||
{Name: "userGroup2"},
|
||||
func TestTeamApiEndpoint(t *testing.T) {
|
||||
Convey("Given two teams", t, func() {
|
||||
mockResult := models.SearchTeamQueryResult{
|
||||
Teams: []*models.Team{
|
||||
{Name: "team1"},
|
||||
{Name: "team2"},
|
||||
},
|
||||
TotalCount: 2,
|
||||
}
|
||||
|
||||
Convey("When searching with no parameters", func() {
|
||||
loggedInUserScenario("When calling GET on", "/api/user-groups/search", func(sc *scenarioContext) {
|
||||
loggedInUserScenario("When calling GET on", "/api/teams/search", func(sc *scenarioContext) {
|
||||
var sentLimit int
|
||||
var sendPage int
|
||||
bus.AddHandler("test", func(query *models.SearchUserGroupsQuery) error {
|
||||
bus.AddHandler("test", func(query *models.SearchTeamsQuery) error {
|
||||
query.Result = mockResult
|
||||
|
||||
sentLimit = query.Limit
|
||||
@@ -33,7 +33,7 @@ func TestUserGroupApiEndpoint(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
|
||||
sc.handlerFunc = SearchUserGroups
|
||||
sc.handlerFunc = SearchTeams
|
||||
sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec()
|
||||
|
||||
So(sentLimit, ShouldEqual, 1000)
|
||||
@@ -43,15 +43,15 @@ func TestUserGroupApiEndpoint(t *testing.T) {
|
||||
So(err, ShouldBeNil)
|
||||
|
||||
So(respJSON.Get("totalCount").MustInt(), ShouldEqual, 2)
|
||||
So(len(respJSON.Get("userGroups").MustArray()), ShouldEqual, 2)
|
||||
So(len(respJSON.Get("teams").MustArray()), ShouldEqual, 2)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When searching with page and perpage parameters", func() {
|
||||
loggedInUserScenario("When calling GET on", "/api/user-groups/search", func(sc *scenarioContext) {
|
||||
loggedInUserScenario("When calling GET on", "/api/teams/search", func(sc *scenarioContext) {
|
||||
var sentLimit int
|
||||
var sendPage int
|
||||
bus.AddHandler("test", func(query *models.SearchUserGroupsQuery) error {
|
||||
bus.AddHandler("test", func(query *models.SearchTeamsQuery) error {
|
||||
query.Result = mockResult
|
||||
|
||||
sentLimit = query.Limit
|
||||
@@ -60,7 +60,7 @@ func TestUserGroupApiEndpoint(t *testing.T) {
|
||||
return nil
|
||||
})
|
||||
|
||||
sc.handlerFunc = SearchUserGroups
|
||||
sc.handlerFunc = SearchTeams
|
||||
sc.fakeReqWithParams("GET", sc.url, map[string]string{"perpage": "10", "page": "2"}).exec()
|
||||
|
||||
So(sentLimit, ShouldEqual, 10)
|
||||
@@ -1,92 +0,0 @@
|
||||
package api
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
// POST /api/user-groups
|
||||
func CreateUserGroup(c *middleware.Context, cmd m.CreateUserGroupCommand) Response {
|
||||
cmd.OrgId = c.OrgId
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if err == m.ErrUserGroupNameTaken {
|
||||
return ApiError(409, "User Group name taken", err)
|
||||
}
|
||||
return ApiError(500, "Failed to create User Group", err)
|
||||
}
|
||||
|
||||
return Json(200, &util.DynMap{
|
||||
"userGroupId": cmd.Result.Id,
|
||||
"message": "User Group created",
|
||||
})
|
||||
}
|
||||
|
||||
// PUT /api/user-groups/:userGroupId
|
||||
func UpdateUserGroup(c *middleware.Context, cmd m.UpdateUserGroupCommand) Response {
|
||||
cmd.Id = c.ParamsInt64(":userGroupId")
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if err == m.ErrUserGroupNameTaken {
|
||||
return ApiError(400, "User Group name taken", err)
|
||||
}
|
||||
return ApiError(500, "Failed to update User Group", err)
|
||||
}
|
||||
|
||||
return ApiSuccess("User Group updated")
|
||||
}
|
||||
|
||||
// DELETE /api/user-groups/:userGroupId
|
||||
func DeleteUserGroupById(c *middleware.Context) Response {
|
||||
if err := bus.Dispatch(&m.DeleteUserGroupCommand{Id: c.ParamsInt64(":userGroupId")}); err != nil {
|
||||
if err == m.ErrUserGroupNotFound {
|
||||
return ApiError(404, "Failed to delete User Group. ID not found", nil)
|
||||
}
|
||||
return ApiError(500, "Failed to update User Group", err)
|
||||
}
|
||||
return ApiSuccess("User Group deleted")
|
||||
}
|
||||
|
||||
// GET /api/user-groups/search
|
||||
func SearchUserGroups(c *middleware.Context) Response {
|
||||
perPage := c.QueryInt("perpage")
|
||||
if perPage <= 0 {
|
||||
perPage = 1000
|
||||
}
|
||||
page := c.QueryInt("page")
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
|
||||
query := m.SearchUserGroupsQuery{
|
||||
Query: c.Query("query"),
|
||||
Name: c.Query("name"),
|
||||
Page: page,
|
||||
Limit: perPage,
|
||||
OrgId: c.OrgId,
|
||||
}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return ApiError(500, "Failed to search User Groups", err)
|
||||
}
|
||||
|
||||
query.Result.Page = page
|
||||
query.Result.PerPage = perPage
|
||||
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
// GET /api/user-groups/:userGroupId
|
||||
func GetUserGroupById(c *middleware.Context) Response {
|
||||
query := m.GetUserGroupByIdQuery{Id: c.ParamsInt64(":userGroupId")}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
if err == m.ErrUserGroupNotFound {
|
||||
return ApiError(404, "User Group not found", err)
|
||||
}
|
||||
|
||||
return ApiError(500, "Failed to get User Group", err)
|
||||
}
|
||||
|
||||
return Json(200, &query.Result)
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package api
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
// GET /api/user-groups/:userGroupId/members
|
||||
func GetUserGroupMembers(c *middleware.Context) Response {
|
||||
query := m.GetUserGroupMembersQuery{UserGroupId: c.ParamsInt64(":userGroupId")}
|
||||
|
||||
if err := bus.Dispatch(&query); err != nil {
|
||||
return ApiError(500, "Failed to get User Group Members", err)
|
||||
}
|
||||
|
||||
return Json(200, query.Result)
|
||||
}
|
||||
|
||||
// POST /api/user-groups/:userGroupId/members
|
||||
func AddUserGroupMember(c *middleware.Context, cmd m.AddUserGroupMemberCommand) Response {
|
||||
cmd.UserGroupId = c.ParamsInt64(":userGroupId")
|
||||
cmd.OrgId = c.OrgId
|
||||
|
||||
if err := bus.Dispatch(&cmd); err != nil {
|
||||
if err == m.ErrUserGroupMemberAlreadyAdded {
|
||||
return ApiError(400, "User is already added to this user group", err)
|
||||
}
|
||||
return ApiError(500, "Failed to add Member to User Group", err)
|
||||
}
|
||||
|
||||
return Json(200, &util.DynMap{
|
||||
"message": "Member added to User Group",
|
||||
})
|
||||
}
|
||||
|
||||
// DELETE /api/user-groups/:userGroupId/members/:userId
|
||||
func RemoveUserGroupMember(c *middleware.Context) Response {
|
||||
if err := bus.Dispatch(&m.RemoveUserGroupMemberCommand{UserGroupId: c.ParamsInt64(":userGroupId"), UserId: c.ParamsInt64(":userId")}); err != nil {
|
||||
return ApiError(500, "Failed to remove Member from User Group", err)
|
||||
}
|
||||
return ApiSuccess("User Group Member removed")
|
||||
}
|
||||
Reference in New Issue
Block a user