Skip to content

Commit

Permalink
On PATCH Workspace Layer/Map update role names to DB
Browse files Browse the repository at this point in the history
  • Loading branch information
index-git committed Nov 29, 2023
1 parent a03b803 commit ef6646e
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 13 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
- [#165](https://github.com/LayerManager/layman/issues/165) Add column `role_name` to table `rights` in prime DB schema. Add constraint that exactly one of columns `role_name` and `id_user` is not null.
#### Data migrations
### Changes
- [#165](https://github.com/LayerManager/layman/issues/165) POST Workspace [Layers](doc/rest.md#post-workspace-layers)/[Maps](doc/rest.md#post-workspace-maps) saves [role names](doc/models.md#role) mentioned in `access_rights.read` and `access_rights.write` parameters into DB.
- [#165](https://github.com/LayerManager/layman/issues/165) POST Workspace [Layers](doc/rest.md#post-workspace-layers)/[Maps](doc/rest.md#post-workspace-maps) and PATCH Workspace [Layer](doc/rest.md#patch-workspace-layer)/[Map](doc/rest.md#patch-workspace-map) saves [role names](doc/models.md#role) mentioned in `access_rights.read` and `access_rights.write` parameters into DB.
- [#165](https://github.com/LayerManager/layman/issues/165) Many endpoints return previously associated [role names](doc/models.md#role) in `access_rights.read` and `access_rights.write` keys:
- [GET](doc/rest.md#get-workspace-layer)/[PATCH](doc/rest.md#patch-workspace-layer) Workspace Layer
- [GET](doc/rest.md#get-workspace-map)/[PATCH](doc/rest.md#patch-workspace-map) Workspace Map
Expand Down
2 changes: 1 addition & 1 deletion doc/about.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Layman supports two main models of geospatial data: layers and maps. **Layer** i
There are multiple client applications for communication with Layman through its REST API: simple web test client shipped with Layman, QGIS desktop client, and HSLayers library. Published data are accessible through standardized OGC APIs: Web Map Service, Web Feature Service, and Catalogue Service.

### Security
Layman`s security system uses two well-known concepts: authentication and authorization. Common configuration consists of authentication based on widely used OAuth2 protocol and authorization allows users to give read and write access rights to each user on publication level.
Layman`s security system uses two well-known concepts: authentication and authorization. Common configuration consists of authentication based on widely used OAuth2 protocol and authorization allows users to give read and write access rights to users and roles on publication level.

### Scalability
Large data files can be easily published thanks to chunk upload. Asynchronous processing ensures fast communication with REST API. Processing tasks can be distributed on multiple servers. Layman also stands on the shoulders of widely used programs like Flask, PostgreSQL, PostGIS, GDAL, GeoServer, QGIS Server, Celery, and Redis.
20 changes: 12 additions & 8 deletions src/layman/common/prime_db_schema/publications.py
Original file line number Diff line number Diff line change
Expand Up @@ -495,8 +495,10 @@ def update_publication(workspace_name, info):
for right_type in right_type_list:
access_rights_changes[right_type] = {
'EVERYONE': None,
'add': set(),
'remove': set(),
'add_users': set(),
'add_roles': set(),
'remove_users': set(),
'remove_roles': set(),
}

external_table_uri = psycopg2.extras.Json({
Expand All @@ -521,10 +523,12 @@ def update_publication(workspace_name, info):
if info['access_rights'].get(right_type):
usernames_list = info["access_rights"].get(right_type)
access_rights_changes[right_type]['EVERYONE'] = ROLE_EVERYONE in usernames_list
usernames_list_clear = get_user_and_role_names_for_db(usernames_list, workspace_name)[0]
usernames_old_list_clear = get_user_and_role_names_for_db(access_rights_changes[right_type]['username_list_old'], workspace_name)[0]
access_rights_changes[right_type]['add'] = usernames_list_clear.difference(usernames_old_list_clear)
access_rights_changes[right_type]['remove'] = usernames_old_list_clear.difference(usernames_list_clear)
usernames_list_clear, roles_list_clear = get_user_and_role_names_for_db(usernames_list, workspace_name)
usernames_old_list_clear, roles_old_list_clear = get_user_and_role_names_for_db(access_rights_changes[right_type]['username_list_old'], workspace_name)
access_rights_changes[right_type]['add_users'] = usernames_list_clear.difference(usernames_old_list_clear)
access_rights_changes[right_type]['add_roles'] = roles_list_clear.difference(roles_old_list_clear)
access_rights_changes[right_type]['remove_users'] = usernames_old_list_clear.difference(usernames_list_clear)
access_rights_changes[right_type]['remove_roles'] = roles_old_list_clear.difference(roles_list_clear)

update_publications_sql = f'''update {DB_SCHEMA}.publications set
title = coalesce(%s, title),
Expand Down Expand Up @@ -555,8 +559,8 @@ def update_publication(workspace_name, info):
pub_id = db_util.run_query(update_publications_sql, data)[0][0]

for right_type in right_type_list:
rights.insert_rights(pub_id, access_rights_changes[right_type]['add'], set(), right_type)
rights.remove_rights(pub_id, access_rights_changes[right_type]['remove'], right_type)
rights.insert_rights(pub_id, access_rights_changes[right_type]['add_users'], access_rights_changes[right_type]['add_roles'], right_type)
rights.remove_rights(pub_id, access_rights_changes[right_type]['remove_users'], access_rights_changes[right_type]['remove_roles'], right_type)

return pub_id

Expand Down
14 changes: 12 additions & 2 deletions src/layman/common/prime_db_schema/publications_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,8 @@ class TestUpdateRights:
workspace_name = 'test_update_rights_workspace'
username = 'test_update_rights_user'
username2 = 'test_update_rights_user2'
role1 = 'TEST_UPDATE_RIGHTS_ROLE1'
role2 = 'TEST_UPDATE_RIGHTS_ROLE2'

publication_name = 'test_update_rights_publication_name'
publication_type = MAP_TYPE
Expand All @@ -354,8 +356,8 @@ class TestUpdateRights:
"publ_type_name": publication_type,
"actor_name": username,
"uuid": uuid.uuid4(),
"access_rights": {"read": {settings.RIGHTS_EVERYONE_ROLE, },
"write": {settings.RIGHTS_EVERYONE_ROLE, },
"access_rights": {"read": {settings.RIGHTS_EVERYONE_ROLE, role1, },
"write": {settings.RIGHTS_EVERYONE_ROLE, role1, },
},
"image_mosaic": False,
}
Expand Down Expand Up @@ -416,6 +418,14 @@ def provide_data(self, request):
[username, settings.RIGHTS_EVERYONE_ROLE, ], [username, settings.RIGHTS_EVERYONE_ROLE, ],
id='personal_everyone_as_anonym',
),
pytest.param(
username,
{"access_rights": {"read": {username, role2, },
"write": {username, role2, }},
"actor_name": username},
[username, role2, ], [username, role2, ],
id='personal_owner_role',
),
])
def test_rights(self, username, publication_update_info, read_to_test, write_to_test, ):
publication_info_original = self.publication_insert_info
Expand Down
14 changes: 13 additions & 1 deletion src/layman/common/prime_db_schema/rights.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def delete_rights_for_publication(id_publication):
)


def remove_rights(id_publication, users_list, right_type):
def remove_rights(id_publication, users_list, roles_list, right_type):
sql = f'''delete from {DB_SCHEMA}.rights
where id_publication = %s
and type = %s
Expand All @@ -59,3 +59,15 @@ def remove_rights(id_publication, users_list, right_type):
username,
)
)

sql = f'''delete from {DB_SCHEMA}.rights
where id_publication = %s
and type = %s
and role_name = %s;'''
for role in roles_list:
db_util.run_statement(sql,
(id_publication,
right_type,
role,
)
)
1 change: 1 addition & 0 deletions tests/dynamic_data/publications/access_rights/test_role.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class TestPublication(base_test.TestSingleRestPublication):

rest_parametrization = [
PublicationTypes,
base_test_classes.RestMethod
]

usernames_to_reserve = [
Expand Down

0 comments on commit ef6646e

Please sign in to comment.