Esempio n. 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)
Esempio n. 2
0
    def request(
        self,
        path: str,
        method: str,
        params: Optional[dict] = None,
        tenant: Optional[Union[bool, auth.Tenant]] = True,
        raise_errors: Optional[bool] = True,
    ):
        if tenant is True:
            tenant = auth.get_current_tenant()
        elif tenant is False:
            tenant = None

        url = "{}/{}".format(current_app.config["VCS_SERVER_ENDPOINT"],
                             path.lstrip("/"))

        hub = Hub.current
        with hub.start_span(op="vcs-server", description=f"{method} {path}"):
            response = requests.request(
                method=method,
                url=url,
                params=({k: v
                         for k, v in params.items()
                         if v is not None} if params else None),
                headers={
                    "Authorization":
                    "Bearer zeus-t-{}".format(
                        auth.generate_token(tenant).decode("utf-8"))
                },
            )
        if raise_errors and not (200 <= response.status_code < 300):
            text = response.text
            data = {}
            try:
                data = json.loads(text)
            except ValueError:
                pass

            # XXX(dcramer): this feels a bit hacky, and ideally would be handled
            # in the vcs implementation
            if data.get("error") == "invalid_pubkey" and params:
                from zeus.tasks import deactivate_repo, DeactivationReason

                deactivate_repo.delay(params["repo_id"],
                                      DeactivationReason.invalid_pubkey)

            if data.get("error") == "invalid_ref":
                raise UnknownRevision(ref=data.get("ref"))

            raise ApiError(text=text, code=response.status_code)

        if raise_errors and not response.headers["Content-Type"].startswith(
                "application/json"):
            raise ApiError(
                text="Request returned invalid content type: {}".format(
                    response.headers["Content-Type"]),
                code=response.status_code,
            )

        return response.json()
Esempio n. 3
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)
Esempio n. 4
0
def test_get_tenant_from_signed_token_user(default_user, default_repo,
                                           default_repo_access):
    # TODO(dcramer): we'd prefer to not generate a dynamic token
    tenant = auth.Tenant.from_user(default_user)
    token = auth.generate_token(tenant)
    tenant = auth.get_tenant_from_signed_token(token)
    assert tenant.user_id == default_user.id
    assert tenant.access == {default_repo.id: Permission.admin}
Esempio n. 5
0
def test_get_tenant_from_headers_token(default_user, default_repo,
                                       default_repo_access):
    # TODO(dcramer): we'd prefer to not generate a dynamic token
    tenant = auth.Tenant.from_user(default_user)
    token = auth.generate_token(tenant).decode("utf-8")
    tenant = auth.get_tenant_from_headers(
        {"Authorization": f"Bearer zeus-t-{token}"})
    assert tenant.user_id == default_user.id
    assert tenant.access == {default_repo.id: Permission.admin}
Esempio n. 6
0
    def dispatch_request(self, *args, **kwargs) -> Response:
        delay = current_app.config.get("API_DELAY", 0)
        if delay:
            sleep(delay / 1000)

        tenant = request.environ.get("zeus.tenant")
        if self.authentication_classes:
            for auth_cls in self.authentication_classes:
                try:
                    _tenant = auth_cls().authenticate()
                    if _tenant:
                        tenant = _tenant
                        break

                except auth.AuthenticationFailed:
                    return self.respond({"error": "invalid_auth"}, 401)

        if tenant:
            auth.set_current_tenant(tenant)
        elif self.auth_required:
            return self.respond({"error": "auth_required"}, 401)

        try:
            method = getattr(self, request.method.lower())
        except AttributeError:
            return self.respond({"message": "resource not found"}, 405)

        try:
            resp = method(*args, **kwargs)
            if not isinstance(resp, Response):
                resp = self.respond(resp)
            if tenant:
                resp.headers["X-Stream-Token"] = auth.generate_token(tenant)
            return resp

        except ValidationError as e:
            return self.respond(e.messages, 403)

        except ConnectionError as exc:
            current_app.logger.exception("failed to handle api request")
            return self.respond(
                {"error": "connection_error", "url": exc.request.url}, 502
            )

        except ApiUnauthorized:
            return self.respond({"error": "auth_required"}, 401)

        except Exception:
            current_app.logger.exception("failed to handle api request")
            return self.error("internal server error", 500)
Esempio n. 7
0
    def get(self, path: str, repo_id: UUID, **params):
        if "tenant" not in params:
            tenant = auth.RepositoryTenant(repository_id=repo_id)
        else:
            tenant = params.pop("tenant", None)

        headers = {}
        if tenant:
            headers["Authorization"] = "Bearer zeus-t-{}".format(
                auth.generate_token(tenant).decode("utf-8"))

        return self.client.get(
            f"{path}?repo_id={repo_id}&{'&'.join('{}={}'.format(k, v) for k, v in params.items())}",
            headers=headers,
        )
Esempio n. 8
0
    def dispatch_request(self, *args, **kwargs) -> Response:
        delay = current_app.config.get('API_DELAY', 0)
        if delay:
            sleep(delay / 1000)

        tenant = request.environ.get('zeus.tenant')
        if self.authentication_classes:
            for auth_cls in self.authentication_classes:
                try:
                    _tenant = auth_cls().authenticate()
                    if _tenant:
                        tenant = _tenant
                        break
                except auth.AuthenticationFailed:
                    return self.respond({
                        'error': 'invalid_auth',
                    }, 401)

        if tenant:
            auth.set_current_tenant(tenant)
        elif self.auth_required:
            return self.respond({
                'error': 'auth_required',
            }, 401)

        try:
            method = getattr(self, request.method.lower())
        except AttributeError:
            return self.respond({'message': 'resource not found'}, 405)

        try:
            resp = method(*args, **kwargs)
            if not isinstance(resp, Response):
                resp = self.respond(resp)
            if tenant:
                resp.headers['X-Stream-Token'] = auth.generate_token(tenant)
            return resp
        except ApiUnauthorized:
            return self.respond({
                'error': 'auth_required',
            }, 401)
        except Exception:
            current_app.logger.exception('failed to handle api request')
            return self.error('internal server error', 500)