Remove owner/perms from consumption templates

This commit is contained in:
shamoon 2023-09-21 22:50:11 -07:00
parent e4a672d1ad
commit 5a2020b706
8 changed files with 24 additions and 45 deletions

View File

@ -290,6 +290,16 @@ Consumption templates can assign:
- Document owner - Document owner
- View and / or edit permissions to users or groups - View and / or edit permissions to users or groups
### Consumption template permissions
All users who have application permissions for editing consumption templates can see the same set
of templates. In other words, templates themselves intentionally do not have an owner or permissions.
Given their potentially far-reaching capabilities, you may want to restrict access to templates.
Upon migration, existing installs will grant access to consumption templates to users who can add
documents (and superusers who can always access all parts of the app).
### Title placeholders ### Title placeholders
Consumption template titles can include placeholders, _only for items that are assigned within the template_. Consumption template titles can include placeholders, _only for items that are assigned within the template_.

View File

@ -11,22 +11,20 @@
<thead> <thead>
<tr> <tr>
<th scope="col" i18n>Name</th> <th scope="col" i18n>Name</th>
<th scope="col" i18n>Sort order</th>
<th scope="col" i18n>Document Sources</th> <th scope="col" i18n>Document Sources</th>
<th scope="col" i18n>File name filter</th>
<th scope="col" i18n>Path filter</th>
<th scope="col" i18n>Actions</th> <th scope="col" i18n>Actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr *ngFor="let template of templates"> <tr *ngFor="let template of templates">
<td scope="row"><button class="btn btn-link p-0" type="button" (click)="editTemplate(template)" [disabled]="!permissionsService.currentUserCan(PermissionAction.Change, PermissionType.ConsumptionTemplate)">{{template.name}}</button></td> <td scope="row"><button class="btn btn-link p-0" type="button" (click)="editTemplate(template)" [disabled]="!permissionsService.currentUserCan(PermissionAction.Change, PermissionType.ConsumptionTemplate)">{{template.name}}</button></td>
<td scope="row"><code>{{template.order}}</code></td>
<td scope="row">{{getSourceList(template)}}</td> <td scope="row">{{getSourceList(template)}}</td>
<td scope="row"><code>{{template.filter_filename}}</code></td>
<td scope="row"><code>{{template.filter_path}}</code></td>
<td scope="row"> <td scope="row">
<div class="btn-group"> <div class="btn-group">
<button *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.ConsumptionTemplate }" [disabled]="!userCanEdit(template)" class="btn btn-sm btn-primary" type="button" (click)="editTemplate(template)" i18n>Edit</button> <button *pngxIfPermissions="{ action: PermissionAction.Change, type: PermissionType.ConsumptionTemplate }" class="btn btn-sm btn-primary" type="button" (click)="editTemplate(template)" i18n>Edit</button>
<button *pngxIfPermissions="{ action: PermissionAction.Delete, type: PermissionType.ConsumptionTemplate }" [disabled]="!userIsOwner(template)" class="btn btn-sm btn-outline-danger" type="button" (click)="deleteTemplate(template)" i18n>Delete</button> <button *pngxIfPermissions="{ action: PermissionAction.Delete, type: PermissionType.ConsumptionTemplate }" class="btn btn-sm btn-outline-danger" type="button" (click)="deleteTemplate(template)" i18n>Delete</button>
</div> </div>
</td> </td>
</tr> </tr>

View File

@ -2,10 +2,7 @@ import { Component, OnInit } from '@angular/core'
import { ConsumptionTemplateService } from 'src/app/services/rest/consumption-template.service' import { ConsumptionTemplateService } from 'src/app/services/rest/consumption-template.service'
import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component' import { ComponentWithPermissions } from '../../with-permissions/with-permissions.component'
import { Subject, takeUntil } from 'rxjs' import { Subject, takeUntil } from 'rxjs'
import { import { PaperlessConsumptionTemplate } from 'src/app/data/paperless-consumption-template'
DocumentSource,
PaperlessConsumptionTemplate,
} from 'src/app/data/paperless-consumption-template'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { ToastService } from 'src/app/services/toast.service' import { ToastService } from 'src/app/services/toast.service'
import { PermissionsService } from 'src/app/services/permissions.service' import { PermissionsService } from 'src/app/services/permissions.service'
@ -109,15 +106,4 @@ export class ConsmptionTemplatesListComponent
}) })
}) })
} }
userCanEdit(template: PaperlessConsumptionTemplate): boolean {
return this.permissionsService.currentUserHasObjectPermissions(
this.PermissionAction.Change,
template
)
}
userIsOwner(template: PaperlessConsumptionTemplate): boolean {
return this.permissionsService.currentUserOwnsObject(template)
}
} }

View File

@ -1,4 +1,4 @@
import { ObjectWithPermissions } from './object-with-permissions' import { ObjectWithId } from './object-with-id'
export enum DocumentSource { export enum DocumentSource {
ConsumeFolder = 1, ConsumeFolder = 1,
@ -6,7 +6,7 @@ export enum DocumentSource {
MailFetch = 3, MailFetch = 3,
} }
export interface PaperlessConsumptionTemplate extends ObjectWithPermissions { export interface PaperlessConsumptionTemplate extends ObjectWithId {
name: string name: string
order: number order: number

View File

@ -206,16 +206,6 @@ class Migration(migrations.Migration):
verbose_name="grant view permissions to these users", verbose_name="grant view permissions to these users",
), ),
), ),
(
"owner",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to=settings.AUTH_USER_MODEL,
verbose_name="owner",
),
),
], ],
options={ options={
"verbose_name": "consumption template", "verbose_name": "consumption template",

View File

@ -740,16 +740,12 @@ class ShareLink(models.Model):
return f"Share Link for {self.document.title}" return f"Share Link for {self.document.title}"
class ConsumptionTemplate(ModelWithOwner): class ConsumptionTemplate(models.Model):
class DocumentSourceChoices(models.IntegerChoices): class DocumentSourceChoices(models.IntegerChoices):
CONSUME_FOLDER = DocumentSource.ConsumeFolder.value, _("Consume Folder") CONSUME_FOLDER = DocumentSource.ConsumeFolder.value, _("Consume Folder")
API_UPLOAD = DocumentSource.ApiUpload.value, _("Api Upload") API_UPLOAD = DocumentSource.ApiUpload.value, _("Api Upload")
MAIL_FETCH = DocumentSource.MailFetch.value, _("Mail Fetch") MAIL_FETCH = DocumentSource.MailFetch.value, _("Mail Fetch")
class Meta:
verbose_name = _("consumption template")
verbose_name_plural = _("consumption templates")
name = models.CharField(_("name"), max_length=256, unique=True) name = models.CharField(_("name"), max_length=256, unique=True)
order = models.IntegerField(_("order"), default=0) order = models.IntegerField(_("order"), default=0)
@ -870,5 +866,9 @@ class ConsumptionTemplate(ModelWithOwner):
verbose_name=_("grant change permissions to these groups"), verbose_name=_("grant change permissions to these groups"),
) )
class Meta:
verbose_name = _("consumption template")
verbose_name_plural = _("consumption templates")
def __str__(self): def __str__(self):
return f"{self.name}" return f"{self.name}"

View File

@ -1040,7 +1040,7 @@ class BulkEditObjectPermissionsSerializer(serializers.Serializer, SetPermissions
return attrs return attrs
class ConsumptionTemplateSerializer(OwnedObjectSerializer): class ConsumptionTemplateSerializer(serializers.ModelSerializer):
order = serializers.IntegerField(required=False) order = serializers.IntegerField(required=False)
sources = fields.MultipleChoiceField( sources = fields.MultipleChoiceField(
choices=ConsumptionTemplate.DocumentSourceChoices.choices, choices=ConsumptionTemplate.DocumentSourceChoices.choices,
@ -1076,10 +1076,6 @@ class ConsumptionTemplateSerializer(OwnedObjectSerializer):
"assign_view_groups", "assign_view_groups",
"assign_change_users", "assign_change_users",
"assign_change_groups", "assign_change_groups",
"owner",
"user_can_change",
"permissions",
"set_permissions",
] ]
def validate(self, attrs): def validate(self, attrs):

View File

@ -1252,12 +1252,11 @@ class BulkEditObjectPermissionsView(GenericAPIView, PassUserMixin):
) )
class ConsumptionTemplateViewSet(ModelViewSet, PassUserMixin): class ConsumptionTemplateViewSet(ModelViewSet):
permission_classes = (IsAuthenticated, PaperlessObjectPermissions) permission_classes = (IsAuthenticated, PaperlessObjectPermissions)
serializer_class = ConsumptionTemplateSerializer serializer_class = ConsumptionTemplateSerializer
pagination_class = StandardPagination pagination_class = StandardPagination
filter_backends = (ObjectOwnedOrGrantedPermissionsFilter,)
model = ConsumptionTemplate model = ConsumptionTemplate