diff --git a/.env.demo b/.env.demo index 315bda697..50cb514e7 100644 --- a/.env.demo +++ b/.env.demo @@ -65,7 +65,7 @@ LAYMAN_CLIENT_URL=http://layman_client:3000/client/ # client LAYMAN_CLIENT_PUBLIC_URL=http://localhost/client/ -LAYMAN_CLIENT_VERSION=v1.17.2 +LAYMAN_CLIENT_VERSION=73a6d0b5d2138e62077d305d07b4992d020168c8 # extra hosts to be added to /etc/hosts EXTRA_HOST1=1.2.3.4:1.2.3.4 diff --git a/.env.dev b/.env.dev index f9518fe9f..5e8ba4cd1 100644 --- a/.env.dev +++ b/.env.dev @@ -65,7 +65,7 @@ LAYMAN_CLIENT_URL=http://layman_client:3000/client/ # client LAYMAN_CLIENT_PUBLIC_URL=http://localhost:3000/client/ -LAYMAN_CLIENT_VERSION=v1.17.2 +LAYMAN_CLIENT_VERSION=73a6d0b5d2138e62077d305d07b4992d020168c8 ############################################################################## diff --git a/.env.test b/.env.test index 9633a26d1..f70011069 100644 --- a/.env.test +++ b/.env.test @@ -65,7 +65,7 @@ LAYMAN_CLIENT_URL=http://layman_client_test:3000/client/ # client LAYMAN_CLIENT_PUBLIC_URL=http://layman_test_run_1:8000/client/ -LAYMAN_CLIENT_VERSION=v1.17.2 +LAYMAN_CLIENT_VERSION=73a6d0b5d2138e62077d305d07b4992d020168c8 ############################################################################## diff --git a/CHANGELOG.md b/CHANGELOG.md index ff48e44c7..05b9cb370 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ ### Upgrade requirements - Change environment variable [LAYMAN_CLIENT_VERSION](doc/env-settings.md#LAYMAN_CLIENT_VERSION): ``` - LAYMAN_CLIENT_VERSION=v1.17.2 + LAYMAN_CLIENT_VERSION=73a6d0b5d2138e62077d305d07b4992d020168c8 ``` It was already required in v1.22.3. - Set new environment variable [LAYMAN_ROLE_SERVICE_URI](doc/env-settings.md#LAYMAN_ROLE_SERVICE_URI) @@ -32,6 +32,7 @@ - [GET](doc/rest.md#get-workspace-map)/[PATCH](doc/rest.md#patch-workspace-map) Workspace Map - GET Workspace [Layers](doc/rest.md#get-workspace-layers)/[Maps](doc/rest.md#get-workspace-maps) - GET [Layers](doc/rest.md#get-layers)/[Maps](doc/rest.md#get-maps)/[Publications](doc/rest.md#get-publications) +- [#165](https://github.com/LayerManager/layman/issues/165) New REST endpoint [GET Roles](doc/rest.md#get-roles) with list of all roles registered in [JDBC Role Service](https://docs.geoserver.org/2.21.x/en/user/security/usergrouprole/roleservices.html#jdbc-role-service), that can be used in access rights. This new endpoint was added to Test Client into tab "Others". - All changes from [v1.22.1](#v1221), [v1.22.2](#v1222) and [v1.22.3](#v1223). - [#960](https://github.com/LayerManager/layman/issues/960) Handle WMS requests with HTTP error more efficiently in timgen. - [#962](https://github.com/LayerManager/layman/issues/962) Make values of `layman_metadata.publication_status` and `status` key(s) more consistent in responses of PATCH Workspace [Layer](doc/rest.md#patch-workspace-layer)/[Map](doc/rest.md#patch-workspace-map) and GET Workspace [Layer](doc/rest.md#get-workspace-layer)/[Map](doc/rest.md#get-workspace-map). diff --git a/doc/rest.md b/doc/rest.md index 0140498c9..e2ae51efb 100644 --- a/doc/rest.md +++ b/doc/rest.md @@ -19,6 +19,7 @@ |Workspace Map Metadata Comparison|`/rest/workspaces//layers//metadata-comparison`|[GET](#get-workspace-map-metadata-comparison) | x | x | x | |Users|`/rest/users`|[GET](#get-users)| x | x | x | |Current [User](models.md#user)|`/rest/current-user`|[GET](#get-current-user)| x | [PATCH](#patch-current-user) | [DELETE](#delete-current-user) | +|Roles|`/rest/roles`|[GET](#get-roles)| x | x | x | |Version|`/rest/about/version`|[GET](#get-version)| x | x | x | #### REST path parameters @@ -850,6 +851,21 @@ Content-Type: `application/json` HTTP status code 200 if credentials were deleted. +## Roles +### URL +`/rest/roles` + +### GET Roles +Get list of roles. + +#### Request. +No action parameters. + +#### Response +Content-Type: `application/json` + +JSON array of role names, where each role name is a `string`. + ## Version ### URL `/rest/about/version` diff --git a/src/layman/__init__.py b/src/layman/__init__.py index 9ebdbcf3c..beb6197e2 100644 --- a/src/layman/__init__.py +++ b/src/layman/__init__.py @@ -47,10 +47,12 @@ from .user.rest_current_user import bp as current_user_bp from .geoserver_proxy import bp as geoserver_proxy_bp from .user.rest_users import bp as users_bp +from .user.rest_roles import bp as roles_bp app.register_blueprint(current_user_bp, url_prefix='/rest/current-user') app.register_blueprint(geoserver_proxy_bp, url_prefix='/geoserver') app.register_blueprint(users_bp, url_prefix=f'/rest/{settings.REST_USERS_PREFIX}') +app.register_blueprint(roles_bp, url_prefix=f'/rest/{settings.REST_ROLES_PREFIX}') logger.info(f"IN_CELERY_WORKER_PROCESS={IN_CELERY_WORKER_PROCESS}") logger.info(f"IN_PYTEST_PROCESS={IN_PYTEST_PROCESS}") diff --git a/src/layman/authz/role_service.py b/src/layman/authz/role_service.py index b09f2a4ef..01780c51b 100644 --- a/src/layman/authz/role_service.py +++ b/src/layman/authz/role_service.py @@ -1,6 +1,10 @@ +import logging + from db import util as db_util from layman import settings +logger = logging.getLogger(__name__) + ROLE_NAME_PATTERN = r'^(?!.{65,})[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$' @@ -22,3 +26,15 @@ def get_existent_roles(roles_to_check): """ rows = db_util.run_query(query, (list(roles_to_check),), uri_str=settings.LAYMAN_ROLE_SERVICE_URI) return {row[0] for row in rows} + + +def get_all_roles(): + query = f""" + select name + from {settings.LAYMAN_ROLE_SERVICE_SCHEMA}.roles + where name not in (%s, %s, %s) + and LEFT(name, 5) != 'USER_' + and name ~ %s + """ + roles = db_util.run_query(query, ('ADMIN', 'GROUP_ADMIN', settings.LAYMAN_GS_ROLE, ROLE_NAME_PATTERN), uri_str=settings.LAYMAN_ROLE_SERVICE_URI) + return [role[0] for role in roles] + [settings.RIGHTS_EVERYONE_ROLE] diff --git a/src/layman/user/rest_roles.py b/src/layman/user/rest_roles.py new file mode 100644 index 000000000..46ce82639 --- /dev/null +++ b/src/layman/user/rest_roles.py @@ -0,0 +1,17 @@ +import logging +from flask import current_app as app, Blueprint, jsonify + +from layman.authz.role_service import get_all_roles + +logger = logging.getLogger(__name__) + +bp = Blueprint('rest_roles', __name__) + + +@bp.route('', methods=['GET']) +def get(): + app.logger.info(f"GET Roles") + + roles = get_all_roles() + + return jsonify(roles), 200 diff --git a/src/layman_settings.py b/src/layman_settings.py index 037e893aa..9d23a463e 100644 --- a/src/layman_settings.py +++ b/src/layman_settings.py @@ -268,6 +268,7 @@ class EnumWfsWmsStatus(Enum): micka.set_settings(DEFAULT_CONNECTION_TIMEOUT) REST_USERS_PREFIX = 'users' +REST_ROLES_PREFIX = 'roles' REST_WORKSPACES_PREFIX = 'workspaces' REST_PUBLICATIONS_PREFIX = 'publications' RESERVED_WORKSPACE_NAMES = {REST_USERS_PREFIX, REST_WORKSPACES_PREFIX} diff --git a/tests/dynamic_data/users_roles/__init__.py b/tests/dynamic_data/users_roles/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/dynamic_data/users_roles/test_roles.py b/tests/dynamic_data/users_roles/test_roles.py new file mode 100644 index 000000000..6bdc82d56 --- /dev/null +++ b/tests/dynamic_data/users_roles/test_roles.py @@ -0,0 +1,30 @@ +import requests +import pytest + +from layman import app, settings +from test_tools import role_service +from test_tools.util import url_for + + +@pytest.mark.usefixtures('ensure_layman') +def test_get_roles(): + rolename = 'TEST_GET_ROLES_ROLE' + + with app.app_context(): + # roles.GET + url = url_for('rest_roles.get') + assert url.endswith('/' + settings.REST_ROLES_PREFIX) + + # Without role + response = requests.get(url, timeout=settings.DEFAULT_CONNECTION_TIMEOUT) + assert response.status_code == 200, response.json() + assert response.json() == [settings.RIGHTS_EVERYONE_ROLE] + + # With role + with app.app_context(): + role_service.ensure_role(rolename) + response = requests.get(url, timeout=settings.DEFAULT_CONNECTION_TIMEOUT) + assert response.status_code == 200, response.json() + assert response.json() == [rolename, settings.RIGHTS_EVERYONE_ROLE] + + role_service.delete_role(rolename) diff --git a/src/layman/user/rest_users_test.py b/tests/dynamic_data/users_roles/test_users.py similarity index 100% rename from src/layman/user/rest_users_test.py rename to tests/dynamic_data/users_roles/test_users.py