2018-01-12 07:43:26 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
#
|
|
|
|
import json
|
|
|
|
|
2018-04-18 04:46:25 +00:00
|
|
|
from django.db import models
|
2018-01-12 07:43:26 +00:00
|
|
|
from django import forms
|
|
|
|
from django.utils import six
|
|
|
|
from django.core.exceptions import ValidationError
|
2018-01-22 09:21:03 +00:00
|
|
|
from django.utils.translation import ugettext as _
|
2018-02-01 09:14:15 +00:00
|
|
|
from rest_framework import serializers
|
2018-04-18 04:46:25 +00:00
|
|
|
from .utils import get_signer
|
|
|
|
|
|
|
|
signer = get_signer()
|
2018-01-12 07:43:26 +00:00
|
|
|
|
|
|
|
|
2018-09-03 07:33:35 +00:00
|
|
|
class FormDictField(forms.Field):
|
2018-01-12 07:43:26 +00:00
|
|
|
widget = forms.Textarea
|
|
|
|
|
|
|
|
def to_python(self, value):
|
|
|
|
"""Returns a Python boolean object."""
|
|
|
|
# Explicitly check for the string 'False', which is what a hidden field
|
|
|
|
# will submit for False. Also check for '0', since this is what
|
|
|
|
# RadioSelect will provide. Because bool("True") == bool('1') == True,
|
|
|
|
# we don't need to handle that explicitly.
|
|
|
|
if isinstance(value, six.string_types):
|
2018-09-03 07:33:35 +00:00
|
|
|
value = value.replace("'", '"')
|
2018-01-12 07:43:26 +00:00
|
|
|
try:
|
|
|
|
value = json.loads(value)
|
|
|
|
return value
|
|
|
|
except json.JSONDecodeError:
|
2018-01-22 09:21:03 +00:00
|
|
|
return ValidationError(_("Not a valid json"))
|
|
|
|
else:
|
|
|
|
return ValidationError(_("Not a string type"))
|
2018-01-12 07:43:26 +00:00
|
|
|
|
|
|
|
def validate(self, value):
|
2018-01-22 09:21:03 +00:00
|
|
|
if isinstance(value, ValidationError):
|
|
|
|
raise value
|
2018-01-12 07:43:26 +00:00
|
|
|
if not value and self.required:
|
|
|
|
raise ValidationError(self.error_messages['required'], code='required')
|
|
|
|
|
|
|
|
def has_changed(self, initial, data):
|
|
|
|
# Sometimes data or initial may be a string equivalent of a boolean
|
|
|
|
# so we should run it through to_python first to get a boolean value
|
|
|
|
return self.to_python(initial) != self.to_python(data)
|
2018-02-01 09:14:15 +00:00
|
|
|
|
|
|
|
|
|
|
|
class StringIDField(serializers.Field):
|
|
|
|
def to_representation(self, value):
|
|
|
|
return {"pk": value.pk, "name": value.__str__()}
|
|
|
|
|
2018-04-10 12:29:06 +00:00
|
|
|
|
|
|
|
class StringManyToManyField(serializers.RelatedField):
|
|
|
|
def to_representation(self, value):
|
2018-04-18 04:46:25 +00:00
|
|
|
return value.__str__()
|
|
|
|
|
|
|
|
|
|
|
|
class EncryptMixin:
|
|
|
|
def from_db_value(self, value, expression, connection, context):
|
|
|
|
if value is not None:
|
|
|
|
return signer.unsign(value)
|
|
|
|
return super().from_db_value(self, value, expression, connection, context)
|
|
|
|
|
|
|
|
def get_prep_value(self, value):
|
|
|
|
if value is None:
|
|
|
|
return value
|
2018-07-31 03:00:48 +00:00
|
|
|
return signer.sign(value)
|
2018-04-18 04:46:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
class EncryptTextField(EncryptMixin, models.TextField):
|
|
|
|
description = _("Encrypt field using Secret Key")
|
|
|
|
|
|
|
|
|
|
|
|
class EncryptCharField(EncryptMixin, models.CharField):
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
kwargs['max_length'] = 2048
|
|
|
|
super().__init__(*args, **kwargs)
|
|
|
|
|
2018-09-03 03:24:25 +00:00
|
|
|
|
|
|
|
class FormEncryptMixin:
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class FormEncryptCharField(FormEncryptMixin, forms.CharField):
|
|
|
|
pass
|
2018-09-03 07:33:35 +00:00
|
|
|
|
|
|
|
|
|
|
|
class FormEncryptDictField(FormEncryptMixin, FormDictField):
|
|
|
|
pass
|
2018-10-10 07:37:20 +00:00
|
|
|
|
|
|
|
|
|
|
|
class ChoiceDisplayField(serializers.ChoiceField):
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
super(ChoiceDisplayField, self).__init__(*args, **kwargs)
|
|
|
|
self.choice_strings_to_display = {
|
|
|
|
six.text_type(key): value for key, value in self.choices.items()
|
|
|
|
}
|
|
|
|
|
|
|
|
def to_representation(self, value):
|
|
|
|
if value is None:
|
|
|
|
return value
|
|
|
|
return {
|
|
|
|
'value': self.choice_strings_to_values.get(six.text_type(value),
|
|
|
|
value),
|
|
|
|
'display': self.choice_strings_to_display.get(six.text_type(value),
|
|
|
|
value),
|
|
|
|
}
|