Skip to content

Commit

Permalink
NAS-131925: Lock ds groups if system is not enterprise (#11071)
Browse files Browse the repository at this point in the history
Co-authored-by: Boris Vasilenko <[email protected]>
  • Loading branch information
bvasilenko and Boris Vasilenko authored Nov 20, 2024
1 parent 9484b1a commit c3d53b8
Show file tree
Hide file tree
Showing 91 changed files with 298 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
[allowNewEntries]="false"
></ix-chips>

<ix-chips
formControlName="ds_groups"
[label]="'Directory Services Groups' | translate"
[autocompleteProvider]="dsGroupsProvider"
[allowNewEntries]="false"
></ix-chips>
@if(isEnterprise()) {
<ix-chips
formControlName="ds_groups"
[label]="'Directory Services Groups' | translate"
[autocompleteProvider]="dsGroupsProvider"
[allowNewEntries]="false"
></ix-chips>
}

<ix-select
formControlName="roles"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,22 @@ import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { ReactiveFormsModule } from '@angular/forms';
import { MatButtonHarness } from '@angular/material/button/testing';
import { createComponentFactory, mockProvider, Spectator } from '@ngneat/spectator/jest';
import { provideMockStore } from '@ngrx/store/testing';
import { of } from 'rxjs';
import { mockCall, mockApi } from 'app/core/testing/utils/mock-api.utils';
import { mockAuth } from 'app/core/testing/utils/mock-auth.utils';
import { Role } from 'app/enums/role.enum';
import { Group } from 'app/interfaces/group.interface';
import { Privilege, PrivilegeRole } from 'app/interfaces/privilege.interface';
import { DialogService } from 'app/modules/dialog/dialog.service';
import { IxSelectHarness } from 'app/modules/forms/ix-forms/components/ix-select/ix-select.harness';
import { IxFormHarness } from 'app/modules/forms/ix-forms/testing/ix-form.harness';
import { SlideInRef } from 'app/modules/slide-ins/slide-in-ref';
import { SLIDE_IN_DATA } from 'app/modules/slide-ins/slide-in.token';
import { PrivilegeFormComponent } from 'app/pages/credentials/groups/privilege/privilege-form/privilege-form.component';
import { ApiService } from 'app/services/websocket/api.service';
import { selectGeneralConfig } from 'app/store/system-config/system-config.selectors';
import { selectIsEnterprise } from 'app/store/system-info/system-info.selectors';

describe('PrivilegeFormComponent', () => {
let spectator: Spectator<PrivilegeFormComponent>;
Expand Down Expand Up @@ -54,8 +59,26 @@ describe('PrivilegeFormComponent', () => {
{ name: Role.SharingSmbRead, title: Role.SharingSmbRead, builtin: false },
{ name: Role.SharingSmbWrite, title: Role.SharingSmbWrite, builtin: false },
] as PrivilegeRole[]),
mockCall('system.general.update'),
]),
mockProvider(SlideInRef),
mockProvider(DialogService, {
confirm: jest.fn(() => of(true)),
}),
provideMockStore({
selectors: [
{
selector: selectIsEnterprise,
value: true,
},
{
selector: selectGeneralConfig,
value: {
ds_auth: false,
},
},
],
}),
mockAuth(),
{ provide: SLIDE_IN_DATA, useValue: undefined },
],
Expand Down Expand Up @@ -91,7 +114,7 @@ describe('PrivilegeFormComponent', () => {
const saveButton = await loader.getHarness(MatButtonHarness.with({ text: 'Save' }));
await saveButton.click();

expect(api.call).toHaveBeenLastCalledWith('privilege.create', [{
expect(api.call).toHaveBeenCalledWith('privilege.create', [{
ds_groups: [],
local_groups: [],
name: 'new privilege',
Expand Down Expand Up @@ -136,7 +159,7 @@ describe('PrivilegeFormComponent', () => {
const saveButton = await loader.getHarness(MatButtonHarness.with({ text: 'Save' }));
await saveButton.click();

expect(api.call).toHaveBeenLastCalledWith('privilege.update', [10, {
expect(api.call).toHaveBeenCalledWith('privilege.update', [10, {
ds_groups: [],
local_groups: [111, 222],
name: 'updated privilege',
Expand Down Expand Up @@ -175,7 +198,7 @@ describe('PrivilegeFormComponent', () => {
const saveButton = await loader.getHarness(MatButtonHarness.with({ text: 'Save' }));
await saveButton.click();

expect(api.call).toHaveBeenLastCalledWith('privilege.update', [10, {
expect(api.call).toHaveBeenCalledWith('privilege.update', [10, {
ds_groups: [],
local_groups: [111, 222],
web_shell: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import {
Component, ChangeDetectionStrategy, ChangeDetectorRef, Inject, OnInit,
} from '@angular/core';
import { toSignal } from '@angular/core/rxjs-interop';
import { Validators, ReactiveFormsModule } from '@angular/forms';
import { MatButton } from '@angular/material/button';
import { MatCard, MatCardContent } from '@angular/material/card';
import { FormBuilder } from '@ngneat/reactive-forms';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { Store } from '@ngrx/store';
import { TranslateService, TranslateModule } from '@ngx-translate/core';
import { Observable, map } from 'rxjs';
import {
Observable, finalize, map, of, switchMap,
} from 'rxjs';
import { RequiresRolesDirective } from 'app/directives/requires-roles/requires-roles.directive';
import { Role, roleNames } from 'app/enums/role.enum';
import { helptextPrivilege } from 'app/helptext/account/priviledge';
import { Group } from 'app/interfaces/group.interface';
import { Privilege, PrivilegeUpdate } from 'app/interfaces/privilege.interface';
import { DialogService } from 'app/modules/dialog/dialog.service';
import { FormActionsComponent } from 'app/modules/forms/ix-forms/components/form-actions/form-actions.component';
import { IxCheckboxComponent } from 'app/modules/forms/ix-forms/components/ix-checkbox/ix-checkbox.component';
import { ChipsProvider } from 'app/modules/forms/ix-forms/components/ix-chips/chips-provider';
Expand All @@ -26,6 +31,10 @@ import { SlideInRef } from 'app/modules/slide-ins/slide-in-ref';
import { SLIDE_IN_DATA } from 'app/modules/slide-ins/slide-in.token';
import { TestDirective } from 'app/modules/test-id/test.directive';
import { ApiService } from 'app/services/websocket/api.service';
import { AppState } from 'app/store';
import { generalConfigUpdated } from 'app/store/system-config/system-config.actions';
import { waitForGeneralConfig } from 'app/store/system-config/system-config.selectors';
import { selectIsEnterprise } from 'app/store/system-info/system-info.selectors';

@UntilDestroy()
@Component({
Expand Down Expand Up @@ -66,6 +75,7 @@ export class PrivilegeFormComponent implements OnInit {
});

protected readonly helptext = helptextPrivilege;
protected readonly isEnterprise = toSignal(this.store$.select(selectIsEnterprise));

get isNew(): boolean {
return !this.existingPrivilege;
Expand Down Expand Up @@ -122,6 +132,8 @@ export class PrivilegeFormComponent implements OnInit {
private cdr: ChangeDetectorRef,
private errorHandler: FormErrorHandlerService,
private slideInRef: SlideInRef<PrivilegeFormComponent>,
private store$: Store<AppState>,
private dialog: DialogService,
@Inject(SLIDE_IN_DATA) private existingPrivilege: Privilege,
) { }

Expand Down Expand Up @@ -161,7 +173,16 @@ export class PrivilegeFormComponent implements OnInit {
request$ = this.api.call('privilege.update', [this.existingPrivilege.id, values]);
}

request$.pipe(untilDestroyed(this)).subscribe({
request$.pipe(
switchMap(() => this.store$.pipe(waitForGeneralConfig)),
switchMap((generalConfig) => {
if (this.isEnterprise() && !generalConfig.ds_auth) {
return this.enableDsAuth();
}
return of(null);
}),
untilDestroyed(this),
).subscribe({
next: () => {
this.isLoading = false;
this.slideInRef.close(true);
Expand All @@ -175,6 +196,22 @@ export class PrivilegeFormComponent implements OnInit {
});
}

private enableDsAuth(): Observable<unknown> {
return this.dialog.confirm({
title: this.translate.instant('Allow access'),
message: this.translate.instant('Allow Directory Service users to access WebUI?'),
buttonText: this.translate.instant('Allow'),
}).pipe(
switchMap((confirmed) => {
if (confirmed) {
return this.api.call('system.general.update', [{ ds_auth: true }])
.pipe(finalize(() => this.store$.dispatch(generalConfigUpdated())));
}
return of(null);
}),
);
}

private get localGroupsUids(): number[] {
return this.localGroups
.filter((group) => this.form.value.local_groups.includes(group.group))
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/af.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@
"Allow Compressed WRITE Records": "",
"Allow DNS Updates": "",
"Allow Directory Service users to access WebUI": "",
"Allow Directory Service users to access WebUI?": "",
"Allow Guest Access": "",
"Allow Kerberos Authentication": "",
"Allow Local User Login": "",
Expand All @@ -352,6 +353,7 @@
"Allow Taking Empty Snapshots": "",
"Allow Transfer Resumption": "",
"Allow Trusted Domains": "",
"Allow access": "",
"Allow all initiators": "",
"Allow all sudo commands": "",
"Allow all sudo commands with no password": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/ar.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@
"Allow Compressed WRITE Records": "",
"Allow DNS Updates": "",
"Allow Directory Service users to access WebUI": "",
"Allow Directory Service users to access WebUI?": "",
"Allow Guest Access": "",
"Allow Kerberos Authentication": "",
"Allow Local User Login": "",
Expand All @@ -352,6 +353,7 @@
"Allow Taking Empty Snapshots": "",
"Allow Transfer Resumption": "",
"Allow Trusted Domains": "",
"Allow access": "",
"Allow all initiators": "",
"Allow all sudo commands": "",
"Allow all sudo commands with no password": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/ast.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@
"Allow Compressed WRITE Records": "",
"Allow DNS Updates": "",
"Allow Directory Service users to access WebUI": "",
"Allow Directory Service users to access WebUI?": "",
"Allow Guest Access": "",
"Allow Kerberos Authentication": "",
"Allow Local User Login": "",
Expand All @@ -352,6 +353,7 @@
"Allow Taking Empty Snapshots": "",
"Allow Transfer Resumption": "",
"Allow Trusted Domains": "",
"Allow access": "",
"Allow all initiators": "",
"Allow all sudo commands": "",
"Allow all sudo commands with no password": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/az.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@
"Allow Compressed WRITE Records": "",
"Allow DNS Updates": "",
"Allow Directory Service users to access WebUI": "",
"Allow Directory Service users to access WebUI?": "",
"Allow Guest Access": "",
"Allow Kerberos Authentication": "",
"Allow Local User Login": "",
Expand All @@ -352,6 +353,7 @@
"Allow Taking Empty Snapshots": "",
"Allow Transfer Resumption": "",
"Allow Trusted Domains": "",
"Allow access": "",
"Allow all initiators": "",
"Allow all sudo commands": "",
"Allow all sudo commands with no password": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/be.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@
"Allow Compressed WRITE Records": "",
"Allow DNS Updates": "",
"Allow Directory Service users to access WebUI": "",
"Allow Directory Service users to access WebUI?": "",
"Allow Guest Access": "",
"Allow Kerberos Authentication": "",
"Allow Local User Login": "",
Expand All @@ -352,6 +353,7 @@
"Allow Taking Empty Snapshots": "",
"Allow Transfer Resumption": "",
"Allow Trusted Domains": "",
"Allow access": "",
"Allow all initiators": "",
"Allow all sudo commands": "",
"Allow all sudo commands with no password": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/bg.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@
"Allow Compressed WRITE Records": "",
"Allow DNS Updates": "",
"Allow Directory Service users to access WebUI": "",
"Allow Directory Service users to access WebUI?": "",
"Allow Guest Access": "",
"Allow Kerberos Authentication": "",
"Allow Local User Login": "",
Expand All @@ -352,6 +353,7 @@
"Allow Taking Empty Snapshots": "",
"Allow Transfer Resumption": "",
"Allow Trusted Domains": "",
"Allow access": "",
"Allow all initiators": "",
"Allow all sudo commands": "",
"Allow all sudo commands with no password": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/bn.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@
"Allow Compressed WRITE Records": "",
"Allow DNS Updates": "",
"Allow Directory Service users to access WebUI": "",
"Allow Directory Service users to access WebUI?": "",
"Allow Guest Access": "",
"Allow Kerberos Authentication": "",
"Allow Local User Login": "",
Expand All @@ -352,6 +353,7 @@
"Allow Taking Empty Snapshots": "",
"Allow Transfer Resumption": "",
"Allow Trusted Domains": "",
"Allow access": "",
"Allow all initiators": "",
"Allow all sudo commands": "",
"Allow all sudo commands with no password": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/br.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@
"Allow Compressed WRITE Records": "",
"Allow DNS Updates": "",
"Allow Directory Service users to access WebUI": "",
"Allow Directory Service users to access WebUI?": "",
"Allow Guest Access": "",
"Allow Kerberos Authentication": "",
"Allow Local User Login": "",
Expand All @@ -352,6 +353,7 @@
"Allow Taking Empty Snapshots": "",
"Allow Transfer Resumption": "",
"Allow Trusted Domains": "",
"Allow access": "",
"Allow all initiators": "",
"Allow all sudo commands": "",
"Allow all sudo commands with no password": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/bs.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@
"Allow Compressed WRITE Records": "",
"Allow DNS Updates": "",
"Allow Directory Service users to access WebUI": "",
"Allow Directory Service users to access WebUI?": "",
"Allow Guest Access": "",
"Allow Kerberos Authentication": "",
"Allow Local User Login": "",
Expand All @@ -352,6 +353,7 @@
"Allow Taking Empty Snapshots": "",
"Allow Transfer Resumption": "",
"Allow Trusted Domains": "",
"Allow access": "",
"Allow all initiators": "",
"Allow all sudo commands": "",
"Allow all sudo commands with no password": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/ca.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@
"Allow Compressed WRITE Records": "",
"Allow DNS Updates": "",
"Allow Directory Service users to access WebUI": "",
"Allow Directory Service users to access WebUI?": "",
"Allow Guest Access": "",
"Allow Kerberos Authentication": "",
"Allow Local User Login": "",
Expand All @@ -352,6 +353,7 @@
"Allow Taking Empty Snapshots": "",
"Allow Transfer Resumption": "",
"Allow Trusted Domains": "",
"Allow access": "",
"Allow all initiators": "",
"Allow all sudo commands": "",
"Allow all sudo commands with no password": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@
"Adjust Scrub/Resilver Priority": "",
"Adjust how often alert notifications are sent, use the Frequency drop-down. Setting the Frequency to NEVER prevents that alert from being added to alert notifications, but the alert can still show in the web interface if it is triggered.": "",
"All Users": "",
"Allow Directory Service users to access WebUI?": "",
"Allow access": "",
"Allow anonymous FTP logins with access to the directory specified in <b>Path</b>.": "",
"Allow any local user to log in. By default, only members of the <i>ftp</i> group are allowed to log in.": "",
"Allow clients to access the TrueNAS server if they are members of domains that have a trust relationship with the domain to which TrueNAS is joined. This requires valid idmap backend configuration for all trusted domains.": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/cy.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@
"Allow Compressed WRITE Records": "",
"Allow DNS Updates": "",
"Allow Directory Service users to access WebUI": "",
"Allow Directory Service users to access WebUI?": "",
"Allow Guest Access": "",
"Allow Kerberos Authentication": "",
"Allow Local User Login": "",
Expand All @@ -352,6 +353,7 @@
"Allow Taking Empty Snapshots": "",
"Allow Transfer Resumption": "",
"Allow Trusted Domains": "",
"Allow access": "",
"Allow all initiators": "",
"Allow all sudo commands": "",
"Allow all sudo commands with no password": "",
Expand Down
2 changes: 2 additions & 0 deletions src/assets/i18n/da.json
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,7 @@
"Allow Compressed WRITE Records": "",
"Allow DNS Updates": "",
"Allow Directory Service users to access WebUI": "",
"Allow Directory Service users to access WebUI?": "",
"Allow Guest Access": "",
"Allow Kerberos Authentication": "",
"Allow Local User Login": "",
Expand All @@ -352,6 +353,7 @@
"Allow Taking Empty Snapshots": "",
"Allow Transfer Resumption": "",
"Allow Trusted Domains": "",
"Allow access": "",
"Allow all initiators": "",
"Allow all sudo commands": "",
"Allow all sudo commands with no password": "",
Expand Down
Loading

0 comments on commit c3d53b8

Please sign in to comment.