diff --git a/v25/messaging/message.py b/v25/messaging/message.py index 52134ba..97961ae 100644 --- a/v25/messaging/message.py +++ b/v25/messaging/message.py @@ -50,7 +50,7 @@ class Message: return self.sfrom, self.sto def seal(self) -> bytes: - assert isinstance(self.sfrom, PrivateSubject) + assert isinstance(self.sfrom, PrivateSubject), 'Subject misuse' scontent: nacl.signing.SignedMessage = self.sfrom.skey.sign(self.pcontent) self.encrypt(scontent) return self.econtent @@ -83,7 +83,7 @@ class Message: def decrypt(self, s: int) -> bytes: subject = self.pair[s] - assert isinstance(subject, PrivateSubject) + assert isinstance(subject, PrivateSubject), 'Subject misuse' key: bytes = nacl.public.SealedBox(subject.ekey).decrypt( [self.econtent[:KEY_SIZE], self.econtent[KEY_SIZE:2 * KEY_SIZE]][s]) return nacl.secret.SecretBox(key).decrypt(self.econtent[2 * KEY_SIZE:]) @@ -118,9 +118,9 @@ class Message: def alter(self, sfrom: Optional[Subject] = None, sto: Optional[Subject] = None): if sfrom is not None: - assert self.sfrom == sfrom + assert self.sfrom == sfrom, 'alter mismatch' self.sfrom = sfrom if sto is not None: - assert self.sto == sto + assert self.sto == sto, 'alter mismatch' self.sto = sto return self diff --git a/v25/storage/dbstorage.py b/v25/storage/dbstorage.py index 77a2e21..309aa8b 100644 --- a/v25/storage/dbstorage.py +++ b/v25/storage/dbstorage.py @@ -105,10 +105,10 @@ class DBStorage(AbstractStorage): session.close() def edit(self, old: Message, new: Message): - assert old.edited(new) + assert old.edited(new), 'edit misuse' session = self.Session() msg = self.one_alike(session, old) - assert msg.en == old.editnonce + assert msg.en == old.editnonce, 'edit misuse' msgn = Msg.from_message(new) msg.en = msgn.en msg.ec = msgn.ec @@ -169,9 +169,9 @@ class DBStorage(AbstractStorage): def flags(self, m: Message, flags: str): session = self.Session() msg: Msg = self.one_alike(session, m) - assert msg.en == m.editnonce - assert Flags(msg.flags).quable() - assert not Flags(flags).quable() + assert msg.en == m.editnonce, 'flags misuse' + assert Flags(msg.flags).quable(), 'flags misuse' + assert not Flags(flags).quable(), 'flags misuse' msg.flags = flags session.commit() session.close() diff --git a/v25/storage/secstorage.py b/v25/storage/secstorage.py index f3240c7..3449f5a 100644 --- a/v25/storage/secstorage.py +++ b/v25/storage/secstorage.py @@ -10,26 +10,29 @@ class SecureStorage(AbstractStorage): self.storage = storage self.subject = subject + def asrt(self): + return self.subject.dumps() + def check(self, subject: Subject) -> dict: - assert self.subject == subject + assert self.subject == subject, self.asrt() return self.storage.check(subject) def push(self, m: Message) -> None: - assert self.subject == m.sfrom + assert self.subject == m.sfrom, self.asrt() return self.storage.push(m) def edit(self, old: Message, new: Message): - assert self.subject == old.sfrom + assert self.subject == old.sfrom, self.asrt() return self.storage.edit(old, new) def delete(self, m: Message): - assert self.subject in m.pair + assert self.subject in m.pair, self.asrt() return self.storage.delete(m) def pull(self, pair: Tuple[Subject, Subject], params: Optional[dict] = None) -> Iterable[Message]: - assert self.subject in pair + assert self.subject in pair, self.asrt() return self.storage.pull(pair, params) def flags(self, m: Message, flags: str): - assert self.subject in m.pair + assert self.subject in m.pair, self.asrt() return self.storage.flags(m, flags) diff --git a/v25/web/server/api.py b/v25/web/server/api.py index 366f401..ceaa5e6 100644 --- a/v25/web/server/api.py +++ b/v25/web/server/api.py @@ -1,7 +1,8 @@ from json import loads -from typing import Tuple +from sys import stderr +from typing import Callable, Tuple, Any -from flask import Flask, jsonify, request +from flask import Flask, jsonify, request, abort from v25.messaging.encoding import Encoding from v25.messaging.message import Message @@ -11,6 +12,13 @@ from v25.storage.storage import AbstractStorage class API(Flask): + def nomessassertcall(self, f: Callable[[Any, SecureStorage], object]) -> str: + try: + return jsonify(f(*self.ss())) + except AssertionError as e: + print('asrt', e, file=stderr) + abort(403) + def __init__(self, import_name, storage: AbstractStorage): self.storage = storage super().__init__(import_name) @@ -19,11 +27,11 @@ class API(Flask): def allowed(self, s: Subject): return 'allowed' in self.storage.check(s) - def ss(self): + def ss(self) -> Tuple[Any, SecureStorage]: d = request.json source: str = d['source'] subject = Subject.loads(d['subject']) - assert self.allowed(subject) + assert self.allowed(subject), subject.dumps() subject.vkey.verify(source.encode(), Encoding.decode(d['signature'])) return loads(source), SecureStorage(self.storage, subject) @@ -36,31 +44,26 @@ class API(Flask): @app.route('/check', methods=['POST']) def check(): - d, storage = self.ss() - return jsonify(storage.check(Subject.loads(d))) + return self.nomessassertcall(lambda d, storage: storage.check(Subject.loads(d))) @app.route('/push', methods=['POST']) def push(): - d, storage = self.ss() - return jsonify(storage.push(Message.loads(d))) + return self.nomessassertcall(lambda d, storage: storage.push(Message.loads(d))) @app.route('/edit', methods=['POST']) def edit(): - d, storage = self.ss() - return jsonify(storage.edit(Message.loads(d['old']), Message.loads(d['new']))) + return self.nomessassertcall( + lambda d, storage: storage.edit(Message.loads(d['old']), Message.loads(d['new']))) @app.route('/delete', methods=['POST']) def delete(): - d, storage = self.ss() - return jsonify(storage.delete(Message.loads(d))) + return self.nomessassertcall(lambda d, storage: storage.delete(Message.loads(d))) @app.route('/pull', methods=['POST']) def pull(): - d, storage = self.ss() - pair: Tuple[Subject, Subject] = Subject.loads(d['pair'][0]), Subject.loads(d['pair'][1]) - return jsonify(list(map(Message.dumps, storage.pull(pair, d['params'])))) + return self.nomessassertcall(lambda d, storage: list(map(Message.dumps, storage.pull( + (Subject.loads(d['pair'][0]), Subject.loads(d['pair'][1])), d['params'])))) @app.route('/flags', methods=['POST']) def flags(): - d, storage = self.ss() - return jsonify(storage.flags(Message.loads(d['m']), d['flags'])) + return self.nomessassertcall(lambda d, storage: storage.flags(Message.loads(d['m']), d['flags']))