From 098f02bc04550343767e3e1cfaef5f57af6b1046 Mon Sep 17 00:00:00 2001 From: lawric1 <67882089+lawric1@users.noreply.github.com> Date: Wed, 25 Nov 2020 02:13:14 -0300 Subject: [PATCH] Fixes: #3944 Authentication error; use tokens instead (#3949) * fixes #3944 authentication error * Fixes: #3944 authentication error * Fixed docstring failure in pre-commit, Fixed request.get params to GitHub REST API standards * run black formatter * Add USER_TOKEN constant and checks if empty, removes deprecated docstring * Add descriptive dict type hint, change headers format to f-string * Add Accept header * Fix pre-commit error * Fix pre-commit error * Add test for fetch_github_info * Remove test function from main file * Create test_fetch_github_info.py * Update test_fetch_github_info.py * Update test_fetch_github_info.py * No need to cover __name__ == __main__ block Co-authored-by: Dhruv Manilawala --- web_programming/fetch_github_info.py | 46 +++++++++++++++++------ web_programming/test_fetch_github_info.py | 27 +++++++++++++ 2 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 web_programming/test_fetch_github_info.py diff --git a/web_programming/fetch_github_info.py b/web_programming/fetch_github_info.py index 227598bb2..c9198460f 100644 --- a/web_programming/fetch_github_info.py +++ b/web_programming/fetch_github_info.py @@ -1,26 +1,50 @@ #!/usr/bin/env python3 - """ Created by sarathkaul on 14/11/19 +Updated by lawric1 on 24/11/20 -Basic authentication using an API password is deprecated and will soon no longer work. -Visit https://developer.github.com/changes/2020-02-14-deprecating-password-auth -for more information around suggested workarounds and removal dates. +Authentication will be made via access token. +To generate your personal access token visit https://github.com/settings/tokens. + +NOTE: +Never hardcode any credential information in the code. Always use an environment +file to store the private information and use the `os` module to get the information +during runtime. + +Create a ".env" file in the root directory and write these two lines in that file +with your token:: + +#!/usr/bin/env bash +export USER_TOKEN="" """ - +import os +from typing import Any, Dict import requests -_GITHUB_API = "https://api.github.com/user" +BASE_URL = "https://api.github.com" + +# https://docs.github.com/en/free-pro-team@latest/rest/reference/users#get-the-authenticated-user +AUTHENTICATED_USER_ENDPOINT = BASE_URL + "/user" + +# https://github.com/settings/tokens +USER_TOKEN = os.environ.get("USER_TOKEN", "") -def fetch_github_info(auth_user: str, auth_pass: str) -> dict: +def fetch_github_info(auth_token: str) -> Dict[Any, Any]: """ Fetch GitHub info of a user using the requests module """ - return requests.get(_GITHUB_API, auth=(auth_user, auth_pass)).json() + headers = { + "Authorization": f"token {auth_token}", + "Accept": "application/vnd.github.v3+json", + } + return requests.get(AUTHENTICATED_USER_ENDPOINT, headers=headers).json() -if __name__ == "__main__": - for key, value in fetch_github_info("", "").items(): - print(f"{key}: {value}") +if __name__ == "__main__": # pragma: no cover + if USER_TOKEN: + for key, value in fetch_github_info(USER_TOKEN).items(): + print(f"{key}: {value}") + else: + raise ValueError("'USER_TOKEN' field cannot be empty.") diff --git a/web_programming/test_fetch_github_info.py b/web_programming/test_fetch_github_info.py new file mode 100644 index 000000000..2da97c782 --- /dev/null +++ b/web_programming/test_fetch_github_info.py @@ -0,0 +1,27 @@ +import json + +import requests + +from .fetch_github_info import AUTHENTICATED_USER_ENDPOINT, fetch_github_info + + +def test_fetch_github_info(monkeypatch): + class FakeResponse: + def __init__(self, content) -> None: + assert isinstance(content, (bytes, str)) + self.content = content + + def json(self): + return json.loads(self.content) + + def mock_response(*args, **kwargs): + assert args[0] == AUTHENTICATED_USER_ENDPOINT + assert "Authorization" in kwargs["headers"] + assert kwargs["headers"]["Authorization"].startswith("token ") + assert "Accept" in kwargs["headers"] + return FakeResponse(b'{"login":"test","id":1}') + + monkeypatch.setattr(requests, "get", mock_response) + result = fetch_github_info("token") + assert result["login"] == "test" + assert result["id"] == 1