make mod backend work
This commit is contained in:
parent
9f7de85a1f
commit
d1a81f319d
@ -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
|
||||
|
@ -30,15 +30,39 @@ class Postable:
|
||||
"""
|
||||
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)
|
||||
|
||||
|
||||
|
@ -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>
|
||||
|
@ -1,3 +1,4 @@
|
||||
captcha
|
||||
django
|
||||
psycopg2
|
||||
pynacl
|
||||
|
Reference in New Issue
Block a user