Beispiel #1
0
    def auth_flow(
        self, request: httpx.Request
    ) -> typing.Generator[httpx.Request, httpx.Response, None]:
        token = self.get_access_token()
        if token:
            request.headers["Authorization"] = f"token {token}"
            response = yield request
            if response.status_code != 401:  # due to access_token
                return

        with self.response_body_read():
            auth_response = yield self.build_access_token_request()
            if auth_response.status_code == 401:  # due to jwt
                auth_response = yield self.build_access_token_request(
                    force=True)

            if auth_response.status_code == 404:
                raise exceptions.MergifyNotInstalled()
            elif auth_response.status_code == 403:
                error_message = auth_response.json()["message"]
                if "This installation has been suspended" in error_message:
                    LOG.debug(
                        "Mergify installation suspended",
                        gh_owner=self._owner_login,
                        error_message=error_message,
                    )
                    raise exceptions.MergifyNotInstalled()

            http.raise_for_status(auth_response)
            token = self._set_access_token(auth_response.json())

        request.headers["Authorization"] = f"token {token}"
        yield request
    async def _retrieve_subscription_from_db(
        cls: typing.Type[SubscriptionT], redis: utils.RedisCache, owner_id: int
    ) -> SubscriptionT:

        print(config.SUBSCRIPTION_BASE_URL)
        print(f"{config.SUBSCRIPTION_BASE_URL}/on-premise/subscription/{owner_id}")
        async with http.AsyncClient() as client:
            try:
                resp = await client.get(
                    f"{config.SUBSCRIPTION_BASE_URL}/on-premise/subscription/{owner_id}",
                    headers={"Authorization": f"token {config.SUBSCRIPTION_TOKEN}"},
                )
            except http.HTTPUnauthorized:
                LOG.critical(
                    "The SUBSCRIPTION_TOKEN is invalid, the subscription can't be checked"
                )
                raise exceptions.MergifyNotInstalled()
            except http.HTTPForbidden:
                LOG.critical(
                    "The subscription attached to SUBSCRIPTION_TOKEN is not valid"
                )
                raise exceptions.MergifyNotInstalled()
            else:
                sub = resp.json()
                if not sub["subscription_active"]:
                    LOG.critical(
                        "The subscription attached to SUBSCRIPTION_TOKEN is not active"
                    )
                    raise exceptions.MergifyNotInstalled()
                return cls.from_dict(redis, owner_id, sub)
Beispiel #3
0
    def auth_flow(self, request):
        if self.installation is None:
            with self.response_body_read():
                installation_response = yield self.build_installation_request()
                if installation_response.status_code == 401:  # due to jwt
                    installation_response = yield self.build_installation_request(
                        force=True
                    )
                if installation_response.is_redirect:
                    installation_response = yield self.build_installation_request(
                        url=installation_response.headers["Location"],
                    )

                if installation_response.status_code == 404:
                    LOG.debug(
                        "Mergify not installed",
                        gh_owner=self.owner,
                        error_message=installation_response.json()["message"],
                    )
                    raise exceptions.MergifyNotInstalled()

                http.raise_for_status(installation_response)

                self._set_installation(installation_response)

        token = self._get_access_token()
        if token:
            request.headers["Authorization"] = f"token {token}"
            response = yield request
            if response.status_code != 401:  # due to access_token
                return

        with self.response_body_read():
            auth_response = yield self.build_access_token_request()
            if auth_response.status_code == 401:  # due to jwt
                auth_response = yield self.build_access_token_request(force=True)

            if auth_response.status_code == 403:
                error_message = auth_response.json()["message"]
                if "This installation has been suspended" in error_message:
                    LOG.debug(
                        "Mergify installation suspended",
                        gh_owner=self.owner,
                        error_message=error_message,
                    )
                    raise exceptions.MergifyNotInstalled()

            http.raise_for_status(auth_response)
            token = self._set_access_token(auth_response.json())

        request.headers["Authorization"] = f"token {token}"
        yield request
Beispiel #4
0
 def get_installation_by_id(self, installation_id):
     try:
         return self._get_installation(
             f"/app/installations/{installation_id}")
     except httpx.HTTPNotFound as e:
         LOG.debug(
             "mergify not installed",
             installation_id=installation_id,
             error_message=e.message,
         )
         raise exceptions.MergifyNotInstalled()
Beispiel #5
0
    async def _retrieve_subscription_from_db(cls: typing.Type[SubscriptionT],
                                             redis: utils.RedisCache,
                                             owner_id: int) -> SubscriptionT:
        async with dashboard.AsyncDashboardOnPremiseClient() as client:
            try:
                resp = await client.get(f"/on-premise/subscription/{owner_id}")
            except http.HTTPUnauthorized:
                LOG.critical(
                    "The SUBSCRIPTION_TOKEN is invalid, the subscription can't be checked"
                )
                raise exceptions.MergifyNotInstalled()
            except http.HTTPForbidden:
                LOG.critical(
                    "The subscription attached to SUBSCRIPTION_TOKEN is not valid"
                )
                raise exceptions.MergifyNotInstalled()
            else:
                sub = resp.json()

                return cls.from_dict(redis, owner_id, sub)
Beispiel #6
0
 async def _retrieve_subscription_from_db(cls: typing.Type[SubscriptionT],
                                          redis: utils.RedisCache,
                                          owner_id: int) -> SubscriptionT:
     async with dashboard.AsyncDashboardSaasClient() as client:
         try:
             resp = await client.get(f"/engine/subscription/{owner_id}")
         except http.HTTPNotFound:
             raise exceptions.MergifyNotInstalled()
         else:
             sub = resp.json()
             return cls.from_dict(redis, owner_id, sub)
async def get_installation_from_id(installation_id):
    url = f"{config.GITHUB_API_URL}/app/installations/{installation_id}"
    async with http.AsyncClient(auth=GithubBearerAuth(),
                                **http.DEFAULT_CLIENT_OPTIONS) as client:
        try:
            installation = (await client.get(url)).json()
            permissions_need_to_be_updated(installation)
            return installation
        except http.HTTPNotFound as e:
            LOG.debug(
                "Mergify not installed",
                error_message=e.message,
            )
            raise exceptions.MergifyNotInstalled()
Beispiel #8
0
def permissions_need_to_be_updated(installation):
    expected_permissions = EXPECTED_MINIMAL_PERMISSIONS[installation["target_type"]]
    for perm_name, perm_level in expected_permissions.items():
        if installation["permissions"].get(perm_name) != perm_level:
            LOG.debug(
                "The Mergify installation doesn't have the required permissions",
                gh_owner=installation["account"]["login"],
                permissions=installation["permissions"],
            )
            # FIXME(sileht): Looks like ton of people have not all permissions
            # Or this is buggy, so disable it for now.
            if perm_name in ["checks", "pull_requests", "contents"]:
                raise exceptions.MergifyNotInstalled()
            return True
    return False
Beispiel #9
0
    async def _retrieve_subscription_from_db(cls: typing.Type[SubscriptionT],
                                             redis: utils.RedisCache,
                                             owner_id: int) -> SubscriptionT:
        async with http.AsyncClient() as client:
            try:

                resp = await client.get(
                    f"{config.SUBSCRIPTION_BASE_URL}/engine/subscription/{owner_id}",
                    auth=(config.OAUTH_CLIENT_ID, config.OAUTH_CLIENT_SECRET),
                )
            except http.HTTPNotFound:
                raise exceptions.MergifyNotInstalled()
            else:
                sub = resp.json()
                return cls.from_dict(redis, owner_id, sub)
Beispiel #10
0
async def get_installation(account):
    owner = account["login"]
    account_type = "users" if account["type"].lower() == "user" else "orgs"
    url = f"{config.GITHUB_API_URL}/{account_type}/{owner}/installation"
    async with http.AsyncClient(auth=GithubBearerAuth(),
                                **http.DEFAULT_CLIENT_OPTIONS) as client:
        try:
            installation = (await client.get(url)).json()
            permissions_need_to_be_updated(installation)
            return installation
        except http.HTTPNotFound as e:
            LOG.debug(
                "Mergify not installed",
                gh_owner=owner,
                error_message=e.message,
            )
            raise exceptions.MergifyNotInstalled()
Beispiel #11
0
async def get_installation_from_login(
    login: github_types.GitHubLogin, ) -> github_types.GitHubInstallation:
    async with AsyncGithubClient(auth=github_app.GithubBearerAuth()) as client:
        try:
            return typing.cast(
                github_types.GitHubInstallation,
                await client.item(
                    f"{config.GITHUB_REST_API_URL}/users/{login}/installation"
                ),
            )
        except http.HTTPNotFound as e:
            LOG.debug(
                "Mergify not installed",
                gh_owner=login,
                error_message=e.message,
            )
            raise exceptions.MergifyNotInstalled()
Beispiel #12
0
    def get_installation(self, owner, repo=None, account_type=None):
        if not account_type and not repo:
            raise RuntimeError("repo or account_type must be passed")

        if repo:
            url = f"/repos/{owner}/{repo}/installation"
        else:
            account_type = "users" if account_type.lower(
            ) == "user" else "orgs"
            url = f"/{account_type}/{owner}/installation"

        try:
            return self._get_installation(url)
        except httpx.HTTPNotFound as e:
            LOG.debug(
                "mergify not installed",
                gh_owner=owner,
                gh_repo=repo,
                error_message=e.message,
            )
            raise exceptions.MergifyNotInstalled()
Beispiel #13
0
    def get_installation(self, owner, repo=None, account_type=None):
        if not account_type and not repo:
            raise RuntimeError("repo or account_type must be passed")

        if repo:
            url = f"/repos/{owner}/{repo}/installation"
        else:
            account_type = "users" if account_type.lower(
            ) == "user" else "orgs"
            url = f"/{account_type}/{owner}/installation"

        try:
            installation = self.get(url).json()
        except httpx.HTTPNotFound as e:
            LOG.warning(
                "mergify not installed",
                gh_owner=owner,
                gh_repo=repo,
                error_message=e.message,
            )
            raise exceptions.MergifyNotInstalled()

        expected_permissions = EXPECTED_MINIMAL_PERMISSIONS[
            installation["target_type"]]
        for perm_name, perm_level in expected_permissions.items():
            if installation["permissions"].get(perm_name) != perm_level:
                LOG.warning(
                    "mergify installation doesn't have required permissions",
                    gh_owner=owner,
                    gh_repo=repo,
                    permissions=installation["permissions"],
                )
                # FIXME(sileht): Looks like ton of people have not all permissions
                # Or this is buggy, so disable it for now.
                # raise exceptions.MergifyNotInstalled()

        return installation