diff --git a/src-ui/src/app/app.component.scss b/src-ui/src/app/app.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src-ui/src/app/app.module.ts b/src-ui/src/app/app.module.ts index 42a226015..0c60abc48 100644 --- a/src-ui/src/app/app.module.ts +++ b/src-ui/src/app/app.module.ts @@ -81,6 +81,7 @@ import { TasksComponent } from './components/admin/tasks/tasks.component' import { TourNgBootstrapModule } from 'ngx-ui-tour-ng-bootstrap' import { UserEditDialogComponent } from './components/common/edit-dialog/user-edit-dialog/user-edit-dialog.component' import { GroupEditDialogComponent } from './components/common/edit-dialog/group-edit-dialog/group-edit-dialog.component' +import { SsoGroupEditDialogComponent } from './components/common/edit-dialog/sso-group-edit-dialog/sso-group-edit-dialog.component' import { PermissionsSelectComponent } from './components/common/permissions-select/permissions-select.component' import { MailAccountEditDialogComponent } from './components/common/edit-dialog/mail-account-edit-dialog/mail-account-edit-dialog.component' import { MailRuleEditDialogComponent } from './components/common/edit-dialog/mail-rule-edit-dialog/mail-rule-edit-dialog.component' @@ -225,6 +226,7 @@ function initializeApp(settings: SettingsService) { TasksComponent, UserEditDialogComponent, GroupEditDialogComponent, + SsoGroupEditDialogComponent, PermissionsSelectComponent, MailAccountEditDialogComponent, MailRuleEditDialogComponent, diff --git a/src-ui/src/app/components/common/edit-dialog/sso-group-edit-dialog/sso-group-edit-dialog.component.html b/src-ui/src/app/components/common/edit-dialog/sso-group-edit-dialog/sso-group-edit-dialog.component.html new file mode 100644 index 000000000..c3b46a2c8 --- /dev/null +++ b/src-ui/src/app/components/common/edit-dialog/sso-group-edit-dialog/sso-group-edit-dialog.component.html @@ -0,0 +1,19 @@ +
+ + + +
diff --git a/src-ui/src/app/components/common/edit-dialog/sso-group-edit-dialog/sso-group-edit-dialog.component.scss b/src-ui/src/app/components/common/edit-dialog/sso-group-edit-dialog/sso-group-edit-dialog.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/src-ui/src/app/components/common/edit-dialog/sso-group-edit-dialog/sso-group-edit-dialog.component.spec.ts b/src-ui/src/app/components/common/edit-dialog/sso-group-edit-dialog/sso-group-edit-dialog.component.spec.ts new file mode 100644 index 000000000..3a7ed4d35 --- /dev/null +++ b/src-ui/src/app/components/common/edit-dialog/sso-group-edit-dialog/sso-group-edit-dialog.component.spec.ts @@ -0,0 +1,57 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing' +import { NgbActiveModal, NgbModule } from '@ng-bootstrap/ng-bootstrap' +import { HttpClientTestingModule } from '@angular/common/http/testing' +import { EditDialogMode } from '../edit-dialog.component' +import { IfOwnerDirective } from 'src/app/directives/if-owner.directive' +import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive' +import { SelectComponent } from '../../input/select/select.component' +import { FormsModule, ReactiveFormsModule } from '@angular/forms' +import { TextComponent } from '../../input/text/text.component' +import { NgSelectModule } from '@ng-select/ng-select' +import { PermissionsFormComponent } from '../../input/permissions/permissions-form/permissions-form.component' +import { SsoGroupEditDialogComponent } from './sso-group-edit-dialog.component' +import { PermissionsSelectComponent } from '../../permissions-select/permissions-select.component' + +describe('GroupEditDialogComponent', () => { + let component: SsoGroupEditDialogComponent + let fixture: ComponentFixture + + beforeEach(async () => { + TestBed.configureTestingModule({ + declarations: [ + SsoGroupEditDialogComponent, + IfPermissionsDirective, + IfOwnerDirective, + SelectComponent, + TextComponent, + PermissionsFormComponent, + PermissionsSelectComponent, + ], + providers: [NgbActiveModal], + imports: [ + HttpClientTestingModule, + FormsModule, + ReactiveFormsModule, + NgSelectModule, + NgbModule, + ], + }).compileComponents() + + fixture = TestBed.createComponent(SsoGroupEditDialogComponent) + component = fixture.componentInstance + + fixture.detectChanges() + }) + + it('should support create and edit modes', () => { + component.dialogMode = EditDialogMode.CREATE + const createTitleSpy = jest.spyOn(component, 'getCreateTitle') + const editTitleSpy = jest.spyOn(component, 'getEditTitle') + fixture.detectChanges() + expect(createTitleSpy).toHaveBeenCalled() + expect(editTitleSpy).not.toHaveBeenCalled() + component.dialogMode = EditDialogMode.EDIT + fixture.detectChanges() + expect(editTitleSpy).toHaveBeenCalled() + }) +}) diff --git a/src-ui/src/app/components/common/edit-dialog/sso-group-edit-dialog/sso-group-edit-dialog.component.ts b/src-ui/src/app/components/common/edit-dialog/sso-group-edit-dialog/sso-group-edit-dialog.component.ts new file mode 100644 index 000000000..fb2dc1ebe --- /dev/null +++ b/src-ui/src/app/components/common/edit-dialog/sso-group-edit-dialog/sso-group-edit-dialog.component.ts @@ -0,0 +1,52 @@ +import { Component } from '@angular/core' +import { FormControl, FormGroup } from '@angular/forms' +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' +import { EditDialogComponent } from 'src/app/components/common/edit-dialog/edit-dialog.component' +import { PaperlessGroup } from 'src/app/data/paperless-group' +import { GroupService } from 'src/app/services/rest/group.service' +import { UserService } from 'src/app/services/rest/user.service' +import { SettingsService } from 'src/app/services/settings.service' +import { PaperlessSSOGroup } from '../../../../data/paperless-sso-group' +import { SsoGroupService } from '../../../../services/rest/sso-group.service' +import { first } from 'rxjs' + +@Component({ + selector: 'app-sso-group-edit-dialog', + templateUrl: './sso-group-edit-dialog.component.html', + styleUrls: ['./sso-group-edit-dialog.component.scss'], +}) +export class SsoGroupEditDialogComponent extends EditDialogComponent { + groups: PaperlessGroup[] + + constructor( + service: SsoGroupService, + activeModal: NgbActiveModal, + userService: UserService, + settingsService: SettingsService, + groupsService: GroupService + ) { + super(service, activeModal, userService, settingsService) + + groupsService + .listAll() + .pipe(first()) + .subscribe((result) => { + this.groups = result.results + }) + } + + getCreateTitle() { + return $localize`Create new sso group` + } + + getEditTitle() { + return $localize`Edit sso group` + } + + getForm(): FormGroup { + return new FormGroup({ + name: new FormControl(''), + group: new FormControl(null), + }) + } +} diff --git a/src-ui/src/app/data/paperless-sso-group.ts b/src-ui/src/app/data/paperless-sso-group.ts new file mode 100644 index 000000000..ac0eaf650 --- /dev/null +++ b/src-ui/src/app/data/paperless-sso-group.ts @@ -0,0 +1,6 @@ +import { ObjectWithId } from './object-with-id' + +export interface PaperlessSSOGroup extends ObjectWithId { + name?: string + group?: number +} diff --git a/src-ui/src/app/services/permissions.service.spec.ts b/src-ui/src/app/services/permissions.service.spec.ts index 820b9ac1f..0eee21119 100644 --- a/src-ui/src/app/services/permissions.service.spec.ts +++ b/src-ui/src/app/services/permissions.service.spec.ts @@ -256,6 +256,10 @@ describe('PermissionsService', () => { 'view_consumptiontemplate', 'change_consumptiontemplate', 'delete_consumptiontemplate', + 'add_ssogroup', + 'change_ssogroup', + 'delete_ssogroup', + 'view_ssogroup', ], { username: 'testuser', diff --git a/src-ui/src/app/services/permissions.service.ts b/src-ui/src/app/services/permissions.service.ts index b22e56177..9fe3c38f6 100644 --- a/src-ui/src/app/services/permissions.service.ts +++ b/src-ui/src/app/services/permissions.service.ts @@ -26,6 +26,7 @@ export enum PermissionType { Admin = '%s_logentry', ShareLink = '%s_sharelink', ConsumptionTemplate = '%s_consumptiontemplate', + SsoGroup = '%s_ssogroup', } @Injectable({ diff --git a/src-ui/src/app/services/rest/sso-group.service.ts b/src-ui/src/app/services/rest/sso-group.service.ts new file mode 100644 index 000000000..02b41d326 --- /dev/null +++ b/src-ui/src/app/services/rest/sso-group.service.ts @@ -0,0 +1,13 @@ +import { HttpClient } from '@angular/common/http' +import { Injectable } from '@angular/core' +import { AbstractNameFilterService } from './abstract-name-filter-service' +import { PaperlessSSOGroup } from '../../data/paperless-sso-group' + +@Injectable({ + providedIn: 'root', +}) +export class SsoGroupService extends AbstractNameFilterService { + constructor(http: HttpClient) { + super(http, 'sso_groups') + } +} diff --git a/src/paperless/filters.py b/src/paperless/filters.py index a3c09d50f..ab9900319 100644 --- a/src/paperless/filters.py +++ b/src/paperless/filters.py @@ -3,6 +3,7 @@ from django.contrib.auth.models import User from django_filters.rest_framework import FilterSet from documents.filters import CHAR_KWARGS +from paperless.models import SSOGroup class UserFilterSet(FilterSet): @@ -15,3 +16,9 @@ class GroupFilterSet(FilterSet): class Meta: model = Group fields = {"name": CHAR_KWARGS} + + +class SSOGroupFilterSet(FilterSet): + class Meta: + model = SSOGroup + fields = {"name": CHAR_KWARGS} diff --git a/src/paperless/serialisers.py b/src/paperless/serialisers.py index 62578ff85..0510b8612 100644 --- a/src/paperless/serialisers.py +++ b/src/paperless/serialisers.py @@ -91,11 +91,6 @@ class GroupSerializer(serializers.ModelSerializer): queryset=Permission.objects.all(), slug_field="codename", ) - sso_groups = serializers.PrimaryKeyRelatedField( - many=True, - queryset=SSOGroup.objects.all(), - required=False, - ) class Meta: model = Group @@ -103,7 +98,6 @@ class GroupSerializer(serializers.ModelSerializer): "id", "name", "permissions", - "sso_groups", ) @@ -111,6 +105,7 @@ class SSOGroupSerializer(serializers.ModelSerializer): class Meta: model = SSOGroup fields = ( + "id", "name", "group", ) diff --git a/src/paperless/views.py b/src/paperless/views.py index ddde65731..21408c604 100644 --- a/src/paperless/views.py +++ b/src/paperless/views.py @@ -15,6 +15,7 @@ from rest_framework.viewsets import ModelViewSet from documents.permissions import PaperlessObjectPermissions from paperless.filters import GroupFilterSet +from paperless.filters import SSOGroupFilterSet from paperless.filters import UserFilterSet from paperless.models import SSOGroup from paperless.serialisers import GroupSerializer @@ -112,5 +113,12 @@ class GroupViewSet(ModelViewSet): class SSOGroupViewSet(ModelViewSet): model = SSOGroup + queryset = SSOGroup.objects + serializer_class = SSOGroupSerializer + pagination_class = StandardPagination + permission_classes = (IsAuthenticated, PaperlessObjectPermissions) + filter_backends = (DjangoFilterBackend, OrderingFilter) + filterset_class = SSOGroupFilterSet + ordering_fields = ("name",)