mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Merge branch 'develop' of github.com:grafana/grafana into develop
This commit is contained in:
@@ -57,6 +57,7 @@ func GetDashboard(c *middleware.Context) Response {
|
||||
|
||||
canEdit, _ := guardian.CanEdit()
|
||||
canSave, _ := guardian.CanSave()
|
||||
canAdmin, _ := guardian.CanAdmin()
|
||||
|
||||
isStarred, err := isDashboardStarredByUser(c, dash.Id)
|
||||
if err != nil {
|
||||
@@ -79,6 +80,7 @@ func GetDashboard(c *middleware.Context) Response {
|
||||
CanStar: c.IsSignedIn,
|
||||
CanSave: canSave,
|
||||
CanEdit: canEdit,
|
||||
CanAdmin: canAdmin,
|
||||
Created: dash.Created,
|
||||
Updated: dash.Updated,
|
||||
UpdatedBy: updater,
|
||||
|
||||
@@ -65,6 +65,7 @@ func TestDashboardApiEndpoint(t *testing.T) {
|
||||
Convey("Should not be able to edit or save dashboard", func() {
|
||||
So(dash.Meta.CanEdit, ShouldBeFalse)
|
||||
So(dash.Meta.CanSave, ShouldBeFalse)
|
||||
So(dash.Meta.CanAdmin, ShouldBeFalse)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -97,6 +98,7 @@ func TestDashboardApiEndpoint(t *testing.T) {
|
||||
Convey("Should be able to view but not save the dashboard", func() {
|
||||
So(dash.Meta.CanEdit, ShouldBeFalse)
|
||||
So(dash.Meta.CanSave, ShouldBeFalse)
|
||||
So(dash.Meta.CanAdmin, ShouldBeFalse)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -130,6 +132,7 @@ func TestDashboardApiEndpoint(t *testing.T) {
|
||||
Convey("Should be able to edit or save dashboard", func() {
|
||||
So(dash.Meta.CanEdit, ShouldBeTrue)
|
||||
So(dash.Meta.CanSave, ShouldBeTrue)
|
||||
So(dash.Meta.CanAdmin, ShouldBeFalse)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -299,6 +302,50 @@ func TestDashboardApiEndpoint(t *testing.T) {
|
||||
Convey("Should be able to get dashboard with edit rights", func() {
|
||||
So(dash.Meta.CanEdit, ShouldBeTrue)
|
||||
So(dash.Meta.CanSave, ShouldBeTrue)
|
||||
So(dash.Meta.CanAdmin, ShouldBeFalse)
|
||||
})
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling DELETE on", "DELETE", "/api/dashboards/2", "/api/dashboards/:id", role, func(sc *scenarioContext) {
|
||||
CallDeleteDashboard(sc)
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/dashboards/id/2/versions/1", "/api/dashboards/id/:dashboardId/versions/:id", role, func(sc *scenarioContext) {
|
||||
CallGetDashboardVersion(sc)
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/dashboards/id/2/versions", "/api/dashboards/id/:dashboardId/versions", role, func(sc *scenarioContext) {
|
||||
CallGetDashboardVersions(sc)
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
|
||||
postDashboardScenario("When calling POST on", "/api/dashboards", "/api/dashboards", role, cmd, func(sc *scenarioContext) {
|
||||
CallPostDashboard(sc)
|
||||
So(sc.resp.Code, ShouldEqual, 200)
|
||||
})
|
||||
})
|
||||
|
||||
Convey("When user is an Org Viewer but has an admin permission", func() {
|
||||
role := m.ROLE_VIEWER
|
||||
|
||||
mockResult := []*m.DashboardAclInfoDTO{
|
||||
{Id: 1, OrgId: 1, DashboardId: 2, UserId: 1, Permission: m.PERMISSION_ADMIN},
|
||||
}
|
||||
|
||||
bus.AddHandler("test", func(query *m.GetDashboardAclInfoListQuery) error {
|
||||
query.Result = mockResult
|
||||
return nil
|
||||
})
|
||||
|
||||
loggedInUserScenarioWithRole("When calling GET on", "GET", "/api/dashboards/2", "/api/dashboards/:id", role, func(sc *scenarioContext) {
|
||||
dash := GetDashboardShouldReturn200(sc)
|
||||
|
||||
Convey("Should be able to get dashboard with edit rights", func() {
|
||||
So(dash.Meta.CanEdit, ShouldBeTrue)
|
||||
So(dash.Meta.CanSave, ShouldBeTrue)
|
||||
So(dash.Meta.CanAdmin, ShouldBeTrue)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ type DashboardMeta struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
CanSave bool `json:"canSave"`
|
||||
CanEdit bool `json:"canEdit"`
|
||||
CanAdmin bool `json:"canAdmin"`
|
||||
CanStar bool `json:"canStar"`
|
||||
Slug string `json:"slug"`
|
||||
Expires time.Time `json:"expires"`
|
||||
|
||||
@@ -168,11 +168,13 @@ export class NavModelSrv {
|
||||
clickHandler: () => dashNavCtrl.openEditView('annotations')
|
||||
});
|
||||
|
||||
menu.push({
|
||||
title: 'Permissions...',
|
||||
icon: 'fa fa-fw fa-lock',
|
||||
clickHandler: () => dashNavCtrl.openEditView('permissions')
|
||||
});
|
||||
if (dashboard.meta.canAdmin) {
|
||||
menu.push({
|
||||
title: 'Permissions...',
|
||||
icon: 'fa fa-fw fa-lock',
|
||||
clickHandler: () => dashNavCtrl.openEditView('permissions')
|
||||
});
|
||||
}
|
||||
|
||||
if (!dashboard.meta.isHome) {
|
||||
menu.push({
|
||||
|
||||
@@ -45,9 +45,6 @@ export class AclCtrl {
|
||||
|
||||
sortItems() {
|
||||
this.items = _.orderBy(this.items, ['sortRank', 'sortName'], ['desc', 'asc']);
|
||||
for (let i of this.items) {
|
||||
console.log(i.sortRank);
|
||||
}
|
||||
}
|
||||
|
||||
prepareViewModel(item: DashboardAcl): DashboardAcl {
|
||||
@@ -69,9 +66,6 @@ export class AclCtrl {
|
||||
item.nameHtml = this.$sce.trustAsHtml(`Everyone with <span class="query-keyword">${item.role}</span> Role`);
|
||||
item.sortName = item.role;
|
||||
item.sortRank = 30;
|
||||
if (item.role === 'Viewer') {
|
||||
item.sortRank += 2;
|
||||
}
|
||||
if (item.role === 'Viewer') {
|
||||
item.sortRank += 1;
|
||||
}
|
||||
@@ -100,7 +94,7 @@ export class AclCtrl {
|
||||
}
|
||||
|
||||
return this.backendSrv.post(`/api/dashboards/id/${this.dashboard.id}/acl`, { items: updated }).then(() => {
|
||||
this.dismiss();
|
||||
return this.dismiss();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2,12 +2,16 @@ import {describe, beforeEach, it, expect, sinon, angularMocks} from 'test/lib/co
|
||||
import {AclCtrl} from '../acl';
|
||||
|
||||
describe('AclCtrl', () => {
|
||||
var ctx: any = {};
|
||||
var backendSrv = {
|
||||
const ctx: any = {};
|
||||
const backendSrv = {
|
||||
get: sinon.stub().returns(Promise.resolve([])),
|
||||
post: sinon.stub().returns(Promise.resolve([]))
|
||||
};
|
||||
|
||||
const dashboardSrv = {
|
||||
getCurrent: sinon.stub().returns({id: 1})
|
||||
};
|
||||
|
||||
beforeEach(angularMocks.module('grafana.core'));
|
||||
beforeEach(angularMocks.module('grafana.controllers'));
|
||||
|
||||
@@ -18,64 +22,59 @@ describe('AclCtrl', () => {
|
||||
ctx.ctrl = $controller(AclCtrl, {
|
||||
$scope: ctx.scope,
|
||||
backendSrv: backendSrv,
|
||||
dashboardSrv: dashboardSrv
|
||||
}, {
|
||||
dashboard: {id: 1}
|
||||
dismiss: () => { return; }
|
||||
});
|
||||
}));
|
||||
|
||||
describe('when user permission is to be added', () => {
|
||||
beforeEach(done => {
|
||||
describe('when permissions are added', () => {
|
||||
beforeEach(() => {
|
||||
backendSrv.get.reset();
|
||||
backendSrv.post.reset();
|
||||
ctx.ctrl.type = 'User';
|
||||
ctx.ctrl.userId = 2;
|
||||
ctx.ctrl.permission = 1;
|
||||
|
||||
ctx.ctrl.addPermission().then(() => {
|
||||
const userItem = {
|
||||
id: 2,
|
||||
login: 'user2',
|
||||
};
|
||||
|
||||
ctx.ctrl.userPicked(userItem);
|
||||
|
||||
const userGroupItem = {
|
||||
id: 2,
|
||||
name: 'ug1',
|
||||
};
|
||||
|
||||
ctx.ctrl.groupPicked(userGroupItem);
|
||||
|
||||
ctx.ctrl.newType = 'Editor';
|
||||
ctx.ctrl.typeChanged();
|
||||
|
||||
ctx.ctrl.newType = 'Viewer';
|
||||
ctx.ctrl.typeChanged();
|
||||
});
|
||||
|
||||
it('should sort the result by role, user group and user', () => {
|
||||
expect(ctx.ctrl.items[0].role).to.eql('Viewer');
|
||||
expect(ctx.ctrl.items[1].role).to.eql('Editor');
|
||||
expect(ctx.ctrl.items[2].userGroupId).to.eql(2);
|
||||
expect(ctx.ctrl.items[3].userId).to.eql(2);
|
||||
});
|
||||
|
||||
it('should save permissions to db', (done) => {
|
||||
ctx.ctrl.update().then(() => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse the result and save to db', () => {
|
||||
expect(backendSrv.post.getCall(0).args[0]).to.eql('/api/dashboards/id/1/acl');
|
||||
expect(backendSrv.post.getCall(0).args[1].userId).to.eql(2);
|
||||
expect(backendSrv.post.getCall(0).args[1].permissions).to.eql(1);
|
||||
});
|
||||
|
||||
it('should refresh the list after saving.', () => {
|
||||
expect(backendSrv.get.getCall(0).args[0]).to.eql('/api/dashboards/id/1/acl');
|
||||
});
|
||||
|
||||
it('should reset userId', () => {
|
||||
expect(ctx.ctrl.userId).to.eql(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when user group permission is to be added', () => {
|
||||
beforeEach(done => {
|
||||
backendSrv.get.reset();
|
||||
backendSrv.post.reset();
|
||||
ctx.ctrl.type = 'User Group';
|
||||
ctx.ctrl.userGroupId = 2;
|
||||
ctx.ctrl.permission = 1;
|
||||
|
||||
ctx.ctrl.addPermission().then(() => {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should parse the result and save to db', () => {
|
||||
expect(backendSrv.post.getCall(0).args[0]).to.eql('/api/dashboards/id/1/acl');
|
||||
expect(backendSrv.post.getCall(0).args[1].userGroupId).to.eql(2);
|
||||
expect(backendSrv.post.getCall(0).args[1].permissions).to.eql(1);
|
||||
});
|
||||
|
||||
it('should refresh the list after saving.', () => {
|
||||
expect(backendSrv.get.getCall(0).args[0]).to.eql('/api/dashboards/id/1/acl');
|
||||
});
|
||||
|
||||
it('should reset userGroupId', () => {
|
||||
expect(ctx.ctrl.userGroupId).to.eql(null);
|
||||
expect(backendSrv.post.getCall(0).args[1].items[0].role).to.eql('Viewer');
|
||||
expect(backendSrv.post.getCall(0).args[1].items[0].permission).to.eql(1);
|
||||
expect(backendSrv.post.getCall(0).args[1].items[1].role).to.eql('Editor');
|
||||
expect(backendSrv.post.getCall(0).args[1].items[1].permission).to.eql(1);
|
||||
expect(backendSrv.post.getCall(0).args[1].items[2].userGroupId).to.eql(2);
|
||||
expect(backendSrv.post.getCall(0).args[1].items[2].permission).to.eql(1);
|
||||
expect(backendSrv.post.getCall(0).args[1].items[3].userId).to.eql(2);
|
||||
expect(backendSrv.post.getCall(0).args[1].items[3].permission).to.eql(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</h2>
|
||||
|
||||
<ul class="gf-tabs">
|
||||
<li class="gf-tabs-item" ng-repeat="tab in ::['General', 'Rows', 'Links', 'Time picker', 'Permissions']">
|
||||
<li class="gf-tabs-item" ng-repeat="tab in ::['General', 'Rows', 'Links', 'Time picker']">
|
||||
<a class="gf-tabs-link" ng-click="editor.index = $index" ng-class="{active: editor.index === $index}">
|
||||
{{::tab}}
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user