Skip to content
Snippets Groups Projects
Commit c613dd28 authored by Tomáš Valenta's avatar Tomáš Valenta
Browse files

refine created_by / approved permissions

parent f22a8ae5
Branches
No related tags found
No related merge requests found
Pipeline #12040 passed
import copy import copy
import typing
from django.contrib import admin from django.contrib import admin
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
...@@ -29,54 +30,83 @@ class IndexHiddenModelAdmin(MarkdownxGuardedModelAdmin): ...@@ -29,54 +30,83 @@ class IndexHiddenModelAdmin(MarkdownxGuardedModelAdmin):
return False return False
class OwnPermissionsMixin: def permissions_mixin_factory(
def has_change_permission(self, request, obj=None) -> bool: change_permission: str,
if ( delete_permission: str,
obj is not None obj_conditional: typing.Callable,
and obj.created_by != request.user change_attr_func: typing.Callable = lambda obj: obj,
and not request.user.has_perm("contracts.edit_others", obj) delete_attr_func: typing.Callable = lambda obj: obj,
): ) -> object:
return False class Mixin:
def has_change_permission(self, request, obj=None) -> bool:
if (
obj is not None
and obj_conditional(request, obj)
and not request.user.has_perm(change_permission, change_attr_func(obj))
):
return False
return super().has_change_permission(request, obj) return super().has_change_permission(request, obj)
def has_delete_permission(self, request, obj=None) -> bool: def has_delete_permission(self, request, obj=None) -> bool:
if ( if (
obj is not None obj is not None
and obj.created_by != request.user and obj_conditional(request, obj)
and not request.user.has_perm("contracts.delete_others", obj) and not request.user.has_perm(delete_permission, delete_attr_func(obj))
): ):
return False return False
return super().has_change_permission(request, obj) return super().has_change_permission(request, obj)
return Mixin
class ParentContractOwnPermissionsMixin:
def has_change_permission(self, request, obj=None) -> bool:
if (
obj is not None
and obj.contract.created_by != request.user
and not request.user.has_perm("contracts.edit_others", obj.contract)
):
return False
return super().has_change_permission(request, obj) get_obj_contract = lambda obj: obj.contract
def has_delete_permission(self, request, obj=None) -> bool:
if (
obj is not None
and obj.contract.created_by != request.user
and not request.user.has_perm("contracts.delete_others", obj.contract)
):
return False
return super().has_change_permission(request, obj) OwnPermissionsMixin = permissions_mixin_factory(
"contracts.edit_others",
"contracts.delete_others",
lambda request, obj: obj.created_by != request.user,
)
def own_permissions_mixin_save_model(self, request, obj, form, change):
if obj.created_by is None:
obj.created_by = request.user
return super().save_model(request, obj, form, change)
OwnPermissionsMixin.save_model = own_permissions_mixin_save_model
ParentContractApprovedPermissionsMixin = permissions_mixin_factory(
"contracts.edit_when_approved",
"contracts.delete_when_approved",
lambda request, obj: get_obj_contract(obj).is_approved,
get_obj_contract,
get_obj_contract,
)
ParentContractOwnPermissionsMixin = permissions_mixin_factory(
"contracts.edit_others",
"contracts.delete_others",
lambda request, obj: get_obj_contract(obj).created_by != request.user,
get_obj_contract,
get_obj_contract,
)
# BEGIN Contracts # BEGIN Contracts
class ContractFileAdmin(IndexHiddenModelAdmin): class ContractFileAdmin(
IndexHiddenModelAdmin,
ParentContractApprovedPermissionsMixin,
ParentContractOwnPermissionsMixin,
):
form = ContractFileAdminForm form = ContractFileAdminForm
...@@ -117,9 +147,14 @@ class ContractIntentInline(NestedTabularInline): ...@@ -117,9 +147,14 @@ class ContractIntentInline(NestedTabularInline):
class ContractAdmin( class ContractAdmin(
OwnPermissionsMixin, OwnPermissionsMixin,
permissions_mixin_factory(
"contracts.edit_when_approved",
"contracts.delete_when_approved",
lambda request, obj: obj.is_approved,
),
MarkdownxGuardedModelAdmin, MarkdownxGuardedModelAdmin,
FieldsetsInlineMixin, FieldsetsInlineMixin,
NestedModelAdmin NestedModelAdmin,
): ):
form = ContractAdminForm form = ContractAdminForm
...@@ -208,7 +243,7 @@ class ContractAdmin( ...@@ -208,7 +243,7 @@ class ContractAdmin(
if ( if (
obj is None # Creating confidential data, creator will be request.user obj is None # Creating confidential data, creator will be request.user
or obj.created_by == request.user or obj.created_by == request.user
or request.user.has_perm("view_confidential", self) or request.user.has_perm("view_confidential", obj)
): ):
fieldsets_with_inlines[0][1]["fields"].insert( fieldsets_with_inlines[0][1]["fields"].insert(
fieldsets_with_inlines[0][1]["fields"].index("is_public") + 1, fieldsets_with_inlines[0][1]["fields"].index("is_public") + 1,
...@@ -237,10 +272,7 @@ class ContractAdmin( ...@@ -237,10 +272,7 @@ class ContractAdmin(
return queryset return queryset
def save_model(self, request, obj, form, change) -> None: def save_model(self, request, obj, form, change):
if obj.created_by is None:
obj.created_by = request.user
if obj.valid_start_date is None: if obj.valid_start_date is None:
last_signature_date = None last_signature_date = None
...@@ -257,13 +289,13 @@ class ContractAdmin( ...@@ -257,13 +289,13 @@ class ContractAdmin(
obj.valid_start_date = last_signature_date obj.valid_start_date = last_signature_date
super().save_model(request, obj, form, change) return super().save_model(request, obj, form, change)
def has_change_permission(self, request, obj=None): def has_change_permission(self, request, obj=None):
if ( if (
obj is not None obj is not None
and obj.is_approved and obj.is_approved
and not request.user.has_perm("contracts.edit_when_approved", self) and not request.user.has_perm("contracts.edit_when_approved", obj)
): ):
return False return False
...@@ -273,7 +305,7 @@ class ContractAdmin( ...@@ -273,7 +305,7 @@ class ContractAdmin(
if ( if (
obj is not None obj is not None
and obj.is_approved and obj.is_approved
and not request.user.has_perm("contracts.delete_when_approved", self) and not request.user.has_perm("contracts.delete_when_approved", obj)
): ):
return False return False
...@@ -326,6 +358,7 @@ class ContractFilingAreaAdmin(MarkdownxGuardedModelAdmin): ...@@ -326,6 +358,7 @@ class ContractFilingAreaAdmin(MarkdownxGuardedModelAdmin):
class ContracteeAdmin(OwnPermissionsMixin, MarkdownxGuardedModelAdmin): class ContracteeAdmin(OwnPermissionsMixin, MarkdownxGuardedModelAdmin):
model = Contractee model = Contractee
search_fields = ( search_fields = (
"name", "name",
"department", "department",
...@@ -395,19 +428,72 @@ class SigneeAdmin(OwnPermissionsMixin, MarkdownxGuardedModelAdmin): ...@@ -395,19 +428,72 @@ class SigneeAdmin(OwnPermissionsMixin, MarkdownxGuardedModelAdmin):
load_ares_data_button.short_description = "ARES" load_ares_data_button.short_description = "ARES"
get_obj_signee_contract = lambda obj: obj.signee.contract
get_obj_contractee_contract = lambda obj: obj.contractee.contract
class SigneeSignatureRepresentativeAdmin(
IndexHiddenModelAdmin,
permissions_mixin_factory(
"contracts.edit_when_approved",
"contracts.delete_when_approved",
lambda request, obj: get_obj_signee_contract(obj).is_approved,
get_obj_signee_contract,
get_obj_signee_contract,
),
permissions_mixin_factory(
"contracts.edit_others",
"contracts.delete_others",
lambda request, obj: get_obj_contractee_contract(obj).created_by != request.user,
get_obj_signee_contract,
get_obj_signee_contract,
),
):
pass
class ContracteeSignatureRepresentativeAdmin(
IndexHiddenModelAdmin,
permissions_mixin_factory(
"contracts.edit_when_approved",
"contracts.delete_when_approved",
lambda request, obj: get_obj_contractee_contract(obj).is_approved,
get_obj_contractee_contract,
get_obj_contractee_contract,
),
permissions_mixin_factory(
"contracts.edit_others",
"contracts.delete_others",
lambda request, obj: get_obj_contractee_contract(obj).created_by != request.user,
get_obj_contractee_contract,
get_obj_contractee_contract,
),
):
pass
# END Signing parties # END Signing parties
class ContractSubmodelAdmin(
IndexHiddenModelAdmin,
ParentContractApprovedPermissionsMixin,
ParentContractOwnPermissionsMixin,
):
pass
admin.site.register(Permission) admin.site.register(Permission)
for model in ( for model in (
SigneeSignature, SigneeSignature,
ContracteeSignature, ContracteeSignature,
ContracteeSignatureRepresentative,
SigneeSignatureRepresentative,
ContractIntent, ContractIntent,
): ):
admin.site.register(model, IndexHiddenModelAdmin) admin.site.register(model, ContractSubmodelAdmin)
admin.site.register(SigneeSignatureRepresentative, SigneeSignatureRepresentativeAdmin)
admin.site.register(ContracteeSignatureRepresentative, ContracteeSignatureRepresentativeAdmin)
admin.site.register(ContractType, ContractTypeAdmin) admin.site.register(ContractType, ContractTypeAdmin)
admin.site.register(ContractIssue, ContractIssueAdmin) admin.site.register(ContractIssue, ContractIssueAdmin)
......
# Generated by Django 4.1.4 on 2023-03-26 18:45
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contracts', '0017_alter_contract_options'),
]
operations = [
migrations.AddField(
model_name='contractee',
name='created_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Vytvořeno uživatelem'),
),
migrations.AddField(
model_name='signee',
name='created_by',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Vytvořeno uživatelem'),
),
]
...@@ -47,6 +47,20 @@ class SignatureCountMixin(models.Model): ...@@ -47,6 +47,20 @@ class SignatureCountMixin(models.Model):
abstract = True abstract = True
class CreatedByMixin(models.Model):
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
blank=True,
null=True,
related_name="+",
verbose_name="Vytvořeno uživatelem",
) # WARNING: exclude in admin
class Meta:
abstract = True
class RepresentativeMixin: class RepresentativeMixin:
@property @property
def name(self): def name(self):
...@@ -65,7 +79,7 @@ class RepresentativeMixin: ...@@ -65,7 +79,7 @@ class RepresentativeMixin:
return result return result
class Signee(OwnPermissionsMixin, SignatureCountMixin, models.Model): class Signee(CreatedByMixin, OwnPermissionsMixin, SignatureCountMixin, models.Model):
name = models.CharField( name = models.CharField(
max_length=256, max_length=256,
verbose_name="Jméno", verbose_name="Jméno",
...@@ -170,7 +184,7 @@ class Signee(OwnPermissionsMixin, SignatureCountMixin, models.Model): ...@@ -170,7 +184,7 @@ class Signee(OwnPermissionsMixin, SignatureCountMixin, models.Model):
permissions = OwnPermissionsMixin.Meta.permissions permissions = OwnPermissionsMixin.Meta.permissions
class Contractee(OwnPermissionsMixin, SignatureCountMixin, models.Model): class Contractee(CreatedByMixin, OwnPermissionsMixin, SignatureCountMixin, models.Model):
name = models.CharField( name = models.CharField(
max_length=256, max_length=256,
default=settings.DEFAULT_CONTRACTEE_NAME, default=settings.DEFAULT_CONTRACTEE_NAME,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment