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 re
import nacl.signing
from binascii import hexlify
from datetime import datetime
import time
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
def time_int(dtime):
return time.mktime(dtime.timetuple())
return int(time.mktime(dtime.timetuple()))
def randstr(l, base=string.digits):
r = ''
@ -39,22 +42,28 @@ def randstr(l, base=string.digits):
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
"""
msg = email.message.Message()
msg['Content-Type'] = 'multipart/mixed'
msg["Subject"] = form["subject"] or "None"
if 'subject' in form:
msg["Subject"] = form["subject"] or "None"
else:
msg["Subject"] = "None"
msg['Date'] = email.utils.format_datetime(datetime.now())
if ref and not msgid_valid(ref):
return None, "invalid reference: {}".format(ref)
if ref:
msg["References"] = ref
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:
msg['Content-Type'] = 'multipart/mixed'
f = files['attachment']
part = email.message.Message()
part['Content-Type'] = f.content_type
@ -62,20 +71,50 @@ def createPost(newsgroup, ref, form, files):
part['Content-Transfer-Encoding'] = 'base64'
part.set_payload(base64.b64encode(f.read()))
msg.attach(part)
text = email.message.Message()
m = '{}'.format(form['message'] or ' ')
text.set_payload(m)
text['Content-Type'] = 'text/plain'
msg.attach(text)
text = email.message.Message()
m = '{}'.format(form['message'] or ' ')
text.set_payload(m)
text['Content-Type'] = 'text/plain'
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['readermode'] = True
response = None
try:
with nntplib.NNTP(**server) as nntp:
nntp.login(**settings.NNTP_LOGIN)
response = nntp.post(msg.as_bytes())
response = nntp.ihave(msg['Message-ID'], data)
except Exception as e:
raise e
return None, 'connection to backend failed, {}'.format(e)
if ref:
return ref, None

View File

@ -29,16 +29,40 @@ class Postable:
handle post request, implement in subclass
"""
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):
ctx = {
'error' : 'invalid captcha'
'error' : 'invalid captcha',
'only_mod': False
}
solution = request.session['captcha']
if solution is not None:
if 'captcha' in request.POST:
if request.POST['captcha'].lower() == solution.lower():
ctx['msgid'], ctx['error'] = self.handle_post(request, **kwargs)
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)
request.session['captcha'] = ''
request.session.save()
code = 201
@ -61,6 +85,7 @@ class BoardView(generic.View, Postable):
name = 'overchan.{}'.format(name)
if not util.newsgroup_valid(name):
return None, "invalid newsgroup: {}".format(name)
self.handle_mod(request)
return util.createPost(name, None, request.POST, request.FILES)

View File

@ -76,7 +76,14 @@
Secret:
</th>
<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>
</tr>
</tbody>

View File

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