Skip to content

Commit

Permalink
feat: handle 403 same as 401, and look for credentials on 404 error (#70
Browse files Browse the repository at this point in the history
)

* Handle 403, 404

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Update src/unearth/auth.py

---------

Co-authored-by: Logan Grado <lgrado@apple.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Frost Ming <mianghong@gmail.com>
  • Loading branch information
4 people committed Sep 19, 2023
1 parent 4c4aa76 commit 66b32c9
Showing 1 changed file with 15 additions and 13 deletions.
28 changes: 15 additions & 13 deletions src/unearth/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@ def __call__(self, req: PreparedRequest) -> PreparedRequest:
if username is not None and password is not None:
req = HTTPBasicAuth(username, password)(req)

# Attach a hook to handle 401 responses
req.register_hook("response", self.handle_401)
# Attach a hook to handle 400 responses
req.register_hook("response", self.handle_400s)

return req

Expand All @@ -284,14 +284,10 @@ def _should_save_password_to_keyring(self) -> bool:
return False
return input("Save credentials to keyring [y/N]: ") == "y"

def handle_401(self, resp: Response, **kwargs: Any) -> Response:
# We only care about 401 responses, anything else we want to just
def handle_400s(self, resp: Response, **kwargs: Any) -> Response:
# We only care about 401, 403, 404 responses, anything else we want to just
# pass through the actual response
if resp.status_code != 401:
return resp

# We are not able to prompt the user so simply return the response
if not self.prompting:
if resp.status_code not in [401, 403, 404]:
return resp

parsed = urlparse(cast(str, resp.url))
Expand All @@ -306,6 +302,11 @@ def handle_401(self, resp: Response, **kwargs: Any) -> Response:
# Prompt the user for a new username and password
save = False
if not username and not password:
# We are not able to prompt the user so simply return the response
# Also, do not prompt on 404
if not self.prompting or resp.status_code == 404:
return resp

username, password, save = self._prompt_for_password(parsed.netloc)

# Store the new username and password to use for future requests
Expand All @@ -326,7 +327,7 @@ def handle_401(self, resp: Response, **kwargs: Any) -> Response:
req = HTTPBasicAuth(username or "", password or "")(resp.request)
# We add new hooks on the fly, since the req is the same as resp.request
# The hook will be picked up by the next iteration of `dispatch_hooks()`
req.register_hook("response", self.warn_on_401)
req.register_hook("response", self.warn_on_401_403_404)

# On successful request, save the credentials that were used to
# keyring. (Note that if the user responded "no" above, this member
Expand All @@ -340,11 +341,12 @@ def handle_401(self, resp: Response, **kwargs: Any) -> Response:

return new_resp

def warn_on_401(self, resp: Response, **kwargs: Any) -> None:
def warn_on_401_403_404(self, resp: Response, **kwargs: Any) -> None:
"""Response callback to warn about incorrect credentials."""
if resp.status_code == 401:
if resp.status_code in [401, 403, 404]:
logger.warning(
"401 Error, Credentials not correct for %s",
"%s Error, Credentials not correct for %s",
resp.status_code,
resp.request.url,
)

Expand Down

0 comments on commit 66b32c9

Please sign in to comment.