[attr.disabled]="!editing ? true : null"
cdsText
/>
- <cds-icon-button
- kind="ghost"
- size="md"
- (click)="updateSiteName()"
- [title]="editing ? 'Save' : 'Edit'"
- >
- <svg
- [cdsIcon]="icons.edit"
- [size]="icons.size32"
- class="cds--btn__icon"
- *ngIf="!editing"
- ></svg>
- <svg
- [cdsIcon]="icons.check"
- [size]="icons.size32"
- class="cds--btn__icon"
- *ngIf="editing"
- ></svg>
- </cds-icon-button>
+ @if (permission.update) {
+ <cds-icon-button
+ kind="ghost"
+ size="md"
+ (click)="updateSiteName()"
+ [title]="editing ? 'Save' : 'Edit'"
+ >
+ <svg
+ [cdsIcon]="icons.edit"
+ [size]="icons.size32"
+ class="cds--btn__icon"
+ *ngIf="!editing"
+ ></svg>
+ <svg
+ [cdsIcon]="icons.check"
+ [size]="icons.size32"
+ class="cds--btn__icon"
+ *ngIf="editing"
+ ></svg>
+ </cds-icon-button>
+ }
<cd-copy-2-clipboard-button
[source]="siteName"
[byId]="false"
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
+import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import { NgbNavModule, NgbProgressbarModule } from '@ng-bootstrap/ng-bootstrap';
import { of } from 'rxjs';
import { RbdMirroringService } from '~/app/shared/api/rbd-mirroring.service';
+import { Permission } from '~/app/shared/models/permissions';
import { SharedModule } from '~/app/shared/shared.module';
import { configureTestBed } from '~/testing/unit-test-helper';
import { DaemonListComponent } from '../daemon-list/daemon-list.component';
expect(rbdMirroringService.setSiteName).toHaveBeenCalledWith('new-site-A');
});
});
+
+ describe('site name edit button visibility', () => {
+ const editButton = () => fixture.debugElement.query(By.css('cds-icon-button'));
+
+ it('should show the edit button when user has update permission', () => {
+ component.permission = new Permission(['read', 'update']);
+ fixture.detectChanges();
+ expect(editButton()).toBeTruthy();
+ });
+
+ it('should hide the edit button when user lacks update permission', () => {
+ component.permission = new Permission(['read']);
+ fixture.detectChanges();
+ expect(editButton()).toBeFalsy();
+ });
+ });
});
User management
</button>
</li>
- <li
- class="cds--overflow-menu-options__option mb-2"
- *ngIf="configOptPermission.read"
- >
- <button
- routerLink="/telemetry"
- class="cds--overflow-menu-options__btn"
- type="button"
- i18n
- >
- Telemetry configuration
- </button>
- </li>
+ @if (configOptPermission.read) {
+ <li class="cds--overflow-menu-options__option mb-2">
+ <button
+ routerLink="/telemetry"
+ class="cds--overflow-menu-options__btn"
+ type="button"
+ i18n
+ >
+ Telemetry configuration
+ </button>
+ </li>
+ }
</cds-overflow-menu>
<ng-template #customTrigger>
- <svg
- cdsIcon="settings"
- size="20"
- title="Settings"
- *ngIf="userPermission.read"
- ></svg>
+ @if (userPermission.read || configOptPermission.read) {
+ <svg
+ cdsIcon="settings"
+ size="20"
+ title="Settings"
+ ></svg>
+ }
<span
i18n
class="d-md-none"
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { By } from '@angular/platform-browser';
+import { Permission } from '~/app/shared/models/permissions';
import { SharedModule } from '~/app/shared/shared.module';
import { configureTestBed } from '~/testing/unit-test-helper';
import { AdministrationComponent } from './administration.component';
it('should create', () => {
expect(component).toBeTruthy();
});
+
+ describe('settings icon visibility', () => {
+ const setPermissions = (user: string[], configOpt: string[]) => {
+ component.userPermission = new Permission(user);
+ component.configOptPermission = new Permission(configOpt);
+ fixture.detectChanges();
+ };
+
+ const settingsIcon = () => fixture.debugElement.query(By.css('[cdsIcon="settings"]'));
+
+ it('should show the settings icon when user has user.read', () => {
+ setPermissions(['read'], []);
+ expect(settingsIcon()).toBeTruthy();
+ });
+
+ it('should show the settings icon when user has configOpt.read', () => {
+ setPermissions([], ['read']);
+ expect(settingsIcon()).toBeTruthy();
+ });
+
+ it('should show the settings icon when user has both user.read and configOpt.read', () => {
+ setPermissions(['read'], ['read']);
+ expect(settingsIcon()).toBeTruthy();
+ });
+
+ it('should hide the settings icon when user has neither user.read nor configOpt.read', () => {
+ setPermissions([], []);
+ expect(settingsIcon()).toBeFalsy();
+ });
+ });
});
);
});
- it('should redirect 403', () => {
+ it('should redirect 403 for api/ requests', () => {
runRouterTest(
{
status: 403
},
- [['error'], {'state': {'header': 'Access Denied', 'icon': 'locked', 'message': 'Sorry, you don’t have permission to view this page or resource.', 'source': 'forbidden'}}] // prettier-ignore
+ [['error'], {'state': {'header': 'Access Denied', 'icon': 'locked', 'message': "Sorry, you don't have permission to view this page or resource.", 'source': 'forbidden'}}] // prettier-ignore
);
});
+ it('should not redirect 403 for ui-api/ requests', () => {
+ const uiApiUrl = 'ui-api/prometheus/prometheus-api-host';
+ httpClient.get(uiApiUrl).subscribe(
+ () => true,
+ (_resp) => undefined
+ );
+ httpTesting.expectOne(uiApiUrl).error(new ErrorEvent('abc'), { status: 403 });
+ httpTesting.verify();
+ expect(router.navigate).not.toHaveBeenCalled();
+ });
+
it('should show notification (error string)', () => {
runNotificationTest(
'foobar',
this.router.navigate(['/login']);
break;
case 403:
- this.router.navigate(['error'], {
- state: {
- message: $localize`Sorry, you don’t have permission to view this page or resource.`,
- header: $localize`Access Denied`,
- icon: 'locked',
- source: 'forbidden'
- }
- });
+ if (!request.url.startsWith('ui-api/')) {
+ this.router.navigate(['error'], {
+ state: {
+ message: $localize`Sorry, you don't have permission to view this page or resource.`,
+ header: $localize`Access Denied`,
+ icon: 'locked',
+ source: 'forbidden'
+ }
+ });
+ }
break;
default:
timeoutId = this.prepareNotification(resp);