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",)