From 561d3094468261561a7799e9c10a513add295b45 Mon Sep 17 00:00:00 2001 From: Alexander Piskun <13381981+bigcat88@users.noreply.github.com> Date: Thu, 1 Feb 2024 22:59:34 +0300 Subject: [PATCH] appapi-2.0.3-api-scopes (#216) Ref: https://github.com/cloud-py-api/app_api/pull/220 No more "optional API Scopes", lets make all simpler :) Signed-off-by: Alexander Piskun --- docs/NextcloudApp.rst | 8 +--- docs/NextcloudTalkBot.rst | 8 +--- docs/conf.py | 1 + examples/as_app/skeleton/Makefile | 6 +-- examples/as_app/skeleton/appinfo/info.xml | 6 +-- examples/as_app/talk_bot/Makefile | 4 +- examples/as_app/talk_bot/appinfo/info.xml | 8 +--- examples/as_app/talk_bot_ai/Makefile | 4 +- examples/as_app/talk_bot_ai/appinfo/info.xml | 8 +--- examples/as_app/to_gif/Makefile | 6 +-- examples/as_app/to_gif/appinfo/info.xml | 8 +--- examples/as_app/ui_example/Makefile | 6 +-- examples/as_app/ui_example/appinfo/info.xml | 4 -- nc_py_api/_version.py | 2 +- nc_py_api/ex_app/defs.py | 2 +- nc_py_api/nextcloud.py | 20 +------- scripts/ci_register.sh | 2 +- scripts/dev_register.sh | 2 +- tests/actual_tests/nc_app_test.py | 48 +------------------- 19 files changed, 31 insertions(+), 122 deletions(-) diff --git a/docs/NextcloudApp.rst b/docs/NextcloudApp.rst index 35557d55..f611eedb 100644 --- a/docs/NextcloudApp.rst +++ b/docs/NextcloudApp.rst @@ -151,12 +151,8 @@ First of all, we modernize info.ixml, add the API groups we need for this to wor .. code-block:: xml - - FILES - NOTIFICATIONS - - - + FILES + NOTIFICATIONS .. note:: Full list of avalaible API scopes can be found `here `_. diff --git a/docs/NextcloudTalkBot.rst b/docs/NextcloudTalkBot.rst index 7a874f1a..1d80499d 100644 --- a/docs/NextcloudTalkBot.rst +++ b/docs/NextcloudTalkBot.rst @@ -13,12 +13,8 @@ The first step is to add the **TALK_BOT** and **TALK** scopes to your `info.xml` .. code-block:: xml - - TALK - TALK_BOT - - - + TALK + TALK_BOT The TALK_BOT scope enables your application to register the bot within the Nextcloud system, while the TALK scope permits access to Talk's endpoints. diff --git a/docs/conf.py b/docs/conf.py index dba6754d..59c9153a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -67,6 +67,7 @@ nitpick_ignore_regex = [ (r"py:class", r"starlette\.requests\.Request"), (r"py:class", r"starlette\.requests\.HTTPConnection"), + (r"py:class", r"ComputedFieldInfo"), (r"py:.*", r"httpx.*"), ] diff --git a/examples/as_app/skeleton/Makefile b/examples/as_app/skeleton/Makefile index b7dfa358..75c72188 100644 --- a/examples/as_app/skeleton/Makefile +++ b/examples/as_app/skeleton/Makefile @@ -69,19 +69,19 @@ run: register27: docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister skeleton --silent --force || true docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register skeleton manual_install --json-info \ - "{\"appid\":\"skeleton\",\"name\":\"App Skeleton\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9030,\"scopes\":{\"required\":[],\"optional\":[]},\"system_app\":0}" \ + "{\"appid\":\"skeleton\",\"name\":\"App Skeleton\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9030,\"scopes\":[],\"system_app\":0}" \ --force-scopes --wait-finish .PHONY: register28 register28: docker exec master-stable28-1 sudo -u www-data php occ app_api:app:unregister skeleton --silent --force || true docker exec master-stable28-1 sudo -u www-data php occ app_api:app:register skeleton manual_install --json-info \ - "{\"appid\":\"skeleton\",\"name\":\"App Skeleton\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9030,\"scopes\":{\"required\":[],\"optional\":[]},\"system_app\":0}" \ + "{\"appid\":\"skeleton\",\"name\":\"App Skeleton\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9030,\"scopes\":[],\"system_app\":0}" \ --force-scopes --wait-finish .PHONY: register register: docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister skeleton --silent --force || true docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register skeleton manual_install --json-info \ - "{\"appid\":\"skeleton\",\"name\":\"App Skeleton\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9030,\"scopes\":{\"required\":[],\"optional\":[]},\"system_app\":0}" \ + "{\"appid\":\"skeleton\",\"name\":\"App Skeleton\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9030,\"scopes\":[],\"system_app\":0}" \ --force-scopes --wait-finish diff --git a/examples/as_app/skeleton/appinfo/info.xml b/examples/as_app/skeleton/appinfo/info.xml index 9b503aaf..588187d2 100644 --- a/examples/as_app/skeleton/appinfo/info.xml +++ b/examples/as_app/skeleton/appinfo/info.xml @@ -16,7 +16,7 @@ https://github.com/cloud-py-api/nc_py_api/issues https://github.com/cloud-py-api/nc_py_api - + @@ -25,10 +25,6 @@ latest - - - - false diff --git a/examples/as_app/talk_bot/Makefile b/examples/as_app/talk_bot/Makefile index 511c606f..25d32dcb 100644 --- a/examples/as_app/talk_bot/Makefile +++ b/examples/as_app/talk_bot/Makefile @@ -54,12 +54,12 @@ run27: register: docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister talk_bot --silent --force || true docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register talk_bot manual_install --json-info \ - "{\"appid\":\"talk_bot\",\"name\":\"TalkBot\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9032,\"scopes\":{\"required\":[\"TALK\", \"TALK_BOT\"],\"optional\":[]},\"system_app\":0}" \ + "{\"appid\":\"talk_bot\",\"name\":\"TalkBot\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9032,\"scopes\":[\"TALK\", \"TALK_BOT\"],\"system_app\":0}" \ --force-scopes --wait-finish .PHONY: register27 register27: docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister talk_bot --force || true docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register talk_bot manual_install --json-info \ - "{\"appid\":\"talk_bot\",\"name\":\"TalkBot\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9032,\"scopes\":{\"required\":[\"TALK\", \"TALK_BOT\"],\"optional\":[]},\"system_app\":0}" \ + "{\"appid\":\"talk_bot\",\"name\":\"TalkBot\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9032,\"scopes\":[\"TALK\", \"TALK_BOT\"],\"system_app\":0}" \ --force-scopes --wait-finish diff --git a/examples/as_app/talk_bot/appinfo/info.xml b/examples/as_app/talk_bot/appinfo/info.xml index dd92abe7..5be16f43 100644 --- a/examples/as_app/talk_bot/appinfo/info.xml +++ b/examples/as_app/talk_bot/appinfo/info.xml @@ -25,12 +25,8 @@ latest - - TALK - TALK_BOT - - - + TALK + TALK_BOT false diff --git a/examples/as_app/talk_bot_ai/Makefile b/examples/as_app/talk_bot_ai/Makefile index f5991fdd..ca412f75 100644 --- a/examples/as_app/talk_bot_ai/Makefile +++ b/examples/as_app/talk_bot_ai/Makefile @@ -54,12 +54,12 @@ run27: register: docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister talk_bot_ai --silent --force || true docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register talk_bot_ai manual_install --json-info \ - "{\"appid\":\"talk_bot_ai\",\"name\":\"TalkBotAI\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9034,\"scopes\":{\"required\":[\"TALK\", \"TALK_BOT\"],\"optional\":[]},\"system_app\":0}" \ + "{\"appid\":\"talk_bot_ai\",\"name\":\"TalkBotAI\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9034,\"scopes\":[\"TALK\", \"TALK_BOT\"],\"system_app\":0}" \ --force-scopes --wait-finish .PHONY: register27 register27: docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister talk_bot_ai --silent --force || true docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register talk_bot_ai manual_install --json-info \ - "{\"appid\":\"talk_bot_ai\",\"name\":\"TalkBotAI\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9034,\"scopes\":{\"required\":[\"TALK\", \"TALK_BOT\"],\"optional\":[]},\"system_app\":0}" \ + "{\"appid\":\"talk_bot_ai\",\"name\":\"TalkBotAI\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9034,\"scopes\":[\"TALK\", \"TALK_BOT\"],\"system_app\":0}" \ --force-scopes --wait-finish diff --git a/examples/as_app/talk_bot_ai/appinfo/info.xml b/examples/as_app/talk_bot_ai/appinfo/info.xml index a613bac2..09756194 100644 --- a/examples/as_app/talk_bot_ai/appinfo/info.xml +++ b/examples/as_app/talk_bot_ai/appinfo/info.xml @@ -25,12 +25,8 @@ latest - - TALK - TALK_BOT - - - + TALK + TALK_BOT false diff --git a/examples/as_app/to_gif/Makefile b/examples/as_app/to_gif/Makefile index aee1f4c6..8ed9a46d 100644 --- a/examples/as_app/to_gif/Makefile +++ b/examples/as_app/to_gif/Makefile @@ -69,19 +69,19 @@ run: register27: docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister to_gif --silent --force || true docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register to_gif manual_install --json-info \ - "{\"appid\":\"to_gif\",\"name\":\"to_gif\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9031,\"scopes\":{\"required\":[\"FILES\", \"NOTIFICATIONS\"],\"optional\":[]},\"system_app\":0}" \ + "{\"appid\":\"to_gif\",\"name\":\"to_gif\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9031,\"scopes\":[\"FILES\", \"NOTIFICATIONS\"],\"system_app\":0}" \ --force-scopes --wait-finish .PHONY: register28 register28: docker exec master-stable28-1 sudo -u www-data php occ app_api:app:unregister to_gif --silent --force || true docker exec master-stable28-1 sudo -u www-data php occ app_api:app:register to_gif manual_install --json-info \ - "{\"appid\":\"to_gif\",\"name\":\"to_gif\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9031,\"scopes\":{\"required\":[\"FILES\", \"NOTIFICATIONS\"],\"optional\":[]},\"system_app\":0}" \ + "{\"appid\":\"to_gif\",\"name\":\"to_gif\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9031,\"scopes\":[\"FILES\", \"NOTIFICATIONS\"],\"system_app\":0}" \ --force-scopes --wait-finish .PHONY: register register: docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister to_gif --silent --force || true docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register to_gif manual_install --json-info \ - "{\"appid\":\"to_gif\",\"name\":\"to_gif\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9031,\"scopes\":{\"required\":[\"FILES\", \"NOTIFICATIONS\"],\"optional\":[]},\"system_app\":0}" \ + "{\"appid\":\"to_gif\",\"name\":\"to_gif\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9031,\"scopes\":[\"FILES\", \"NOTIFICATIONS\"],\"system_app\":0}" \ --force-scopes --wait-finish diff --git a/examples/as_app/to_gif/appinfo/info.xml b/examples/as_app/to_gif/appinfo/info.xml index 850eddc1..1c2bb1e6 100644 --- a/examples/as_app/to_gif/appinfo/info.xml +++ b/examples/as_app/to_gif/appinfo/info.xml @@ -25,12 +25,8 @@ latest - - FILES - NOTIFICATIONS - - - + FILES + NOTIFICATIONS false diff --git a/examples/as_app/ui_example/Makefile b/examples/as_app/ui_example/Makefile index a4aabc3e..a5bd9eee 100644 --- a/examples/as_app/ui_example/Makefile +++ b/examples/as_app/ui_example/Makefile @@ -69,19 +69,19 @@ run: register27: docker exec master-stable27-1 sudo -u www-data php occ app_api:app:unregister ui_example --silent --force || true docker exec master-stable27-1 sudo -u www-data php occ app_api:app:register ui_example manual_install --json-info \ - "{\"appid\":\"ui_example\",\"name\":\"UI Example\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9035,\"scopes\":{\"required\":[],\"optional\":[]},\"system_app\":0}" \ + "{\"appid\":\"ui_example\",\"name\":\"UI Example\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9035,\"scopes\":[],\"system_app\":0}" \ --force-scopes --wait-finish .PHONY: register28 register28: docker exec master-stable28-1 sudo -u www-data php occ app_api:app:unregister ui_example --silent --force || true docker exec master-stable28-1 sudo -u www-data php occ app_api:app:register ui_example manual_install --json-info \ - "{\"appid\":\"ui_example\",\"name\":\"UI Example\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9035,\"scopes\":{\"required\":[],\"optional\":[]},\"system_app\":0}" \ + "{\"appid\":\"ui_example\",\"name\":\"UI Example\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9035,\"scopes\":[],\"system_app\":0}" \ --force-scopes --wait-finish .PHONY: register register: docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:unregister ui_example --silent --force || true docker exec master-nextcloud-1 sudo -u www-data php occ app_api:app:register ui_example manual_install --json-info \ - "{\"appid\":\"ui_example\",\"name\":\"UI Example\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9035,\"scopes\":{\"required\":[],\"optional\":[]},\"system_app\":0}" \ + "{\"appid\":\"ui_example\",\"name\":\"UI Example\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"port\":9035,\"scopes\":[],\"system_app\":0}" \ --force-scopes --wait-finish diff --git a/examples/as_app/ui_example/appinfo/info.xml b/examples/as_app/ui_example/appinfo/info.xml index f3664398..5cf0d53b 100644 --- a/examples/as_app/ui_example/appinfo/info.xml +++ b/examples/as_app/ui_example/appinfo/info.xml @@ -25,10 +25,6 @@ latest - - - - false diff --git a/nc_py_api/_version.py b/nc_py_api/_version.py index 7a194cd9..d1dbca05 100644 --- a/nc_py_api/_version.py +++ b/nc_py_api/_version.py @@ -1,3 +1,3 @@ """Version of nc_py_api.""" -__version__ = "0.9.0" +__version__ = "0.10.0.dev0" diff --git a/nc_py_api/ex_app/defs.py b/nc_py_api/ex_app/defs.py index c65f4e86..be2e2cab 100644 --- a/nc_py_api/ex_app/defs.py +++ b/nc_py_api/ex_app/defs.py @@ -19,7 +19,7 @@ class LogLvl(enum.IntEnum): class ApiScope(enum.IntEnum): - """Default API scopes. Should be used as a parameter to the :py:meth:`~.NextcloudApp.scope_allowed` method.""" + """Defined API scopes.""" SYSTEM = 2 """Allows access to the System APIs.""" diff --git a/nc_py_api/nextcloud.py b/nc_py_api/nextcloud.py index ed35fd59..7560a5db 100644 --- a/nc_py_api/nextcloud.py +++ b/nc_py_api/nextcloud.py @@ -30,7 +30,7 @@ from .activity import _ActivityAPI, _AsyncActivityAPI from .apps import _AppsAPI, _AsyncAppsAPI from .calendar import _CalendarAPI -from .ex_app.defs import ApiScope, LogLvl +from .ex_app.defs import LogLvl from .ex_app.providers.providers import AsyncProvidersApi, ProvidersApi from .ex_app.ui.ui import AsyncUiApi, UiApi from .files.files import AsyncFilesAPI, FilesAPI @@ -330,15 +330,6 @@ def users_list(self) -> list[str]: """Returns list of users on the Nextcloud instance. **Available** only for ``System`` applications.""" return self._session.ocs("GET", f"{self._session.ae_url}/users") - def scope_allowed(self, scope: ApiScope) -> bool: - """Check if API scope is avalaible for application. - - Useful for applications that declare optional scopes to check if they are allowed. - """ - if self.check_capabilities("app_api"): - return False - return scope in self.capabilities["app_api"]["scopes"] - @property def user(self) -> str: """Property containing the current user ID. @@ -470,15 +461,6 @@ async def users_list(self) -> list[str]: """Returns list of users on the Nextcloud instance. **Available** only for ``System`` applications.""" return await self._session.ocs("GET", f"{self._session.ae_url}/users") - async def scope_allowed(self, scope: ApiScope) -> bool: - """Check if API scope is avalaible for application. - - Useful for applications that declare optional scopes to check if they are allowed. - """ - if await self.check_capabilities("app_api"): - return False - return scope in (await self.capabilities)["app_api"]["scopes"] - @property async def user(self) -> str: """Property containing the current user ID. diff --git a/scripts/ci_register.sh b/scripts/ci_register.sh index c307b7d4..f2e65a2b 100755 --- a/scripts/ci_register.sh +++ b/scripts/ci_register.sh @@ -5,5 +5,5 @@ php occ app_api:daemon:register manual_install "Manual Install" manual-install http "$4" 0 php occ app_api:app:register "$1" manual_install --json-info \ - "{\"appid\":\"$1\",\"name\":\"$1\",\"daemon_config_name\":\"manual_install\",\"version\":\"$2\",\"secret\":\"$3\",\"scopes\":{\"required\":[\"ALL\"],\"optional\":[]},\"port\":$5,\"system_app\":1}" \ + "{\"appid\":\"$1\",\"name\":\"$1\",\"daemon_config_name\":\"manual_install\",\"version\":\"$2\",\"secret\":\"$3\",\"scopes\":[\"ALL\"],\"port\":$5,\"system_app\":1}" \ --force-scopes --wait-finish diff --git a/scripts/dev_register.sh b/scripts/dev_register.sh index 40f74822..cdf2be1a 100644 --- a/scripts/dev_register.sh +++ b/scripts/dev_register.sh @@ -7,6 +7,6 @@ echo "unregistering nc_py_api as an app for $1 container" docker exec "$1" sudo -u www-data php occ app_api:app:unregister nc_py_api --silent --force || true echo "registering nc_py_api as an app for $1 container" docker exec "$1" sudo -u www-data php occ app_api:app:register nc_py_api manual_install --json-info \ - "{\"appid\":\"nc_py_api\",\"name\":\"nc_py_api\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"scopes\":{\"required\":[\"ALL\"],\"optional\":[]},\"port\":9009,\"system_app\":1}" \ + "{\"appid\":\"nc_py_api\",\"name\":\"nc_py_api\",\"daemon_config_name\":\"manual_install\",\"version\":\"1.0.0\",\"secret\":\"12345\",\"scopes\":[\"ALL\"],\"port\":9009,\"system_app\":1}" \ --force-scopes --wait-finish echo "nc_py_api for $1 is ready to use" diff --git a/tests/actual_tests/nc_app_test.py b/tests/actual_tests/nc_app_test.py index b54f7bb3..10c1295b 100644 --- a/tests/actual_tests/nc_app_test.py +++ b/tests/actual_tests/nc_app_test.py @@ -3,7 +3,7 @@ import pytest -from nc_py_api.ex_app import ApiScope, set_handlers +from nc_py_api.ex_app import set_handlers def test_get_users_list(nc_app): @@ -19,27 +19,6 @@ async def test_get_users_list_async(anc_app): assert await anc_app.user in users -def test_scope_allowed(nc_app): - for i in ApiScope: - if i == ApiScope.ALL.value: - assert nc_app.scope_allowed(i) - else: - assert not nc_app.scope_allowed(i) - assert not nc_app.scope_allowed(0) # noqa - assert not nc_app.scope_allowed(999999999) # noqa - - -@pytest.mark.asyncio(scope="session") -async def test_scope_allowed_async(anc_app): - for i in ApiScope: - if i == ApiScope.ALL.value: - assert await anc_app.scope_allowed(i) - else: - assert not await anc_app.scope_allowed(i) - assert not await anc_app.scope_allowed(0) # noqa - assert not await anc_app.scope_allowed(999999999) # noqa - - def test_app_cfg(nc_app): app_cfg = nc_app.app_cfg assert app_cfg.app_name == environ["APP_ID"] @@ -55,31 +34,6 @@ async def test_app_cfg_async(anc_app): assert app_cfg.app_secret == environ["APP_SECRET"] -def test_scope_allow_app_ecosystem_disabled(nc_client, nc_app): - assert nc_app.scope_allowed(ApiScope.ALL) - nc_client.apps.disable("app_api") - try: - assert nc_app.scope_allowed(ApiScope.ALL) - nc_app.update_server_info() - assert not nc_app.scope_allowed(ApiScope.ALL) - finally: - nc_client.apps.enable("app_api") - nc_app.update_server_info() - - -@pytest.mark.asyncio(scope="session") -async def test_scope_allow_app_ecosystem_disabled_async(anc_client, anc_app): - assert await anc_app.scope_allowed(ApiScope.ALL) - await anc_client.apps.disable("app_api") - try: - assert await anc_app.scope_allowed(ApiScope.ALL) - await anc_app.update_server_info() - assert not await anc_app.scope_allowed(ApiScope.ALL) - finally: - await anc_client.apps.enable("app_api") - await anc_app.update_server_info() - - def test_change_user(nc_app): orig_user = nc_app.user try: