diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 50443dc1adcbd814755730c8b2f5d93d390cd6dc..0ab6774c251d2aff99db97416b6407549f6b55d3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -439,60 +439,6 @@ test-dashboard-service: junit: ./dbrepo-dashboard-service/coverage.xml coverage: '/TOTAL.*?([0-9]{1,3})%/' -test-dashboard-service-init: - image: docker.io/python:${PYTHON_VERSION}-alpine${ALPINE_VERSION} - stage: test - only: - - merge_requests - - master - variables: - PIPENV_PIPFILE: "./dbrepo-dashboard-service/init/Pipfile" - needs: - - build-dashboard-service - dependencies: - - build-dashboard-service - script: - - "pip install pipenv" - - "pipenv install gunicorn && pipenv install --dev --system --deploy" - - cd ./dbrepo-dashboard-service/init/ && coverage run --rcfile=.coveragerc -m pytest tests/test_app.py && coverage html && coverage xml && coverage report > ./coverage.txt - - "cat ./coverage.txt | grep -o 'TOTAL[^%]*%'" - artifacts: - when: always - paths: - - ./dbrepo-dashboard-service/init/coverage.xml - - ./dbrepo-dashboard-service/init/coverage.txt - expire_in: 1 days - reports: - junit: ./dbrepo-dashboard-service/init/coverage.xml - coverage: '/TOTAL.*?([0-9]{1,3})%/' - -test-search-service-init: - image: docker.io/python:${PYTHON_VERSION}-alpine${ALPINE_VERSION} - stage: test - only: - - merge_requests - - master - variables: - PIPENV_PIPFILE: "./dbrepo-search-service/init/Pipfile" - needs: - - build-search-service - dependencies: - - build-search-service - script: - - "pip install pipenv" - - "pipenv install gunicorn && pipenv install --dev --system --deploy" - - cd ./dbrepo-search-service/init/ && coverage run --rcfile=.coveragerc -m pytest tests/test_unit_app.py && coverage html && coverage xml && coverage report > ./coverage.txt - - "cat ./coverage.txt | grep -o 'TOTAL[^%]*%'" - artifacts: - when: always - paths: - - ./dbrepo-search-service/coverage.xml - - ./dbrepo-search-service/coverage.txt - expire_in: 1 days - reports: - junit: ./dbrepo-search-service/coverage.xml - coverage: '/TOTAL.*?([0-9]{1,3})%/' - test-python-lib: image: docker.io/python:${PYTHON_VERSION}-alpine${ALPINE_VERSION} stage: test diff --git a/dbrepo-auth-service/listeners/target/create-event-listener.jar b/dbrepo-auth-service/listeners/target/create-event-listener.jar index 2a6b125340f46d51901a493f0ed050373730761a..e6ee56c50203b9ba4e75d7964141c3c353ff933d 100644 Binary files a/dbrepo-auth-service/listeners/target/create-event-listener.jar and b/dbrepo-auth-service/listeners/target/create-event-listener.jar differ diff --git a/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ac/at/ifs/dbrepo/config/MariaDbConfig.java b/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ac/at/ifs/dbrepo/config/MariaDbConfig.java index 9a9f827a27b1bce3ba8bcc06d23afdcc06e59866..af4f12dc84bce16f9f13f50447206b258c4ff6d8 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ac/at/ifs/dbrepo/config/MariaDbConfig.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ac/at/ifs/dbrepo/config/MariaDbConfig.java @@ -241,7 +241,7 @@ public class MariaDbConfig { log.trace("connect to database {}", jdbc); try (Connection connection = DriverManager.getConnection(jdbc, database.getContainer().getUsername(), database.getContainer().getPassword())) { final Statement statement = connection.createStatement(); - statement.executeUpdate(query); + statement.execute(query); } } diff --git a/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ac/at/ifs/dbrepo/config/MariaDbContainerConfig.java b/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ac/at/ifs/dbrepo/config/MariaDbContainerConfig.java index be54df64c4776e23384861285b6eaa760fc63c70..215d0aa146c248a7dde7dff8ecd13fd0f84e5ec3 100644 --- a/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ac/at/ifs/dbrepo/config/MariaDbContainerConfig.java +++ b/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ac/at/ifs/dbrepo/config/MariaDbContainerConfig.java @@ -3,10 +3,13 @@ package at.ac.tuwien.ac.at.ifs.dbrepo.config; import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.testcontainers.containers.ContainerLaunchException; import org.testcontainers.containers.MariaDBContainer; import org.testcontainers.images.PullPolicy; +import org.testcontainers.utility.DockerImageName; /** * This class configures the MariaDB container for the integration tests. @@ -48,13 +51,22 @@ public class MariaDbContainerConfig extends BaseTest { } private CustomMariaDBContainer(String dockerImageName) { - super(dockerImageName); + super(DockerImageName.parse(dockerImageName).asCompatibleSubstituteFor("mariadb")); } @Override protected void configure() { super.configure(); - this.addEnv("MYSQL_USER", "test"); // MariaDB does not allow this to be root + this.addEnv("MARIADB_EXTRA_FLAGS", "--max_connections=20 --max-statement-time=10"); + if (this.getPassword() != null && !this.getPassword().isEmpty()) { + this.addEnv("MARIADB_ROOT_PASSWORD", this.getPassword()); + } else { + if (!"root".equalsIgnoreCase(this.getUsername())) { + throw new ContainerLaunchException("Empty password can be used only with the root user"); + } + this.addEnv("MARIADB_ALLOW_EMPTY_PASSWORD", "yes"); + } + this.setStartupAttempts(3); } @Override diff --git a/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ac/at/ifs/dbrepo/config/MariadbConfigTest.java b/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ac/at/ifs/dbrepo/config/MariadbConfigTest.java new file mode 100644 index 0000000000000000000000000000000000000000..4068421d4fd9e1580b56c40ee5c0ac20672083db --- /dev/null +++ b/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ac/at/ifs/dbrepo/config/MariadbConfigTest.java @@ -0,0 +1,63 @@ +package at.ac.tuwien.ac.at.ifs.dbrepo.config; + +import at.ac.tuwien.ac.at.ifs.dbrepo.service.DatabaseService; +import at.ac.tuwien.ifs.dbrepo.core.test.BaseTest; +import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.testcontainers.containers.MariaDBContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.sql.SQLException; +import java.sql.SQLTimeoutException; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +@Log4j2 +@SpringBootTest +@ExtendWith(SpringExtension.class) +@Testcontainers +public class MariadbConfigTest extends BaseTest { + + @Autowired + private DatabaseService databaseService; + + @Container + private static MariaDBContainer<?> mariaDBContainer = MariaDbContainerConfig.getContainer(); + + @BeforeAll + public static void beforeAll() throws InterruptedException { + Thread.sleep(1000) /* wait for test container some more */; + } + + @BeforeEach + public void beforeEach() throws SQLException, InterruptedException { + /* metadata database */ + MariaDbConfig.dropDatabase(CONTAINER_1_PRIVILEGED_DTO, DATABASE_1_INTERNAL_NAME); + MariaDbConfig.createInitDatabase(DATABASE_1_PRIVILEGED_DTO); + Thread.sleep(1000) /* wait for test container some more */; + } + + @Test + public void longRunningQuery_succeeds() throws SQLException { + + /* test */ + MariaDbConfig.execute(DATABASE_1_PRIVILEGED_DTO, "SELECT SLEEP(8);"); // -2 + } + + @Test + public void tooLongRunningQuery_succeeds() { + + /* test */ + assertThrows(SQLTimeoutException.class, () -> { + MariaDbConfig.execute(DATABASE_1_PRIVILEGED_DTO, "SELECT SLEEP(12);"); // +2 + }); + } + +} diff --git a/dbrepo-ui/components/table/TableToolbar.vue b/dbrepo-ui/components/table/TableToolbar.vue index 7311e0afd5775a620f6cddbd2fef005d192fc782..72d20ebdc259ab52a2d790594b3c2776dcc790d4 100644 --- a/dbrepo-ui/components/table/TableToolbar.vue +++ b/dbrepo-ui/components/table/TableToolbar.vue @@ -30,14 +30,6 @@ :text="$t('toolbars.database.import-csv.permanent') + ($vuetify.display.mdAndUp ? ' ' + $t('toolbars.database.import-csv.xl') : '')" class="mr-2" :to="`/database/${$route.params.database_id}/table/${$route.params.table_id}/import`" /> - <v-btn - v-if="canExecuteQuery" - :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-wrench' : null" - color="secondary" - variant="flat" - :text="($vuetify.display.mdAndUp ? $t('toolbars.database.create-subset.xl') + ' ' : '') + $t('toolbars.database.create-subset.permanent')" - class="mr-2" - :to="`/database/${$route.params.database_id}/subset/create?tid=${$route.params.table_id}`" /> <v-btn v-if="canCreateView" :prepend-icon="$vuetify.display.mdAndUp ? 'mdi-view-carousel' : null" @@ -124,21 +116,15 @@ export default { } return this.roles.includes('update-table') && this.table.owner.id === this.cacheUser.uid }, - canExecuteQuery () { - if (!this.roles || !this.table || !this.cacheUser) { - return false - } - return this.hasReadAccess && this.roles.includes('execute-query') - }, isOwner () { const databaseService = useDatabaseService() return databaseService.isOwner(this.database, this.cacheUser) }, canCreateView () { - if (!this.roles || !this.table || !this.cacheUser) { + if (!this.roles || !this.cacheUser || !this.isOwner) { return false } - return this.isOwner && this.roles.includes('create-database-view') + return this.roles.includes('create-database-view') }, canViewData () { if (!this.table) { diff --git a/helm/dbrepo/files/create-event-listener.jar b/helm/dbrepo/files/create-event-listener.jar index 2a6b125340f46d51901a493f0ed050373730761a..e6ee56c50203b9ba4e75d7964141c3c353ff933d 100644 Binary files a/helm/dbrepo/files/create-event-listener.jar and b/helm/dbrepo/files/create-event-listener.jar differ diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/BaseTest.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/BaseTest.java index 3a714d0fa8d6e00a6b1d0e1f7e59114298ea17c1..78269ab3086009ca047d71a841ecbad57b5b8969 100644 --- a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/BaseTest.java +++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/test/BaseTest.java @@ -133,7 +133,7 @@ import static java.time.temporal.ChronoUnit.MINUTES; public class BaseTest { public final static String MINIO_IMAGE = "minio/minio:RELEASE.2024-06-06T09-36-42Z"; - public final static String MARIADB_IMAGE = "mariadb:11.3.2"; + public final static String MARIADB_IMAGE = "bitnami/mariadb:11.3.2"; public final static String RABBITMQ_IMAGE = "rabbitmq:3.13.7"; public final static String KEYCLOAK_IMAGE = "quay.io/keycloak/keycloak:26.0.4";