Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

forms.py 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. from __future__ import absolute_import, unicode_literals
  2. import hashlib
  3. import hmac
  4. import json
  5. from django import forms
  6. from django.conf import settings
  7. from django.core.exceptions import ValidationError
  8. from django.db import connections
  9. from django.utils.crypto import constant_time_compare
  10. from django.utils.encoding import force_bytes
  11. from django.utils.functional import cached_property
  12. from debug_toolbar.panels.sql.utils import reformat_sql
  13. class SQLSelectForm(forms.Form):
  14. """
  15. Validate params
  16. sql: The sql statement with interpolated params
  17. raw_sql: The sql statement with placeholders
  18. params: JSON encoded parameter values
  19. duration: time for SQL to execute passed in from toolbar just for redisplay
  20. hash: the hash of (secret + sql + params) for tamper checking
  21. """
  22. sql = forms.CharField()
  23. raw_sql = forms.CharField()
  24. params = forms.CharField()
  25. alias = forms.CharField(required=False, initial='default')
  26. duration = forms.FloatField()
  27. hash = forms.CharField()
  28. def __init__(self, *args, **kwargs):
  29. initial = kwargs.get('initial', None)
  30. if initial is not None:
  31. initial['hash'] = self.make_hash(initial)
  32. super(SQLSelectForm, self).__init__(*args, **kwargs)
  33. for name in self.fields:
  34. self.fields[name].widget = forms.HiddenInput()
  35. def clean_raw_sql(self):
  36. value = self.cleaned_data['raw_sql']
  37. if not value.lower().strip().startswith('select'):
  38. raise ValidationError("Only 'select' queries are allowed.")
  39. return value
  40. def clean_params(self):
  41. value = self.cleaned_data['params']
  42. try:
  43. return json.loads(value)
  44. except ValueError:
  45. raise ValidationError('Is not valid JSON')
  46. def clean_alias(self):
  47. value = self.cleaned_data['alias']
  48. if value not in connections:
  49. raise ValidationError("Database alias '%s' not found" % value)
  50. return value
  51. def clean_hash(self):
  52. hash = self.cleaned_data['hash']
  53. if not constant_time_compare(hash, self.make_hash(self.data)):
  54. raise ValidationError('Tamper alert')
  55. return hash
  56. def reformat_sql(self):
  57. return reformat_sql(self.cleaned_data['sql'])
  58. def make_hash(self, data):
  59. m = hmac.new(key=force_bytes(settings.SECRET_KEY), digestmod=hashlib.sha1)
  60. for item in [data['sql'], data['params']]:
  61. m.update(force_bytes(item))
  62. return m.hexdigest()
  63. @property
  64. def connection(self):
  65. return connections[self.cleaned_data['alias']]
  66. @cached_property
  67. def cursor(self):
  68. return self.connection.cursor()