diff --git a/gui/src/components/uploads/EditMembersDialog.js b/gui/src/components/uploads/EditMembersDialog.js index 7440007e19aec2139efc23c83302aebd6e755b53..43f40efc8598bdf4e25e0618befb145a12f20b49 100644 --- a/gui/src/components/uploads/EditMembersDialog.js +++ b/gui/src/components/uploads/EditMembersDialog.js @@ -454,7 +454,7 @@ function EditMembersDialog({...props}) { </DialogContentText> <Tooltip title="If checked, the upload can be viewed before publication even by unregistered users."> <FormControlLabel - label="Visible for all" + label="Publicly visible" control={ <Checkbox checked={isVisibleForAll} onChange={handleIsVisibleForAll} /> } diff --git a/gui/src/components/uploads/EditMembersDialog.spec.js b/gui/src/components/uploads/EditMembersDialog.spec.js index 6565b53024f644790fa82e21dbaab2fef269acf2..eb07e0090bcf0ba27850f6cd9ddf85e74deb54be 100644 --- a/gui/src/components/uploads/EditMembersDialog.spec.js +++ b/gui/src/components/uploads/EditMembersDialog.spec.js @@ -248,7 +248,7 @@ test('Toggle visible for all checkbox', async () => { render(<UploadPage uploadId='dft_upload'/>) let dialog = await openMembersDialog() - let checkbox = await within(dialog).findByRoleAndText('checkbox', 'Visible for all') + let checkbox = await within(dialog).findByRoleAndText('checkbox', 'Publicly visible') expect(checkbox.checked).toEqual(false) fireEvent.click(checkbox) expect(checkbox.checked).toEqual(true) @@ -256,7 +256,7 @@ test('Toggle visible for all checkbox', async () => { await waitForGUI(2000, true) dialog = await openMembersDialog() - checkbox = await within(dialog).findByRoleAndText('checkbox', 'Visible for all') + checkbox = await within(dialog).findByRoleAndText('checkbox', 'Publicly visible') expect(checkbox.checked).toEqual(true) fireEvent.click(checkbox) expect(checkbox.checked).toEqual(false) @@ -264,7 +264,7 @@ test('Toggle visible for all checkbox', async () => { await waitForGUI(2000, true) dialog = await openMembersDialog() - checkbox = await within(dialog).findByRoleAndText('checkbox', 'Visible for all') + checkbox = await within(dialog).findByRoleAndText('checkbox', 'Publicly visible') expect(checkbox.checked).toEqual(false) closeAPI() diff --git a/nomad/app/v1/routers/uploads.py b/nomad/app/v1/routers/uploads.py index dae2381bf3579c46a76389e41d1e7c05020068f1..595ef7cfc762bc9ae75c3926ca18090727b54f0b 100644 --- a/nomad/app/v1/routers/uploads.py +++ b/nomad/app/v1/routers/uploads.py @@ -718,6 +718,10 @@ async def get_uploads( None, description='Only return uploads where the user has one of the given roles.', ), + include_all: bool = FastApiQuery( + False, + description='Include uploads that are shared with all users.', + ), query: UploadProcDataQuery = Depends(upload_proc_data_query_parameters), pagination: UploadProcDataPagination = Depends( upload_proc_data_pagination_parameters @@ -729,7 +733,7 @@ async def get_uploads( """ # Build query mongo_query = Q() - mongo_query &= get_role_query(roles, user) + mongo_query &= get_role_query(roles, user, include_all=include_all) if query.upload_id: mongo_query &= Q(upload_id__in=query.upload_id) @@ -2635,14 +2639,14 @@ def _query_mongodb(**kwargs): return Upload.objects(**kwargs) -def get_role_query(roles: List[UploadRole], user: User) -> Q: +def get_role_query(roles: List[UploadRole], user: User, include_all=False) -> Q: """ Create MongoDB filter query for user with given roles (default: all roles) """ if not roles: roles = list(UploadRole) - group_ids = get_group_ids(user.user_id) + group_ids = get_group_ids(user.user_id, include_all=include_all) role_query = Q() if UploadRole.main_author in roles: diff --git a/nomad/groups.py b/nomad/groups.py index 66ef9c08ce24a12c57180e1beda45ba02d118713..99a2085d2bfb42a9c671a7986f6c934c9c0d77c8 100644 --- a/nomad/groups.py +++ b/nomad/groups.py @@ -48,12 +48,12 @@ class UserGroup(Document): return user_groups @classmethod - def get_ids_by_user_id(cls, user_id: Optional[str]) -> List[str]: + def get_ids_by_user_id(cls, user_id: Optional[str], include_all=True) -> List[str]: """ Returns ids of all user groups where user_id is owner or member. Does include special group 'all', even if user_id is missing or not a user. """ - group_ids = ['all'] + group_ids = ['all'] if include_all else [] if user_id is not None: group_ids.extend(group.group_id for group in cls.get_by_user_id(user_id)) return group_ids @@ -99,5 +99,5 @@ def user_group_exists(group_id: str, *, include_all=True) -> bool: return get_user_group(group_id) is not None -def get_group_ids(user_id): - return UserGroup.get_ids_by_user_id(user_id) +def get_group_ids(user_id, include_all=True): + return UserGroup.get_ids_by_user_id(user_id, include_all=include_all) diff --git a/ops/kubernetes/nomad/values.yaml b/ops/kubernetes/nomad/values.yaml index ef04f09902890b6dc6f26020856ca9867e285c4c..33955dbdfcf0fb45db2a4357c11dbe92e89858ca 100644 --- a/ops/kubernetes/nomad/values.yaml +++ b/ops/kubernetes/nomad/values.yaml @@ -477,6 +477,7 @@ jupyterhub: # Workaround for webtop based images (no connection to jupyterhub itself) if tool.get('privileged'): spawner.privileged = True + spawner.allow_privilege_escalation = True spawner.uid = 0 c.Spawner.pre_spawn_hook = pre_spawn_hook diff --git a/pyproject.toml b/pyproject.toml index ce34cebb61826b94e3dbb09f6ad443f8a412dac3..d57fbcbe43586ed000581140d8c17a89de2f0e0c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -45,7 +45,7 @@ dependencies = [ 'python-magic==0.4.24', 'pytz>=2022.7.1', 'pyyaml>=6.0', - 'requests>=2.27.1', + 'requests>=2.27.1,<2.32.0', 'rfc3161ng>=2.1.3', 'scikit-learn>=1.0.2', 'scipy>=1.7.1', diff --git a/requirements-dev.txt b/requirements-dev.txt index c2915e9e7a7c5f48fb8685553d41fcb5e1324cec..e9841e78c294d82ef783f41e389717e4441425f5 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -306,7 +306,7 @@ rdkit==2023.9.5 # via -r requirements.txt, nomad-lab (pyproject.toml) readme-renderer==43.0 # via twine recommonmark==0.7.1 # via -r requirements.txt, nomad-lab (pyproject.toml) regex==2024.5.15 # via mkdocs-material -requests==2.32.2 # via docker, hyperspy, jupyterhub, jupyterlab-server, mkdocs-material, oauthenticator, optimade, pooch, pybis, pymatgen, python-gitlab, python-keycloak, requests-toolbelt, rfc3161ng, sphinx, twine, -r requirements.txt, nomad-lab (pyproject.toml) +requests==2.31.0 # via docker, hyperspy, jupyterhub, jupyterlab-server, mkdocs-material, oauthenticator, optimade, pooch, pybis, pymatgen, python-gitlab, python-keycloak, requests-toolbelt, rfc3161ng, sphinx, twine, -r requirements.txt, nomad-lab (pyproject.toml) requests-toolbelt==1.0.0 # via python-gitlab, python-keycloak, twine, -r requirements.txt rfc3161ng==2.1.3 # via -r requirements.txt, nomad-lab (pyproject.toml) rfc3339-validator==0.1.4 # via jsonschema, -r requirements.txt diff --git a/tests/app/v1/routers/uploads/test_group_uploads.py b/tests/app/v1/routers/uploads/test_group_uploads.py index 9bdb5a2968ba85ab726429ad872a76bc6611312c..1c407a0ed3c1e360e4446bc02ce1b083880da502 100644 --- a/tests/app/v1/routers/uploads/test_group_uploads.py +++ b/tests/app/v1/routers/uploads/test_group_uploads.py @@ -25,7 +25,6 @@ def get_agents_from_upload(upload): 'id_RGg2', 'id_CGg123', 'id_RGg123', - 'id_RGall', ], 200, id='no-args', @@ -43,11 +42,21 @@ def get_agents_from_upload(upload): [ 'id_RGg2', 'id_RGg123', - 'id_RGall', ], 200, id='reviewer', ), + pytest.param( + 'user2', + {'roles': 'reviewer', 'include_all': 'True'}, + [ + 'id_RGg2', + 'id_RGg123', + 'id_RGall', + ], + 200, + id='include-all', + ), ], ) def test_get_group_uploads(