Example #1
0
def test_token_generation(default_user, default_repo, default_repo_access):
    tenant = auth.Tenant.from_user(default_user)
    token = auth.generate_token(tenant)
    assert isinstance(token, bytes)
    result = auth.parse_token(token)
    assert result["access"] == {str(default_repo.id): Permission.admin}
    assert result["uid"] == str(default_user.id)
Example #2
0
def test_token_generation(default_user, default_repo, default_repo_access):
    tenant = auth.Tenant.from_user(default_user)
    token = auth.generate_token(tenant)
    assert isinstance(token, bytes)
    result = auth.parse_token(token)
    assert result['repo_ids'] == [str(default_repo.id)]
    assert result['uid'] == str(default_user.id)
Example #3
0
async def stream(request):
    client_guid = str(uuid4())

    sentry.tags_context({"client_guid": client_guid})

    if request.headers.get("accept") != "text/event-stream":
        return Response(status=406)

    if request.method != "GET":
        return Response(status=405)

    token = request.query.get("token")
    if not token:
        return Response(status=401)

    build_ids = frozenset(request.query.get("build") or [])
    repo_ids = frozenset(request.query.get("repo") or [])

    token = auth.parse_token(token)
    if not token:
        return Response(status=401)

    if "uid" in token:
        sentry.user_context({"id": token["uid"]})

    current_app.logger.debug("pubsub.client.connected guid=%s tenant=%s",
                             client_guid, token)

    loop = request.app.loop

    parts = urlparse(current_app.config["REDIS_URL"])

    conn = await aioredis.create_redis(
        address=(parts.hostname or "localhost", parts.port or "6379"),
        db=parts.path.split("1", 1)[:-1] or 0,
        password=parts.password,
        loop=loop,
    )
    try:
        queue = asyncio.Queue(loop=loop)

        res = await conn.subscribe("builds")
        asyncio.ensure_future(worker(res[0], queue, token, repo_ids,
                                     build_ids))

        resp = StreamResponse(status=200, reason="OK")
        resp.headers["Content-Type"] = "text/event-stream"
        resp.headers["Cache-Control"] = "no-cache"
        resp.headers["Connection"] = "keep-alive"
        if "Origin" in request.headers and is_valid_origin(request):
            resp.headers["Access-Control-Allow-Origin"] = request.headers.get(
                "Origin")
            resp.headers["Access-Control-Expose-Headers"] = "*"
        resp.enable_chunked_encoding()

        await resp.prepare(request)

        # loop.create_task(ping(loop, resp, client_guid))

        # resp.write(b'retry: 100\r\n\r\n')

        while True:
            event = await queue.get()
            if event is None:
                break

            buffer = io.BytesIO()
            if event.id:
                buffer.write(b"id: %s\r\n" % (event.id.encode("utf-8"), ))
            if event.event:
                buffer.write(b"event: %s\r\n" % (event.event.encode("utf-8")))
            if event.data:
                buffer.write(b"data: %s\r\n" %
                             (json.dumps(event.data).encode("utf-8")))
            buffer.write(b"\r\n")
            resp.write(buffer.getvalue())
            queue.task_done()
            current_app.logger.debug("pubsub.event.sent qsize=%s",
                                     queue.qsize())
            # Yield to the scheduler so other processes do stuff.
            await resp.drain()

        await resp.write_eof()
        return resp

    finally:
        conn.close()
        await conn.wait_closed()
        current_app.logger.debug("client.disconnected guid=%s",
                                 client_guid,
                                 exc_info=True)
Example #4
0
async def stream(request):
    client_guid = str(uuid4())

    sentry.tags_context({'client_guid': client_guid})

    if request.headers.get('accept') != 'text/event-stream':
        return Response(status=406)

    if request.method != 'GET':
        return Response(status=405)

    token = request.query.get('token')
    if not token:
        return Response(status=401)

    build_ids = frozenset(request.query.get('build') or [])
    repo_ids = frozenset(request.query.get('repo') or [])

    token = auth.parse_token(token)
    if not token:
        return Response(status=401)

    if 'uid' in token:
        sentry.user_context({'id': token['uid']})

    current_app.logger.debug('pubsub.client.connected guid=%s tenant=%s',
                             client_guid, token)

    loop = request.app.loop

    parts = urlparse(current_app.config['REDIS_URL'])

    conn = await aioredis.create_redis(
        address=(parts.hostname or 'localhost', parts.port or '6379'),
        db=parts.path.split('1', 1)[:-1] or 0,
        password=parts.password,
        loop=loop,
    )
    try:
        queue = asyncio.Queue(loop=loop)

        res = await conn.subscribe('builds')
        asyncio.ensure_future(worker(res[0], queue, token, repo_ids,
                                     build_ids))

        resp = StreamResponse(status=200, reason='OK')
        resp.headers['Content-Type'] = 'text/event-stream'
        resp.headers['Cache-Control'] = 'no-cache'
        resp.headers['Connection'] = 'keep-alive'
        if 'Origin' in request.headers and is_valid_origin(request):
            resp.headers['Access-Control-Allow-Origin'] = request.headers.get(
                'Origin')
            resp.headers['Access-Control-Expose-Headers'] = '*'
        resp.enable_chunked_encoding()

        await resp.prepare(request)

        # loop.create_task(ping(loop, resp, client_guid))

        # resp.write(b'retry: 100\r\n\r\n')

        while True:
            event = await queue.get()
            if event is None:
                break
            buffer = io.BytesIO()
            if event.id:
                buffer.write(b"id: %s\r\n" % (event.id.encode('utf-8'), ))
            if event.event:
                buffer.write(b"event: %s\r\n" % (event.event.encode('utf-8')))
            if event.data:
                buffer.write(b"data: %s\r\n" %
                             (json.dumps(event.data).encode('utf-8')))
            buffer.write(b'\r\n')
            resp.write(buffer.getvalue())
            queue.task_done()
            current_app.logger.debug('pubsub.event.sent qsize=%s',
                                     queue.qsize())
            # Yield to the scheduler so other processes do stuff.
            await resp.drain()

        await resp.write_eof()
        return resp
    finally:
        conn.close()
        await conn.wait_closed()
        current_app.logger.debug('client.disconnected guid=%s',
                                 client_guid,
                                 exc_info=True)