Archived
1
0

make mod backend work

This commit is contained in:
Jeff Becker 2016-11-09 14:32:26 -05:00
parent 9f7de85a1f
commit d1a81f319d
No known key found for this signature in database
GPG Key ID: AB950234D6EA286B
4 changed files with 86 additions and 14 deletions

View File

@ -4,6 +4,9 @@ import base64
import hashlib import hashlib
import re import re
import nacl.signing
from binascii import hexlify
from datetime import datetime from datetime import datetime
import time import time
import string import string
@ -29,7 +32,7 @@ def msgid_valid(msgid):
return re.match("<[a-zA-Z0-9\$\._\-\|]+@[a-zA-Z0-9\$\._\-\|]+>$", msgid) is not None return re.match("<[a-zA-Z0-9\$\._\-\|]+@[a-zA-Z0-9\$\._\-\|]+>$", msgid) is not None
def time_int(dtime): def time_int(dtime):
return time.mktime(dtime.timetuple()) return int(time.mktime(dtime.timetuple()))
def randstr(l, base=string.digits): def randstr(l, base=string.digits):
r = '' r = ''
@ -39,22 +42,28 @@ def randstr(l, base=string.digits):
return r return r
def createPost(newsgroup, ref, form, files): def createPost(newsgroup, ref, form, files, secretKey=None):
""" """
create a post and post it to a news server create a post and post it to a news server
""" """
msg = email.message.Message() msg = email.message.Message()
msg['Content-Type'] = 'multipart/mixed' if 'subject' in form:
msg["Subject"] = form["subject"] or "None" msg["Subject"] = form["subject"] or "None"
else:
msg["Subject"] = "None"
msg['Date'] = email.utils.format_datetime(datetime.now()) msg['Date'] = email.utils.format_datetime(datetime.now())
if ref and not msgid_valid(ref): if ref and not msgid_valid(ref):
return None, "invalid reference: {}".format(ref) return None, "invalid reference: {}".format(ref)
if ref: if ref:
msg["References"] = ref msg["References"] = ref
msg["Newsgroups"] = newsgroup msg["Newsgroups"] = newsgroup
msg["From"] = '{} <anon@django.nntpchan.tld>'.format(form['name'] or 'Anonymous') name = "Anonymous"
if 'name' in form:
name = form['name'] or name
msg["From"] = '{} <anon@django.nntpchan.tld>'.format(name)
if 'attachment' in files: if 'attachment' in files:
msg['Content-Type'] = 'multipart/mixed'
f = files['attachment'] f = files['attachment']
part = email.message.Message() part = email.message.Message()
part['Content-Type'] = f.content_type part['Content-Type'] = f.content_type
@ -67,15 +76,45 @@ def createPost(newsgroup, ref, form, files):
text.set_payload(m) text.set_payload(m)
text['Content-Type'] = 'text/plain' text['Content-Type'] = 'text/plain'
msg.attach(text) msg.attach(text)
else:
msg['Content-Type'] = 'text/plain; charset=UTF-8'
m = '{}'.format(form['message'] or ' ')
msg.set_payload(m)
msg['Message-Id'] = '<{}${}@signed.{}>'.format(randstr(5), int(time_int(datetime.now())), settings.FRONTEND_NAME)
if secretKey:
msg['Path'] = settings.FRONTEND_NAME
# sign
keypair = nacl.signing.SigningKey(secretKey, nacl.signing.encoding.HexEncoder)
pubkey = hexlify(keypair.verify_key.encode()).decode('ascii')
outerMsg = email.message.Message()
h = hashlib.sha512()
body = msg.as_bytes()
h.update(body)
sig = hexlify(keypair.sign(h.digest()).signature).decode('ascii')
data = '''Content-Type: message/rfc822; charset=UTF-8
Message-ID: {}
Content-Transfer-Encoding: 8bit
Newsgroups: {}
X-Pubkey-Ed25519: {}
X-Signature-Ed25519-Sha512: {}
From: {}
Date: {}
Subject: {}
{}'''.format(msg["Message-ID"], newsgroup, pubkey, sig, msg["From"], msg["Date"], msg['Subject'], msg.as_string())
data = data.encode('utf-8')
else:
data = msg.as_bytes()
server = settings.NNTP_SERVER server = settings.NNTP_SERVER
server['readermode'] = True server['readermode'] = True
response = None response = None
try: try:
with nntplib.NNTP(**server) as nntp: with nntplib.NNTP(**server) as nntp:
nntp.login(**settings.NNTP_LOGIN) nntp.login(**settings.NNTP_LOGIN)
response = nntp.post(msg.as_bytes()) response = nntp.ihave(msg['Message-ID'], data)
except Exception as e: except Exception as e:
raise e
return None, 'connection to backend failed, {}'.format(e) return None, 'connection to backend failed, {}'.format(e)
if ref: if ref:
return ref, None return ref, None

View File

@ -30,14 +30,38 @@ class Postable:
""" """
return None, 'handle_post() not implemented' return None, 'handle_post() not implemented'
def handle_mod(self, request):
"""
handle moderation parameters
"""
if 'modactions' in request.POST:
actions = request.POST['modactions'] + '\n'
body = ''
for line in actions.split('\n'):
line = line.strip()
if len(line) > 0:
body += '{}\n'.format(line)
key = None
if 'secret' in request.POST:
key = request.POST['secret']
_, err = util.createPost('ctl', '', {'message': body}, {}, key)
return True, err
return False, None
def post(self, request, **kwargs): def post(self, request, **kwargs):
ctx = { ctx = {
'error' : 'invalid captcha' 'error' : 'invalid captcha',
'only_mod': False
} }
solution = request.session['captcha'] solution = request.session['captcha']
if solution is not None: if solution is not None:
if 'captcha' in request.POST: if 'captcha' in request.POST:
if request.POST['captcha'].lower() == solution.lower(): if request.POST['captcha'].lower() == solution.lower():
processed, err = self.handle_mod(request)
if processed:
ctx['error'] = err or 'report made'
ctx['msgid'] = ''
else:
ctx['msgid'], ctx['error'] = self.handle_post(request, **kwargs) ctx['msgid'], ctx['error'] = self.handle_post(request, **kwargs)
request.session['captcha'] = '' request.session['captcha'] = ''
request.session.save() request.session.save()
@ -61,6 +85,7 @@ class BoardView(generic.View, Postable):
name = 'overchan.{}'.format(name) name = 'overchan.{}'.format(name)
if not util.newsgroup_valid(name): if not util.newsgroup_valid(name):
return None, "invalid newsgroup: {}".format(name) return None, "invalid newsgroup: {}".format(name)
self.handle_mod(request)
return util.createPost(name, None, request.POST, request.FILES) return util.createPost(name, None, request.POST, request.FILES)

View File

@ -76,7 +76,14 @@
Secret: Secret:
</th> </th>
<td> <td>
<input type="password" name="modkey"></input> <input type="password" name="secret"></input>
</td>
</tr>
<tr>
<th>
<button onclick="document.getElementById('postform').submit()">report</button>
</th>
<td>
</td> </td>
</tr> </tr>
</tbody> </tbody>

View File

@ -1,3 +1,4 @@
captcha captcha
django django
psycopg2 psycopg2
pynacl