##// END OF EJS Templates
Added some minor info
neko259 -
r1238:a83ac0a9 decentral
parent child Browse files
Show More
@@ -1,160 +1,164 b''
1 import xml.etree.ElementTree as et
1 import xml.etree.ElementTree as et
2 from django.db import transaction
2 from django.db import transaction
3 from boards.models import KeyPair, GlobalId, Signature, Post
3 from boards.models import KeyPair, GlobalId, Signature, Post
4
4
5 ENCODING_UNICODE = 'unicode'
5 ENCODING_UNICODE = 'unicode'
6
6
7 TAG_MODEL = 'model'
7 TAG_MODEL = 'model'
8 TAG_REQUEST = 'request'
8 TAG_REQUEST = 'request'
9 TAG_RESPONSE = 'response'
9 TAG_RESPONSE = 'response'
10 TAG_ID = 'id'
10 TAG_ID = 'id'
11 TAG_STATUS = 'status'
11 TAG_STATUS = 'status'
12 TAG_MODELS = 'models'
12 TAG_MODELS = 'models'
13 TAG_TITLE = 'title'
13 TAG_TITLE = 'title'
14 TAG_TEXT = 'text'
14 TAG_TEXT = 'text'
15 TAG_THREAD = 'thread'
15 TAG_THREAD = 'thread'
16 TAG_PUB_TIME = 'pub-time'
16 TAG_PUB_TIME = 'pub-time'
17 TAG_SIGNATURES = 'signatures'
17 TAG_SIGNATURES = 'signatures'
18 TAG_SIGNATURE = 'signature'
18 TAG_SIGNATURE = 'signature'
19 TAG_CONTENT = 'content'
19 TAG_CONTENT = 'content'
20 TAG_ATTACHMENTS = 'attachments'
20 TAG_ATTACHMENTS = 'attachments'
21 TAG_ATTACHMENT = 'attachment'
21 TAG_ATTACHMENT = 'attachment'
22
22
23 TYPE_GET = 'get'
23 TYPE_GET = 'get'
24
24
25 ATTR_VERSION = 'version'
25 ATTR_VERSION = 'version'
26 ATTR_TYPE = 'type'
26 ATTR_TYPE = 'type'
27 ATTR_NAME = 'name'
27 ATTR_NAME = 'name'
28 ATTR_VALUE = 'value'
28 ATTR_VALUE = 'value'
29 ATTR_MIMETYPE = 'mimetype'
29 ATTR_MIMETYPE = 'mimetype'
30 ATTR_KEY = 'key'
30 ATTR_KEY = 'key'
31
31
32 STATUS_SUCCESS = 'success'
32 STATUS_SUCCESS = 'success'
33
33
34
34
35 class SyncManager:
35 class SyncManager:
36 @staticmethod
36 @staticmethod
37 def generate_response_get(model_list: list):
37 def generate_response_get(model_list: list):
38 response = et.Element(TAG_RESPONSE)
38 response = et.Element(TAG_RESPONSE)
39
39
40 status = et.SubElement(response, TAG_STATUS)
40 status = et.SubElement(response, TAG_STATUS)
41 status.text = STATUS_SUCCESS
41 status.text = STATUS_SUCCESS
42
42
43 models = et.SubElement(response, TAG_MODELS)
43 models = et.SubElement(response, TAG_MODELS)
44
44
45 for post in model_list:
45 for post in model_list:
46 model = et.SubElement(models, TAG_MODEL)
46 model = et.SubElement(models, TAG_MODEL)
47 model.set(ATTR_NAME, 'post')
47 model.set(ATTR_NAME, 'post')
48
48
49 content_tag = et.SubElement(model, TAG_CONTENT)
49 content_tag = et.SubElement(model, TAG_CONTENT)
50
50
51 tag_id = et.SubElement(content_tag, TAG_ID)
51 tag_id = et.SubElement(content_tag, TAG_ID)
52 post.global_id.to_xml_element(tag_id)
52 post.global_id.to_xml_element(tag_id)
53
53
54 title = et.SubElement(content_tag, TAG_TITLE)
54 title = et.SubElement(content_tag, TAG_TITLE)
55 title.text = post.title
55 title.text = post.title
56
56
57 text = et.SubElement(content_tag, TAG_TEXT)
57 text = et.SubElement(content_tag, TAG_TEXT)
58 text.text = post.get_sync_text()
58 text.text = post.get_sync_text()
59
59
60 if not post.is_opening():
60 if not post.is_opening():
61 thread = et.SubElement(content_tag, TAG_THREAD)
61 thread = et.SubElement(content_tag, TAG_THREAD)
62 thread_id = et.SubElement(thread, TAG_ID)
62 thread_id = et.SubElement(thread, TAG_ID)
63 post.get_thread().get_opening_post().global_id.to_xml_element(thread_id)
63 post.get_thread().get_opening_post().global_id.to_xml_element(thread_id)
64 else:
64 else:
65 # TODO Output tags here
65 # TODO Output tags here
66 pass
66 pass
67
67
68 pub_time = et.SubElement(content_tag, TAG_PUB_TIME)
68 pub_time = et.SubElement(content_tag, TAG_PUB_TIME)
69 pub_time.text = str(post.get_pub_time_str())
69 pub_time.text = str(post.get_pub_time_str())
70
70
71 signatures_tag = et.SubElement(model, TAG_SIGNATURES)
71 signatures_tag = et.SubElement(model, TAG_SIGNATURES)
72 post_signatures = post.signature.all()
72 post_signatures = post.signature.all()
73 if post_signatures:
73 if post_signatures:
74 signatures = post.signatures
74 signatures = post_signatures
75 # TODO Adding signature to a post is not yet added. For now this
76 # block is useless
75 else:
77 else:
76 # TODO Maybe the signature can be computed only once after
78 # TODO Maybe the signature can be computed only once after
77 # the post is added? Need to add some on_save signal queue
79 # the post is added? Need to add some on_save signal queue
78 # and add this there.
80 # and add this there.
79 key = KeyPair.objects.get(public_key=post.global_id.key)
81 key = KeyPair.objects.get(public_key=post.global_id.key)
80 signatures = [Signature(
82 signatures = [Signature(
81 key_type=key.key_type,
83 key_type=key.key_type,
82 key=key.public_key,
84 key=key.public_key,
83 signature=key.sign(et.tostring(content_tag, ENCODING_UNICODE)),
85 signature=key.sign(et.tostring(content_tag, ENCODING_UNICODE)),
84 )]
86 )]
85 for signature in signatures:
87 for signature in signatures:
86 signature_tag = et.SubElement(signatures_tag, TAG_SIGNATURE)
88 signature_tag = et.SubElement(signatures_tag, TAG_SIGNATURE)
87 signature_tag.set(ATTR_TYPE, signature.key_type)
89 signature_tag.set(ATTR_TYPE, signature.key_type)
88 signature_tag.set(ATTR_VALUE, signature.signature)
90 signature_tag.set(ATTR_VALUE, signature.signature)
89 signature_tag.set(ATTR_KEY, signature.key)
91 signature_tag.set(ATTR_KEY, signature.key)
90
92
91 return et.tostring(response, ENCODING_UNICODE)
93 return et.tostring(response, ENCODING_UNICODE)
92
94
93 @staticmethod
95 @staticmethod
94 @transaction.atomic
96 @transaction.atomic
95 def parse_response_get(response_xml):
97 def parse_response_get(response_xml):
96 tag_root = et.fromstring(response_xml)
98 tag_root = et.fromstring(response_xml)
97 tag_status = tag_root.find(TAG_STATUS)
99 tag_status = tag_root.find(TAG_STATUS)
98 if STATUS_SUCCESS == tag_status.text:
100 if STATUS_SUCCESS == tag_status.text:
99 tag_models = tag_root.find(TAG_MODELS)
101 tag_models = tag_root.find(TAG_MODELS)
100 for tag_model in tag_models:
102 for tag_model in tag_models:
101 tag_content = tag_model.find(TAG_CONTENT)
103 tag_content = tag_model.find(TAG_CONTENT)
102
104
103 valid = SyncManager.verify_model(tag_content, tag_model)
105 valid = SyncManager._verify_model(tag_content, tag_model)
104
106
105 if not valid:
107 if not valid:
106 raise Exception('Invalid model signature')
108 raise Exception('Invalid model signature')
107
109
108 tag_id = tag_content.find(TAG_ID)
110 tag_id = tag_content.find(TAG_ID)
109 global_id, exists = GlobalId.from_xml_element(tag_id)
111 global_id, exists = GlobalId.from_xml_element(tag_id)
110
112
111 if exists:
113 if exists:
112 print('Post with same ID already exists')
114 print('Post with same ID already exists')
113 else:
115 else:
114 global_id.save()
116 global_id.save()
115
117
116 title = tag_content.find(TAG_TITLE).text
118 title = tag_content.find(TAG_TITLE).text
117 text = tag_content.find(TAG_TEXT).text
119 text = tag_content.find(TAG_TEXT).text
118 pub_time = tag_content.find(TAG_PUB_TIME).text
120 pub_time = tag_content.find(TAG_PUB_TIME).text
119
121
120 thread = tag_content.find(TAG_THREAD)
122 thread = tag_content.find(TAG_THREAD)
121 if thread:
123 if thread:
122 opening_post = Post.objects.get(
124 opening_post = Post.objects.get(
123 id=thread.find(TAG_ID).text)
125 id=thread.find(TAG_ID).text)
124 else:
126 else:
125 opening_post = None
127 opening_post = None
126 # TODO Get tags here
128 # TODO Get tags here
127
129
128 # TODO Check that the replied posts are already present
130 # TODO Check that the replied posts are already present
129 # before adding new ones
131 # before adding new ones
130
132
133 # TODO Get images
134
131 post = Post.objects.import_post(
135 post = Post.objects.import_post(
132 title=title, text=text, pub_time=pub_time,
136 title=title, text=text, pub_time=pub_time,
133 opening_post=opening_post)
137 opening_post=opening_post)
134 post.global_id = global_id
138 post.global_id = global_id
135 else:
139 else:
136 # TODO Throw an exception?
140 # TODO Throw an exception?
137 pass
141 pass
138
142
139 @staticmethod
143 @staticmethod
140 def verify_model(tag_content, tag_model):
144 def _verify_model(tag_content, tag_model):
141 """
145 """
142 Verifies all signatures for a single model.
146 Verifies all signatures for a single model.
143 """
147 """
144
148
145 valid = True
149 valid = True
146
150
147 tag_signatures = tag_model.find(TAG_SIGNATURES)
151 tag_signatures = tag_model.find(TAG_SIGNATURES)
148 for tag_signature in tag_signatures:
152 for tag_signature in tag_signatures:
149 signature_type = tag_signature.get(ATTR_TYPE)
153 signature_type = tag_signature.get(ATTR_TYPE)
150 signature_value = tag_signature.get(ATTR_VALUE)
154 signature_value = tag_signature.get(ATTR_VALUE)
151 signature_key = tag_signature.get(ATTR_KEY)
155 signature_key = tag_signature.get(ATTR_KEY)
152
156
153 if not KeyPair.objects.verify(
157 if not KeyPair.objects.verify(
154 signature_key,
158 signature_key,
155 et.tostring(tag_content, ENCODING_UNICODE),
159 et.tostring(tag_content, ENCODING_UNICODE),
156 signature_value, signature_type):
160 signature_value, signature_type):
157 valid = False
161 valid = False
158 break
162 break
159
163
160 return valid
164 return valid
General Comments 0
You need to be logged in to leave comments. Login now