##// END OF EJS Templates
Generate GET request and response (not full yet). Add global id to the posts...
neko259 -
r827:9fc1212e decentral
parent child Browse files
Show More
@@ -0,0 +1,90 b''
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 # Deleting field 'Post.public_key'
12 db.delete_column('boards_post', 'public_key')
13
14 # Adding field 'Post.global_id'
15 db.add_column('boards_post', 'global_id',
16 self.gf('django.db.models.fields.TextField')(null=True, blank=True),
17 keep_default=False)
18
19
20 def backwards(self, orm):
21 # Adding field 'Post.public_key'
22 db.add_column('boards_post', 'public_key',
23 self.gf('django.db.models.fields.TextField')(null=True, blank=True),
24 keep_default=False)
25
26 # Deleting field 'Post.global_id'
27 db.delete_column('boards_post', 'global_id')
28
29
30 models = {
31 'boards.ban': {
32 'Meta': {'object_name': 'Ban'},
33 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
34 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
35 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
36 'reason': ('django.db.models.fields.CharField', [], {'max_length': '200', 'default': "'Auto'"})
37 },
38 'boards.keypair': {
39 'Meta': {'object_name': 'KeyPair'},
40 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
41 'key_type': ('django.db.models.fields.TextField', [], {}),
42 'primary': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
43 'private_key': ('django.db.models.fields.TextField', [], {}),
44 'public_key': ('django.db.models.fields.TextField', [], {})
45 },
46 'boards.post': {
47 'Meta': {'ordering': "('id',)", 'object_name': 'Post'},
48 '_text_rendered': ('django.db.models.fields.TextField', [], {}),
49 'global_id': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
50 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
51 'images': ('django.db.models.fields.related.ManyToManyField', [], {'db_index': 'True', 'null': 'True', 'to': "orm['boards.PostImage']", 'related_name': "'ip+'", 'blank': 'True', 'symmetrical': 'False'}),
52 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}),
53 'poster_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
54 'poster_user_agent': ('django.db.models.fields.TextField', [], {}),
55 'pub_time': ('django.db.models.fields.DateTimeField', [], {}),
56 'referenced_posts': ('django.db.models.fields.related.ManyToManyField', [], {'db_index': 'True', 'null': 'True', 'to': "orm['boards.Post']", 'related_name': "'rfp+'", 'blank': 'True', 'symmetrical': 'False'}),
57 'refmap': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
58 'text': ('markupfield.fields.MarkupField', [], {'rendered_field': 'True'}),
59 'text_markup_type': ('django.db.models.fields.CharField', [], {'max_length': '30', 'default': "'bbcode'"}),
60 'thread_new': ('django.db.models.fields.related.ForeignKey', [], {'null': 'True', 'default': 'None', 'to': "orm['boards.Thread']"}),
61 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
62 },
63 'boards.postimage': {
64 'Meta': {'ordering': "('id',)", 'object_name': 'PostImage'},
65 'hash': ('django.db.models.fields.CharField', [], {'max_length': '36'}),
66 'height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
67 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
68 'image': ('boards.thumbs.ImageWithThumbsField', [], {'max_length': '100', 'blank': 'True'}),
69 'pre_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
70 'pre_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
71 'width': ('django.db.models.fields.IntegerField', [], {'default': '0'})
72 },
73 'boards.tag': {
74 'Meta': {'ordering': "('name',)", 'object_name': 'Tag'},
75 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
76 'name': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '100'}),
77 'threads': ('django.db.models.fields.related.ManyToManyField', [], {'null': 'True', 'to': "orm['boards.Thread']", 'symmetrical': 'False', 'blank': 'True', 'related_name': "'tag+'"})
78 },
79 'boards.thread': {
80 'Meta': {'object_name': 'Thread'},
81 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
82 'bump_time': ('django.db.models.fields.DateTimeField', [], {}),
83 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
84 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}),
85 'replies': ('django.db.models.fields.related.ManyToManyField', [], {'null': 'True', 'to': "orm['boards.Post']", 'symmetrical': 'False', 'blank': 'True', 'related_name': "'tre+'"}),
86 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['boards.Tag']"})
87 }
88 }
89
90 complete_apps = ['boards'] No newline at end of file
@@ -0,0 +1,147 b''
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 'Signature'
12 db.create_table('boards_signature', (
13 ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
14 ('key_type', self.gf('django.db.models.fields.TextField')()),
15 ('key', self.gf('django.db.models.fields.TextField')()),
16 ('signature', self.gf('django.db.models.fields.TextField')()),
17 ))
18 db.send_create_signal('boards', ['Signature'])
19
20 # Adding model 'GlobalId'
21 db.create_table('boards_globalid', (
22 ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
23 ('key', self.gf('django.db.models.fields.TextField')()),
24 ('key_type', self.gf('django.db.models.fields.TextField')()),
25 ('local_id', self.gf('django.db.models.fields.IntegerField')()),
26 ))
27 db.send_create_signal('boards', ['GlobalId'])
28
29 # Adding M2M table for field signature on 'Post'
30 m2m_table_name = db.shorten_name('boards_post_signature')
31 db.create_table(m2m_table_name, (
32 ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
33 ('post', models.ForeignKey(orm['boards.post'], null=False)),
34 ('signature', models.ForeignKey(orm['boards.signature'], null=False))
35 ))
36 db.create_unique(m2m_table_name, ['post_id', 'signature_id'])
37
38
39 # Renaming column for 'Post.global_id' to match new field type.
40 db.rename_column('boards_post', 'global_id', 'global_id_id')
41 # Changing field 'Post.global_id'
42 db.alter_column('boards_post', 'global_id_id', self.gf('django.db.models.fields.related.OneToOneField')(null=True, to=orm['boards.GlobalId'], unique=True))
43 # Adding index on 'Post', fields ['global_id']
44 db.create_index('boards_post', ['global_id_id'])
45
46 # Adding unique constraint on 'Post', fields ['global_id']
47 db.create_unique('boards_post', ['global_id_id'])
48
49
50 def backwards(self, orm):
51 # Removing unique constraint on 'Post', fields ['global_id']
52 db.delete_unique('boards_post', ['global_id_id'])
53
54 # Removing index on 'Post', fields ['global_id']
55 db.delete_index('boards_post', ['global_id_id'])
56
57 # Deleting model 'Signature'
58 db.delete_table('boards_signature')
59
60 # Deleting model 'GlobalId'
61 db.delete_table('boards_globalid')
62
63 # Removing M2M table for field signature on 'Post'
64 db.delete_table(db.shorten_name('boards_post_signature'))
65
66
67 # Renaming column for 'Post.global_id' to match new field type.
68 db.rename_column('boards_post', 'global_id_id', 'global_id')
69 # Changing field 'Post.global_id'
70 db.alter_column('boards_post', 'global_id', self.gf('django.db.models.fields.TextField')(null=True))
71
72 models = {
73 'boards.ban': {
74 'Meta': {'object_name': 'Ban'},
75 'can_read': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
76 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
77 'ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
78 'reason': ('django.db.models.fields.CharField', [], {'default': "'Auto'", 'max_length': '200'})
79 },
80 'boards.globalid': {
81 'Meta': {'object_name': 'GlobalId'},
82 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
83 'key': ('django.db.models.fields.TextField', [], {}),
84 'key_type': ('django.db.models.fields.TextField', [], {}),
85 'local_id': ('django.db.models.fields.IntegerField', [], {})
86 },
87 'boards.keypair': {
88 'Meta': {'object_name': 'KeyPair'},
89 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
90 'key_type': ('django.db.models.fields.TextField', [], {}),
91 'primary': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
92 'private_key': ('django.db.models.fields.TextField', [], {}),
93 'public_key': ('django.db.models.fields.TextField', [], {})
94 },
95 'boards.post': {
96 'Meta': {'object_name': 'Post', 'ordering': "('id',)"},
97 '_text_rendered': ('django.db.models.fields.TextField', [], {}),
98 'global_id': ('django.db.models.fields.related.OneToOneField', [], {'null': 'True', 'to': "orm['boards.GlobalId']", 'unique': 'True', 'blank': 'True'}),
99 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
100 'images': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['boards.PostImage']", 'blank': 'True', 'db_index': 'True', 'related_name': "'ip+'", 'null': 'True'}),
101 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}),
102 'poster_ip': ('django.db.models.fields.GenericIPAddressField', [], {'max_length': '39'}),
103 'poster_user_agent': ('django.db.models.fields.TextField', [], {}),
104 'pub_time': ('django.db.models.fields.DateTimeField', [], {}),
105 'referenced_posts': ('django.db.models.fields.related.ManyToManyField', [], {'symmetrical': 'False', 'to': "orm['boards.Post']", 'blank': 'True', 'db_index': 'True', 'related_name': "'rfp+'", 'null': 'True'}),
106 'refmap': ('django.db.models.fields.TextField', [], {'blank': 'True', 'null': 'True'}),
107 'signature': ('django.db.models.fields.related.ManyToManyField', [], {'null': 'True', 'to': "orm['boards.Signature']", 'symmetrical': 'False', 'blank': 'True'}),
108 'text': ('markupfield.fields.MarkupField', [], {'rendered_field': 'True'}),
109 'text_markup_type': ('django.db.models.fields.CharField', [], {'default': "'bbcode'", 'max_length': '30'}),
110 'thread_new': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['boards.Thread']", 'default': 'None', 'null': 'True'}),
111 'title': ('django.db.models.fields.CharField', [], {'max_length': '200'})
112 },
113 'boards.postimage': {
114 'Meta': {'object_name': 'PostImage', 'ordering': "('id',)"},
115 'hash': ('django.db.models.fields.CharField', [], {'max_length': '36'}),
116 'height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
117 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
118 'image': ('boards.thumbs.ImageWithThumbsField', [], {'blank': 'True', 'max_length': '100'}),
119 'pre_height': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
120 'pre_width': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
121 'width': ('django.db.models.fields.IntegerField', [], {'default': '0'})
122 },
123 'boards.signature': {
124 'Meta': {'object_name': 'Signature'},
125 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
126 'key': ('django.db.models.fields.TextField', [], {}),
127 'key_type': ('django.db.models.fields.TextField', [], {}),
128 'signature': ('django.db.models.fields.TextField', [], {})
129 },
130 'boards.tag': {
131 'Meta': {'object_name': 'Tag', 'ordering': "('name',)"},
132 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
133 'name': ('django.db.models.fields.CharField', [], {'max_length': '100', 'db_index': 'True'}),
134 'threads': ('django.db.models.fields.related.ManyToManyField', [], {'null': 'True', 'to': "orm['boards.Thread']", 'symmetrical': 'False', 'related_name': "'tag+'", 'blank': 'True'})
135 },
136 'boards.thread': {
137 'Meta': {'object_name': 'Thread'},
138 'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
139 'bump_time': ('django.db.models.fields.DateTimeField', [], {}),
140 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
141 'last_edit_time': ('django.db.models.fields.DateTimeField', [], {}),
142 'replies': ('django.db.models.fields.related.ManyToManyField', [], {'null': 'True', 'to': "orm['boards.Post']", 'symmetrical': 'False', 'related_name': "'tre+'", 'blank': 'True'}),
143 'tags': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['boards.Tag']", 'symmetrical': 'False'})
144 }
145 }
146
147 complete_apps = ['boards'] No newline at end of file
@@ -1,9 +1,9 b''
1 1 __author__ = 'neko259'
2 2
3 3 from boards.models.signature import GlobalId, Signature
4 from boards.models.sync_key import KeyPair
4 5 from boards.models.image import PostImage
5 6 from boards.models.thread import Thread
6 7 from boards.models.post import Post
7 8 from boards.models.tag import Tag
8 9 from boards.models.user import Ban
9 from boards.models.sync_key import KeyPair
@@ -2,15 +2,17 b' from datetime import datetime, timedelta'
2 2 from datetime import time as dtime
3 3 import logging
4 4 import re
5 import xml.etree.ElementTree as et
5 6
6 7 from django.core.cache import cache
7 8 from django.core.urlresolvers import reverse
8 9 from django.db import models, transaction
9 10 from django.template.loader import render_to_string
10 11 from django.utils import timezone
12
11 13 from markupfield.fields import MarkupField
12 14
13 from boards.models import PostImage
15 from boards.models import PostImage, KeyPair, GlobalId
14 16 from boards.models.base import Viewable
15 17 from boards.models.thread import Thread
16 18
@@ -38,6 +40,24 b" UNKNOWN_UA = ''"
38 40
39 41 REGEX_REPLY = re.compile(r'\[post\](\d+)\[/post\]')
40 42
43 TAG_MODEL = 'model'
44 TAG_REQUEST = 'request'
45 TAG_RESPONSE = 'response'
46 TAG_ID = 'id'
47 TAG_STATUS = 'status'
48 TAG_MODELS = 'models'
49 TAG_TITLE = 'title'
50 TAG_TEXT = 'text'
51
52 TYPE_GET = 'get'
53
54 ATTR_VERSION = 'version'
55 ATTR_TYPE = 'type'
56 ATTR_NAME = 'name'
57 ATTR_REF_ID = 'ref-id'
58
59 STATUS_SUCCESS = 'success'
60
41 61 logger = logging.getLogger(__name__)
42 62
43 63
@@ -71,6 +91,8 b' class PostManager(models.Manager):'
71 91 # last!
72 92 last_edit_time=posting_time)
73 93
94 post.set_global_id()
95
74 96 if image:
75 97 post_image = PostImage.objects.create(image=image)
76 98 post.images.add(post_image)
@@ -164,6 +186,52 b' class PostManager(models.Manager):'
164 186 return ppd
165 187
166 188
189 def generate_request_get(self, model_list: list):
190 """
191 Form a get request from a list of ModelId objects.
192 """
193
194 request = et.Element(TAG_REQUEST)
195 request.set(ATTR_TYPE, TYPE_GET)
196 request.set(ATTR_VERSION, '1.0')
197
198 model = et.SubElement(request, TAG_MODEL)
199 model.set(ATTR_VERSION, '1.0')
200 model.set(ATTR_NAME, 'post')
201
202 for post in model_list:
203 tag_id = et.SubElement(model, TAG_ID)
204 post.global_id.to_xml_element(tag_id)
205
206 return et.tostring(request, 'unicode')
207
208 def generate_response_get(self, model_list: list):
209 response = et.Element(TAG_RESPONSE)
210
211 status = et.SubElement(response, TAG_STATUS)
212 status.text = STATUS_SUCCESS
213
214 models = et.SubElement(response, TAG_MODELS)
215
216 ref_id = 1
217 for post in model_list:
218 model = et.SubElement(models, TAG_MODEL)
219 model.set(ATTR_NAME, 'post')
220 model.set(ATTR_REF_ID, str(ref_id))
221 ref_id += 1
222
223 tag_id = et.SubElement(model, TAG_ID)
224 post.global_id.to_xml_element(tag_id)
225
226 title = et.SubElement(model, TAG_TITLE)
227 title.text = post.title
228
229 text = et.SubElement(model, TAG_TEXT)
230 text.text = post.text.rendered
231
232 return et.tostring(response, 'unicode')
233
234
167 235 class Post(models.Model, Viewable):
168 236 """A post is a message."""
169 237
@@ -355,3 +423,25 b' class Post(models.Model, Viewable):'
355 423 self.images.all().delete()
356 424
357 425 super(Post, self).delete(using)
426
427 def set_global_id(self, key_pair=None):
428 """
429 Sets global id based on the given key pair. If no key pair is given,
430 default one is used.
431 """
432
433 if key_pair:
434 key = key_pair
435 else:
436 try:
437 key = KeyPair.objects.get(primary=True)
438 except KeyPair.DoesNotExist:
439 # Do not update the global id because there is no key defined
440 return
441 global_id = GlobalId(key_type=key.key_type,
442 key=key.public_key,
443 local_id = self.id)
444
445 self.global_id = global_id
446
447 self.save(update_fields=['global_id'])
@@ -1,6 +1,12 b''
1 import xml.etree.ElementTree as et
1 2 from django.db import models
2 3
3 4
5 ATTR_KEY = 'key'
6 ATTR_KEY_TYPE = 'type'
7 ATTR_LOCAL_ID = 'local-id'
8
9
4 10 class GlobalId(models.Model):
5 11 class Meta:
6 12 app_label = 'boards'
@@ -20,6 +26,15 b' class GlobalId(models.Model):'
20 26 def __str__(self):
21 27 return '%s / %s / %d' % (self.key_type, self.key, self.local_id)
22 28
29 def to_xml_element(self, element: et.SubElement):
30 """
31 Exports global id to an XML element.
32 """
33
34 element.set(ATTR_KEY, self.key)
35 element.set(ATTR_KEY_TYPE, self.key_type)
36 element.set(ATTR_LOCAL_ID, str(self.local_id))
37
23 38
24 39 class Signature(models.Model):
25 40 class Meta:
@@ -1,6 +1,10 b''
1 import logging
2
1 3 from django.test import TestCase
2 from boards.models import KeyPair, GlobalId
3 from boards.views.sync import generate_request_get
4 from boards.models import KeyPair, GlobalId, Post
5
6
7 logger = logging.getLogger(__name__)
4 8
5 9
6 10 class KeyTest(TestCase):
@@ -28,12 +32,38 b' class KeyTest(TestCase):'
28 32 except Exception:
29 33 pass
30 34
31 def test_request_get(self):
35 def test_model_id_save(self):
32 36 model_id = GlobalId(key_type='test', key='test key', local_id='1')
33 37 model_id.save()
34 38
39 def test_request_get(self):
40 post = self._create_post_with_key()
41
42 request = Post.objects.generate_request_get([post])
43 logger.debug(request)
44
35 45 self.assertTrue('<request type="get" version="1.0"><model '
36 'name="post" version="1.0"><id key="test key" '
37 'local-id="1" type="test" /></model></request>' in
38 generate_request_get([model_id]),
46 'name="post" version="1.0"><id key="pubkey" '
47 'local-id="1" type="test_key_type" /></model></request>' in
48 request,
39 49 'Wrong XML generated for the GET request.')
50
51 def test_response_get(self):
52 post = self._create_post_with_key()
53
54 response = Post.objects.generate_response_get([post])
55 logger.debug(response)
56
57 self.assertTrue('<response><status>success</status><models><model '
58 'name="post" ref-id="1"><id key="pubkey" local-id="1"'
59 ' type="test_key_type" /><title>test_title</title>'
60 '<text>test_text</text>'
61 '</model></models></response>' in response,
62 'Wrong XML generated for the GET response.')
63
64 def _create_post_with_key(self):
65 key = KeyPair(public_key='pubkey', private_key='privkey',
66 key_type='test_key_type', primary=True)
67 key.save()
68
69 return Post.objects.create_post(title='test_title', text='test_text')
@@ -1,44 +1,6 b''
1 import xml.etree.ElementTree as et
2
3 TAG_MODEL = 'model'
4 TAG_REQUEST = 'request'
5 TAG_ID = 'id'
6
7 TYPE_GET = 'get'
8
9 ATTR_VERSION = 'version'
10 ATTR_TYPE = 'type'
11 ATTR_NAME = 'name'
12 ATTR_KEY = 'key'
13 ATTR_KEY_TYPE = 'type'
14 ATTR_LOCAL_ID = 'local-id'
15
16
17 1 def respond_pull(request):
18 2 pass
19 3
20 4
21 5 def respond_get(request):
22 6 pass
23
24
25 def generate_request_get(id_list: list):
26 """
27 Form a get request from a list of ModelId objects.
28 """
29
30 request = et.Element(TAG_REQUEST)
31 request.set(ATTR_TYPE, TYPE_GET)
32 request.set(ATTR_VERSION, '1.0')
33
34 model = et.SubElement(request, TAG_MODEL)
35 model.set(ATTR_VERSION, '1.0')
36 model.set(ATTR_NAME, 'post')
37
38 for model_id in id_list:
39 tag_id = et.SubElement(model, TAG_ID)
40 tag_id.set(ATTR_KEY, model_id.key)
41 tag_id.set(ATTR_KEY_TYPE, model_id.key_type)
42 tag_id.set(ATTR_LOCAL_ID, model_id.local_id)
43
44 return et.tostring(request, 'unicode')
General Comments 0
You need to be logged in to leave comments. Login now