From 927b226f853af8769aecd6b56c8db44adb804774 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Oct 2021 17:03:41 +0000 Subject: [PATCH 01/12] build(deps-dev): bump autopep8 from 1.5.7 to 1.6.0 Bumps [autopep8](https://github.com/hhatto/autopep8) from 1.5.7 to 1.6.0. - [Release notes](https://github.com/hhatto/autopep8/releases) - [Commits](https://github.com/hhatto/autopep8/compare/v1.5.7...v1.6.0) --- updated-dependencies: - dependency-name: autopep8 dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 16d01f5a..dc6df745 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -21,7 +21,7 @@ safety==1.10.3 types-requests==2.25.11 # Code formatting tools -autopep8==1.5.7 +autopep8==1.6.0 # HTML changelogs grip==4.5.2 From 034a662c48efbe6c8343a5ad8f5895b24cadce63 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Nov 2021 17:04:09 +0000 Subject: [PATCH 02/12] build(deps-dev): bump coverage[toml] from 6.0.2 to 6.1.1 Bumps [coverage[toml]](https://github.com/nedbat/coveragepy) from 6.0.2 to 6.1.1. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/6.0.2...6.1.1) --- updated-dependencies: - dependency-name: coverage[toml] dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 16d01f5a..1198a685 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -33,7 +33,7 @@ py2exe==0.10.4.1; sys_platform == 'win32' # Testing pytest==6.2.5 pytest-cov==3.0.0 # Pytest code coverage support -coverage[toml]==6.0.2 # pytest-cov dep. This is here to ensure that it includes TOML support for pyproject.toml configs +coverage[toml]==6.1.1 # pytest-cov dep. This is here to ensure that it includes TOML support for pyproject.toml configs # For manipulating folder permissions and the like. pywin32==302; sys_platform == 'win32' From 48c10978c6c78cac0f64c6865cae7fabb9e7996d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Nov 2021 17:03:39 +0000 Subject: [PATCH 03/12] build(deps): bump actions/checkout from 2.3.5 to 2.4.0 Bumps [actions/checkout](https://github.com/actions/checkout) from 2.3.5 to 2.4.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2.3.5...v2.4.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/pr-checks.yml | 2 +- .github/workflows/push-checks.yml | 2 +- .github/workflows/windows-build.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 03dc1744..5361f84e 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -28,7 +28,7 @@ jobs: # based on. - name: Checkout head commits # https://github.com/actions/checkout - uses: actions/checkout@v2.3.5 + uses: actions/checkout@v2.4.0 #with: #ref: ${{github.head.sha}} #repository: ${{github.event.pull_request.head.repo.full_name}} diff --git a/.github/workflows/push-checks.yml b/.github/workflows/push-checks.yml index 8c7f54b3..021b9109 100644 --- a/.github/workflows/push-checks.yml +++ b/.github/workflows/push-checks.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-18.04 steps: - - uses: actions/checkout@v2.3.5 + - uses: actions/checkout@v2.4.0 with: fetch-depth: 0 - name: Set up Python 3.9 diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index 06c1c027..05e01364 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -16,7 +16,7 @@ jobs: shell: powershell steps: - - uses: actions/checkout@v2.3.5 + - uses: actions/checkout@v2.4.0 - uses: actions/setup-python@v2.2.2 with: python-version: "3.9.7" From 87cecf4f96070ab359b4a059219a9b9782e30f57 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Nov 2021 17:03:50 +0000 Subject: [PATCH 04/12] build(deps-dev): bump isort from 5.9.3 to 5.10.0 Bumps [isort](https://github.com/pycqa/isort) from 5.9.3 to 5.10.0. - [Release notes](https://github.com/pycqa/isort/releases) - [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md) - [Commits](https://github.com/pycqa/isort/compare/5.9.3...5.10.0) --- updated-dependencies: - dependency-name: isort dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 71401129..4d2c0a0c 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -8,7 +8,7 @@ flake8-annotations-coverage==0.0.5 flake8-cognitive-complexity==0.1.0 flake8-comprehensions==3.7.0 flake8-docstrings==1.6.0 -isort==5.9.3 +isort==5.10.0 flake8-isort==4.1.1 flake8-json==21.7.0 flake8-noqa==1.2.0 From 8e32ecd216997251f7e22c57000f4a4eb7aa3b62 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 5 Nov 2021 17:52:50 +0000 Subject: [PATCH 05/12] CAPI: Actually try to use Refresh Token if CAPI says unauthorized The refactor for threaded CAPI worker has inadvertently caused us to always try *full* re-auth when the CAPI signals the Access Token is expired. --- EDMarketConnector.py | 7 +++++++ companion.py | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 35d2c58a..e561eb24 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1159,6 +1159,13 @@ class AppWindow(object): # LANG: Frontier CAPI server error when fetching data self.status['text'] = _('Frontier CAPI server error') + except companion.CredentialsRequireRefresh: + # LANG: Frontier CAPI Access Token expired, trying to get a new one + self.status['text'] = _('CAPI: Refreshing access token...') + if companion.session.login(): + logger.debug('Initial query failed, but login() just worked, trying again...') + companion.session.retrying = True + except companion.CredentialsError: companion.session.retrying = False companion.session.invalidate() diff --git a/companion.py b/companion.py index 1a811858..7c9cc96a 100644 --- a/companion.py +++ b/companion.py @@ -265,6 +265,15 @@ class CredentialsError(Exception): self.args = (_('Error: Invalid Credentials'),) +class CredentialsRequireRefresh(Exception): + """Exception Class for CAPI credentials requiring refresh.""" + + def __init__(self, *args) -> None: + self.args = args + if not args: + self.args = ('CAPI: Requires refresh of Access Token',) + + class CmdrError(Exception): """Exception Class for CAPI Commander error. @@ -772,6 +781,7 @@ class Session(object): self.dump(r) if r.status_code == 401: # CAPI doesn't think we're Auth'd + # TODO: This needs to try a REFRESH, not a full re-auth # No need for translation, we'll go straight into trying new Auth # and thus any message would be overwritten. raise CredentialsError('Frontier CAPI said Auth required') from e From 7a52ddd27801fc979d31408e496e3e206adbf93d Mon Sep 17 00:00:00 2001 From: Athanasius Date: Fri, 5 Nov 2021 17:57:35 +0000 Subject: [PATCH 06/12] CAPI: Add retry of request after refreshing Access Token --- EDMarketConnector.py | 2 ++ companion.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index e561eb24..32e4072a 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1165,6 +1165,8 @@ class AppWindow(object): if companion.session.login(): logger.debug('Initial query failed, but login() just worked, trying again...') companion.session.retrying = True + self.w.after(int(SERVER_RETRY * 1000), lambda: self.capi_request_data(event)) + return # early exit to avoid starting cooldown count except companion.CredentialsError: companion.session.retrying = False diff --git a/companion.py b/companion.py index 7c9cc96a..18b53402 100644 --- a/companion.py +++ b/companion.py @@ -784,7 +784,7 @@ class Session(object): # TODO: This needs to try a REFRESH, not a full re-auth # No need for translation, we'll go straight into trying new Auth # and thus any message would be overwritten. - raise CredentialsError('Frontier CAPI said Auth required') from e + raise CredentialsRequireRefresh('Frontier CAPI said "unauthorized"') from e if r.status_code == 418: # "I'm a teapot" - used to signal maintenance # LANG: Frontier CAPI returned 418, meaning down for maintenance From 919136874d3c32b354a3ea9d3fa2872cb233b754 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 6 Nov 2021 08:41:09 +0000 Subject: [PATCH 07/12] CAPI: Re-auth when Access Token expired: Need to .close() first The old code did this, and without it we enter a loop of: 1. CAPI says unauthorized 2. We call login() 3. But companion.session.state == STATE_OK, so do nothing 4. Re-scheduled CAPI request goes back to 1. --- EDMarketConnector.py | 2 ++ monitor.py | 1 + 2 files changed, 3 insertions(+) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 32e4072a..3b969d8b 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -1160,6 +1160,8 @@ class AppWindow(object): self.status['text'] = _('Frontier CAPI server error') except companion.CredentialsRequireRefresh: + # We need to 'close' the auth else it'll see STATE_OK and think login() isn't needed + companion.session.close() # LANG: Frontier CAPI Access Token expired, trying to get a new one self.status['text'] = _('CAPI: Refreshing access token...') if companion.session.login(): diff --git a/monitor.py b/monitor.py index debba020..65119f7f 100644 --- a/monitor.py +++ b/monitor.py @@ -1210,6 +1210,7 @@ class EDLogs(FileSystemEventHandler): # type: ignore # See below } except KeyError: + # TODO: Log the exception details too, for some clue about *which* key logger.error(f"LoadoutEquipModule: {entry}") elif event_type == 'loadoutremovemodule': From 6bec46be4e644cafbff1e5a337160ca4d8773fc6 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 6 Nov 2021 10:41:33 +0000 Subject: [PATCH 08/12] CAPI: Implement a one-shot override of the Access Token This allows you to force use of an expired token so as to test the code paths for that without waiting up to 4 hours for the current one to expire. NB: The Access Token is *only* stored in the headers of the `requests` object. --- EDMarketConnector.py | 11 +++++++++++ companion.py | 6 ++++++ config.py | 1 + 3 files changed, 18 insertions(+) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 3b969d8b..24453a47 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -151,6 +151,12 @@ if __name__ == '__main__': # noqa: C901 action='store_true' ) + parser.add_argument( + '--capi-use-debug-access-token', + help='Load a debug Access Token from disk (from config.app_dir_pathapp_dir_path / access_token.txt)', + action='store_true' + ) + parser.add_argument( '--eddn-url', help='Specify an alternate EDDN upload URL', @@ -170,6 +176,11 @@ if __name__ == '__main__': # noqa: C901 logger.info('Pretending CAPI is down') conf_module.capi_pretend_down = True + if args.capi_use_debug_access_token: + import config as conf_module + with open(conf_module.config.app_dir_path / 'access_token.txt', 'r') as at: + conf_module.capi_debug_access_token = at.readline().strip() + level_to_set: Optional[int] = None if args.trace or args.trace_on: level_to_set = logging.TRACE # type: ignore # it exists diff --git a/companion.py b/companion.py index 18b53402..2682fd8a 100644 --- a/companion.py +++ b/companion.py @@ -759,7 +759,13 @@ class Session(object): if conf_module.capi_pretend_down: raise ServerConnectionError(f'Pretending CAPI down: {capi_endpoint}') + if conf_module.capi_debug_access_token is not None: + self.requests_session.headers['Authorization'] = f'Bearer {conf_module.capi_debug_access_token}' # type: ignore # noqa: E501 + # This is one-shot + conf_module.capi_debug_access_token = None + r = self.requests_session.get(self.server + capi_endpoint, timeout=timeout) # type: ignore + logger.trace_if('capi.worker', '... got result...') r.raise_for_status() # Typically 403 "Forbidden" on token expiry # May also fail here if token expired since response is empty diff --git a/config.py b/config.py index d690da56..8660397f 100644 --- a/config.py +++ b/config.py @@ -46,6 +46,7 @@ debug_senders: List[str] = [] trace_on: List[str] = [] capi_pretend_down: bool = False +capi_debug_access_token: Optional[str] # This must be done here in order to avoid an import cycle with EDMCLogging. # Other code should use EDMCLogging.get_main_logger if os.getenv("EDMC_NO_UI"): From b8719edb9277af43f100085d23fbfe73f4bff5f5 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 6 Nov 2021 14:19:33 +0000 Subject: [PATCH 09/12] Pre-Release 5.2.1-rc1: appversion and changelog --- ChangeLog.md | 10 ++++++++++ config.py | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index b4f5a1f8..7b10f97f 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -27,6 +27,16 @@ produce the Windows executables and installer. --- +Pre-Release 5.2.1-rc1 +=== + +This release primarily addresses the issue of the program asking for +Frontier authorization much too often. + +* Actually utilise the Frontier Refresh Token when the CAPI response is + "Unauthorized". The re-factoring of this code to make CAPI queries + threaded inadvertently prevented this. + Release 5.2.0 === diff --git a/config.py b/config.py index 8660397f..611e15f5 100644 --- a/config.py +++ b/config.py @@ -33,7 +33,7 @@ appcmdname = 'EDMC' # # Major.Minor.Patch(-prerelease)(+buildmetadata) # NB: Do *not* import this, use the functions appversion() and appversion_nobuild() -_static_appversion = '5.2.0' +_static_appversion = '5.2.1-rc1' _cached_version: Optional[semantic_version.Version] = None copyright = '© 2015-2019 Jonathan Harris, 2020-2021 EDCD' From 7bf564d3b322eaa9dbe0f0fe3946506f7702f54b Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 6 Nov 2021 14:56:57 +0000 Subject: [PATCH 10/12] CAPI: ensure config.capi_debug_access_token is bound/set --- config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.py b/config.py index 8660397f..702873ee 100644 --- a/config.py +++ b/config.py @@ -46,7 +46,7 @@ debug_senders: List[str] = [] trace_on: List[str] = [] capi_pretend_down: bool = False -capi_debug_access_token: Optional[str] +capi_debug_access_token: Optional[str] = None # This must be done here in order to avoid an import cycle with EDMCLogging. # Other code should use EDMCLogging.get_main_logger if os.getenv("EDMC_NO_UI"): From 39a303fd179d54f8cbff45800892d9b482b16d8c Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sat, 6 Nov 2021 14:58:30 +0000 Subject: [PATCH 11/12] Pre-Release 5.2.1-rc2: appversion and changelog --- ChangeLog.md | 6 ++++++ config.py | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ChangeLog.md b/ChangeLog.md index 7b10f97f..8eb87880 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -27,6 +27,12 @@ produce the Windows executables and installer. --- +Pre-Release 5.2.1-rc2 +=== + +This fixes a code error that prevented caused some new debug code to cause +CAPI queries to fail. + Pre-Release 5.2.1-rc1 === diff --git a/config.py b/config.py index 4d74ca23..b530324f 100644 --- a/config.py +++ b/config.py @@ -33,7 +33,7 @@ appcmdname = 'EDMC' # # Major.Minor.Patch(-prerelease)(+buildmetadata) # NB: Do *not* import this, use the functions appversion() and appversion_nobuild() -_static_appversion = '5.2.1-rc1' +_static_appversion = '5.2.1-rc2' _cached_version: Optional[semantic_version.Version] = None copyright = '© 2015-2019 Jonathan Harris, 2020-2021 EDCD' From b589ac39a5624e8a017496a729a95e940c0f36e3 Mon Sep 17 00:00:00 2001 From: Athanasius Date: Sun, 7 Nov 2021 11:59:26 +0000 Subject: [PATCH 12/12] Release 5.2.1: appversion and changelog --- ChangeLog.md | 8 +------- config.py | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index 8eb87880..7c2b8ad3 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -27,13 +27,7 @@ produce the Windows executables and installer. --- -Pre-Release 5.2.1-rc2 -=== - -This fixes a code error that prevented caused some new debug code to cause -CAPI queries to fail. - -Pre-Release 5.2.1-rc1 +Release 5.2.1 === This release primarily addresses the issue of the program asking for diff --git a/config.py b/config.py index b530324f..d50d5495 100644 --- a/config.py +++ b/config.py @@ -33,7 +33,7 @@ appcmdname = 'EDMC' # # Major.Minor.Patch(-prerelease)(+buildmetadata) # NB: Do *not* import this, use the functions appversion() and appversion_nobuild() -_static_appversion = '5.2.1-rc2' +_static_appversion = '5.2.1' _cached_version: Optional[semantic_version.Version] = None copyright = '© 2015-2019 Jonathan Harris, 2020-2021 EDCD'