From 61853c2bc6b0881ce1bbfca54443e992501e39c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Mon, 17 Nov 2014 14:35:19 +0100 Subject: [PATCH] refactor SMS applications (#5786) SMS application models were subclass of a non-abtract MessageGateway, it didn't bring anything but a classmethod and complications for migrations; it's now removed in favour of directly subclassing BaseResource. Migrations are added, and new table names are defined to avoid collisions. The passerelle.messages application has also been moved to passerelle.sms, this avoids the conflicting name 'messages' that is also claimed by django.contrib.messages. --- passerelle/apps/choosit/migrations/0001_initial.py | 129 +++++++++++++++++++++ passerelle/apps/choosit/migrations/__init__.py | 0 passerelle/apps/choosit/models.py | 18 ++- passerelle/apps/choosit/views.py | 2 +- passerelle/apps/mobyt/migrations/0001_initial.py | 67 +++++++++++ passerelle/apps/mobyt/migrations/__init__.py | 0 passerelle/apps/mobyt/models.py | 8 +- passerelle/apps/mobyt/views.py | 2 +- passerelle/apps/ovh/migrations/0001_initial.py | 73 ++++++++++++ passerelle/apps/ovh/migrations/__init__.py | 0 passerelle/apps/ovh/models.py | 8 +- passerelle/apps/ovh/views.py | 2 +- passerelle/apps/oxyd/migrations/0001_initial.py | 65 +++++++++++ passerelle/apps/oxyd/migrations/__init__.py | 0 passerelle/apps/oxyd/models.py | 8 +- passerelle/apps/oxyd/views.py | 2 +- passerelle/default_settings.py | 2 - passerelle/messages/__init__.py | 0 passerelle/messages/admin.py | 1 - passerelle/messages/models.py | 36 ------ passerelle/messages/templates/messages/view.html | 4 - passerelle/messages/tests.py | 23 ---- passerelle/messages/views.py | 29 ----- passerelle/register/__init__.py | 0 passerelle/register/admin.py | 0 passerelle/register/models.py | 10 -- passerelle/register/templates/register/view.html | 4 - passerelle/register/urls.py | 13 --- passerelle/register/views.py | 36 ------ passerelle/sms/__init__.py | 23 ++++ passerelle/sms/tests.py | 22 ++++ passerelle/sms/views.py | 29 +++++ 32 files changed, 441 insertions(+), 175 deletions(-) create mode 100644 passerelle/apps/choosit/migrations/0001_initial.py create mode 100644 passerelle/apps/choosit/migrations/__init__.py create mode 100644 passerelle/apps/mobyt/migrations/0001_initial.py create mode 100644 passerelle/apps/mobyt/migrations/__init__.py create mode 100644 passerelle/apps/ovh/migrations/0001_initial.py create mode 100644 passerelle/apps/ovh/migrations/__init__.py create mode 100644 passerelle/apps/oxyd/migrations/0001_initial.py create mode 100644 passerelle/apps/oxyd/migrations/__init__.py delete mode 100644 passerelle/messages/__init__.py delete mode 100644 passerelle/messages/admin.py delete mode 100644 passerelle/messages/models.py delete mode 100644 passerelle/messages/templates/messages/view.html delete mode 100644 passerelle/messages/tests.py delete mode 100644 passerelle/messages/views.py delete mode 100644 passerelle/register/__init__.py delete mode 100644 passerelle/register/admin.py delete mode 100644 passerelle/register/models.py delete mode 100644 passerelle/register/templates/register/view.html delete mode 100644 passerelle/register/urls.py delete mode 100644 passerelle/register/views.py create mode 100644 passerelle/sms/__init__.py create mode 100644 passerelle/sms/tests.py create mode 100644 passerelle/sms/views.py diff --git a/passerelle/apps/choosit/migrations/0001_initial.py b/passerelle/apps/choosit/migrations/0001_initial.py new file mode 100644 index 0000000..a0fa2dc --- /dev/null +++ b/passerelle/apps/choosit/migrations/0001_initial.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'ChoositSMSGateway' + db.create_table('sms_choosit', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('title', self.gf('django.db.models.fields.CharField')(max_length=50)), + ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)), + ('description', self.gf('django.db.models.fields.TextField')()), + ('key', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('default_country_code', self.gf('django.db.models.fields.CharField')(default=u'33', max_length=3)), + )) + db.send_create_signal(u'choosit', ['ChoositSMSGateway']) + + # Adding M2M table for field users on 'ChoositSMSGateway' + m2m_table_name = db.shorten_name('sms_choosit_users') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('choositsmsgateway', models.ForeignKey(orm[u'choosit.choositsmsgateway'], null=False)), + ('apiuser', models.ForeignKey(orm[u'base.apiuser'], null=False)) + )) + db.create_unique(m2m_table_name, ['choositsmsgateway_id', 'apiuser_id']) + + # Adding model 'ChoositRegisterNewsletter' + db.create_table('newsletter_choosit', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('name', self.gf('django.db.models.fields.CharField')(max_length=16)), + ('description', self.gf('django.db.models.fields.CharField')(max_length=128, blank=True)), + )) + db.send_create_signal(u'choosit', ['ChoositRegisterNewsletter']) + + # Adding model 'ChoositRegisterGateway' + db.create_table('registration_choosit', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('title', self.gf('django.db.models.fields.CharField')(max_length=50)), + ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)), + ('description', self.gf('django.db.models.fields.TextField')()), + ('url', self.gf('django.db.models.fields.CharField')(max_length=200)), + ('key', self.gf('django.db.models.fields.CharField')(max_length=64)), + )) + db.send_create_signal(u'choosit', ['ChoositRegisterGateway']) + + # Adding M2M table for field users on 'ChoositRegisterGateway' + m2m_table_name = db.shorten_name('registration_choosit_users') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('choositregistergateway', models.ForeignKey(orm[u'choosit.choositregistergateway'], null=False)), + ('apiuser', models.ForeignKey(orm[u'base.apiuser'], null=False)) + )) + db.create_unique(m2m_table_name, ['choositregistergateway_id', 'apiuser_id']) + + # Adding M2M table for field newsletters on 'ChoositRegisterGateway' + m2m_table_name = db.shorten_name('registration_choosit_newsletters') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('choositregistergateway', models.ForeignKey(orm[u'choosit.choositregistergateway'], null=False)), + ('choositregisternewsletter', models.ForeignKey(orm[u'choosit.choositregisternewsletter'], null=False)) + )) + db.create_unique(m2m_table_name, ['choositregistergateway_id', 'choositregisternewsletter_id']) + + + def backwards(self, orm): + # Deleting model 'ChoositSMSGateway' + db.delete_table('sms_choosit') + + # Removing M2M table for field users on 'ChoositSMSGateway' + db.delete_table(db.shorten_name('sms_choosit_users')) + + # Deleting model 'ChoositRegisterNewsletter' + db.delete_table('newsletter_choosit') + + # Deleting model 'ChoositRegisterGateway' + db.delete_table('registration_choosit') + + # Removing M2M table for field users on 'ChoositRegisterGateway' + db.delete_table(db.shorten_name('registration_choosit_users')) + + # Removing M2M table for field newsletters on 'ChoositRegisterGateway' + db.delete_table(db.shorten_name('registration_choosit_newsletters')) + + + models = { + u'base.apiuser': { + 'Meta': {'object_name': 'ApiUser'}, + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'fullname': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ipsource': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), + 'keytype': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'choosit.choositregistergateway': { + 'Meta': {'object_name': 'ChoositRegisterGateway', 'db_table': "'registration_choosit'"}, + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'newsletters': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['choosit.ChoositRegisterNewsletter']", 'symmetrical': 'False', 'blank': 'True'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'url': ('django.db.models.fields.CharField', [], {'max_length': '200'}), + 'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['base.ApiUser']", 'symmetrical': 'False', 'blank': 'True'}) + }, + u'choosit.choositregisternewsletter': { + 'Meta': {'object_name': 'ChoositRegisterNewsletter', 'db_table': "'newsletter_choosit'"}, + 'description': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '16'}) + }, + u'choosit.choositsmsgateway': { + 'Meta': {'object_name': 'ChoositSMSGateway', 'db_table': "'sms_choosit'"}, + 'default_country_code': ('django.db.models.fields.CharField', [], {'default': "u'33'", 'max_length': '3'}), + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['base.ApiUser']", 'symmetrical': 'False', 'blank': 'True'}) + } + } + + complete_apps = ['choosit'] \ No newline at end of file diff --git a/passerelle/apps/choosit/migrations/__init__.py b/passerelle/apps/choosit/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/passerelle/apps/choosit/models.py b/passerelle/apps/choosit/models.py index 4fd3d1a..7916f2c 100644 --- a/passerelle/apps/choosit/models.py +++ b/passerelle/apps/choosit/models.py @@ -5,8 +5,8 @@ import logging import json from django.db import models -from passerelle.messages.models import MessageGateway -from passerelle.register.models import RegisterGateway +from passerelle.base.models import BaseResource +from passerelle.sms import SMSGatewayMixin from django.core.urlresolvers import reverse from .choosit import ChoositRegisterWS @@ -15,13 +15,14 @@ from .choosit import ChoositRegisterWS class ChoositError(Exception): pass -class ChoositSMSGateway(MessageGateway): +class ChoositSMSGateway(BaseResource, SMSGatewayMixin): key = models.CharField(max_length=64) default_country_code = models.CharField(max_length=3, default=u'33') # FIXME: add regexp field, to check destination and from format class Meta: verbose_name = 'Choosit' + db_table = 'sms_choosit' @classmethod def get_verbose_name(cls): @@ -75,15 +76,24 @@ class ChoositRegisterNewsletter(models.Model): name = models.CharField(max_length=16) description = models.CharField(max_length=128, blank=True) + class Meta: + verbose_name = 'Choosit Registration' + db_table = 'newsletter_choosit' + def __unicode__(self): return u'%s: %s' % (self.name, self.description or u'') -class ChoositRegisterGateway(RegisterGateway): + +class ChoositRegisterGateway(BaseResource): url = models.CharField(max_length=200) key = models.CharField(max_length=64) newsletters = models.ManyToManyField(ChoositRegisterNewsletter, blank=True) + class Meta: + verbose_name = 'Choosit Registration' + db_table = 'registration_choosit' + def get_list(self, user): reg = ChoositRegisterWS(self.url, self.key) diff --git a/passerelle/apps/choosit/views.py b/passerelle/apps/choosit/views.py index 737a6c9..4bd084f 100644 --- a/passerelle/apps/choosit/views.py +++ b/passerelle/apps/choosit/views.py @@ -3,7 +3,7 @@ from django.core.urlresolvers import reverse from django.views.generic.edit import CreateView, UpdateView, DeleteView from passerelle.base.views import ResourceView -from passerelle.messages.views import SendView +from passerelle.sms.views import SendView from .models import ChoositSMSGateway from .forms import ChoositSMSGatewayForm diff --git a/passerelle/apps/mobyt/migrations/0001_initial.py b/passerelle/apps/mobyt/migrations/0001_initial.py new file mode 100644 index 0000000..cafde75 --- /dev/null +++ b/passerelle/apps/mobyt/migrations/0001_initial.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'MobytSMSGateway' + db.create_table('sms_mobyt', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('title', self.gf('django.db.models.fields.CharField')(max_length=50)), + ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)), + ('description', self.gf('django.db.models.fields.TextField')()), + ('username', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('password', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('quality', self.gf('django.db.models.fields.CharField')(default='l', max_length=4)), + ('default_country_code', self.gf('django.db.models.fields.CharField')(default=u'33', max_length=3)), + )) + db.send_create_signal(u'mobyt', ['MobytSMSGateway']) + + # Adding M2M table for field users on 'MobytSMSGateway' + m2m_table_name = db.shorten_name('sms_mobyt_users') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('mobytsmsgateway', models.ForeignKey(orm[u'mobyt.mobytsmsgateway'], null=False)), + ('apiuser', models.ForeignKey(orm[u'base.apiuser'], null=False)) + )) + db.create_unique(m2m_table_name, ['mobytsmsgateway_id', 'apiuser_id']) + + + def backwards(self, orm): + # Deleting model 'MobytSMSGateway' + db.delete_table('sms_mobyt') + + # Removing M2M table for field users on 'MobytSMSGateway' + db.delete_table(db.shorten_name('sms_mobyt_users')) + + + models = { + u'base.apiuser': { + 'Meta': {'object_name': 'ApiUser'}, + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'fullname': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ipsource': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), + 'keytype': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'mobyt.mobytsmsgateway': { + 'Meta': {'object_name': 'MobytSMSGateway', 'db_table': "'sms_mobyt'"}, + 'default_country_code': ('django.db.models.fields.CharField', [], {'default': "u'33'", 'max_length': '3'}), + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'quality': ('django.db.models.fields.CharField', [], {'default': "'l'", 'max_length': '4'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'username': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['base.ApiUser']", 'symmetrical': 'False', 'blank': 'True'}) + } + } + + complete_apps = ['mobyt'] \ No newline at end of file diff --git a/passerelle/apps/mobyt/migrations/__init__.py b/passerelle/apps/mobyt/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/passerelle/apps/mobyt/models.py b/passerelle/apps/mobyt/models.py index db014ac..af09c22 100644 --- a/passerelle/apps/mobyt/models.py +++ b/passerelle/apps/mobyt/models.py @@ -8,17 +8,18 @@ from django.utils.translation import ugettext_lazy as _ from django.db import models from django.core.urlresolvers import reverse -from passerelle.messages.models import MessageGateway +from passerelle.base.models import BaseResource +from passerelle.sms import SMSGatewayMixin -logger = logging.getLogger('passerelle.messages.mobyt') +logger = logging.getLogger('passerelle.apps.mobyt') class MobytError(Exception): pass -class MobytSMSGateway(MessageGateway): +class MobytSMSGateway(BaseResource, SMSGatewayMixin): URL = 'http://multilevel.mobyt.fr/sms/batch.php' MESSAGES_QUALITIES = ( ('l', _('sms direct')), @@ -34,6 +35,7 @@ class MobytSMSGateway(MessageGateway): class Meta: verbose_name = 'Mobyt' + db_table = 'sms_mobyt' @classmethod def get_verbose_name(cls): diff --git a/passerelle/apps/mobyt/views.py b/passerelle/apps/mobyt/views.py index b2b66db..ca25ae4 100644 --- a/passerelle/apps/mobyt/views.py +++ b/passerelle/apps/mobyt/views.py @@ -2,7 +2,7 @@ from django.core.urlresolvers import reverse from django.views.generic.edit import CreateView, UpdateView, DeleteView from passerelle.base.views import ResourceView -from passerelle.messages.views import SendView +from passerelle.sms.views import SendView from .models import MobytSMSGateway from .forms import MobytSMSGatewayForm diff --git a/passerelle/apps/ovh/migrations/0001_initial.py b/passerelle/apps/ovh/migrations/0001_initial.py new file mode 100644 index 0000000..3f397e4 --- /dev/null +++ b/passerelle/apps/ovh/migrations/0001_initial.py @@ -0,0 +1,73 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'OVHSMSGateway' + db.create_table('sms_ovh', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('title', self.gf('django.db.models.fields.CharField')(max_length=50)), + ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)), + ('description', self.gf('django.db.models.fields.TextField')()), + ('account', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('username', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('password', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('msg_class', self.gf('django.db.models.fields.IntegerField')(default=1)), + ('credit_threshold_alert', self.gf('django.db.models.fields.PositiveIntegerField')(default=100)), + ('default_country_code', self.gf('django.db.models.fields.CharField')(default=u'33', max_length=3)), + ('credit_left', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)), + )) + db.send_create_signal(u'ovh', ['OVHSMSGateway']) + + # Adding M2M table for field users on 'OVHSMSGateway' + m2m_table_name = db.shorten_name('sms_ovh_users') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('ovhsmsgateway', models.ForeignKey(orm[u'ovh.ovhsmsgateway'], null=False)), + ('apiuser', models.ForeignKey(orm[u'base.apiuser'], null=False)) + )) + db.create_unique(m2m_table_name, ['ovhsmsgateway_id', 'apiuser_id']) + + + def backwards(self, orm): + # Deleting model 'OVHSMSGateway' + db.delete_table('sms_ovh') + + # Removing M2M table for field users on 'OVHSMSGateway' + db.delete_table(db.shorten_name('sms_ovh_users')) + + + models = { + u'base.apiuser': { + 'Meta': {'object_name': 'ApiUser'}, + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'fullname': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ipsource': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), + 'keytype': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'ovh.ovhsmsgateway': { + 'Meta': {'object_name': 'OVHSMSGateway', 'db_table': "'sms_ovh'"}, + 'account': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'credit_left': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}), + 'credit_threshold_alert': ('django.db.models.fields.PositiveIntegerField', [], {'default': '100'}), + 'default_country_code': ('django.db.models.fields.CharField', [], {'default': "u'33'", 'max_length': '3'}), + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'msg_class': ('django.db.models.fields.IntegerField', [], {'default': '1'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'username': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['base.ApiUser']", 'symmetrical': 'False', 'blank': 'True'}) + } + } + + complete_apps = ['ovh'] \ No newline at end of file diff --git a/passerelle/apps/ovh/migrations/__init__.py b/passerelle/apps/ovh/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/passerelle/apps/ovh/models.py b/passerelle/apps/ovh/models.py index f8a052c..b78ac0e 100644 --- a/passerelle/apps/ovh/models.py +++ b/passerelle/apps/ovh/models.py @@ -8,16 +8,17 @@ from django.utils.translation import ugettext_lazy as _ from django.db import models from django.core.urlresolvers import reverse -from passerelle.messages.models import MessageGateway +from passerelle.base.models import BaseResource +from passerelle.sms import SMSGatewayMixin -logger = logging.getLogger('passerelle.messages.ovh') +logger = logging.getLogger('passerelle.apps.ovh') class OVHError(Exception): pass -class OVHSMSGateway(MessageGateway): +class OVHSMSGateway(BaseResource, SMSGatewayMixin): URL = 'https://www.ovh.com/cgi-bin/sms/http2sms.cgi' MESSAGES_CLASSES = ( (0, _('Message are directly shown to users on phone screen ' @@ -42,6 +43,7 @@ class OVHSMSGateway(MessageGateway): class Meta: verbose_name = 'OVH' + db_table = 'sms_ovh' @classmethod def get_verbose_name(cls): diff --git a/passerelle/apps/ovh/views.py b/passerelle/apps/ovh/views.py index a995672..367ccc4 100644 --- a/passerelle/apps/ovh/views.py +++ b/passerelle/apps/ovh/views.py @@ -2,7 +2,7 @@ from django.core.urlresolvers import reverse from django.views.generic.edit import CreateView, UpdateView, DeleteView from passerelle.base.views import ResourceView -from passerelle.messages.views import SendView +from passerelle.sms.views import SendView from .models import OVHSMSGateway from .forms import OVHSMSGatewayForm diff --git a/passerelle/apps/oxyd/migrations/0001_initial.py b/passerelle/apps/oxyd/migrations/0001_initial.py new file mode 100644 index 0000000..d0da81e --- /dev/null +++ b/passerelle/apps/oxyd/migrations/0001_initial.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +from south.utils import datetime_utils as datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'OxydSMSGateway' + db.create_table('sms_oxyd', ( + (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('title', self.gf('django.db.models.fields.CharField')(max_length=50)), + ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)), + ('description', self.gf('django.db.models.fields.TextField')()), + ('username', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('password', self.gf('django.db.models.fields.CharField')(max_length=64)), + ('default_country_code', self.gf('django.db.models.fields.CharField')(default=u'33', max_length=3)), + )) + db.send_create_signal(u'oxyd', ['OxydSMSGateway']) + + # Adding M2M table for field users on 'OxydSMSGateway' + m2m_table_name = db.shorten_name('sms_oxyd_users') + db.create_table(m2m_table_name, ( + ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)), + ('oxydsmsgateway', models.ForeignKey(orm[u'oxyd.oxydsmsgateway'], null=False)), + ('apiuser', models.ForeignKey(orm[u'base.apiuser'], null=False)) + )) + db.create_unique(m2m_table_name, ['oxydsmsgateway_id', 'apiuser_id']) + + + def backwards(self, orm): + # Deleting model 'OxydSMSGateway' + db.delete_table('sms_oxyd') + + # Removing M2M table for field users on 'OxydSMSGateway' + db.delete_table(db.shorten_name('sms_oxyd_users')) + + + models = { + u'base.apiuser': { + 'Meta': {'object_name': 'ApiUser'}, + 'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}), + 'fullname': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ipsource': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}), + 'key': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}), + 'keytype': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + u'oxyd.oxydsmsgateway': { + 'Meta': {'object_name': 'OxydSMSGateway', 'db_table': "'sms_oxyd'"}, + 'default_country_code': ('django.db.models.fields.CharField', [], {'default': "u'33'", 'max_length': '3'}), + 'description': ('django.db.models.fields.TextField', [], {}), + u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}), + 'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}), + 'username': ('django.db.models.fields.CharField', [], {'max_length': '64'}), + 'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['base.ApiUser']", 'symmetrical': 'False', 'blank': 'True'}) + } + } + + complete_apps = ['oxyd'] \ No newline at end of file diff --git a/passerelle/apps/oxyd/migrations/__init__.py b/passerelle/apps/oxyd/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/passerelle/apps/oxyd/models.py b/passerelle/apps/oxyd/models.py index ae12a96..6a78c42 100644 --- a/passerelle/apps/oxyd/models.py +++ b/passerelle/apps/oxyd/models.py @@ -7,16 +7,17 @@ import json from django.db import models from django.core.urlresolvers import reverse -from passerelle.messages.models import MessageGateway +from passerelle.base.models import BaseResource +from passerelle.sms import SMSGatewayMixin -logger = logging.getLogger('passerelle.messages.oxyd') +logger = logging.getLogger('passerelle.apps.oxyd') class OxydError(Exception): pass -class OxydSMSGateway(MessageGateway): +class OxydSMSGateway(BaseResource, SMSGatewayMixin): username = models.CharField(max_length=64) password = models.CharField(max_length=64) default_country_code = models.CharField(max_length=3, default=u'33') @@ -24,6 +25,7 @@ class OxydSMSGateway(MessageGateway): class Meta: verbose_name = 'Oxyd' + db_table = 'sms_oxyd' @classmethod def get_verbose_name(cls): diff --git a/passerelle/apps/oxyd/views.py b/passerelle/apps/oxyd/views.py index 0ce2527..e846f9d 100644 --- a/passerelle/apps/oxyd/views.py +++ b/passerelle/apps/oxyd/views.py @@ -2,7 +2,7 @@ from django.core.urlresolvers import reverse from django.views.generic.edit import CreateView, UpdateView, DeleteView from passerelle.base.views import ResourceView -from passerelle.messages.views import SendView +from passerelle.sms.views import SendView from .models import OxydSMSGateway from .forms import OxydSMSGatewayForm diff --git a/passerelle/default_settings.py b/passerelle/default_settings.py index fb9a72b..ea453fc 100644 --- a/passerelle/default_settings.py +++ b/passerelle/default_settings.py @@ -97,8 +97,6 @@ INSTALLED_APPS = ( 'passerelle.base', 'passerelle.datasources', 'passerelle.repost', - 'passerelle.messages', - 'passerelle.register', # connectors 'clicrdv', 'gdc', diff --git a/passerelle/messages/__init__.py b/passerelle/messages/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/passerelle/messages/admin.py b/passerelle/messages/admin.py deleted file mode 100644 index 8b13789..0000000 --- a/passerelle/messages/admin.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/passerelle/messages/models.py b/passerelle/messages/models.py deleted file mode 100644 index 875bf89..0000000 --- a/passerelle/messages/models.py +++ /dev/null @@ -1,36 +0,0 @@ -import re - -from django.db import models -from django.utils.translation import ugettext_lazy as _ - -from passerelle.base.models import BaseResource - - -class MessageGateway(BaseResource): - category = _('SMS Providers') - - @classmethod - def clean_numbers(cls, destinations, default_country_code, prefix='+'): - numbers = [] - for dest in destinations: - # most gateways needs the number prefixed by the country code, this is - # really unfortunate. - number = ''.join(re.findall('[0-9]', dest)) - if dest.startswith('+'): - pass # it already is fully qualified - elif number.startswith('00'): - # assumes 00 is international access code, remove it - number = number[2:] - elif number.startswith('0'): - # local prefix, remove 0 and add default country code - number = default_country_code + number[1:] - numbers.append(prefix + number) - return numbers - - def send(self, message, sender, destinations): - raise NotImplementedError - - def status(self): - return u'' - - diff --git a/passerelle/messages/templates/messages/view.html b/passerelle/messages/templates/messages/view.html deleted file mode 100644 index cbf600e..0000000 --- a/passerelle/messages/templates/messages/view.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends "passerelle/base/view.html" %} -{% load i18n %} - -{% block link_jsonp %}{% endblock %} diff --git a/passerelle/messages/tests.py b/passerelle/messages/tests.py deleted file mode 100644 index 5e2f22e..0000000 --- a/passerelle/messages/tests.py +++ /dev/null @@ -1,23 +0,0 @@ -from django.test import TestCase -from django.contrib.auth.models import User, Group -from django.db import transaction - -from .models import MessageGateway - -class MessageTestCase(TestCase): - def test_clean_numbers(self): - self.assertEqual(MessageGateway.clean_numbers(['+ 33 12'], '33'), - ['+3312']) - self.assertEqual(MessageGateway.clean_numbers(['0 0 33 12'], '33'), - ['+3312']) - self.assertEqual(MessageGateway.clean_numbers(['0 12'], '33'), - ['+3312']) - - def test_clean_numbers_no_prefix(self): - self.assertEqual(MessageGateway.clean_numbers(['+ 33 12'], '33', prefix=''), - ['3312']) - self.assertEqual(MessageGateway.clean_numbers(['0 0 33 12'], '33', prefix=''), - ['3312']) - self.assertEqual(MessageGateway.clean_numbers(['0 12'], '33', prefix=''), - ['3312']) - diff --git a/passerelle/messages/views.py b/passerelle/messages/views.py deleted file mode 100644 index 5870b54..0000000 --- a/passerelle/messages/views.py +++ /dev/null @@ -1,29 +0,0 @@ -import json - -from jsonresponse import to_json - -from django.views.generic.base import View -from django.views.generic.detail import SingleObjectMixin -from django.views.decorators.csrf import csrf_exempt -from django.utils.decorators import method_decorator - -from passerelle import utils - -class SendView(View, SingleObjectMixin): - @method_decorator(csrf_exempt) - def dispatch(self, *args, **kwargs): - return super(SendView, self).dispatch(*args, **kwargs) - - @to_json('api') - @utils.protected_api('can_send_messages') - def post(self, request, *args, **kwargs): - data = json.loads(request.body) - assert isinstance(data, dict), 'JSON payload is not a dict' - assert 'message' in data, 'missing "message" in JSON payload' - assert 'from' in data, 'missing "from" in JSON payload' - assert 'to' in data, 'missing "to" in JSON payload' - assert isinstance(data['message'], unicode), 'message is not a string' - assert isinstance(data['from'], unicode), 'from is not a string' - assert all(map(lambda x: isinstance(x, unicode), data['to'])), \ - 'to is not a list of strings' - return self.get_object().send(data['message'], data['from'], data['to']) diff --git a/passerelle/register/__init__.py b/passerelle/register/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/passerelle/register/admin.py b/passerelle/register/admin.py deleted file mode 100644 index e69de29..0000000 diff --git a/passerelle/register/models.py b/passerelle/register/models.py deleted file mode 100644 index e71fbde..0000000 --- a/passerelle/register/models.py +++ /dev/null @@ -1,10 +0,0 @@ -from django.db import models -from passerelle.base.models import BaseResource - -class RegisterGateway(BaseResource): - def get_list(self, user): - raise NotImplementedError - - def post(self, user, data): - raise NotImplementedError - diff --git a/passerelle/register/templates/register/view.html b/passerelle/register/templates/register/view.html deleted file mode 100644 index cbf600e..0000000 --- a/passerelle/register/templates/register/view.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends "passerelle/base/view.html" %} -{% load i18n %} - -{% block link_jsonp %}{% endblock %} diff --git a/passerelle/register/urls.py b/passerelle/register/urls.py deleted file mode 100644 index 4a1350b..0000000 --- a/passerelle/register/urls.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.conf.urls import patterns, url, include - -from ..base.views import ResourceIndexView, ResourceView -from models import RegisterGateway - -urlpatterns = patterns('passerelle.register.views', - # human views - url(r'^$', ResourceIndexView.as_view(model=RegisterGateway)), - url(r'^(?P[\w-]+)/$', ResourceView.as_view(model=RegisterGateway, - template_name='register/view.html')), - # technical views (JSON) - url(r'^(?P[\w-]+)/json$', 'json_view'), -) diff --git a/passerelle/register/views.py b/passerelle/register/views.py deleted file mode 100644 index 82a2f04..0000000 --- a/passerelle/register/views.py +++ /dev/null @@ -1,36 +0,0 @@ -import json - -from django.views.decorators.csrf import csrf_exempt -from jsonresponse import to_json - -from models import RegisterGateway - - -def get_list(register, user, **kwargs): - return register.get_list(user, **kwargs) - -def post(register, user, data, **kwargs): - assert user is not None, 'missing user argument' - assert isinstance(data, list), 'JSON payload is not a list' - for row in data: - assert isinstance(row, dict), 'all elements must be dict' - assert isinstance(row['name'], unicode) - assert isinstance(row['transports'], list) - return register.post(user, data, **kwargs) - - -@csrf_exempt -@to_json('api') -def json_view(request, slug, **kwargs): - reg = RegisterGateway.objects.get_slug(slug, request) - kwargs = {} - for param in (reg.parameters or ()): - kwargs[param] = request.GET.get(param) - user = request.GET.get('user') - if request.method == 'GET': - return get_list(reg, user, **kwargs) - if request.method == 'POST': - data = json.loads(request.body) - return post(reg, user, data, **kwargs) - raise NotImplementedError - diff --git a/passerelle/sms/__init__.py b/passerelle/sms/__init__.py new file mode 100644 index 0000000..0eaa4b2 --- /dev/null +++ b/passerelle/sms/__init__.py @@ -0,0 +1,23 @@ +from django.utils.translation import ugettext_lazy as _ + +class SMSGatewayMixin(object): + category = _('SMS Providers') + + @classmethod + def clean_numbers(cls, destinations, default_country_code, prefix='+'): + numbers = [] + for dest in destinations: + # most gateways needs the number prefixed by the country code, this is + # really unfortunate. + number = ''.join(re.findall('[0-9]', dest)) + if dest.startswith('+'): + pass # it already is fully qualified + elif number.startswith('00'): + # assumes 00 is international access code, remove it + number = number[2:] + elif number.startswith('0'): + # local prefix, remove 0 and add default country code + number = default_country_code + number[1:] + numbers.append(prefix + number) + return numbers + diff --git a/passerelle/sms/tests.py b/passerelle/sms/tests.py new file mode 100644 index 0000000..7e637be --- /dev/null +++ b/passerelle/sms/tests.py @@ -0,0 +1,22 @@ +from django.test import TestCase +from django.contrib.auth.models import User, Group +from django.db import transaction + +from . import SMSGatewayMixin + +class MessageTestCase(TestCase): + def test_clean_numbers(self): + self.assertEqual(SMSGatewayMixin.clean_numbers(['+ 33 12'], '33'), + ['+3312']) + self.assertEqual(SMSGatewayMixin.clean_numbers(['0 0 33 12'], '33'), + ['+3312']) + self.assertEqual(SMSGatewayMixin.clean_numbers(['0 12'], '33'), + ['+3312']) + + def test_clean_numbers_no_prefix(self): + self.assertEqual(SMSGatewayMixin.clean_numbers(['+ 33 12'], '33', prefix=''), + ['3312']) + self.assertEqual(SMSGatewayMixin.clean_numbers(['0 0 33 12'], '33', prefix=''), + ['3312']) + self.assertEqual(SMSGatewayMixin.clean_numbers(['0 12'], '33', prefix=''), + ['3312']) diff --git a/passerelle/sms/views.py b/passerelle/sms/views.py new file mode 100644 index 0000000..ee9fa23 --- /dev/null +++ b/passerelle/sms/views.py @@ -0,0 +1,29 @@ +import json + +from jsonresponse import to_json + +from django.utils.decorators import method_decorator +from django.views.decorators.csrf import csrf_exempt +from django.views.generic.base import View +from django.views.generic.detail import SingleObjectMixin + +from passerelle import utils + +class SendView(View, SingleObjectMixin): + @method_decorator(csrf_exempt) + def dispatch(self, *args, **kwargs): + return super(SendView, self).dispatch(*args, **kwargs) + + @to_json('api') + @utils.protected_api('can_send_messages') + def post(self, request, *args, **kwargs): + data = json.loads(request.body) + assert isinstance(data, dict), 'JSON payload is not a dict' + assert 'message' in data, 'missing "message" in JSON payload' + assert 'from' in data, 'missing "from" in JSON payload' + assert 'to' in data, 'missing "to" in JSON payload' + assert isinstance(data['message'], unicode), 'message is not a string' + assert isinstance(data['from'], unicode), 'from is not a string' + assert all(map(lambda x: isinstance(x, unicode), data['to'])), \ + 'to is not a list of strings' + return self.get_object().send(data['message'], data['from'], data['to']) -- 2.1.3