diff --git a/lib/solitude/api.py b/lib/solitude/api.py index 6ec062f28..dd2148727 100644 --- a/lib/solitude/api.py +++ b/lib/solitude/api.py @@ -9,7 +9,6 @@ from ..utils import SlumberWrapper from .constants import ACCESS_PURCHASE from .errors import ERROR_STRINGS -from webpay.pay.models import Issuer log = logging.getLogger('w.solitude') @@ -273,10 +272,6 @@ def get_transaction(self, uuid): notes = transaction['notes'] if notes: transaction['notes'] = json.loads(notes) - issuer = transaction['notes'].get('issuer') - if issuer: - # If there's an issuer there, get it. - transaction['notes']['issuer'] = Issuer.objects.get(pk=issuer) return transaction diff --git a/lib/solitude/tests.py b/lib/solitude/tests.py index 88acce9fa..2e9c26a7e 100644 --- a/lib/solitude/tests.py +++ b/lib/solitude/tests.py @@ -10,7 +10,6 @@ from lib.solitude.api import client, SellerNotConfigured from lib.solitude.errors import ERROR_STRINGS -from webpay.pay.models import Issuer class SolitudeAPITest(TestCase): @@ -234,11 +233,3 @@ def test_notes_transactions(self, slumber): } trans = client.get_transaction('x') eq_(trans['notes'], {'foo': 'bar'}) - - def test_notes_issuer_transactions(self, slumber): - iss = Issuer.objects.create() - slumber.generic.transaction.get_object.return_value = { - 'notes': json.dumps({'issuer': iss.pk}) - } - trans = client.get_transaction('x') - eq_(trans['notes']['issuer'], iss) diff --git a/migrations/012-drop-notices.sql b/migrations/012-drop-notices.sql new file mode 100644 index 000000000..335c04825 --- /dev/null +++ b/migrations/012-drop-notices.sql @@ -0,0 +1 @@ +DROP TABLE `notices`; diff --git a/migrations/013-drop-issuers.sql b/migrations/013-drop-issuers.sql new file mode 100644 index 000000000..3f0fac9cb --- /dev/null +++ b/migrations/013-drop-issuers.sql @@ -0,0 +1 @@ +DROP TABLE `issuers`; diff --git a/webpay/pay/constants.py b/webpay/pay/constants.py new file mode 100644 index 000000000..228c2e68a --- /dev/null +++ b/webpay/pay/constants.py @@ -0,0 +1,3 @@ +NOT_SIMULATED = 0 +SIMULATED_POSTBACK = 1 +SIMULATED_CHARGEBACK = 2 diff --git a/webpay/pay/fields.py b/webpay/pay/fields.py new file mode 100644 index 000000000..05d8415b9 --- /dev/null +++ b/webpay/pay/fields.py @@ -0,0 +1,11 @@ +from django.db import models + + +class BlobField(models.Field): + """ + MySQL blob column. + """ + description = "blob" + + def db_type(self, **kw): + return 'blob' diff --git a/webpay/pay/models.py b/webpay/pay/models.py deleted file mode 100644 index a4d995dbe..000000000 --- a/webpay/pay/models.py +++ /dev/null @@ -1,121 +0,0 @@ -from django.conf import settings -from django.db import connection -from django.db import models - -from tower import ugettext_lazy as _ - -ISSUER_ACTIVE = 1 -ISSUER_INACTIVE = 2 -ISSUER_REVOKED = 3 - -NOT_SIMULATED = 0 -SIMULATED_POSTBACK = 1 -SIMULATED_CHARGEBACK = 2 - - -class BlobField(models.Field): - """ - MySQL blob column. - """ - description = "blob" - - def db_type(self, **kw): - return 'blob' - - -class Issuer(models.Model): - """Apps that can issue payment JWTs.""" - status = models.IntegerField(choices=[(ISSUER_ACTIVE, _('Active')), - (ISSUER_INACTIVE, _('Inactive')), - (ISSUER_REVOKED, _('Revoked'))], - default=ISSUER_ACTIVE) - domain = models.CharField(max_length=255) - chargeback_url = models.CharField( - max_length=200, verbose_name=u'Chargeback URL', - help_text=u'Relative URL to domain for posting a JWT ' - u'a chargeback to. For example: /payments/chargeback') - postback_url = models.CharField( - max_length=200, verbose_name=u'Postback URL', - help_text=u'Relative URL to domain for ' - u'posting a confirmed transaction to. For example: ' - u'/payments/postback') - issuer_key = models.CharField(max_length=255, unique=True, db_index=True, - help_text='Value from the iss (issuer) ' - 'field in payment JWTs') - - # It feels like all the key and timestamps should be done in solitude, - # so this is just a temp setting. - key_timestamp = models.CharField(max_length=10, blank=True, null=True, - db_index=True, - help_text='Timestamp of the disk key ' - 'used to encrypt the private ' - 'key in the db.') - # Allow https to be configurable only if it's declared in settings. - # This is intended for development. - is_https = models.BooleanField( - default=True, - help_text=u'Use SSL when posting to app') - - _encrypted_private_key = BlobField(blank=True, null=True, - db_column='private_key') - - def set_private_key(self, raw_value): - """Store the private key in the database.""" - if isinstance(raw_value, unicode): - raw_value = raw_value.encode('ascii') - timestamp, key = _get_key() - cursor = connection.cursor() - cursor.execute('UPDATE issuers SET ' - 'private_key = AES_ENCRYPT(%s, %s), ' - 'key_timestamp = %s WHERE id=%s', - [raw_value, key, timestamp, self.id]) - - def get_private_key(self): - """Get the real private key from the database.""" - timestamp, key = _get_key(timestamp=self.key_timestamp) - cursor = connection.cursor() - cursor.execute('select AES_DECRYPT(private_key, %s) ' - 'from issuers where id=%s', [key, self.id]) - secret = cursor.fetchone()[0] - if not secret: - raise ValueError('Secret was empty! It either was not set or ' - 'the decryption key is wrong') - return str(secret) - - def app_protocol(self): - """Protocol to use when posting to this app domain.""" - raise NotImplementedError - - class Meta: - db_table = 'issuers' - - -def _get_key(timestamp=None): - """Get (timestamp, key) used to encrypt data in the db.""" - try: - if not timestamp: - # Get the most recent date in settings. - timestamp = sorted(settings.INAPP_KEY_PATHS.keys())[-1] - keypath = settings.INAPP_KEY_PATHS[timestamp] - except (IndexError, KeyError), exc: - ms = 'key %r not in INAPP_KEY_PATHS (%s)' % (timestamp, exc) - exc.args = (ms,) + exc.args[1:] - raise - if (not settings.DEBUG and - keypath.endswith('sample.key')): - raise EnvironmentError('encryption key looks like the one we ' - 'committed to the repo!') - with open(keypath, 'rb') as fp: - return timestamp, fp.read() - - -class Notice(models.Model): - """Notifications sent to issuers about transactions.""" - url = models.CharField(max_length=255) - success = models.BooleanField() # App responded OK to notification. - last_error = models.CharField(max_length=255, null=True, blank=True) - transaction_uuid = models.CharField(max_length=255) - simulated = models.IntegerField(default=NOT_SIMULATED) - - class Meta: - db_table = 'notices' diff --git a/webpay/pay/tasks.py b/webpay/pay/tasks.py index e5db933ab..e6e4cb31f 100644 --- a/webpay/pay/tasks.py +++ b/webpay/pay/tasks.py @@ -20,8 +20,7 @@ from webpay.base.helpers import absolutify from webpay.constants import TYP_CHARGEBACK, TYP_POSTBACK -from .models import (Notice, NOT_SIMULATED, SIMULATED_POSTBACK, - SIMULATED_CHARGEBACK) +from .constants import NOT_SIMULATED, SIMULATED_POSTBACK, SIMULATED_CHARGEBACK from .utils import send_pay_notice, trans_id log = logging.getLogger('w.pay.tasks') @@ -361,13 +360,6 @@ def _notify(notifier_task, trans, extra_response=None, simulated=NOT_SIMULATED, success, last_error = send_pay_notice(url, trans['type'], signed_notice, trans['uuid'], notifier_task, task_args, simulated=simulated) - s = Notice._meta.get_field_by_name('last_error')[0].max_length - last_error = last_error[:s] # truncate to fit - Notice.objects.create(transaction_uuid=trans['uuid'], - success=success, - url=url, - simulated=simulated, - last_error=last_error) def _prepare_notice(trans): diff --git a/webpay/pay/tests/__init__.py b/webpay/pay/tests/__init__.py index 6cf398093..6c4b89ce4 100644 --- a/webpay/pay/tests/__init__.py +++ b/webpay/pay/tests/__init__.py @@ -6,7 +6,6 @@ from lib.solitude import constants from webpay.base.tests import BasicSessionCase -from webpay.pay.models import Issuer, ISSUER_ACTIVE from webpay.pay.samples import JWTtester sample = os.path.join(os.path.dirname(__file__), 'sample.key') @@ -19,7 +18,6 @@ def setUp(self): self.url = reverse('pay.lobby') self.key = 'public.key' self.secret = 'private.secret' - self.create() def get(self, payload): return self.client.get('%s?req=%s' % (self.url, payload)) @@ -35,14 +33,6 @@ def request(self, **kw): kw.setdefault('app_secret', settings.SECRET) return super(Base, self).request(**kw) - def create(self, key=None, secret=None): - key = key or self.key - secret = secret or self.secret - self.iss = Issuer.objects.create(issuer_key=key, - status=ISSUER_ACTIVE) - with self.settings(INAPP_KEY_PATHS={None: sample}, DEBUG=True): - self.iss.set_private_key(secret) - def set_secret(self, get_active_product): get_active_product.return_value = { 'secret': self.secret, diff --git a/webpay/pay/tests/test_forms.py b/webpay/pay/tests/test_forms.py index 5c5260608..ee54932da 100644 --- a/webpay/pay/tests/test_forms.py +++ b/webpay/pay/tests/test_forms.py @@ -9,7 +9,6 @@ from nose.tools import eq_ from webpay.pay.forms import VerifyForm -from webpay.pay.models import ISSUER_INACTIVE from . import Base, sample @@ -89,8 +88,6 @@ def test_not_public(self): # an active status in solitude. raise SkipTest - self.iss.status = ISSUER_INACTIVE - self.iss.save() payload = self.request(iss=self.key, app_secret=self.secret) with self.settings(INAPP_KEY_PATHS={None: sample}, DEBUG=True): form = VerifyForm({'req': payload}) diff --git a/webpay/pay/tests/test_tasks.py b/webpay/pay/tests/test_tasks.py index 241ba774f..2de86e8f9 100644 --- a/webpay/pay/tests/test_tasks.py +++ b/webpay/pay/tests/test_tasks.py @@ -25,7 +25,6 @@ from lib.solitude import constants from webpay.constants import TYP_CHARGEBACK, TYP_POSTBACK from webpay.pay import tasks -from webpay.pay.models import Notice, SIMULATED_POSTBACK, SIMULATED_CHARGEBACK from webpay.pay.samples import JWTtester from .test_views import sample @@ -90,10 +89,6 @@ def req_ok(req): .has_attr(text=self.trans_uuid) .expects('raise_for_status')) self.notify() - notice = Notice.objects.get() - eq_(notice.transaction_uuid, self.trans_uuid) - eq_(notice.success, True) - eq_(notice.url, url) @fudge.patch('webpay.pay.utils.requests') @mock.patch('lib.solitude.api.client.slumber') @@ -117,10 +112,6 @@ def req_ok(req): .has_attr(text=self.trans_uuid) .expects('raise_for_status')) self.do_chargeback('refund') - notice = Notice.objects.get() - eq_(notice.transaction_uuid, self.trans_uuid) - eq_(notice.success, True) - eq_(notice.url, url) @fudge.patch('webpay.pay.utils.requests') @mock.patch('lib.solitude.api.client.slumber') @@ -139,10 +130,6 @@ def req_ok(req): .has_attr(text=self.trans_uuid) .expects('raise_for_status')) self.do_chargeback('reversal') - notice = Notice.objects.get() - eq_(notice.transaction_uuid, self.trans_uuid) - eq_(notice.last_error, '') - eq_(notice.success, True) @mock.patch('webpay.pay.utils.requests') @mock.patch('lib.solitude.api.client.slumber') @@ -160,10 +147,6 @@ def test_notify_timeout(self, marketplace, solitude, requests): self.set_secret_mock(solitude, 'f') requests.post.side_effect = Timeout('Timeout') self.notify() - notice = Notice.objects.get() - eq_(notice.success, False) - er = notice.last_error - assert 'Timeout' in er, 'Unexpected: %s' % er @mock.patch('lib.solitude.api.client.slumber') @mock.patch('webpay.pay.tasks.payment_notify.retry') @@ -182,10 +165,6 @@ def test_any_error(self, fake_req, marketplace, solitude): self.set_secret_mock(solitude, 'f') fake_req.expects('post').raises(RequestException('some http error')) self.notify() - notice = Notice.objects.get() - eq_(notice.success, False) - er = notice.last_error - assert 'some http error' in er, 'Unexpected: %s' % er @fudge.patch('webpay.pay.utils.requests') @mock.patch('lib.solitude.api.client.slumber') @@ -198,10 +177,6 @@ def test_bad_status(self, fake_req, marketplace, solitude): .raises(urllib2.HTTPError('url', 500, 'Error', [], None))) self.notify() - notice = Notice.objects.get() - eq_(notice.success, False) - er = notice.last_error - assert 'HTTP Error' in er, 'Unexpected: %s' % er @fudge.patch('webpay.pay.utils.requests') @mock.patch('lib.solitude.api.client.slumber') @@ -211,8 +186,6 @@ def test_invalid_app_response(self, fake_req, slumber): .provides('raise_for_status') .has_attr(text='')) self.notify() - notice = Notice.objects.get() - eq_(notice.success, False) @mock.patch('lib.solitude.api.client.slumber') @mock.patch('webpay.pay.utils.requests') @@ -298,11 +271,6 @@ def req_ok(req): .has_attr(text=self.trans_uuid) .expects('raise_for_status')) self.notify(payload) - notice = Notice.objects.get() - assert notice.transaction_uuid, notice - eq_(notice.success, True) - eq_(notice.url, url) - eq_(notice.simulated, SIMULATED_POSTBACK) @fudge.patch('webpay.pay.utils.requests') def test_chargeback(self, slumber, fake_req): @@ -325,11 +293,6 @@ def req_ok(req): .has_attr(text=self.trans_uuid) .expects('raise_for_status')) self.notify(payload) - notice = Notice.objects.get() - assert notice.transaction_uuid, notice - eq_(notice.success, True) - eq_(notice.url, url) - eq_(notice.simulated, SIMULATED_CHARGEBACK) @fudge.patch('webpay.pay.utils.requests') def test_chargeback_reason(self, slumber, fake_req): diff --git a/webpay/pay/utils.py b/webpay/pay/utils.py index 19bc91e7b..a4a11e8c7 100644 --- a/webpay/pay/utils.py +++ b/webpay/pay/utils.py @@ -14,7 +14,7 @@ from lib.marketplace.api import client -from .models import NOT_SIMULATED +from .constants import NOT_SIMULATED log = logging.getLogger('w.pay.utils')