Projet

Général

Profil

0001-refactor-SMS-applications-5786.patch

Frédéric Péters, 24 novembre 2014 15:12

Télécharger (43 ko)

Voir les différences:

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
passerelle/apps/choosit/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from south.utils import datetime_utils as datetime
3
from south.db import db
4
from south.v2 import SchemaMigration
5
from django.db import models
6

  
7

  
8
class Migration(SchemaMigration):
9

  
10
    def forwards(self, orm):
11
        # Adding model 'ChoositSMSGateway'
12
        db.create_table('sms_choosit', (
13
            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
14
            ('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
15
            ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)),
16
            ('description', self.gf('django.db.models.fields.TextField')()),
17
            ('key', self.gf('django.db.models.fields.CharField')(max_length=64)),
18
            ('default_country_code', self.gf('django.db.models.fields.CharField')(default=u'33', max_length=3)),
19
        ))
20
        db.send_create_signal(u'choosit', ['ChoositSMSGateway'])
21

  
22
        # Adding M2M table for field users on 'ChoositSMSGateway'
23
        m2m_table_name = db.shorten_name('sms_choosit_users')
24
        db.create_table(m2m_table_name, (
25
            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
26
            ('choositsmsgateway', models.ForeignKey(orm[u'choosit.choositsmsgateway'], null=False)),
27
            ('apiuser', models.ForeignKey(orm[u'base.apiuser'], null=False))
28
        ))
29
        db.create_unique(m2m_table_name, ['choositsmsgateway_id', 'apiuser_id'])
30

  
31
        # Adding model 'ChoositRegisterNewsletter'
32
        db.create_table('newsletter_choosit', (
33
            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
34
            ('name', self.gf('django.db.models.fields.CharField')(max_length=16)),
35
            ('description', self.gf('django.db.models.fields.CharField')(max_length=128, blank=True)),
36
        ))
37
        db.send_create_signal(u'choosit', ['ChoositRegisterNewsletter'])
38

  
39
        # Adding model 'ChoositRegisterGateway'
40
        db.create_table('registration_choosit', (
41
            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
42
            ('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
43
            ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)),
44
            ('description', self.gf('django.db.models.fields.TextField')()),
45
            ('url', self.gf('django.db.models.fields.CharField')(max_length=200)),
46
            ('key', self.gf('django.db.models.fields.CharField')(max_length=64)),
47
        ))
48
        db.send_create_signal(u'choosit', ['ChoositRegisterGateway'])
49

  
50
        # Adding M2M table for field users on 'ChoositRegisterGateway'
51
        m2m_table_name = db.shorten_name('registration_choosit_users')
52
        db.create_table(m2m_table_name, (
53
            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
54
            ('choositregistergateway', models.ForeignKey(orm[u'choosit.choositregistergateway'], null=False)),
55
            ('apiuser', models.ForeignKey(orm[u'base.apiuser'], null=False))
56
        ))
57
        db.create_unique(m2m_table_name, ['choositregistergateway_id', 'apiuser_id'])
58

  
59
        # Adding M2M table for field newsletters on 'ChoositRegisterGateway'
60
        m2m_table_name = db.shorten_name('registration_choosit_newsletters')
61
        db.create_table(m2m_table_name, (
62
            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
63
            ('choositregistergateway', models.ForeignKey(orm[u'choosit.choositregistergateway'], null=False)),
64
            ('choositregisternewsletter', models.ForeignKey(orm[u'choosit.choositregisternewsletter'], null=False))
65
        ))
66
        db.create_unique(m2m_table_name, ['choositregistergateway_id', 'choositregisternewsletter_id'])
67

  
68

  
69
    def backwards(self, orm):
70
        # Deleting model 'ChoositSMSGateway'
71
        db.delete_table('sms_choosit')
72

  
73
        # Removing M2M table for field users on 'ChoositSMSGateway'
74
        db.delete_table(db.shorten_name('sms_choosit_users'))
75

  
76
        # Deleting model 'ChoositRegisterNewsletter'
77
        db.delete_table('newsletter_choosit')
78

  
79
        # Deleting model 'ChoositRegisterGateway'
80
        db.delete_table('registration_choosit')
81

  
82
        # Removing M2M table for field users on 'ChoositRegisterGateway'
83
        db.delete_table(db.shorten_name('registration_choosit_users'))
84

  
85
        # Removing M2M table for field newsletters on 'ChoositRegisterGateway'
86
        db.delete_table(db.shorten_name('registration_choosit_newsletters'))
87

  
88

  
89
    models = {
90
        u'base.apiuser': {
91
            'Meta': {'object_name': 'ApiUser'},
92
            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
93
            'fullname': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
94
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
95
            'ipsource': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
96
            'key': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
97
            'keytype': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}),
98
            'username': ('django.db.models.fields.CharField', [], {'max_length': '50'})
99
        },
100
        u'choosit.choositregistergateway': {
101
            'Meta': {'object_name': 'ChoositRegisterGateway', 'db_table': "'registration_choosit'"},
102
            'description': ('django.db.models.fields.TextField', [], {}),
103
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
104
            'key': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
105
            'newsletters': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['choosit.ChoositRegisterNewsletter']", 'symmetrical': 'False', 'blank': 'True'}),
106
            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
107
            'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
108
            'url': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
109
            'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['base.ApiUser']", 'symmetrical': 'False', 'blank': 'True'})
110
        },
111
        u'choosit.choositregisternewsletter': {
112
            'Meta': {'object_name': 'ChoositRegisterNewsletter', 'db_table': "'newsletter_choosit'"},
113
            'description': ('django.db.models.fields.CharField', [], {'max_length': '128', 'blank': 'True'}),
114
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
115
            'name': ('django.db.models.fields.CharField', [], {'max_length': '16'})
116
        },
117
        u'choosit.choositsmsgateway': {
118
            'Meta': {'object_name': 'ChoositSMSGateway', 'db_table': "'sms_choosit'"},
119
            'default_country_code': ('django.db.models.fields.CharField', [], {'default': "u'33'", 'max_length': '3'}),
120
            'description': ('django.db.models.fields.TextField', [], {}),
121
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
122
            'key': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
123
            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
124
            'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
125
            'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['base.ApiUser']", 'symmetrical': 'False', 'blank': 'True'})
126
        }
127
    }
128

  
129
    complete_apps = ['choosit']
passerelle/apps/choosit/models.py
5 5
import json
6 6

  
7 7
from django.db import models
8
from passerelle.messages.models import MessageGateway
9
from passerelle.register.models import RegisterGateway
8
from passerelle.base.models import BaseResource
9
from passerelle.sms import SMSGatewayMixin
10 10
from django.core.urlresolvers import reverse
11 11

  
12 12
from .choosit import ChoositRegisterWS
......
15 15
class ChoositError(Exception):
16 16
    pass
17 17

  
18
class ChoositSMSGateway(MessageGateway):
18
class ChoositSMSGateway(BaseResource, SMSGatewayMixin):
19 19
    key = models.CharField(max_length=64)
20 20
    default_country_code = models.CharField(max_length=3, default=u'33')
21 21
    # FIXME: add regexp field, to check destination and from format
22 22

  
23 23
    class Meta:
24 24
        verbose_name = 'Choosit'
25
        db_table = 'sms_choosit'
25 26

  
26 27
    @classmethod
27 28
    def get_verbose_name(cls):
......
75 76
    name = models.CharField(max_length=16)
76 77
    description = models.CharField(max_length=128, blank=True)
77 78

  
79
    class Meta:
80
        verbose_name = 'Choosit Registration'
81
        db_table = 'newsletter_choosit'
82

  
78 83
    def __unicode__(self):
79 84
        return u'%s: %s' % (self.name, self.description or u'<unnamed>')
80 85

  
81
class ChoositRegisterGateway(RegisterGateway):
86

  
87
class ChoositRegisterGateway(BaseResource):
82 88
    url = models.CharField(max_length=200)
83 89
    key = models.CharField(max_length=64)
84 90
    newsletters = models.ManyToManyField(ChoositRegisterNewsletter,
85 91
        blank=True)
86 92

  
93
    class Meta:
94
        verbose_name = 'Choosit Registration'
95
        db_table = 'registration_choosit'
96

  
87 97
    def get_list(self, user):
88 98
        reg = ChoositRegisterWS(self.url, self.key)
89 99

  
passerelle/apps/choosit/views.py
3 3
from django.views.generic.edit import CreateView, UpdateView, DeleteView
4 4

  
5 5
from passerelle.base.views import ResourceView
6
from passerelle.messages.views import SendView
6
from passerelle.sms.views import SendView
7 7

  
8 8
from .models import ChoositSMSGateway
9 9
from .forms import ChoositSMSGatewayForm
passerelle/apps/mobyt/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from south.utils import datetime_utils as datetime
3
from south.db import db
4
from south.v2 import SchemaMigration
5
from django.db import models
6

  
7

  
8
class Migration(SchemaMigration):
9

  
10
    def forwards(self, orm):
11
        # Adding model 'MobytSMSGateway'
12
        db.create_table('sms_mobyt', (
13
            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
14
            ('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
15
            ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)),
16
            ('description', self.gf('django.db.models.fields.TextField')()),
17
            ('username', self.gf('django.db.models.fields.CharField')(max_length=64)),
18
            ('password', self.gf('django.db.models.fields.CharField')(max_length=64)),
19
            ('quality', self.gf('django.db.models.fields.CharField')(default='l', max_length=4)),
20
            ('default_country_code', self.gf('django.db.models.fields.CharField')(default=u'33', max_length=3)),
21
        ))
22
        db.send_create_signal(u'mobyt', ['MobytSMSGateway'])
23

  
24
        # Adding M2M table for field users on 'MobytSMSGateway'
25
        m2m_table_name = db.shorten_name('sms_mobyt_users')
26
        db.create_table(m2m_table_name, (
27
            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
28
            ('mobytsmsgateway', models.ForeignKey(orm[u'mobyt.mobytsmsgateway'], null=False)),
29
            ('apiuser', models.ForeignKey(orm[u'base.apiuser'], null=False))
30
        ))
31
        db.create_unique(m2m_table_name, ['mobytsmsgateway_id', 'apiuser_id'])
32

  
33

  
34
    def backwards(self, orm):
35
        # Deleting model 'MobytSMSGateway'
36
        db.delete_table('sms_mobyt')
37

  
38
        # Removing M2M table for field users on 'MobytSMSGateway'
39
        db.delete_table(db.shorten_name('sms_mobyt_users'))
40

  
41

  
42
    models = {
43
        u'base.apiuser': {
44
            'Meta': {'object_name': 'ApiUser'},
45
            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
46
            'fullname': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
47
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
48
            'ipsource': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
49
            'key': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
50
            'keytype': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}),
51
            'username': ('django.db.models.fields.CharField', [], {'max_length': '50'})
52
        },
53
        u'mobyt.mobytsmsgateway': {
54
            'Meta': {'object_name': 'MobytSMSGateway', 'db_table': "'sms_mobyt'"},
55
            'default_country_code': ('django.db.models.fields.CharField', [], {'default': "u'33'", 'max_length': '3'}),
56
            'description': ('django.db.models.fields.TextField', [], {}),
57
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
58
            'password': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
59
            'quality': ('django.db.models.fields.CharField', [], {'default': "'l'", 'max_length': '4'}),
60
            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
61
            'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
62
            'username': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
63
            'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['base.ApiUser']", 'symmetrical': 'False', 'blank': 'True'})
64
        }
65
    }
66

  
67
    complete_apps = ['mobyt']
passerelle/apps/mobyt/models.py
8 8
from django.db import models
9 9
from django.core.urlresolvers import reverse
10 10

  
11
from passerelle.messages.models import MessageGateway
11
from passerelle.base.models import BaseResource
12
from passerelle.sms import SMSGatewayMixin
12 13

  
13 14

  
14
logger = logging.getLogger('passerelle.messages.mobyt')
15
logger = logging.getLogger('passerelle.apps.mobyt')
15 16

  
16 17

  
17 18
class MobytError(Exception):
18 19
    pass
19 20

  
20 21

  
21
class MobytSMSGateway(MessageGateway):
22
class MobytSMSGateway(BaseResource, SMSGatewayMixin):
22 23
    URL = 'http://multilevel.mobyt.fr/sms/batch.php'
23 24
    MESSAGES_QUALITIES = (
24 25
            ('l', _('sms direct')),
......
34 35

  
35 36
    class Meta:
36 37
        verbose_name = 'Mobyt'
38
        db_table = 'sms_mobyt'
37 39

  
38 40
    @classmethod
39 41
    def get_verbose_name(cls):
passerelle/apps/mobyt/views.py
2 2
from django.views.generic.edit import CreateView, UpdateView, DeleteView
3 3

  
4 4
from passerelle.base.views import ResourceView
5
from passerelle.messages.views import SendView
5
from passerelle.sms.views import SendView
6 6

  
7 7
from .models import MobytSMSGateway
8 8
from .forms import MobytSMSGatewayForm
passerelle/apps/ovh/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from south.utils import datetime_utils as datetime
3
from south.db import db
4
from south.v2 import SchemaMigration
5
from django.db import models
6

  
7

  
8
class Migration(SchemaMigration):
9

  
10
    def forwards(self, orm):
11
        # Adding model 'OVHSMSGateway'
12
        db.create_table('sms_ovh', (
13
            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
14
            ('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
15
            ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)),
16
            ('description', self.gf('django.db.models.fields.TextField')()),
17
            ('account', self.gf('django.db.models.fields.CharField')(max_length=64)),
18
            ('username', self.gf('django.db.models.fields.CharField')(max_length=64)),
19
            ('password', self.gf('django.db.models.fields.CharField')(max_length=64)),
20
            ('msg_class', self.gf('django.db.models.fields.IntegerField')(default=1)),
21
            ('credit_threshold_alert', self.gf('django.db.models.fields.PositiveIntegerField')(default=100)),
22
            ('default_country_code', self.gf('django.db.models.fields.CharField')(default=u'33', max_length=3)),
23
            ('credit_left', self.gf('django.db.models.fields.PositiveIntegerField')(default=0)),
24
        ))
25
        db.send_create_signal(u'ovh', ['OVHSMSGateway'])
26

  
27
        # Adding M2M table for field users on 'OVHSMSGateway'
28
        m2m_table_name = db.shorten_name('sms_ovh_users')
29
        db.create_table(m2m_table_name, (
30
            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
31
            ('ovhsmsgateway', models.ForeignKey(orm[u'ovh.ovhsmsgateway'], null=False)),
32
            ('apiuser', models.ForeignKey(orm[u'base.apiuser'], null=False))
33
        ))
34
        db.create_unique(m2m_table_name, ['ovhsmsgateway_id', 'apiuser_id'])
35

  
36

  
37
    def backwards(self, orm):
38
        # Deleting model 'OVHSMSGateway'
39
        db.delete_table('sms_ovh')
40

  
41
        # Removing M2M table for field users on 'OVHSMSGateway'
42
        db.delete_table(db.shorten_name('sms_ovh_users'))
43

  
44

  
45
    models = {
46
        u'base.apiuser': {
47
            'Meta': {'object_name': 'ApiUser'},
48
            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
49
            'fullname': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
50
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
51
            'ipsource': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
52
            'key': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
53
            'keytype': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}),
54
            'username': ('django.db.models.fields.CharField', [], {'max_length': '50'})
55
        },
56
        u'ovh.ovhsmsgateway': {
57
            'Meta': {'object_name': 'OVHSMSGateway', 'db_table': "'sms_ovh'"},
58
            'account': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
59
            'credit_left': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
60
            'credit_threshold_alert': ('django.db.models.fields.PositiveIntegerField', [], {'default': '100'}),
61
            'default_country_code': ('django.db.models.fields.CharField', [], {'default': "u'33'", 'max_length': '3'}),
62
            'description': ('django.db.models.fields.TextField', [], {}),
63
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
64
            'msg_class': ('django.db.models.fields.IntegerField', [], {'default': '1'}),
65
            'password': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
66
            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
67
            'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
68
            'username': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
69
            'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['base.ApiUser']", 'symmetrical': 'False', 'blank': 'True'})
70
        }
71
    }
72

  
73
    complete_apps = ['ovh']
passerelle/apps/ovh/models.py
8 8
from django.db import models
9 9
from django.core.urlresolvers import reverse
10 10

  
11
from passerelle.messages.models import MessageGateway
11
from passerelle.base.models import BaseResource
12
from passerelle.sms import SMSGatewayMixin
12 13

  
13
logger = logging.getLogger('passerelle.messages.ovh')
14
logger = logging.getLogger('passerelle.apps.ovh')
14 15

  
15 16

  
16 17
class OVHError(Exception):
17 18
    pass
18 19

  
19 20

  
20
class OVHSMSGateway(MessageGateway):
21
class OVHSMSGateway(BaseResource, SMSGatewayMixin):
21 22
    URL = 'https://www.ovh.com/cgi-bin/sms/http2sms.cgi'
22 23
    MESSAGES_CLASSES = (
23 24
            (0, _('Message are directly shown to users on phone screen '
......
42 43

  
43 44
    class Meta:
44 45
        verbose_name = 'OVH'
46
        db_table = 'sms_ovh'
45 47

  
46 48
    @classmethod
47 49
    def get_verbose_name(cls):
passerelle/apps/ovh/views.py
2 2
from django.views.generic.edit import CreateView, UpdateView, DeleteView
3 3

  
4 4
from passerelle.base.views import ResourceView
5
from passerelle.messages.views import SendView
5
from passerelle.sms.views import SendView
6 6

  
7 7
from .models import OVHSMSGateway
8 8
from .forms import OVHSMSGatewayForm
passerelle/apps/oxyd/migrations/0001_initial.py
1
# -*- coding: utf-8 -*-
2
from south.utils import datetime_utils as datetime
3
from south.db import db
4
from south.v2 import SchemaMigration
5
from django.db import models
6

  
7

  
8
class Migration(SchemaMigration):
9

  
10
    def forwards(self, orm):
11
        # Adding model 'OxydSMSGateway'
12
        db.create_table('sms_oxyd', (
13
            (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
14
            ('title', self.gf('django.db.models.fields.CharField')(max_length=50)),
15
            ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)),
16
            ('description', self.gf('django.db.models.fields.TextField')()),
17
            ('username', self.gf('django.db.models.fields.CharField')(max_length=64)),
18
            ('password', self.gf('django.db.models.fields.CharField')(max_length=64)),
19
            ('default_country_code', self.gf('django.db.models.fields.CharField')(default=u'33', max_length=3)),
20
        ))
21
        db.send_create_signal(u'oxyd', ['OxydSMSGateway'])
22

  
23
        # Adding M2M table for field users on 'OxydSMSGateway'
24
        m2m_table_name = db.shorten_name('sms_oxyd_users')
25
        db.create_table(m2m_table_name, (
26
            ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
27
            ('oxydsmsgateway', models.ForeignKey(orm[u'oxyd.oxydsmsgateway'], null=False)),
28
            ('apiuser', models.ForeignKey(orm[u'base.apiuser'], null=False))
29
        ))
30
        db.create_unique(m2m_table_name, ['oxydsmsgateway_id', 'apiuser_id'])
31

  
32

  
33
    def backwards(self, orm):
34
        # Deleting model 'OxydSMSGateway'
35
        db.delete_table('sms_oxyd')
36

  
37
        # Removing M2M table for field users on 'OxydSMSGateway'
38
        db.delete_table(db.shorten_name('sms_oxyd_users'))
39

  
40

  
41
    models = {
42
        u'base.apiuser': {
43
            'Meta': {'object_name': 'ApiUser'},
44
            'description': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
45
            'fullname': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
46
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
47
            'ipsource': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39', 'null': 'True', 'blank': 'True'}),
48
            'key': ('django.db.models.fields.CharField', [], {'max_length': '256', 'blank': 'True'}),
49
            'keytype': ('django.db.models.fields.CharField', [], {'max_length': '4', 'blank': 'True'}),
50
            'username': ('django.db.models.fields.CharField', [], {'max_length': '50'})
51
        },
52
        u'oxyd.oxydsmsgateway': {
53
            'Meta': {'object_name': 'OxydSMSGateway', 'db_table': "'sms_oxyd'"},
54
            'default_country_code': ('django.db.models.fields.CharField', [], {'default': "u'33'", 'max_length': '3'}),
55
            'description': ('django.db.models.fields.TextField', [], {}),
56
            u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
57
            'password': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
58
            'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'}),
59
            'title': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
60
            'username': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
61
            'users': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['base.ApiUser']", 'symmetrical': 'False', 'blank': 'True'})
62
        }
63
    }
64

  
65
    complete_apps = ['oxyd']
passerelle/apps/oxyd/models.py
7 7
from django.db import models
8 8
from django.core.urlresolvers import reverse
9 9

  
10
from passerelle.messages.models import MessageGateway
10
from passerelle.base.models import BaseResource
11
from passerelle.sms import SMSGatewayMixin
11 12

  
12
logger = logging.getLogger('passerelle.messages.oxyd')
13
logger = logging.getLogger('passerelle.apps.oxyd')
13 14

  
14 15

  
15 16
class OxydError(Exception):
16 17
    pass
17 18

  
18 19

  
19
class OxydSMSGateway(MessageGateway):
20
class OxydSMSGateway(BaseResource, SMSGatewayMixin):
20 21
    username = models.CharField(max_length=64)
21 22
    password = models.CharField(max_length=64)
22 23
    default_country_code = models.CharField(max_length=3, default=u'33')
......
24 25

  
25 26
    class Meta:
26 27
        verbose_name = 'Oxyd'
28
        db_table = 'sms_oxyd'
27 29

  
28 30
    @classmethod
29 31
    def get_verbose_name(cls):
passerelle/apps/oxyd/views.py
2 2
from django.views.generic.edit import CreateView, UpdateView, DeleteView
3 3

  
4 4
from passerelle.base.views import ResourceView
5
from passerelle.messages.views import SendView
5
from passerelle.sms.views import SendView
6 6

  
7 7
from .models import OxydSMSGateway
8 8
from .forms import OxydSMSGatewayForm
passerelle/default_settings.py
97 97
    'passerelle.base',
98 98
    'passerelle.datasources',
99 99
    'passerelle.repost',
100
    'passerelle.messages',
101
    'passerelle.register',
102 100
    # connectors
103 101
    'clicrdv',
104 102
    'gdc',
passerelle/messages/admin.py
1

  
passerelle/messages/models.py
1
import re
2

  
3
from django.db import models
4
from django.utils.translation import ugettext_lazy as _
5

  
6
from passerelle.base.models import BaseResource
7

  
8

  
9
class MessageGateway(BaseResource):
10
    category = _('SMS Providers')
11

  
12
    @classmethod
13
    def clean_numbers(cls, destinations, default_country_code, prefix='+'):
14
        numbers = []
15
        for dest in destinations:
16
            # most gateways needs the number prefixed by the country code, this is
17
            # really unfortunate.
18
            number = ''.join(re.findall('[0-9]', dest))
19
            if dest.startswith('+'):
20
                pass # it already is fully qualified
21
            elif number.startswith('00'):
22
                # assumes 00 is international access code, remove it
23
                number = number[2:]
24
            elif number.startswith('0'):
25
                # local prefix, remove 0 and add default country code
26
                number = default_country_code + number[1:]
27
            numbers.append(prefix + number)
28
        return numbers
29

  
30
    def send(self, message, sender, destinations):
31
        raise NotImplementedError
32

  
33
    def status(self):
34
        return u''
35

  
36

  
passerelle/messages/templates/messages/view.html
1
{% extends "passerelle/base/view.html" %}
2
{% load i18n %}
3

  
4
{% block link_jsonp %}{% endblock %}
passerelle/messages/tests.py
1
from django.test import TestCase
2
from django.contrib.auth.models import User, Group
3
from django.db import transaction
4

  
5
from .models import MessageGateway
6

  
7
class MessageTestCase(TestCase):
8
    def test_clean_numbers(self):
9
        self.assertEqual(MessageGateway.clean_numbers(['+ 33 12'], '33'),
10
            ['+3312'])
11
        self.assertEqual(MessageGateway.clean_numbers(['0 0 33 12'], '33'),
12
            ['+3312'])
13
        self.assertEqual(MessageGateway.clean_numbers(['0 12'], '33'),
14
            ['+3312'])
15

  
16
    def test_clean_numbers_no_prefix(self):
17
        self.assertEqual(MessageGateway.clean_numbers(['+ 33 12'], '33', prefix=''),
18
            ['3312'])
19
        self.assertEqual(MessageGateway.clean_numbers(['0 0 33 12'], '33', prefix=''),
20
            ['3312'])
21
        self.assertEqual(MessageGateway.clean_numbers(['0 12'], '33', prefix=''),
22
            ['3312'])
23

  
passerelle/messages/views.py
1
import json
2

  
3
from jsonresponse import to_json
4

  
5
from django.views.generic.base import View
6
from django.views.generic.detail import SingleObjectMixin
7
from django.views.decorators.csrf import csrf_exempt
8
from django.utils.decorators import method_decorator
9

  
10
from passerelle import utils
11

  
12
class SendView(View, SingleObjectMixin):
13
    @method_decorator(csrf_exempt)
14
    def dispatch(self, *args, **kwargs):
15
        return super(SendView, self).dispatch(*args, **kwargs)
16

  
17
    @to_json('api')
18
    @utils.protected_api('can_send_messages')
19
    def post(self, request, *args, **kwargs):
20
        data = json.loads(request.body)
21
        assert isinstance(data, dict), 'JSON payload is not a dict'
22
        assert 'message' in data, 'missing "message" in JSON payload'
23
        assert 'from' in data, 'missing "from" in JSON payload'
24
        assert 'to' in data, 'missing "to" in JSON payload'
25
        assert isinstance(data['message'], unicode), 'message is not a string'
26
        assert isinstance(data['from'], unicode), 'from is not a string'
27
        assert all(map(lambda x: isinstance(x, unicode), data['to'])), \
28
                'to is not a list of strings'
29
        return self.get_object().send(data['message'], data['from'], data['to'])
passerelle/register/models.py
1
from django.db import models
2
from passerelle.base.models import BaseResource
3

  
4
class RegisterGateway(BaseResource):
5
    def get_list(self, user):
6
        raise NotImplementedError
7

  
8
    def post(self, user, data):
9
        raise NotImplementedError
10

  
passerelle/register/templates/register/view.html
1
{% extends "passerelle/base/view.html" %}
2
{% load i18n %}
3

  
4
{% block link_jsonp %}{% endblock %}
passerelle/register/urls.py
1
from django.conf.urls import patterns, url, include
2

  
3
from ..base.views import ResourceIndexView, ResourceView
4
from models import RegisterGateway
5

  
6
urlpatterns = patterns('passerelle.register.views',
7
    # human views
8
    url(r'^$', ResourceIndexView.as_view(model=RegisterGateway)),
9
    url(r'^(?P<slug>[\w-]+)/$', ResourceView.as_view(model=RegisterGateway,
10
        template_name='register/view.html')),
11
    # technical views (JSON)
12
    url(r'^(?P<slug>[\w-]+)/json$', 'json_view'),
13
)
passerelle/register/views.py
1
import json
2

  
3
from django.views.decorators.csrf import csrf_exempt
4
from jsonresponse import to_json
5

  
6
from models import RegisterGateway
7

  
8

  
9
def get_list(register, user, **kwargs):
10
    return register.get_list(user, **kwargs)
11

  
12
def post(register, user, data, **kwargs):
13
    assert user is not None, 'missing user argument'
14
    assert isinstance(data, list), 'JSON payload is not a list'
15
    for row in data:
16
        assert isinstance(row, dict), 'all elements must be dict'
17
        assert isinstance(row['name'], unicode)
18
        assert isinstance(row['transports'], list)
19
    return register.post(user, data, **kwargs)
20

  
21

  
22
@csrf_exempt
23
@to_json('api')
24
def json_view(request, slug, **kwargs):
25
    reg = RegisterGateway.objects.get_slug(slug, request)
26
    kwargs = {}
27
    for param in (reg.parameters or ()):
28
        kwargs[param] = request.GET.get(param)
29
    user = request.GET.get('user')
30
    if request.method == 'GET':
31
        return get_list(reg, user, **kwargs)
32
    if request.method == 'POST':
33
        data = json.loads(request.body)
34
        return post(reg, user, data, **kwargs)
35
    raise NotImplementedError
36

  
passerelle/sms/__init__.py
1
from django.utils.translation import ugettext_lazy as _
2

  
3
class SMSGatewayMixin(object):
4
    category = _('SMS Providers')
5

  
6
    @classmethod
7
    def clean_numbers(cls, destinations, default_country_code, prefix='+'):
8
        numbers = []
9
        for dest in destinations:
10
            # most gateways needs the number prefixed by the country code, this is
11
            # really unfortunate.
12
            number = ''.join(re.findall('[0-9]', dest))
13
            if dest.startswith('+'):
14
                pass # it already is fully qualified
15
            elif number.startswith('00'):
16
                # assumes 00 is international access code, remove it
17
                number = number[2:]
18
            elif number.startswith('0'):
19
                # local prefix, remove 0 and add default country code
20
                number = default_country_code + number[1:]
21
            numbers.append(prefix + number)
22
        return numbers
23

  
passerelle/sms/tests.py
1
from django.test import TestCase
2
from django.contrib.auth.models import User, Group
3
from django.db import transaction
4

  
5
from . import SMSGatewayMixin
6

  
7
class MessageTestCase(TestCase):
8
    def test_clean_numbers(self):
9
        self.assertEqual(SMSGatewayMixin.clean_numbers(['+ 33 12'], '33'),
10
            ['+3312'])
11
        self.assertEqual(SMSGatewayMixin.clean_numbers(['0 0 33 12'], '33'),
12
            ['+3312'])
13
        self.assertEqual(SMSGatewayMixin.clean_numbers(['0 12'], '33'),
14
            ['+3312'])
15

  
16
    def test_clean_numbers_no_prefix(self):
17
        self.assertEqual(SMSGatewayMixin.clean_numbers(['+ 33 12'], '33', prefix=''),
18
            ['3312'])
19
        self.assertEqual(SMSGatewayMixin.clean_numbers(['0 0 33 12'], '33', prefix=''),
20
            ['3312'])
21
        self.assertEqual(SMSGatewayMixin.clean_numbers(['0 12'], '33', prefix=''),
22
            ['3312'])
passerelle/sms/views.py
1
import json
2

  
3
from jsonresponse import to_json
4

  
5
from django.utils.decorators import method_decorator
6
from django.views.decorators.csrf import csrf_exempt
7
from django.views.generic.base import View
8
from django.views.generic.detail import SingleObjectMixin
9

  
10
from passerelle import utils
11

  
12
class SendView(View, SingleObjectMixin):
13
    @method_decorator(csrf_exempt)
14
    def dispatch(self, *args, **kwargs):
15
        return super(SendView, self).dispatch(*args, **kwargs)
16

  
17
    @to_json('api')
18
    @utils.protected_api('can_send_messages')
19
    def post(self, request, *args, **kwargs):
20
        data = json.loads(request.body)
21
        assert isinstance(data, dict), 'JSON payload is not a dict'
22
        assert 'message' in data, 'missing "message" in JSON payload'
23
        assert 'from' in data, 'missing "from" in JSON payload'
24
        assert 'to' in data, 'missing "to" in JSON payload'
25
        assert isinstance(data['message'], unicode), 'message is not a string'
26
        assert isinstance(data['from'], unicode), 'from is not a string'
27
        assert all(map(lambda x: isinstance(x, unicode), data['to'])), \
28
                'to is not a list of strings'
29
        return self.get_object().send(data['message'], data['from'], data['to'])
0
-