コード例 #1
0
ファイル: test_server.py プロジェクト: em-2/em2
async def test_missing_field(client):
    data = {
        'address': '*****@*****.**',
        'timestamp': datetime.now(),
    }
    r = await client.post('/123/messages/add/', data=encoding.encode(data), headers=AUTH_HEADER)
    assert r.status == 400
    assert await r.text() == '{"event_id": ["required field"]}\n'
コード例 #2
0
ファイル: test_server.py プロジェクト: em-2/em2
async def test_authenticate_wrong_fields(client):
    data = {
        'platform': PLATFORM,
        'timestamp': TIMESTAMP,
    }
    r = await client.post('/authenticate', data=encoding.encode(data))
    assert r.status == 400
    assert await r.text() == '{"signature": ["required field"]}\n'
コード例 #3
0
ファイル: test_server.py プロジェクト: em-2/em2
async def test_authenticate_failed(client):
    data = {
        'platform': 'wham.com',
        'timestamp': TIMESTAMP,
        'signature': VALID_SIGNATURE
    }
    r = await client.post('/authenticate', data=encoding.encode(data))
    assert r.status == 400
    assert await r.text() == 'invalid signature\n'
コード例 #4
0
ファイル: push.py プロジェクト: em-2/em2
 async def _push_data(self, domains, action_attrs, event_id, **kwargs):
     action_attrs['item'] = action_attrs['item'] or ''
     path = '{conv}/{component}/{verb}/{item}'.format(**action_attrs)
     post_data = {
         'address': action_attrs['address'],
         'timestamp': action_attrs['timestamp'],
         'event_id': event_id,
         'kwargs': kwargs,
     }
     post_data = encoding.encode(post_data)
     cos = [self._post(domain, path, post_data) for domain in domains]
     # TODO better error checks
     await asyncio.gather(*cos, loop=self.loop)
コード例 #5
0
ファイル: test_server.py プロジェクト: em-2/em2
async def test_domain_miss_match(client):
    data = {
        'address': '*****@*****.**',
        'timestamp': datetime.now(),
        'event_id': '123',
        'kwargs': {
            'parent_id': '123',
            'body': 'reply',
        }
    }
    r = await client.post('/123/messages/add/', data=encoding.encode(data), headers=AUTH_HEADER)
    assert await r.text() == '"example.com" does not use "already-authenticated.com"\n'
    assert r.status == 403
コード例 #6
0
ファイル: test_server.py プロジェクト: em-2/em2
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
コード例 #7
0
ファイル: push.py プロジェクト: em-2/em2
 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']
コード例 #8
0
ファイル: client.py プロジェクト: em-2/em2-net
async def auth(s):
    timestamp = now_unix_secs()
    msg = '{}:{}'.format(LOCAL_DOMAIN, timestamp)
    h = SHA256.new(msg.encode())
    private_domain_key = Path('private8000.pem').read_text()
    key = RSA.importKey(private_domain_key)
    signer = PKCS1_v1_5.new(key)
    signature = base64.urlsafe_b64encode(signer.sign(h)).decode()
    auth_data = {
        'platform': LOCAL_DOMAIN,
        'timestamp': timestamp,
        'signature': signature,
    }
    return await s.post('authenticate',
                        data=encoding.encode(auth_data),
                        headers=CT_HEADER)
コード例 #9
0
ファイル: test_server.py プロジェクト: em-2/em2
async def test_missing_conversation(client):
    ts = datetime.now()
    action2 = Action('*****@*****.**', '123', Verbs.ADD, Components.MESSAGES, timestamp=ts)
    data = {
        'address': '*****@*****.**',
        'timestamp': ts,
        'event_id': action2.calc_event_id(),
        'kwargs': {
            'parent_id': '123',
            'body': 'reply',
        }
    }
    r = await client.post('/123/messages/add/', data=encoding.encode(data), headers=AUTH_HEADER)
    assert r.status == 400
    content = await r.read()
    assert content == b'ConversationNotFound: conversation 123 not found\n'
コード例 #10
0
ファイル: views.py プロジェクト: em-2/em2
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)
コード例 #11
0
ファイル: test_server.py プロジェクト: em-2/em2
async def test_add_message(client):
    action = Action('*****@*****.**', None, Verbs.ADD)
    conv_id = await client.em2_ctrl.act(action, subject='foo bar', body='hi, how are you?')
    conv_ds = client.em2_ctrl.ds.new_conv_ds(conv_id, None)
    msg1_id = list(conv_ds.conv_obj['messages'])[0]
    ts = action.timestamp + timedelta(seconds=1)
    action2 = Action('*****@*****.**', conv_id, Verbs.ADD, Components.MESSAGES, timestamp=ts)
    data = {
        'address': '*****@*****.**',
        'timestamp': ts,
        'event_id': action2.calc_event_id(),
        'kwargs': {
            'parent_id': msg1_id,
            'body': 'reply',
        }
    }
    r = await client.post('/{}/messages/add/'.format(conv_id), data=encoding.encode(data), headers=AUTH_HEADER)
    assert r.status == 201
    assert await r.text() == '\n'
コード例 #12
0
ファイル: views.py プロジェクト: em-2/em2
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)
コード例 #13
0
ファイル: client.py プロジェクト: em-2/em2-net
async def publish(s):
    response = await auth(s)
    verb = Verbs.ADD
    component = Components.CONVERSATIONS
    address = '*****@*****.**'
    ts = datetime.utcnow().replace(tzinfo=timezone.utc)
    conv = hash_id(address, to_unix_ms(ts), 'foo bar', sha256=True)
    data = {
        'address': address,
        'timestamp': ts,
        'event_id': hash_id(to_unix_ms(ts), address, conv, verb, component,
                            None),
        'kwargs': {
            'data': PUBLISH_KWARGS
        },
    }
    url = f'{conv}/{component}/{verb}/'

    headers = dict(Authorization=response['key'], **CT_HEADER)
    await s.post(url, data=encoding.encode(data), headers=headers)
コード例 #14
0
ファイル: test_server.py プロジェクト: em-2/em2
async def test_valid_data_list(client):
    r = await client.post('/123/messages/add/', data=encoding.encode([1, 2, 3]), headers=AUTH_HEADER)
    assert r.status == 400
    assert await r.text() == 'request data is not a dictionary\n'