mirror of https://github.com/grafana/grafana
parent
af67aea2a9
commit
233cd7af4a
@ -0,0 +1,66 @@ |
||||
package api |
||||
|
||||
import ( |
||||
"github.com/grafana/grafana/pkg/bus" |
||||
"github.com/grafana/grafana/pkg/metrics" |
||||
"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) |
||||
} |
||||
|
||||
metrics.M_Api_UserGroup_Create.Inc(1) |
||||
|
||||
return Json(200, &util.DynMap{ |
||||
"userGroupId": cmd.Result.Id, |
||||
"message": "User Group created", |
||||
}) |
||||
} |
||||
|
||||
// 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, |
||||
} |
||||
|
||||
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) |
||||
} |
@ -0,0 +1,71 @@ |
||||
package api |
||||
|
||||
import ( |
||||
"testing" |
||||
|
||||
"github.com/grafana/grafana/pkg/bus" |
||||
"github.com/grafana/grafana/pkg/components/simplejson" |
||||
"github.com/grafana/grafana/pkg/models" |
||||
|
||||
. "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"}, |
||||
}, |
||||
TotalCount: 2, |
||||
} |
||||
|
||||
Convey("When searching with no parameters", func() { |
||||
loggedInUserScenario("When calling GET on", "/api/user-groups/search", func(sc *scenarioContext) { |
||||
var sentLimit int |
||||
var sendPage int |
||||
bus.AddHandler("test", func(query *models.SearchUserGroupsQuery) error { |
||||
query.Result = mockResult |
||||
|
||||
sentLimit = query.Limit |
||||
sendPage = query.Page |
||||
|
||||
return nil |
||||
}) |
||||
|
||||
sc.handlerFunc = SearchUserGroups |
||||
sc.fakeReqWithParams("GET", sc.url, map[string]string{}).exec() |
||||
|
||||
So(sentLimit, ShouldEqual, 1000) |
||||
So(sendPage, ShouldEqual, 1) |
||||
|
||||
respJSON, err := simplejson.NewJson(sc.resp.Body.Bytes()) |
||||
So(err, ShouldBeNil) |
||||
|
||||
So(respJSON.Get("totalCount").MustInt(), ShouldEqual, 2) |
||||
So(len(respJSON.Get("userGroups").MustArray()), ShouldEqual, 2) |
||||
}) |
||||
}) |
||||
|
||||
Convey("When searching with page and perpage parameters", func() { |
||||
loggedInUserScenario("When calling GET on", "/api/user-groups/search", func(sc *scenarioContext) { |
||||
var sentLimit int |
||||
var sendPage int |
||||
bus.AddHandler("test", func(query *models.SearchUserGroupsQuery) error { |
||||
query.Result = mockResult |
||||
|
||||
sentLimit = query.Limit |
||||
sendPage = query.Page |
||||
|
||||
return nil |
||||
}) |
||||
|
||||
sc.handlerFunc = SearchUserGroups |
||||
sc.fakeReqWithParams("GET", sc.url, map[string]string{"perpage": "10", "page": "2"}).exec() |
||||
|
||||
So(sentLimit, ShouldEqual, 10) |
||||
So(sendPage, ShouldEqual, 2) |
||||
}) |
||||
}) |
||||
}) |
||||
} |
@ -0,0 +1,60 @@ |
||||
<navbar icon="icon-gf icon-gf-users" title="User Groups" title-url="org"> |
||||
</navbar> |
||||
|
||||
<div class="page-container"> |
||||
<div class="page-header"> |
||||
<h1>User Groups</h1> |
||||
|
||||
<div class="page-header-tabs"> |
||||
<a class="btn btn-success" href="/org/user-groups/create"> |
||||
<i class="fa fa-plus"></i> |
||||
Create User Group |
||||
</a> |
||||
</div> |
||||
</div> |
||||
<div class="search-field-wrapper pull-right width-18"> |
||||
<span style="position: relative;"> |
||||
<input type="text" placeholder="Find User Group by name" tabindex="1" give-focus="true" |
||||
ng-model="ctrl.query" ng-model-options="{ debounce: 500 }" spellcheck='false' ng-change="ctrl.get()" /> |
||||
</span> |
||||
</div> |
||||
<div class="admin-list-table"> |
||||
<table class="filter-table form-inline"> |
||||
<thead> |
||||
<tr> |
||||
<th>Id</th> |
||||
<th>Name</th> |
||||
<th></th> |
||||
</tr> |
||||
</thead> |
||||
<tbody> |
||||
<tr ng-repeat="userGroup in ctrl.userGroups"> |
||||
<td>{{userGroup.id}}</td> |
||||
<td>{{userGroup.name}}</td> |
||||
<td class="text-right"> |
||||
<a href="org/user-groups/edit/{{userGroup.id}}" class="btn btn-inverse btn-small"> |
||||
<i class="fa fa-edit"></i> |
||||
Edit |
||||
</a> |
||||
|
||||
<a ng-click="ctrl.deleteUserGroup(userGroup)" class="btn btn-danger btn-small"> |
||||
<i class="fa fa-remove"></i> |
||||
</a> |
||||
</td> |
||||
</tr> |
||||
</tbody> |
||||
|
||||
</table> |
||||
</div> |
||||
|
||||
<div class="admin-list-paging" ng-if="ctrl.showPaging"> |
||||
<ol> |
||||
<li ng-repeat="page in ctrl.pages"> |
||||
<button |
||||
class="btn btn-small" |
||||
ng-class="{'btn-secondary': page.current, 'btn-inverse': !page.current}" |
||||
ng-click="ctrl.navigateToPage(page)">{{page.page}}</button> |
||||
</li> |
||||
</ol> |
||||
</div> |
||||
</div> |
@ -0,0 +1,68 @@ |
||||
///<reference path="../../headers/common.d.ts" />
|
||||
|
||||
import coreModule from 'app/core/core_module'; |
||||
|
||||
export default class UserGroupsCtrl { |
||||
userGroups: any; |
||||
pages = []; |
||||
perPage = 50; |
||||
page = 1; |
||||
totalPages: number; |
||||
showPaging = false; |
||||
query: any = ''; |
||||
|
||||
/** @ngInject */ |
||||
constructor(private $scope, private $http, private backendSrv) { |
||||
this.get(); |
||||
} |
||||
|
||||
get() { |
||||
this.backendSrv.get(`/api/user-groups/search?perpage=${this.perPage}&page=${this.page}&query=${this.query}`) |
||||
.then((result) => { |
||||
this.userGroups = result.userGroups; |
||||
this.page = result.page; |
||||
this.perPage = result.perPage; |
||||
this.totalPages = Math.ceil(result.totalCount / result.perPage); |
||||
this.showPaging = this.totalPages > 1; |
||||
this.pages = []; |
||||
|
||||
for (var i = 1; i < this.totalPages+1; i++) { |
||||
this.pages.push({ page: i, current: i === this.page}); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
navigateToPage(page) { |
||||
this.page = page.page; |
||||
this.get(); |
||||
} |
||||
|
||||
deleteUserGroup(userGroup) { |
||||
this.$scope.appEvent('confirm-modal', { |
||||
title: 'Delete', |
||||
text: 'Are you sure you want to delete User Group ' + userGroup.name + '?', |
||||
yesText: "Delete", |
||||
icon: "fa-warning", |
||||
onConfirm: () => { |
||||
this.deleteUserGroupConfirmed(userGroup); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
deleteUserGroupConfirmed(userGroup) { |
||||
this.backendSrv.delete('/api/user-groups/' + userGroup.id) |
||||
.then(this.get.bind(this)); |
||||
} |
||||
|
||||
openUserGroupModal() { |
||||
var modalScope = this.$scope.$new(); |
||||
|
||||
this.$scope.appEvent('show-modal', { |
||||
src: 'public/app/features/org/partials/add_user.html', |
||||
modalClass: 'user-group-modal', |
||||
scope: modalScope |
||||
}); |
||||
} |
||||
} |
||||
|
||||
coreModule.controller('UserGroupsCtrl', UserGroupsCtrl); |
Loading…
Reference in new issue