def test_data_daemons(self):
return self.ORCHESTRATOR_TEST_DATA['daemons']
- @DashboardTestCase.RunAs('test', 'test', ['block-manager'])
+ @DashboardTestCase.RunAs('test', 'test', ['rgw-manager'])
def test_access_permissions(self):
self._get(self.URL_HOST, version='1.1')
self.assertStatus(403)
'quorum': data.get('quorum', {})
}
- if self._has_permissions(Permission.READ, Scope.OSD):
+ if (self._has_permissions(Permission.READ, Scope.OSD)
+ or self._has_permissions(Permission.READ, Scope.POOL)):
summary['osdmap'] = {
'in': data.get('osdmap', {}).get('num_in_osds'),
'up': data.get('osdmap', {}).get('num_up_osds'),
></a
>
</ng-container>
- @if (canViewSilences) {
+ @if (prometheusPermissions.read) {
<ng-container ngbNavItem>
- <a class="nav-link"
- routerLink="/monitoring/silences"
- routerLinkActive="active"
- ariaCurrentWhenActive="page"
- [routerLinkActiveOptions]="{exact: true}"
- i18n>Silences</a>
+ <a
+ class="nav-link"
+ routerLink="/monitoring/silences"
+ routerLinkActive="active"
+ ariaCurrentWhenActive="page"
+ [routerLinkActiveOptions]="{ exact: true }"
+ i18n
+ >Silences</a
+ >
</ng-container>
}
<ng-container ngbNavItem>
});
it('should show silences to users with read access', () => {
- expect(component.canViewSilences).toBe(true);
+ expect(component.prometheusPermissions.read).toBe(true);
});
});
import { PrometheusAlertService } from '~/app/shared/services/prometheus-alert.service';
import { AuthStorageService } from '~/app/shared/services/auth-storage.service';
+import { Permission } from '~/app/shared/models/permissions';
@Component({
selector: 'cd-prometheus-tabs',
standalone: false
})
export class PrometheusTabsComponent {
- canViewSilences: boolean;
+ prometheusPermissions: Permission;
constructor(
public prometheusAlertService: PrometheusAlertService,
private authStorageService: AuthStorageService
) {
- const prometheusPermission = this.authStorageService.getPermissions().prometheus;
- this.canViewSilences = prometheusPermission.read;
+ this.prometheusPermissions = this.authStorageService.getPermissions().prometheus;
}
}
);
readonly hasNoOSDs$ = this.healthData$.pipe(
- map((data: HealthSnapshotMap) => (data?.osdmap?.num_osds ?? 0) === 0),
+ map((data: HealthSnapshotMap) => {
+ if (data?.osdmap == null) {
+ return false;
+ }
+ return data.osdmap.num_osds === 0;
+ }),
shareReplay({ bufferSize: 1, refCount: true })
);
></svg>
</a>
</li>
- <cds-overflow-menu-option (click)="openAboutModal()"
- i18n>About</cds-overflow-menu-option>
+ <cds-overflow-menu-option
+ (click)="openAboutModal()"
+ i18n
+ >About</cds-overflow-menu-option
+ >
@if (configOptPermission.read) {
- <cds-overflow-menu-option (click)="openFeedbackModal()"
- i18n>Report an issue...</cds-overflow-menu-option>
+ <cds-overflow-menu-option
+ (click)="openFeedbackModal()"
+ i18n
+ >Report an issue...</cds-overflow-menu-option
+ >
}
</cds-overflow-menu>
expect(component).toBeTruthy();
});
+ it('should show report issue when config-opt is readable', () => {
+ const options = fixture.debugElement.queryAll(By.css('cds-overflow-menu-option'));
+ // About + Report an issue (Documentation and API are plain <li> links)
+ expect(options.length).toBe(2);
+ expect(options.map((o) => o.nativeElement.textContent.trim())).toEqual([
+ 'About',
+ 'Report an issue...'
+ ]);
+ });
+
it('should hide report issue when config-opt is not readable', () => {
permissions.configOpt = new Permission([]);
(TestBed.inject(AuthStorageService).getPermissions as jasmine.Spy).and.returnValue(permissions);
fixture.detectChanges();
const options = fixture.debugElement.queryAll(By.css('cds-overflow-menu-option'));
- expect(options.length).toBe(3);
+ // Only About remains; Documentation and API are plain <li> links
+ expect(options.length).toBe(1);
+ expect(options[0].nativeElement.textContent.trim()).toBe('About');
});
});
# read-only role provides read-only permission for all scopes
READ_ONLY_ROLE = Role(
'read-only',
- 'allows read permission for all security scope except user, dashboard settings and config-opt', {
+ 'allows read permission for all security scope except user, '
+ 'dashboard settings and config-opt', {
scope_name: [_P.READ] for scope_name in Scope.all_scopes()
if scope_name not in (Scope.USER, Scope.DASHBOARD_SETTINGS, Scope.CONFIG_OPT)
})
Scope.POOL: [_P.READ],
Scope.ISCSI: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
Scope.RBD_MIRRORING: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
+ Scope.HOSTS: [_P.READ],
Scope.GRAFANA: [_P.READ],
Scope.NVME_OF: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
Scope.PROMETHEUS: [_P.READ]
'smb-manager', 'allows full permissions for the smb scope', {
Scope.SMB: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
Scope.HOSTS: [_P.READ],
+ Scope.POOL: [_P.READ],
Scope.CEPHFS: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
Scope.RGW: [_P.READ, _P.CREATE, _P.UPDATE, _P.DELETE],
Scope.GRAFANA: [_P.READ],
self.assertEqual(role['name'], 'read-only')
self.assertEqual(
role['description'],
- 'allows read permission for all security scope except user, dashboard settings and config-opt'
+ 'allows read permission for all security scope except user, '
+ 'dashboard settings and config-opt'
)
def test_cluster_manager_role_has_pool_read(self):
role = self.exec_cmd('ac-role-show', rolename='smb-manager')
self.assertEqual(role['scopes_permissions'][Scope.HOSTS], [Permission.READ])
+ def test_smb_manager_role_has_pool_read(self):
+ role = self.exec_cmd('ac-role-show', rolename='smb-manager')
+ self.assertEqual(role['scopes_permissions'][Scope.POOL], [Permission.READ])
+
+ def test_block_manager_role_has_pool_read(self):
+ role = self.exec_cmd('ac-role-show', rolename='block-manager')
+ self.assertEqual(role['scopes_permissions'][Scope.POOL], [Permission.READ])
+
+ def test_block_manager_role_has_hosts_read(self):
+ role = self.exec_cmd('ac-role-show', rolename='block-manager')
+ self.assertEqual(role['scopes_permissions'][Scope.HOSTS], [Permission.READ])
+
def test_delete_system_role(self):
with self.assertRaises(CmdException) as ctx:
self.exec_cmd('ac-role-delete', rolename='administrator')