diff --git a/platformio/commands/account/client.py b/platformio/commands/account/client.py index 312b9f36..b25365c0 100644 --- a/platformio/commands/account/client.py +++ b/platformio/commands/account/client.py @@ -25,6 +25,9 @@ from platformio.commands.account import exception class AccountClient(object): + + SUMMARY_CACHE_TTL = 60 * 60 * 24 * 7 + def __init__( self, api_base_url=__pioaccount_api__, retries=3, ): @@ -54,6 +57,14 @@ class AccountClient(object): def delete_local_session(): app.delete_state_item("account") + @staticmethod + def delete_local_state(key): + account = app.get_state_item("account") + if not account or key not in account: + return + del account[key] + app.set_state_item("account", account) + def login(self, username, password): try: self.fetch_authentication_token() @@ -182,13 +193,19 @@ class AccountClient(object): headers={"Authorization": "Bearer %s" % token}, data=profile, ) + self.delete_local_state("summary") return self.raise_error_from_response(response) def get_account_info(self, offline): + account = app.get_state_item("account") + if not account: + raise exception.AccountNotAuthorized() + if ( + account.get("summary") + and account["summary"].get("expire_at", 0) > time.time() + ): + return account["summary"] if offline: - account = app.get_state_item("account") - if not account: - raise exception.AccountNotAuthorized() return { "profile": { "email": account.get("email"), @@ -203,7 +220,12 @@ class AccountClient(object): self.api_base_url + "/v1/summary", headers={"Authorization": "Bearer %s" % token}, ) - return self.raise_error_from_response(response) + result = self.raise_error_from_response(response) + account["summary"] = dict( + **result, expire_at=int(time.time()) + self.SUMMARY_CACHE_TTL + ) + app.set_state_item("account", account) + return result def fetch_authentication_token(self): if "PLATFORMIO_AUTH_TOKEN" in os.environ: diff --git a/tests/commands/test_account.py b/tests/commands/test_account.py index 6355f561..ef7ffbad 100644 --- a/tests/commands/test_account.py +++ b/tests/commands/test_account.py @@ -389,6 +389,16 @@ def test_account_summary(clirunner, credentials, validate_cliresult, isolated_pi ) validate_cliresult(result) + result = clirunner.invoke(cmd_account, ["show", "--json-output", "--offline"]) + validate_cliresult(result) + json_result = json.loads(result.output.strip()) + assert not json_result.get("user_id") + assert json_result.get("profile") + assert json_result.get("profile").get("username") + assert json_result.get("profile").get("email") + assert not json_result.get("packages") + assert not json_result.get("subscriptions") + result = clirunner.invoke(cmd_account, ["show"]) validate_cliresult(result) assert credentials["login"] in result.output @@ -415,12 +425,19 @@ def test_account_summary(clirunner, credentials, validate_cliresult, isolated_pi result = clirunner.invoke(cmd_account, ["show", "--json-output", "--offline"]) validate_cliresult(result) json_result = json.loads(result.output.strip()) - assert not json_result.get("user_id") + assert json_result.get("user_id") assert json_result.get("profile") assert json_result.get("profile").get("username") assert json_result.get("profile").get("email") - assert not json_result.get("packages") - assert not json_result.get("subscriptions") + assert credentials["login"] == json_result.get("profile").get( + "username" + ) or credentials["login"] == json_result.get("profile").get("email") + assert json_result.get("profile").get("firstname") + assert json_result.get("profile").get("lastname") + assert json_result.get("packages") + assert json_result.get("packages")[0].get("name") + assert json_result.get("packages")[0].get("path") + assert json_result.get("subscriptions") is not None finally: clirunner.invoke(cmd_account, ["logout"])