Merge pull request #24851 from rhcs-dashboard/grafana-roles

mgr/dashboard: Show/Hide Grafana tabs according to user role

Reviewed-by: Alfonso Martínez <almartin@redhat.com>
Reviewed-by: Ernesto Puerta <epuertat@redhat.com>
Reviewed-by: Tiago Melo <tmelo@suse.com>
Reviewed-by: Volker Theile <vtheile@suse.com>
This commit is contained in:
Lenz Grimmer 2018-11-20 10:21:04 +01:00 committed by GitHub
commit ac743f2a91
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 74 additions and 37 deletions

View File

@ -89,12 +89,8 @@ class Grafana(BaseController):
@Endpoint()
@ReadPermission
def status(self):
grafana = GrafanaRestClient.instance()
available, msg = grafana.is_service_online()
response = {'available': available}
if msg:
response['message'] = msg
def url(self):
response = {'instance': Settings.GRAFANA_API_URL}
return response

View File

@ -41,6 +41,7 @@
</cd-cephfs-clients>
</tab>
<tab i18n-heading
*ngIf="grafanaPermission.read"
heading="Performance Details">
<cd-grafana [grafanaPath]="'rRfFzWtik/mds-performance?var-mds_servers=mds.' + grafanaId"
grafanaStyle="one">

View File

@ -5,8 +5,10 @@ import * as _ from 'lodash';
import { CephfsService } from '../../../shared/api/cephfs.service';
import { CdTableSelection } from '../../../shared/models/cd-table-selection';
import { Permission } from '../../../shared/models/permissions';
import { DimlessBinaryPipe } from '../../../shared/pipes/dimless-binary.pipe';
import { DimlessPipe } from '../../../shared/pipes/dimless.pipe';
import { AuthStorageService } from '../../../shared/services/auth-storage.service';
@Component({
selector: 'cd-cephfs-detail',
@ -32,16 +34,20 @@ export class CephfsDetailComponent implements OnChanges, OnInit {
clientCount: number;
mdsCounters = {};
grafanaId: any;
grafanaPermission: Permission;
objectValues = Object.values;
clientsSelect = false;
constructor(
private authStorageService: AuthStorageService,
private cephfsService: CephfsService,
private dimlessBinary: DimlessBinaryPipe,
private dimless: DimlessPipe,
private i18n: I18n
) {}
) {
this.grafanaPermission = this.authStorageService.getPermissions().grafana;
}
ngOnChanges() {
if (this.selection.hasSelection) {

View File

@ -1,4 +1,4 @@
<tabset *ngIf="selection.hasSingleSelection">
<tabset *ngIf="selection.hasSingleSelection && grafanaPermission.read">
<tab i18n-heading
heading="Performance Details">
<cd-grafana [grafanaPath]="'7IGu2Ttmz/host-details?'"

View File

@ -1,6 +1,8 @@
import { Component, Input, OnChanges } from '@angular/core';
import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
import { Permission } from '../../../../shared/models/permissions';
import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
@Component({
selector: 'cd-host-details',
@ -8,11 +10,14 @@ import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
styleUrls: ['./host-details.component.scss']
})
export class HostDetailsComponent implements OnChanges {
grafanaPermission: Permission;
@Input()
selection: CdTableSelection;
host: any;
constructor() {}
constructor(private authStorageService: AuthStorageService) {
this.grafanaPermission = this.authStorageService.getPermissions().grafana;
}
ngOnChanges() {
if (this.selection.hasSelection) {

View File

@ -25,6 +25,7 @@
</cd-table>
</tab>
<tab i18n-heading
*ngIf="permissions.grafana.read"
heading="Overall Performance">
<cd-grafana [grafanaPath]="'lxnjcTAmk/host-overview?'"
grafanaStyle="two">

View File

@ -42,6 +42,7 @@
</div>
</tab>
<tab i18n-heading
*ngIf="grafanaPermission.read"
heading="Performance Details">
<cd-grafana [grafanaPath]="'MKj_9ipiz/osd-device-details?var-osd_id=' + osd['id']"
grafanaStyle="GrafanaStyles.two">

View File

@ -4,6 +4,8 @@ import * as _ from 'lodash';
import { OsdService } from '../../../../shared/api/osd.service';
import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
import { Permission } from '../../../../shared/models/permissions';
import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
@Component({
selector: 'cd-osd-details',
@ -15,8 +17,11 @@ export class OsdDetailsComponent implements OnChanges {
selection: CdTableSelection;
osd: any;
grafanaPermission: Permission;
constructor(private osdService: OsdService) {}
constructor(private osdService: OsdService, private authStorageService: AuthStorageService) {
this.grafanaPermission = this.authStorageService.getPermissions().grafana;
}
ngOnChanges() {
this.osd = {

View File

@ -8,7 +8,7 @@
(updateSelection)="updateSelection($event)"
[updateSelectionOnRefresh]="'never'">
<div class="table-actions btn-toolbar">
<cd-table-actions [permission]="permission"
<cd-table-actions [permission]="permissions.osd"
[selection]="selection"
class="btn-group"
[tableActions]="tableActions">
@ -46,6 +46,7 @@
</ng-template>
</tab>
<tab i18n-heading
*ngIf="permissions.grafana.read"
heading="Overall Performance">
<cd-grafana [grafanaPath]="'lo02I1Aiz/osd-overview?'"
grafanaStyle="three">

View File

@ -51,6 +51,7 @@ describe('OsdListComponent', () => {
component.selection.selected = selection;
component.selection.update();
component.osds = data;
component.permissions = fakeAuthStorageService.getPermissions();
};
const openActionModal = (actionName) => {
@ -110,7 +111,7 @@ describe('OsdListComponent', () => {
};
beforeEach(() => {
permissionHelper = new PermissionHelper(component.permission, () =>
permissionHelper = new PermissionHelper(component.permissions.osd, () =>
getTableActionComponent()
);
scenario = {

View File

@ -12,7 +12,7 @@ import { CellTemplate } from '../../../../shared/enum/cell-template.enum';
import { CdTableAction } from '../../../../shared/models/cd-table-action';
import { CdTableColumn } from '../../../../shared/models/cd-table-column';
import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
import { Permission } from '../../../../shared/models/permissions';
import { Permissions } from '../../../../shared/models/permissions';
import { DimlessBinaryPipe } from '../../../../shared/pipes/dimless-binary.pipe';
import { AuthStorageService } from '../../../../shared/services/auth-storage.service';
import { OsdFlagsModalComponent } from '../osd-flags-modal/osd-flags-modal.component';
@ -40,7 +40,7 @@ export class OsdListComponent implements OnInit {
@ViewChild('safeToDestroyBodyTpl')
safeToDestroyBodyTpl: TemplateRef<any>;
permission: Permission;
permissions: Permissions;
tableActions: CdTableAction[];
bsModalRef: BsModalRef;
columns: CdTableColumn[];
@ -59,7 +59,7 @@ export class OsdListComponent implements OnInit {
private modalService: BsModalService,
private i18n: I18n
) {
this.permission = this.authStorageService.getPermissions().osd;
this.permissions = this.authStorageService.getPermissions();
this.tableActions = [
{
name: this.i18n('Scrub'),

View File

@ -10,7 +10,7 @@
selectionType="single"
(updateSelection)="updateSelection($event)">
<cd-table-actions class="table-actions"
[permission]="permission"
[permission]="permissions.pool"
[selection]="selection"
[tableActions]="tableActions">
</cd-table-actions>
@ -23,6 +23,7 @@
</cd-table-key-value>
</tab>
<tab i18n-heading
*ngIf="permissions.grafana.read"
heading="Performance Details">
<cd-grafana [grafanaPath]="'8ypfkWpik/ceph-pool-detail?var-pool_name='
+ selection.first()['pool_name']"
@ -34,6 +35,7 @@
</tab>
<tab i18n-heading
*ngIf="permissions.grafana.read"
heading="Overall Performance">
<cd-grafana [grafanaPath]="'z99hzWtmk/ceph-pools-overview?'"
grafanaStyle="two">

View File

@ -37,7 +37,7 @@ describe('PoolListComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(PoolListComponent);
component = fixture.componentInstance;
component.permission.read = true;
component.permissions.pool.read = true;
poolService = TestBed.get(PoolService);
fixture.detectChanges();
});

View File

@ -13,7 +13,7 @@ import { CdTableColumn } from '../../../shared/models/cd-table-column';
import { CdTableSelection } from '../../../shared/models/cd-table-selection';
import { ExecutingTask } from '../../../shared/models/executing-task';
import { FinishedTask } from '../../../shared/models/finished-task';
import { Permission } from '../../../shared/models/permissions';
import { Permissions } from '../../../shared/models/permissions';
import { AuthStorageService } from '../../../shared/services/auth-storage.service';
import { TaskListService } from '../../../shared/services/task-list.service';
import { TaskWrapperService } from '../../../shared/services/task-wrapper.service';
@ -34,7 +34,7 @@ export class PoolListComponent implements OnInit {
selection = new CdTableSelection();
modalRef: BsModalRef;
executingTasks: ExecutingTask[] = [];
permission: Permission;
permissions: Permissions;
tableActions: CdTableAction[];
viewCacheStatusList: any[];
@ -46,7 +46,7 @@ export class PoolListComponent implements OnInit {
private modalService: BsModalService,
private i18n: I18n
) {
this.permission = this.authStorageService.getPermissions().pool;
this.permissions = this.authStorageService.getPermissions();
this.tableActions = [
{
permission: 'create',

View File

@ -12,6 +12,7 @@
</cd-table-performance-counter>
</tab>
<tab i18n-heading
*ngIf="grafanaPermission.read"
heading="Performance Details">
<cd-grafana [grafanaPath]="'x5ARzZtmk/rgw-instance-detail?var-rgw_servers=rgw.' + this.selection.first().id"
grafanaStyle="one">

View File

@ -4,6 +4,8 @@ import * as _ from 'lodash';
import { RgwDaemonService } from '../../../shared/api/rgw-daemon.service';
import { CdTableSelection } from '../../../shared/models/cd-table-selection';
import { Permission } from '../../../shared/models/permissions';
import { AuthStorageService } from '../../../shared/services/auth-storage.service';
@Component({
selector: 'cd-rgw-daemon-details',
@ -13,11 +15,17 @@ import { CdTableSelection } from '../../../shared/models/cd-table-selection';
export class RgwDaemonDetailsComponent implements OnChanges {
metadata: any;
serviceId = '';
grafanaPermission: Permission;
@Input()
selection: CdTableSelection;
constructor(private rgwDaemonService: RgwDaemonService) {}
constructor(
private rgwDaemonService: RgwDaemonService,
private authStorageService: AuthStorageService
) {
this.grafanaPermission = this.authStorageService.getPermissions().grafana;
}
ngOnChanges() {
// Get the service id of the first selected row.

View File

@ -12,6 +12,7 @@
</tab>
<tab i18n-heading
*ngIf="grafanaPermission.read"
heading="Overall Performance">
<cd-grafana [grafanaPath]="'WAkugZpiz/rgw-overview?'"
grafanaStyle="two">

View File

@ -6,7 +6,9 @@ import { RgwDaemonService } from '../../../shared/api/rgw-daemon.service';
import { CdTableColumn } from '../../../shared/models/cd-table-column';
import { CdTableFetchDataContext } from '../../../shared/models/cd-table-fetch-data-context';
import { CdTableSelection } from '../../../shared/models/cd-table-selection';
import { Permission } from '../../../shared/models/permissions';
import { CephShortVersionPipe } from '../../../shared/pipes/ceph-short-version.pipe';
import { AuthStorageService } from '../../../shared/services/auth-storage.service';
@Component({
selector: 'cd-rgw-daemon-list',
@ -17,12 +19,15 @@ export class RgwDaemonListComponent {
columns: CdTableColumn[] = [];
daemons: object[] = [];
selection: CdTableSelection = new CdTableSelection();
grafanaPermission: Permission;
constructor(
private rgwDaemonService: RgwDaemonService,
private authStorageService: AuthStorageService,
cephShortVersionPipe: CephShortVersionPipe,
private i18n: I18n
) {
this.grafanaPermission = this.authStorageService.getPermissions().grafana;
this.columns = [
{
name: this.i18n('ID'),

View File

@ -2,19 +2,19 @@ import { HttpClientTestingModule, HttpTestingController } from '@angular/common/
import { TestBed } from '@angular/core/testing';
import { configureTestBed } from '../../../testing/unit-test-helper';
import { SettingsService } from './settings.service';
import { GrafanaService } from './grafana.service';
describe('SettingsService', () => {
let service: SettingsService;
describe('GrafanaService', () => {
let service: GrafanaService;
let httpTesting: HttpTestingController;
configureTestBed({
providers: [SettingsService],
providers: [GrafanaService],
imports: [HttpClientTestingModule]
});
beforeEach(() => {
service = TestBed.get(SettingsService);
service = TestBed.get(GrafanaService);
httpTesting = TestBed.get(HttpTestingController);
});
@ -28,7 +28,7 @@ describe('SettingsService', () => {
it('should get protocol', () => {
service.getGrafanaApiUrl().subscribe();
const req = httpTesting.expectOne('api/settings/GRAFANA_API_URL');
const req = httpTesting.expectOne('api/grafana/url');
expect(req.request.method).toBe('GET');
});
});

View File

@ -6,10 +6,10 @@ import { ApiModule } from './api.module';
@Injectable({
providedIn: ApiModule
})
export class SettingsService {
export class GrafanaService {
constructor(private http: HttpClient) {}
getGrafanaApiUrl() {
return this.http.get('api/settings/GRAFANA_API_URL');
return this.http.get('api/grafana/url');
}
}

View File

@ -5,7 +5,8 @@ import { RouterTestingModule } from '@angular/router/testing';
import { AlertModule } from 'ngx-bootstrap/alert';
import { configureTestBed, i18nProviders } from '../../../../testing/unit-test-helper';
import { SettingsService } from '../../../shared/api/settings.service';
import { GrafanaService } from '../../../shared/api/grafana.service';
import { SummaryService } from '../../../shared/services/summary.service';
import { CephReleaseNamePipe } from '../../pipes/ceph-release-name.pipe';
import { InfoPanelComponent } from '../info-panel/info-panel.component';
@ -19,7 +20,7 @@ describe('GrafanaComponent', () => {
configureTestBed({
declarations: [GrafanaComponent, InfoPanelComponent, LoadingPanelComponent],
imports: [AlertModule.forRoot(), HttpClientTestingModule, RouterTestingModule],
providers: [CephReleaseNamePipe, SettingsService, SummaryService, i18nProviders]
providers: [CephReleaseNamePipe, GrafanaService, SummaryService, i18nProviders]
});
beforeEach(() => {

View File

@ -3,9 +3,9 @@ import { Component, Input, OnChanges, OnInit } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { SafeUrl } from '@angular/platform-browser';
import { SettingsService } from '../../api/settings.service';
import { CephReleaseNamePipe } from '../../pipes/ceph-release-name.pipe';
import { SummaryService } from '../../services/summary.service';
import { GrafanaService } from '../../../shared/api/grafana.service';
import { CephReleaseNamePipe } from '../../../shared/pipes/ceph-release-name.pipe';
import { SummaryService } from '../../../shared/services/summary.service';
@Component({
selector: 'cd-grafana',
@ -38,7 +38,7 @@ export class GrafanaComponent implements OnInit, OnChanges {
constructor(
private summaryService: SummaryService,
private sanitizer: DomSanitizer,
private settingsService: SettingsService,
private grafanaService: GrafanaService,
private cephReleaseNamePipe: CephReleaseNamePipe
) {}
@ -64,8 +64,8 @@ export class GrafanaComponent implements OnInit, OnChanges {
}, 0);
});
this.settingsService.getGrafanaApiUrl().subscribe((data: any) => {
this.grafanaUrl = data.value;
this.grafanaService.getGrafanaApiUrl().subscribe((data: any) => {
this.grafanaUrl = data.instance;
if (this.grafanaUrl === '') {
this.grafanaExist = false;
return;

View File

@ -26,6 +26,7 @@ export class Permissions {
manager: Permission;
log: Permission;
user: Permission;
grafana: Permission;
constructor(serverPermissions: any) {
this.hosts = new Permission(serverPermissions['hosts']);
@ -41,5 +42,6 @@ export class Permissions {
this.manager = new Permission(serverPermissions['manager']);
this.log = new Permission(serverPermissions['log']);
this.user = new Permission(serverPermissions['user']);
this.grafana = new Permission(serverPermissions['grafana']);
}
}