| @@ -9,10 +9,12 @@ | |||||
| # Going Async from Flask to Twisted Klein: https://crossbario.com/blog/Going-Asynchronous-from-Flask-to-Twisted-Klein/ | # Going Async from Flask to Twisted Klein: https://crossbario.com/blog/Going-Asynchronous-from-Flask-to-Twisted-Klein/ | ||||
| # Klein POST docs: https://klein.readthedocs.io/en/latest/examples/handlingpost.html | # Klein POST docs: https://klein.readthedocs.io/en/latest/examples/handlingpost.html | ||||
| from contextlib import nested | |||||
| from klein import Klein | from klein import Klein | ||||
| from kleintest import * | |||||
| from twisted.trial import unittest | from twisted.trial import unittest | ||||
| from twisted.web.iweb import IRequest | from twisted.web.iweb import IRequest | ||||
| from kleintest import * | |||||
| from cli import Persona, MDBase | |||||
| import hashlib | import hashlib | ||||
| import mock | import mock | ||||
| @@ -20,9 +22,18 @@ import os.path | |||||
| import shutil | import shutil | ||||
| import tempfile | import tempfile | ||||
| defaultfile = 'mediaserver.store.pasn1' | |||||
| class MEDAServer: | class MEDAServer: | ||||
| def __init__(self, fname): | |||||
| self._trustedkeys = {} | |||||
| app = Klein() | app = Klein() | ||||
| def addpubkey(self, pubkey): | |||||
| persona = Persona.from_pubkey(pubkey) | |||||
| self._trustedkeys[persona.uuid] = persona | |||||
| def store(self): | def store(self): | ||||
| pass | pass | ||||
| @@ -30,6 +41,24 @@ class MEDAServer: | |||||
| def home(request): | def home(request): | ||||
| return 'hello' | return 'hello' | ||||
| @app.route('/store') | |||||
| def storeobj(self, request): | |||||
| try: | |||||
| obj = MDBase.decode(request.content.read()) | |||||
| #if obj.type == 'identity': | |||||
| keyuuid = obj.uuid | |||||
| #else: | |||||
| # keyuuid = obj.created_by_ref | |||||
| persona = self._trustedkeys[keyuuid] | |||||
| persona.verify(obj) | |||||
| request.setResponseCode(201) | |||||
| except Exception: | |||||
| request.setResponseCode(401) | |||||
| # twistd support | # twistd support | ||||
| #medaserver = MEDAServer() | #medaserver = MEDAServer() | ||||
| #resource = medaserver.app.resource | #resource = medaserver.app.resource | ||||
| @@ -38,12 +67,19 @@ def main(): | |||||
| from optparse import OptionParser | from optparse import OptionParser | ||||
| parser = OptionParser() | parser = OptionParser() | ||||
| parser.add_option('-a', action='append', dest='addpubkey', | |||||
| default=[], help='Add specified public key as a trusted key.') | |||||
| options, args = parser.parse_args() | options, args = parser.parse_args() | ||||
| medaserver = MEDAServer() | |||||
| medaserver = MEDAServer(defaultfile) | |||||
| try: | try: | ||||
| if options.addpubkey: | |||||
| for i in options.addpubkey: | |||||
| medaserver.addpubkey(i) | |||||
| return | |||||
| medaserver.app.run() | medaserver.app.run() | ||||
| finally: | finally: | ||||
| medaserver.store() | medaserver.store() | ||||
| @@ -55,7 +91,8 @@ class _TestCases(unittest.TestCase): | |||||
| def setUp(self): | def setUp(self): | ||||
| d = os.path.realpath(tempfile.mkdtemp()) | d = os.path.realpath(tempfile.mkdtemp()) | ||||
| self.basetempdir = d | self.basetempdir = d | ||||
| self.medaserver = MEDAServer() | |||||
| self.medaserverfile = os.path.join(self.basetempdir, 'serverstore.pasn1') | |||||
| self.medaserver = MEDAServer(self.medaserverfile) | |||||
| self.requests = FakeRequests(self.medaserver.app) | self.requests = FakeRequests(self.medaserver.app) | ||||
| def tearDown(self): | def tearDown(self): | ||||
| @@ -67,12 +104,56 @@ class _TestCases(unittest.TestCase): | |||||
| r = self.requests.get('/chash/%s' % h) | r = self.requests.get('/chash/%s' % h) | ||||
| self.assertEqual(r.status_code, 404) | self.assertEqual(r.status_code, 404) | ||||
| def test_addpubkey(self): | |||||
| def test_pubkeystorage(self): | |||||
| import cli | |||||
| # that an identity | |||||
| persona = cli.Persona() | |||||
| persona.generate_key() | |||||
| # that by default, put's | |||||
| r = self.requests.put('/store', data=persona.get_identity().encode()) | |||||
| # are denied | |||||
| self.assertEqual(r.status_code, 401) | |||||
| # can have it's public key added to the server | |||||
| self.medaserver.addpubkey(persona.get_pubkey()) | |||||
| # that it can store the pubkey's identity | |||||
| r = self.requests.put('/store', data=persona.get_identity().encode()) | |||||
| self.assertEqual(r.status_code, 201) | |||||
| # that when stored | |||||
| self.medaserver.store() | |||||
| tmpmedaserver = MEDAServer(self.medaserverfile) | |||||
| @mock.patch('klein.Klein.run') | |||||
| def test_addpubkey(self, apprun): | |||||
| import cli | import cli | ||||
| persona = cli.Persona() | persona = cli.Persona() | ||||
| persona.generate_key() | persona.generate_key() | ||||
| with nested(mock.patch('server.MEDAServer.addpubkey'), | |||||
| mock.patch('sys.argv', [ 'progname', '-a', | |||||
| persona.get_pubkey() ])) as (addpub, argv): | |||||
| main() | |||||
| addpub.assert_called_with(persona.get_pubkey()) | |||||
| apprun.assert_not_called() | |||||
| # Note: because of this mock, it hides the actual app.run call w/ | |||||
| # a mock | |||||
| @mock.patch('server.MEDAServer') | |||||
| def test_medaserverinstanciated(self, medaserver): | |||||
| # that when main is run | |||||
| main() | |||||
| # that it gets called with the default storage file | |||||
| medaserver.assert_called_with('mediaserver.store.pasn1') | |||||
| @mock.patch('server.MEDAServer.store') | @mock.patch('server.MEDAServer.store') | ||||
| @mock.patch('klein.Klein.run') | @mock.patch('klein.Klein.run') | ||||
| def test_appruns(self, kleinrun, storefun): | def test_appruns(self, kleinrun, storefun): | ||||