Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

appapi-2.0.3-api-scopes #216

Merged
merged 1 commit into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions docs/NextcloudApp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,8 @@ First of all, we modernize info.ixml, add the API groups we need for this to wor
.. code-block:: xml

<scopes>
<required>
<value>FILES</value>
<value>NOTIFICATIONS</value>
</required>
<optional>
</optional>
<value>FILES</value>
<value>NOTIFICATIONS</value>
</scopes>

.. note:: Full list of avalaible API scopes can be found `here <https://cloud-py-api.github.io/app_api/tech_details/ApiScopes.html>`_.
Expand Down
8 changes: 2 additions & 6 deletions docs/NextcloudTalkBot.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,8 @@ The first step is to add the **TALK_BOT** and **TALK** scopes to your `info.xml`
.. code-block:: xml

<scopes>
<required>
<value>TALK</value>
<value>TALK_BOT</value>
</required>
<optional>
</optional>
<value>TALK</value>
<value>TALK_BOT</value>
</scopes>

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.
Expand Down
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.*"),
]

Expand Down
6 changes: 3 additions & 3 deletions examples/as_app/skeleton/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
6 changes: 1 addition & 5 deletions examples/as_app/skeleton/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<bugs>https://github.com/cloud-py-api/nc_py_api/issues</bugs>
<repository type="git">https://github.com/cloud-py-api/nc_py_api</repository>
<dependencies>
<nextcloud min-version="27" max-version="29"/>
<nextcloud min-version="27" max-version="30"/>
</dependencies>
<external-app>
<docker-install>
Expand All @@ -25,10 +25,6 @@
<image-tag>latest</image-tag>
</docker-install>
<scopes>
<required>
</required>
<optional>
</optional>
</scopes>
<system>false</system>
</external-app>
Expand Down
4 changes: 2 additions & 2 deletions examples/as_app/talk_bot/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 2 additions & 6 deletions examples/as_app/talk_bot/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,8 @@
<image-tag>latest</image-tag>
</docker-install>
<scopes>
<required>
<value>TALK</value>
<value>TALK_BOT</value>
</required>
<optional>
</optional>
<value>TALK</value>
<value>TALK_BOT</value>
</scopes>
<system>false</system>
</external-app>
Expand Down
4 changes: 2 additions & 2 deletions examples/as_app/talk_bot_ai/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 2 additions & 6 deletions examples/as_app/talk_bot_ai/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,8 @@
<image-tag>latest</image-tag>
</docker-install>
<scopes>
<required>
<value>TALK</value>
<value>TALK_BOT</value>
</required>
<optional>
</optional>
<value>TALK</value>
<value>TALK_BOT</value>
</scopes>
<system>false</system>
</external-app>
Expand Down
6 changes: 3 additions & 3 deletions examples/as_app/to_gif/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 2 additions & 6 deletions examples/as_app/to_gif/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,8 @@
<image-tag>latest</image-tag>
</docker-install>
<scopes>
<required>
<value>FILES</value>
<value>NOTIFICATIONS</value>
</required>
<optional>
</optional>
<value>FILES</value>
<value>NOTIFICATIONS</value>
</scopes>
<system>false</system>
</external-app>
Expand Down
6 changes: 3 additions & 3 deletions examples/as_app/ui_example/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 0 additions & 4 deletions examples/as_app/ui_example/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@
<image-tag>latest</image-tag>
</docker-install>
<scopes>
<required>
</required>
<optional>
</optional>
</scopes>
<system>false</system>
</external-app>
Expand Down
2 changes: 1 addition & 1 deletion nc_py_api/_version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Version of nc_py_api."""

__version__ = "0.9.0"
__version__ = "0.10.0.dev0"
2 changes: 1 addition & 1 deletion nc_py_api/ex_app/defs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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."""
Expand Down
20 changes: 1 addition & 19 deletions nc_py_api/nextcloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion scripts/ci_register.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion scripts/dev_register.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
48 changes: 1 addition & 47 deletions tests/actual_tests/nc_app_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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"]
Expand All @@ -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:
Expand Down
Loading