async def test_authenticate(client): data = { 'platform': PLATFORM, 'timestamp': TIMESTAMP, 'signature': VALID_SIGNATURE } r = await client.post('/authenticate', data=encoding.encode(data)) assert r.status == 201 r = encoding.decode(await r.read()) assert isinstance(r, dict) assert list(r.keys()) == ['key'] assert r['key'].startswith('foobar.com:2461536000:') assert len(r['key']) == 86
async def _authenticate_direct(self, domain, data): url = 'https://{}/authenticate'.format(domain) # TODO more error checks try: async with self.session.post(url, data=encoding.encode(data), headers=JSON_HEADER) as r: body = await r.read() except aiohttp.ClientOSError as e: # generally "could not resolve host" or "connection refused", # the exception is fairly useless at giving specifics raise ConnectionError('cannot connect to "{}"'.format(url)) from e else: if r.status != 201: raise FailedOutboundAuthentication('{} response {} != 201, response: {}'.format(url, r.status, body)) data = encoding.decode(body) return data['key']
async def act(request): auth, platform = await _check_token(request) body_data = await request.read() try: timezone = pytz.timezone(request.headers.get('timezone', 'utc')) except pytz.UnknownTimeZoneError as e: raise HTTPBadRequestStr(e.args[0]) from e try: obj = encoding.decode(body_data, tz=timezone) except ValueError as e: raise HTTPBadRequestStr('Error Decoding msgpack: {}'.format(e)) from e if not isinstance(obj, dict): raise HTTPBadRequestStr('request data is not a dictionary') v = Validator(ACT_SCHEMA) if not v(obj): raise HTTPBadRequestStr(json.dumps(v.errors, sort_keys=True)) address = obj.pop('address') address_domain = address[address.index('@') + 1:] try: await auth.check_domain_platform(address_domain, platform) except DomainPlatformMismatch as e: raise HTTPForbiddenStr(e.args[0]) from e conversation = request.match_info['conv'] component = request.match_info['component'] verb = request.match_info['verb'] item = request.match_info['item'] or None timestamp = obj.pop('timestamp') kwargs = obj.pop('kwargs', {}) action = Action(address, conversation, verb, component, item=item, timestamp=timestamp, event_id=obj['event_id'], parent_event_id=obj.get('parent_event_id')) controller = request.app['controller'] try: response = await controller.act(action, **kwargs) except Em2Exception as e: raise HTTPBadRequestStr('{}: {}'.format(e.__class__.__name__, e)) body = encoding.encode(response) if response else b'\n' return web.Response(body=body, status=201, content_type=encoding.MSGPACK_CONTENT_TYPE)
async def authenticate(request): logger.info('authentication request from %s', get_ip(request)) body_data = await request.read() try: obj = encoding.decode(body_data) except ValueError as e: logger.info('bad request: invalid msgpack data') raise HTTPBadRequestStr('error decoding data: {}'.format(e)) from e v = Validator(AUTHENTICATION_SCHEMA) if not v(obj): raise HTTPBadRequestStr(json.dumps(v.errors, sort_keys=True)) auth = request.app['authenticator'] try: key = await auth.authenticate_platform(obj['platform'], obj['timestamp'], obj['signature']) except FailedInboundAuthentication as e: raise HTTPBadRequestStr(e.args[0]) from e return web.Response(body=encoding.encode({'key': key}), status=201, content_type=encoding.MSGPACK_CONTENT_TYPE)
async def request(self, method, uri, *args, **kwargs): url = BASE_URL + uri print(f'{method}: {url}') func = { 'get': self.session.get, 'post': self.session.post, }[method.lower()] async with func(url, *args, **kwargs) as r: print(f'status: {r.status}') print('headers:') for k, v in r.headers.items(): print(f' {k:15}: {v}') ct = r.headers.get('Content-Type') if 'text/' in ct: content = await r.text() print(f'response: {content}') elif 'application/msgpack' in ct: content = await r.read() content = encoding.decode(content) print(f'response: {content}') else: content = await r.read() print(f'raw response: {content}') return content