Unverified Commit ca9bf294 authored by Nicola Soranzo's avatar Nicola Soranzo
Browse files

Merge branch 'release_24.0' into release_24.1

parents c3b6cbfa 7fb43de9
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -88,13 +88,14 @@ inv.task('build')
    .using(conda_image)
        .withHostConfig({binds = bind_args})
        .run('/bin/sh', '-c', preinstall
            .. conda_bin .. ' create --quiet --yes -p /usr/local/env --copy  && '
            .. conda_bin .. ' install '
            .. channel_args .. ' '
            .. target_args
            .. ' --strict-channel-priority -p /usr/local --copy --yes '
            .. ' --strict-channel-priority -p /usr/local/env --copy --yes '
            .. verbose
            .. postinstall)
    .wrap('build/dist')
    .wrap('build/dist/env')
        .at('/usr/local')
        .inImage(destination_base_image)
        .as(repo)
+14 −2
Original line number Diff line number Diff line
@@ -5,6 +5,10 @@ import json
import logging
import sys
import tempfile
from typing import (
    Dict,
    List,
)

from galaxy.tool_util.deps.conda_util import CondaContext
from galaxy.util import (
@@ -122,7 +126,7 @@ class CondaSearch:
    def __init__(self, channel):
        self.channel = channel

    def get_json(self, search_string):
    def get_json(self, search_string) -> List[Dict[str, str]]:
        """
        Function takes search_string variable and returns results from the bioconda channel in JSON format

@@ -135,8 +139,16 @@ class CondaSearch:
        except Exception as e:
            logging.info(f"Search failed with: {e}")
            return []
        header_found = False
        lines_fields: List[List[str]] = []
        for line in raw_out.splitlines():
            if line.startswith("#"):
                header_found = True
            elif header_found:
                lines_fields.append(line.split())
        return [
            {"package": n.split()[0], "version": n.split()[1], "build": n.split()[2]} for n in raw_out.split("\n")[2:-1]
            {"package": line_fields[0], "version": line_fields[1], "build": line_fields[2]}
            for line_fields in lines_fields
        ]


+12 −2
Original line number Diff line number Diff line
@@ -979,6 +979,7 @@ class UserAPIController(BaseGalaxyAPIController, UsesTagsMixin, BaseUIController
        extra_user_pref_data = {}
        extra_pref_keys = self._get_extra_user_preferences(trans)
        user_vault = UserVaultWrapper(trans.app.vault, user)
        current_extra_user_pref_data = json.loads(user.preferences.get("extra_user_preferences", "{}"))
        if extra_pref_keys is not None:
            for key in extra_pref_keys:
                key_prefix = f"{key}|"
@@ -991,8 +992,17 @@ class UserAPIController(BaseGalaxyAPIController, UsesTagsMixin, BaseUIController
                            input = matching_input[0]
                            if input.get("required") and payload[item] == "":
                                raise exceptions.ObjectAttributeMissingException("Please fill the required field")
                            if not (input.get("type") == "secret" and payload[item] == "__SECRET_PLACEHOLDER__"):
                                if input.get("store") == "vault":
                            input_type = input.get("type")
                            is_secret_value_unchanged = (
                                input_type == "secret" and payload[item] == "__SECRET_PLACEHOLDER__"
                            )
                            is_stored_in_vault = input.get("store") == "vault"
                            if is_secret_value_unchanged:
                                if not is_stored_in_vault:
                                    # If the value is unchanged, keep the current value
                                    extra_user_pref_data[item] = current_extra_user_pref_data.get(item, "")
                            else:
                                if is_stored_in_vault:
                                    user_vault.write_secret(f"preferences/{keys[0]}/{keys[1]}", str(payload[item]))
                                else:
                                    extra_user_pref_data[item] = payload[item]
+83 −0
Original line number Diff line number Diff line
@@ -129,6 +129,89 @@ class TestExtraUserPreferences(integration_util.IntegrationTestCase, integration
            == "an_updated_secret_value"
        )

    def test_extra_prefs_secret_not_in_vault(self):
        user = self._setup_user(TEST_USER_EMAIL)
        url = self.__url("information/inputs", user)
        app = cast(Any, self._test_driver.app if self._test_driver else None)
        db_user = self._get_dbuser(app, user)

        # create some initial data
        put(
            url,
            data=json.dumps(
                {
                    "non_vault_test_section|user": "test_user",
                    "non_vault_test_section|pass": "test_pass",
                }
            ),
        )

        # retrieve saved data
        response = get(url).json()

        def get_input_by_name(inputs, name):
            return [input for input in inputs if input["name"] == name][0]

        inputs = [section for section in response["inputs"] if section["name"] == "non_vault_test_section"][0]["inputs"]

        # value should be what we saved
        input_user = get_input_by_name(inputs, "user")
        assert input_user["value"] == "test_user"

        # the secret should not be stored in the vault
        assert app.vault.read_secret(f"user/{db_user.id}/preferences/non_vault_test_section/pass") is None
        # it should be in the user preferences model
        app.model.session.refresh(db_user)
        assert db_user.extra_preferences["non_vault_test_section|pass"] == "test_pass"

        # secret type values should not be retrievable by the client
        input_pass = get_input_by_name(inputs, "pass")
        assert input_pass["value"] != "test_pass"
        assert input_pass["value"] == "__SECRET_PLACEHOLDER__"

        # changing the text property value should not change the secret property value
        put(
            url,
            data=json.dumps(
                {
                    "non_vault_test_section|user": "a_new_test_user",
                    "non_vault_test_section|pass": "__SECRET_PLACEHOLDER__",
                }
            ),
        )

        response = get(url).json()
        inputs = [section for section in response["inputs"] if section["name"] == "non_vault_test_section"][0]["inputs"]
        input_user = get_input_by_name(inputs, "user")
        assert input_user["value"] == "a_new_test_user"
        # the secret value is not exposed to the client
        input_pass = get_input_by_name(inputs, "pass")
        assert input_pass["value"] == "__SECRET_PLACEHOLDER__"

        # The secret value should not have changed in the internal user preferences model
        app.model.session.refresh(db_user)
        assert db_user.extra_preferences["non_vault_test_section|pass"] == "test_pass"

        # changing the secret value should update the secret value
        put(
            url,
            data=json.dumps(
                {
                    "non_vault_test_section|user": "a_new_test_user",
                    "non_vault_test_section|pass": "a_new_test_pass",
                }
            ),
        )

        response = get(url).json()
        inputs = [section for section in response["inputs"] if section["name"] == "non_vault_test_section"][0]["inputs"]
        input_pass = get_input_by_name(inputs, "pass")
        assert input_pass["value"] == "__SECRET_PLACEHOLDER__"

        # the secret value should be updated in the internal user preferences model
        app.model.session.refresh(db_user)
        assert db_user.extra_preferences["non_vault_test_section|pass"] == "a_new_test_pass"

    def __url(self, action, user):
        return self._api_url(f"users/{user['id']}/{action}", params=dict(key=self.master_api_key))

+12 −0
Original line number Diff line number Diff line
@@ -21,3 +21,15 @@ preferences:
              type: secret
              store: vault
              required: True

    non_vault_test_section:
        description: For testing Settings
        inputs:
            - name: user
              label: User
              type: text
              required: True
            - name: pass
              label: Pass
              type: secret # It's a secret but not stored in vault
              required: True
Loading