mirror of
https://gitlab.crans.org/bde/nk20
synced 2025-06-20 17:41:55 +02:00
🐛 Prevent transactions where note balances go out integer bounds
This commit is contained in:
@ -5,6 +5,7 @@ from rest_framework import serializers
|
||||
from rest_polymorphic.serializers import PolymorphicSerializer
|
||||
from note_kfet.middlewares import get_current_authenticated_user
|
||||
from permission.backends import PermissionBackend
|
||||
from rest_framework.utils import model_meta
|
||||
|
||||
from ..models.notes import Note, NoteClub, NoteSpecial, NoteUser, Alias
|
||||
from ..models.transactions import TransactionTemplate, Transaction, MembershipTransaction, TemplateCategory, \
|
||||
@ -209,5 +210,23 @@ class TransactionPolymorphicSerializer(PolymorphicSerializer):
|
||||
except ImportError: # Activity app is not loaded
|
||||
pass
|
||||
|
||||
def validate(self, attrs):
|
||||
resource_type = attrs.pop(self.resource_type_field_name)
|
||||
serializer = self._get_serializer_from_resource_type(resource_type)
|
||||
if self.instance:
|
||||
instance = self.instance
|
||||
info = model_meta.get_field_info(instance)
|
||||
for attr, value in attrs.items():
|
||||
if attr in info.relations and info.relations[attr].to_many:
|
||||
field = getattr(instance, attr)
|
||||
field.set(value)
|
||||
else:
|
||||
setattr(instance, attr, value)
|
||||
instance.validate(True)
|
||||
else:
|
||||
serializer.Meta.model(**attrs).validate(True)
|
||||
attrs[self.resource_type_field_name] = resource_type
|
||||
return super().validate(attrs)
|
||||
|
||||
class Meta:
|
||||
model = Transaction
|
||||
|
@ -164,10 +164,43 @@ class Transaction(PolymorphicModel):
|
||||
models.Index(fields=['destination']),
|
||||
]
|
||||
|
||||
def validate(self, reset=False):
|
||||
previous_source_balance = self.source.balance
|
||||
previous_dest_balance = self.destination.balance
|
||||
|
||||
created = self.pk is None
|
||||
to_transfer = self.amount * self.quantity
|
||||
if not created:
|
||||
# Revert old transaction
|
||||
old_transaction = Transaction.objects.get(pk=self.pk)
|
||||
if old_transaction.valid:
|
||||
self.source.balance += to_transfer
|
||||
self.destination.balance -= to_transfer
|
||||
|
||||
if self.valid:
|
||||
self.source.balance -= to_transfer
|
||||
self.destination.balance += to_transfer
|
||||
|
||||
# When a transaction is declared valid, we ensure that the invalidity reason is null, if it was
|
||||
# previously invalid
|
||||
self.invalidity_reason = None
|
||||
|
||||
source_balance = self.source.balance
|
||||
dest_balance = self.destination.balance
|
||||
|
||||
if reset:
|
||||
self.source.balance = previous_source_balance
|
||||
self.destination.balance = previous_dest_balance
|
||||
|
||||
if source_balance > 2147483647 or source_balance < -2147483648\
|
||||
or dest_balance > 2147483647 or dest_balance < -2147483648:
|
||||
raise ValidationError(_("The note balances must be between - 21 474 836.47 € and 21 474 836.47 €."))
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
"""
|
||||
When saving, also transfer money between two notes
|
||||
"""
|
||||
self.validate(False)
|
||||
|
||||
if not self.source.is_active or not self.destination.is_active:
|
||||
if 'force_insert' not in kwargs or not kwargs['force_insert']:
|
||||
@ -187,23 +220,6 @@ class Transaction(PolymorphicModel):
|
||||
super().save(*args, **kwargs)
|
||||
return
|
||||
|
||||
created = self.pk is None
|
||||
to_transfer = self.amount * self.quantity
|
||||
if not created:
|
||||
# Revert old transaction
|
||||
old_transaction = Transaction.objects.get(pk=self.pk)
|
||||
if old_transaction.valid:
|
||||
self.source.balance += to_transfer
|
||||
self.destination.balance -= to_transfer
|
||||
|
||||
if self.valid:
|
||||
self.source.balance -= to_transfer
|
||||
self.destination.balance += to_transfer
|
||||
|
||||
# When a transaction is declared valid, we ensure that the invalidity reason is null, if it was
|
||||
# previously invalid
|
||||
self.invalidity_reason = None
|
||||
|
||||
# We save first the transaction, in case of the user has no right to transfer money
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
|
Reference in New Issue
Block a user