diff --git a/.docker/docker-compose.yml b/.docker/docker-compose.yml index 1b826fedfdaa47fe087d255dff50723d1dc9e25d..1d92839127f3d43db210f8fa1e24b2501a35852a 100644 --- a/.docker/docker-compose.yml +++ b/.docker/docker-compose.yml @@ -84,6 +84,12 @@ services: - ./config/import-realms.sh:/docker-entrypoint-initdb.d/import-realms.sh - ./config/master-realm.json:/opt/keycloak/data/import/master-realm.json - ./config/dbrepo-realm.json:/opt/keycloak/data/import/dbrepo-realm.json +<<<<<<< Updated upstream +======= + - ./config/create-event-listener.jar:/opt/bitnami/keycloak/providers/create-event-listener.jar + ports: + - "8080:8080" +>>>>>>> Stashed changes environment: KEYCLOAK_ENABLE_HTTPS: "false" KEYCLOAK_ENABLE_STATISTICS: "true" @@ -92,6 +98,9 @@ services: KEYCLOAK_DATABASE_NAME: "${AUTH_DB_NAME:-keycloak}" KEYCLOAK_DATABASE_USER: "${AUTH_DB_USERNAME:-keycloak}" KEYCLOAK_DATABASE_PASSWORD: "${AUTH_DB_PASSWORD:-dbrepo}" + METADATA_SERVICE_ENDPOINT: "${METADATA_SERVICE_ENDPOINT:-http://metadata-service:8080}/api/user" + SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" + SYSTEM_PASSWORD: "${SYSTEM_PASSWORD:-admin}" healthcheck: test: curl --head -fsS http://localhost:9000/health/ready interval: 10s @@ -105,11 +114,39 @@ services: logging: driver: json-file +<<<<<<< Updated upstream +======= + dbrepo-auth-service-init: + init: true + restart: "no" + container_name: dbrepo-auth-service-init + image: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.6.3 + environment: + AUTH_SERVICE_ADMIN: ${AUTH_SERVICE_ADMIN:-admin} + AUTH_SERVICE_ADMIN_PASSWORD: ${AUTH_SERVICE_ADMIN_PASSWORD:-admin} + AUTH_SERVICE_ENDPOINT: ${AUTH_SERVICE_ENDPOINT:-http://auth-service:8080} + METADATA_DB: "${METADATA_DB:-dbrepo}" + METADATA_DB_PASSWORD: "${METADATA_DB_PASSWORD:-dbrepo}" + METADATA_USERNAME: "root" + SYSTEM_USERNAME: "${SYSTEM_USERNAME:-admin}" + depends_on: + dbrepo-auth-service: + condition: service_healthy + dbrepo-metadata-db: + condition: service_healthy + logging: + driver: json-file + +>>>>>>> Stashed changes dbrepo-metadata-service: restart: "no" container_name: dbrepo-metadata-service hostname: metadata-service +<<<<<<< Updated upstream image: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.4.7 +======= + image: registry.datalab.tuwien.ac.at/dbrepo/metadata-service:1.6.3 +>>>>>>> Stashed changes volumes: - "${SHARED_VOLUME:-/tmp}:/tmp" environment: @@ -172,7 +209,11 @@ services: restart: "no" container_name: dbrepo-analyse-service hostname: analyse-service +<<<<<<< Updated upstream image: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.4.7 +======= + image: registry.datalab.tuwien.ac.at/dbrepo/analyse-service:1.6.3 +>>>>>>> Stashed changes environment: AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} @@ -225,7 +266,11 @@ services: restart: "no" container_name: dbrepo-search-db hostname: search-db +<<<<<<< Updated upstream image: registry.datalab.tuwien.ac.at/dbrepo/search-db:1.4.7 +======= + image: registry.datalab.tuwien.ac.at/dbrepo/search-db:1.6.3 +>>>>>>> Stashed changes healthcheck: test: curl -sSL localhost:9200/_plugins/_security/health | jq .status | grep UP interval: 10s @@ -249,7 +294,11 @@ services: restart: "no" container_name: dbrepo-search-service hostname: search-service +<<<<<<< Updated upstream image: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.4.7 +======= + image: registry.datalab.tuwien.ac.at/dbrepo/search-service:1.6.3 +>>>>>>> Stashed changes environment: AUTH_SERVICE_CLIENT: ${AUTH_SERVICE_CLIENT:-dbrepo-client} AUTH_SERVICE_CLIENT_SECRET: ${AUTH_SERVICE_CLIENT_SECRET:-MUwRc7yfXSJwX8AdRMWaQC3Nep1VjwgG} @@ -292,7 +341,11 @@ services: restart: "no" container_name: dbrepo-ui hostname: ui +<<<<<<< Updated upstream image: registry.datalab.tuwien.ac.at/dbrepo/ui:1.4.7 +======= + image: registry.datalab.tuwien.ac.at/dbrepo/ui:1.6.3 +>>>>>>> Stashed changes environment: NUXT_PUBLIC_API_CLIENT: "${BASE_URL:-http://localhost}" NUXT_PUBLIC_API_SERVER: "${BASE_URL:-http://localhost}" @@ -360,7 +413,11 @@ services: init: true container_name: dbrepo-search-service-init hostname: search-service-init +<<<<<<< Updated upstream image: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.4.7 +======= + image: registry.datalab.tuwien.ac.at/dbrepo/search-service-init:1.6.3 +>>>>>>> Stashed changes environment: METADATA_SERVICE_ENDPOINT: ${METADATA_SERVICE_ENDPOINT:-http://metadata-service:8080} OPENSEARCH_HOST: ${OPENSEARCH_HOST:-search-db} @@ -414,7 +471,15 @@ services: restart: "no" container_name: dbrepo-dashboard-service hostname: dashboard-service +<<<<<<< Updated upstream image: registry.datalab.tuwien.ac.at/dbrepo/dashboard-service:1.4.7 +======= + image: registry.datalab.tuwien.ac.at/dbrepo/dashboard-service:1.6.3 + ports: + - "3000:3000" + volumes: + - dashboard-service-data:/opt/bitnami/grafana/data +>>>>>>> Stashed changes environment: LDAP_ADMIN_USERNAME: "${IDENTITY_SERVICE_ADMIN_USERNAME:-admin}" LDAP_ADMIN_PASSWORD: "${IDENTITY_SERVICE_ADMIN_PASSWORD:-admin}" @@ -435,7 +500,11 @@ services: init: true container_name: dbrepo-storage-service-init hostname: storage-service-init +<<<<<<< Updated upstream image: registry.datalab.tuwien.ac.at/dbrepo/storage-service-init:1.4.7 +======= + image: registry.datalab.tuwien.ac.at/dbrepo/storage-service-init:1.6.3 +>>>>>>> Stashed changes environment: WEED_CLUSTER_SW_MASTER: "${STORAGE_SERVICE_MASTER_ENDPOINT:-storage-service:9333}" S3_BUCKET: "${S3_BUCKET:-dbrepo}" @@ -475,7 +544,11 @@ services: restart: "no" container_name: dbrepo-data-service hostname: data-service +<<<<<<< Updated upstream image: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.4.7 +======= + image: registry.datalab.tuwien.ac.at/dbrepo/data-service:1.6.3 +>>>>>>> Stashed changes volumes: - "${SHARED_VOLUME:-/tmp}:/tmp" environment: diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f571fba1d16722ed56e3152dbe634272ebcbd284..16b1ef00c8f8878983faa12ca55a4bfa9cc7a774 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -32,6 +32,95 @@ stages: - verify - scan +<<<<<<< Updated upstream +======= +lint-docker-compose: + image: docker.io/alpine:${ALPINE_VERSION} + stage: lint + variables: + VERSION: 4.45.1 + BINARY: yq_linux_amd64 + before_script: + - 'apk --no-cache add bash wget' + - 'wget https://github.com/mikefarah/yq/releases/download/v${VERSION}/${BINARY} -O /usr/bin/yq && chmod +x /usr/bin/yq' + script: + - "bash .scripts/check-compose.sh" + - "diff <(yq '.volumes' docker-compose.yml) <(yq '.volumes' .docker/docker-compose.yml)" + - "IGNORE_IMAGE=1 IGNORE_PORTS=1 bash .scripts/check-service.sh 'dbrepo-analyse-service'" + - "IGNORE_PORTS=1 bash .scripts/check-service.sh 'dbrepo-auth-db'" + - "IGNORE_IMAGE=1 IGNORE_PORTS=1 bash .scripts/check-service.sh 'dbrepo-auth-service'" + - "IGNORE_VOLUMES=1 IGNORE_IMAGE=1 bash .scripts/check-service.sh 'dbrepo-auth-service-init'" + - "IGNORE_IMAGE=1 IGNORE_PORTS=1 bash .scripts/check-service.sh 'dbrepo-broker-service'" + - "IGNORE_PORTS=1 bash .scripts/check-service.sh 'dbrepo-dashboard-service'" + - "bash .scripts/check-service.sh 'dbrepo-data-db'" + - "IGNORE_IMAGE=1 IGNORE_PORTS=1 bash .scripts/check-service.sh 'dbrepo-data-service'" + - "IGNORE_VOLUMES=1 bash .scripts/check-service.sh 'dbrepo-gateway-service'" + - "IGNORE_VOLUMES=1 IGNORE_PORTS=1 bash .scripts/check-service.sh 'dbrepo-identity-service'" + - "IGNORE_VOLUMES=1 bash .scripts/check-service.sh 'dbrepo-metadata-db'" + - "IGNORE_IMAGE=1 IGNORE_PORTS=1 bash .scripts/check-service.sh 'dbrepo-metadata-service'" + - "IGNORE_VOLUMES=1 IGNORE_PORTS=1 bash .scripts/check-service.sh 'dbrepo-metric-db'" + - "IGNORE_IMAGE=1 bash .scripts/check-service.sh 'dbrepo-search-db'" + - "IGNORE_IMAGE=1 IGNORE_PORTS=1 bash .scripts/check-service.sh 'dbrepo-search-service'" + - "IGNORE_IMAGE=1 bash .scripts/check-service.sh 'dbrepo-search-service-init'" + - "IGNORE_VOLUMES=1 bash .scripts/check-service.sh 'dbrepo-storage-service'" + - "IGNORE_VOLUMES=1 IGNORE_IMAGE=1 bash .scripts/check-service.sh 'dbrepo-storage-service-init'" + - "IGNORE_IMAGE=1 bash .scripts/check-service.sh 'dbrepo-ui'" + - "IGNORE_VOLUMES=1 bash .scripts/check-service.sh 'dbrepo-upload-service'" + +lint-helm-chart: + image: docker.io/alpine:${ALPINE_VERSION} + stage: lint + before_script: + - apk --no-cache add helm git bash + - cp ./helm/dbrepo/values.schema.json ./CI_values.schema.json + - helm plugin install https://github.com/losisin/helm-values-schema-json.git + - helm dependency update ./helm/seaweedfs + - helm package ./helm/seaweedfs --destination ./build + - helm dependency update ./helm/dbrepo + script: + - bash .scripts/check-helm.sh + - helm lint ./helm/dbrepo + - helm schema -input ./helm/dbrepo/values.yaml -output ./helm/dbrepo/values.schema.json + - diff ./CI_values.schema.json ./helm/dbrepo/values.schema.json + - diff ./dbrepo-metadata-db/1_setup-schema.sql ./helm/dbrepo/files/01-setup-schema.sql + - diff ./dbrepo-auth-service/listeners/target/create-event-listener.jar ./helm/dbrepo/files/create-event-listener.jar + artifacts: + when: always + paths: + - ./helm/dbrepo/values.schema.json + expire_in: 1 days + +lint-helm-readme: + image: docker.io/node:${NODE_VERSION}-alpine${ALPINE_VERSION} + stage: lint + before_script: + - apk --no-cache add alpine-sdk bash git + - cp ./helm/dbrepo/README.md ./CI_README.md + - git clone https://github.com/bitnami/readme-generator-for-helm + - (cd ./readme-generator-for-helm && npm install && npm install -g pkg && pkg . -o /usr/local/sbin/readme-generator) + script: + - readme-generator --readme ./helm/dbrepo/README.md --values ./helm/dbrepo/values.yaml + - diff ./CI_README.md ./helm/dbrepo/README.md + artifacts: + when: always + paths: + - ./helm/dbrepo/README.md + expire_in: 1 days + +lint-open-api-version: + image: docker.io/alpine:${ALPINE_VERSION} + stage: lint + variables: + VERSION: 4.45.1 + BINARY: yq_linux_amd64 + before_script: + - 'apk --no-cache add bash wget' + - 'wget https://github.com/mikefarah/yq/releases/download/v${VERSION}/${BINARY} -O /usr/bin/yq && chmod +x /usr/bin/yq' + script: + - yq '.externalDocs.url' ./.docs/.openapi/api.base.yaml | grep "${DOC_VERSION}" + - yq '.info.version' ./.docs/.openapi/api.base.yaml | grep "${DOC_VERSION}" + +>>>>>>> Stashed changes build-metadata-service: image: maven:3-openjdk-17 stage: build diff --git a/dbrepo-analyse-service/Pipfile.lock b/dbrepo-analyse-service/Pipfile.lock index bcff34a23efb2e4a660fb11c850aba569369e918..771c2b474b94c937d15f4afd9411f399a1db1816 100644 --- a/dbrepo-analyse-service/Pipfile.lock +++ b/dbrepo-analyse-service/Pipfile.lock @@ -1,7 +1,11 @@ { "_meta": { "hash": { +<<<<<<< Updated upstream "sha256": "9e1fb16b1632a76b8a2fb6ac372b92556c573a7246bd37dd32813559bb27c8d9" +======= + "sha256": "9cc4c161729b642069bbf4ab379c0f4a9122035afcb3ac7b5b1bfc13281f76aa" +>>>>>>> Stashed changes }, "pipfile-spec": 6, "requires": { @@ -440,7 +444,11 @@ }, "dbrepo": { "hashes": [ +<<<<<<< Updated upstream "sha256:84607677b0826bb9b2fa120aacdf56d16c8d9ae423f435b2bd2c22b1c965a33c" +======= + "sha256:7f98329f08d1da6fe45da8130cfb3ebd6e947a4101d46f92b31d7204b29a153d" +>>>>>>> Stashed changes ], "markers": "python_version >= '3.11'", "path": "./lib/dbrepo-1.4.7.tar.gz" diff --git a/dbrepo-analyse-service/lib/dbrepo-1.6.3-py3-none-any.whl b/dbrepo-analyse-service/lib/dbrepo-1.6.3-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..d9c6af3e4a3f6a722cc5d1248c9aafd04a41cbda Binary files /dev/null and b/dbrepo-analyse-service/lib/dbrepo-1.6.3-py3-none-any.whl differ diff --git a/dbrepo-analyse-service/lib/dbrepo-1.6.3.tar.gz b/dbrepo-analyse-service/lib/dbrepo-1.6.3.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..3e302ea2286d2d6548e9917019397abab93a22e0 Binary files /dev/null and b/dbrepo-analyse-service/lib/dbrepo-1.6.3.tar.gz differ diff --git a/dbrepo-auth-service/listeners/target/create-event-listener.jar b/dbrepo-auth-service/listeners/target/create-event-listener.jar new file mode 100644 index 0000000000000000000000000000000000000000..221bdd325f056ff953e0a44a46773470eb08e91e Binary files /dev/null and b/dbrepo-auth-service/listeners/target/create-event-listener.jar differ diff --git a/dbrepo-data-service/Dockerfile b/dbrepo-data-service/Dockerfile index bd6d428695f2b85126a0a1b4dea604667510198c..c136386d345a5aca8879212309106ed540f5b1ce 100644 --- a/dbrepo-data-service/Dockerfile +++ b/dbrepo-data-service/Dockerfile @@ -6,22 +6,26 @@ LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" FROM maven:3-openjdk-17 AS build LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" +<<<<<<< Updated upstream COPY ./pom.xml ./ RUN mvn -fn -B dependency:go-offline +======= +>>>>>>> Stashed changes COPY --from=dependency /root/.m2/repository/at/tuwien /root/.m2/repository/at/tuwien COPY ./querystore ./querystore COPY ./report ./report COPY ./rest-service ./rest-service COPY ./services ./services +COPY ./pom.xml ./ # Make sure it compiles RUN mvn clean package -DskipTests ###### THIRD STAGE ###### -FROM amazoncorretto:17-alpine3.19 AS runtime +FROM amazoncorretto:17-alpine3.21 AS runtime LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" RUN apk add --no-cache curl bash jq @@ -30,7 +34,7 @@ WORKDIR /app USER 1001 -COPY --from=build --chown=1001 ./rest-service/target/rest-service-*.jar ./data-service.jar +COPY --from=build --chown=1001 ./rest-service/target/data-service.jar ./data-service.jar # non-root port EXPOSE 8080 diff --git a/dbrepo-data-service/pom.xml b/dbrepo-data-service/pom.xml index 6517de47460bdf48ad1f31397a1e67416e3dbc31..38125987c8e9c729352c8346abd8da11f23991f1 100644 --- a/dbrepo-data-service/pom.xml +++ b/dbrepo-data-service/pom.xml @@ -249,6 +249,7 @@ </dependencies> <build> + <finalName>data-service</finalName> <resources> <resource> <directory>${basedir}/src/main/resources</directory> diff --git a/dbrepo-metadata-service/Dockerfile b/dbrepo-metadata-service/Dockerfile index 74e82043731ab8970c2d42b58032f2b5e5b00f3c..18b77afe428e2a93472e1b7fd191187f1bbfaba1 100644 --- a/dbrepo-metadata-service/Dockerfile +++ b/dbrepo-metadata-service/Dockerfile @@ -1,5 +1,9 @@ ###### FIRST STAGE ###### +<<<<<<< Updated upstream FROM maven:3-openjdk-17 AS build +======= +FROM maven:3-amazoncorretto-17-alpine AS build +>>>>>>> Stashed changes LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" COPY ./pom.xml ./ @@ -12,7 +16,11 @@ COPY ./rest-service/pom.xml ./rest-service/ COPY ./services/pom.xml ./services/ COPY ./test/pom.xml ./test/ +<<<<<<< Updated upstream RUN mvn verify -B -fn +======= +RUN mvn dependency:go-offline +>>>>>>> Stashed changes COPY ./api ./api COPY ./entities ./entities @@ -27,7 +35,7 @@ COPY ./test ./test RUN mvn clean install -DskipTests ###### SECOND STAGE ###### -FROM amazoncorretto:17-alpine3.19 AS runtime +FROM amazoncorretto:17-alpine3.21 AS runtime LABEL org.opencontainers.image.authors="martin.weise@tuwien.ac.at" RUN apk add --no-cache curl bash jq @@ -36,9 +44,9 @@ WORKDIR /app USER 1001 -COPY --from=build --chown=1001 ./rest-service/target/dbrepo-metadata-service-rest-service-*.jar ./metadata-service.jar +COPY --from=build --chown=1001 ./rest-service/target/metadata-service.jar ./metadata-service.jar # non-root port EXPOSE 8080 -ENTRYPOINT ["java", "-Dlog4j2.formatMsgNoLookups=true", "-jar", "./metadata-service.jar"] +ENTRYPOINT ["java", "-jar", "./metadata-service.jar"] diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerDto.java index 7e46b80c1cfc745b158f6bffffd02bdd617a1987..d767e25a1647cf9aa2758e87297ba98a49656c7d 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/container/ContainerDto.java @@ -14,6 +14,10 @@ import java.time.Instant; @Getter @Setter @Builder +<<<<<<< Updated upstream +======= +@EqualsAndHashCode(callSuper = false) +>>>>>>> Stashed changes @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java index dcdb1b944893b63fee80c385aad735d443b43c8a..ca464f33ba477296c3f88a95c588d0877d5f2c38 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/DatabaseDto.java @@ -18,6 +18,10 @@ import java.util.List; @Getter @Setter @Builder +<<<<<<< Updated upstream +======= +@EqualsAndHashCode(callSuper = false) +>>>>>>> Stashed changes @NoArgsConstructor @AllArgsConstructor @Jacksonized @@ -59,6 +63,14 @@ public class DatabaseDto { @ToString.Exclude @NotNull +<<<<<<< Updated upstream +======= + @JsonProperty("is_schema_public") + @Schema(example = "true") + private Boolean isSchemaPublic; + + @NotNull +>>>>>>> Stashed changes private ContainerDto container; private List<DatabaseAccessDto> accesses; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java index 30f16448d36462da23dc27ba38512f61dab58b25..96dfaff1ed0e2b6cae422e99ff86f866043bc93a 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/ViewDto.java @@ -19,6 +19,10 @@ import java.util.UUID; @Getter @Setter @Builder +<<<<<<< Updated upstream +======= +@EqualsAndHashCode(callSuper = false) +>>>>>>> Stashed changes @NoArgsConstructor @AllArgsConstructor @Jacksonized @@ -64,6 +68,7 @@ public class ViewDto { @Schema(example = "7de03e818900b6ea6d58ad0306d4a741d658c6df3d1964e89ed2395d8c7e7916") private String queryHash; +<<<<<<< Updated upstream @NotNull @Schema(example = "2021-03-12T15:26:21Z") @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC") @@ -71,6 +76,10 @@ public class ViewDto { @JsonIgnore private UUID createdBy; +======= + @ToString.Exclude + private DatabaseDto database; +>>>>>>> Stashed changes @NotNull private UserDto creator; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java index a512cf8010195e5c107f35d8d2756251460bca62..794ec747b824d7c084aff2b1adf15bfcb246c52d 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/database/table/TableDto.java @@ -21,6 +21,10 @@ import java.util.UUID; @Getter @Setter @Builder +<<<<<<< Updated upstream +======= +@EqualsAndHashCode(callSuper = false) +>>>>>>> Stashed changes @NoArgsConstructor @AllArgsConstructor @Jacksonized @@ -110,8 +114,13 @@ public class TableDto { @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC") private Instant created; +<<<<<<< Updated upstream @NotNull private List<ColumnDto> columns; +======= + @ToString.Exclude + private DatabaseDto database; +>>>>>>> Stashed changes @NotNull private ConstraintsDto constraints; diff --git a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDto.java b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDto.java index 00a866bfd2923cc1ae88abc8273cd2d4b912295e..eef0eb5cc0f9d20a7f2d521c07729456253f822c 100644 --- a/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDto.java +++ b/dbrepo-metadata-service/api/src/main/java/at/tuwien/api/user/UserDto.java @@ -12,6 +12,10 @@ import java.util.UUID; @Getter @Setter @Builder +<<<<<<< Updated upstream +======= +@EqualsAndHashCode(callSuper = false) +>>>>>>> Stashed changes @NoArgsConstructor @AllArgsConstructor @Jacksonized diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/Container.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/Container.java index 7545260ce1a83f2a39b7900e9b29de5e0a4bedde..203b6ccd6abdfdd37b76f5c0a4590b42b295eb05 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/Container.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/container/Container.java @@ -61,7 +61,10 @@ public class Container { @Column private String uiAdditionalFlags; +<<<<<<< Updated upstream @ToString.Exclude +======= +>>>>>>> Stashed changes @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) @JoinColumns({ @JoinColumn(name = "cid", referencedColumnName = "id", insertable = false, updatable = false) diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/Table.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/Table.java index 08f6bd9426a8906d4edc4863ecc6f3540cb39448..cc7df44e9384333dcd3835bbf2d759ae15fb1a22 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/Table.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/Table.java @@ -23,7 +23,7 @@ import java.util.UUID; @Data @Entity -@Builder +@Builder(toBuilder = true) @Log4j2 @ToString @AllArgsConstructor diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java index 841dbde754a09a5fdd51cec7872ae4c8a4e5e946..3122eb22195cc8de969d3aac7103acc31d3bcd32 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java @@ -119,6 +119,14 @@ public class TableColumn implements Comparable<TableColumn> { @Column(name = "std_dev") private BigDecimal stdDev; +<<<<<<< Updated upstream +======= + @CreatedDate + @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP default NOW()") + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC") + private Instant created; + +>>>>>>> Stashed changes @LastModifiedDate @Column(columnDefinition = "TIMESTAMP") private Instant lastModified; diff --git a/dbrepo-metadata-service/pom.xml b/dbrepo-metadata-service/pom.xml index a2de622dcacd12a615c2d8dc0f536df88ebc87dd..dfecd7779409533e7a85bff9b71350af02e9ad9a 100644 --- a/dbrepo-metadata-service/pom.xml +++ b/dbrepo-metadata-service/pom.xml @@ -96,6 +96,10 @@ <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-webflux</artifactId> + </dependency> <!-- Open API --> <dependency> <groupId>org.springdoc</groupId> @@ -268,6 +272,7 @@ </dependencies> <build> + <finalName>metadata-service</finalName> <resources> <resource> <directory>${basedir}/src/main/resources</directory> diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceConnectionException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceConnectionException.java index d68185102a00e33419ae8cf2c4250c0775082a23..2cf18262d3069f6369026e64508a687f3d2e419a 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceConnectionException.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceConnectionException.java @@ -4,7 +4,7 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(code = HttpStatus.BAD_GATEWAY, reason = "error.search.connection") -public class SearchServiceConnectionException extends Exception { +public class SearchServiceConnectionException extends RuntimeException { public SearchServiceConnectionException(String msg) { super(msg); diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceException.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceException.java index aef3ae7f7cd75db6ec7ed59f95980f2c8e021c2b..528b3aadd1e0cdd0ea9ef6c19374f29b8d62ab15 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceException.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/exception/SearchServiceException.java @@ -4,7 +4,7 @@ import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.ResponseStatus; @ResponseStatus(code = HttpStatus.SERVICE_UNAVAILABLE, reason = "error.search.invalid") -public class SearchServiceException extends Exception { +public class SearchServiceException extends RuntimeException { public SearchServiceException(String message) { super(message); diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index 738e30d4e48aba2dc52703d0ca2bd3cb53b2b63a..7c706ca18bcd430f1a0b7d569e37a9e9b86ba1af 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -1,7 +1,12 @@ package at.tuwien.endpoints; +<<<<<<< Updated upstream import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.TableCreateDto; +======= +import at.tuwien.api.database.table.CreateTableDto; +import at.tuwien.api.database.table.TableBriefDto; +>>>>>>> Stashed changes import at.tuwien.api.database.table.TableDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; @@ -351,10 +356,73 @@ public class TableEndpoint { endpointValidator.validateOnlyAccess(database, principal, true); endpointValidator.validateColumnCreateConstraints(data); final Table table = tableService.createTable(database, data, principal); +<<<<<<< Updated upstream final TableDto dto = metadataMapper.customTableToTableDto(table); log.info("Created table with id {}", dto.getId()); return ResponseEntity.status(HttpStatus.CREATED) .body(dto); +======= + return ResponseEntity.status(HttpStatus.CREATED) + .body(metadataMapper.tableToTableBriefDto(table)); + } + + @PutMapping("/{tableId}") + @Transactional(rollbackFor = {Exception.class}) + @PreAuthorize("hasAuthority('update-table')") + @Observed(name = "dbrepo_table_update") + @Operation(summary = "Update table", + description = "Updates a table in the database with id. Requires role `update-table`.", + security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "202", + description = "Updated the table", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = TableBriefDto.class))}), + @ApiResponse(responseCode = "400", + description = "Update table visibility payload is malformed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Update table visibility not permitted", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Table could not be found", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "502", + description = "Connection to search service failed", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "503", + description = "Failed to save in search service", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + }) + public ResponseEntity<TableBriefDto> update(@NotNull @PathVariable("databaseId") Long databaseId, + @NotNull @PathVariable("tableId") Long tableId, + @NotNull @Valid @RequestBody TableUpdateDto data, + @NotNull Principal principal) throws NotAllowedException, + DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, TableNotFoundException, + SearchServiceException, SearchServiceConnectionException { + log.debug("endpoint update table, databaseId={}, data.is_public={}, data.is_schema_public={}, principal.name={}", + databaseId, data.getIsPublic(), data.getIsSchemaPublic(), principal.getName()); + final Database database = databaseService.findById(databaseId); + final Table table = tableService.findById(database, tableId); + if (!table.getOwner().getId().equals(getId(principal))) { + log.error("Failed to update table: not owner"); + throw new NotAllowedException("Failed to update table: not owner"); + } + return ResponseEntity.accepted() + .body(metadataMapper.tableToTableBriefDto( + tableService.updateTable(table, data))); +>>>>>>> Stashed changes } @GetMapping("/{tableId}") diff --git a/dbrepo-metadata-service/rest-service/src/main/resources/datatypes.json b/dbrepo-metadata-service/rest-service/src/main/resources/datatypes.json deleted file mode 100644 index 3779d12cbe32b67fa163cf6b0285b9e01f7dc681..0000000000000000000000000000000000000000 --- a/dbrepo-metadata-service/rest-service/src/main/resources/datatypes.json +++ /dev/null @@ -1,15 +0,0 @@ -[ - { - "name": "", - "size": { - "min": 0, - "required": true - }, - "d": { - "required": false - }, - "documentation": "https://mariadb.com/kb/en/bigint/", - "quoted": false, - "buildable": true - } -] \ No newline at end of file diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java index aa1c9d4f056f61680aeb341f2cebafdbe262a2b5..148b2d31b80a65718806a2afbc05e4c4ab40d7cd 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java @@ -37,7 +37,11 @@ public class SearchServiceGatewayUnitTest extends AbstractUnitTest { @Test public void update_succeeds() throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { +<<<<<<< Updated upstream final ResponseEntity<DatabaseDto> mock = ResponseEntity.status(HttpStatus.ACCEPTED) +======= + final ResponseEntity<DatabaseDto> mock = ResponseEntity.accepted() +>>>>>>> Stashed changes .build(); /* mock */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java index 648bb6ab290b319a817aba31d49310d43416e4a3..9ce405b4f208313412fcaebfdc5c047f94b0c4cb 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java @@ -38,8 +38,7 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; @ExtendWith(SpringExtension.class) @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD) @@ -138,8 +137,14 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { /* mock */ when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(dataCiteBodyParameterizedTypeReference))) .thenReturn(mock); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ dataCiteIdentifierService.save(DATABASE_1, USER_1, IDENTIFIER_1_SAVE_DTO); @@ -153,8 +158,14 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { doThrow(HttpClientErrorException.BadRequest.class) .when(restTemplate) .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(dataCiteBodyParameterizedTypeReference)); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ assertThrows(MalformedException.class, () -> { @@ -170,8 +181,14 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { doThrow(RestClientException.class) .when(restTemplate) .exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(dataCiteBodyParameterizedTypeReference)); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ assertThrows(DataServiceConnectionException.class, () -> { @@ -330,8 +347,14 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { IdentifierNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ dataCiteIdentifierService.delete(IDENTIFIER_1); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java index 1e7633b851f9c052fd8fe60d14193698565421f3..a5e00468b99a086390937213a31f9f02737bc628 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java @@ -88,6 +88,263 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { } @Test +<<<<<<< Updated upstream +======= + public void updatePassword_succeeds() throws DataServiceException, DatabaseNotFoundException, + DataServiceConnectionException { + + /* mock */ + when(databaseRepository.findAllAtLestReadAccessDesc(USER_1_ID)) + .thenReturn(List.of(DATABASE_1)); + doNothing() + .when(dataServiceGateway) + .updateDatabase(eq(DATABASE_1_ID), any(UpdateUserPasswordDto.class)); + + /* test */ + databaseService.updatePassword(DATABASE_1, USER_1); + } + + @Test + public void modifyImage_succeeds() throws SearchServiceException, DatabaseNotFoundException, SearchServiceConnectionException { + final byte[] image = new byte[]{1, 2, 3, 4, 5}; + + /* mock */ + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + final Database response = databaseService.modifyImage(DATABASE_1, image); + assertNotNull(response); + } + + @Test + public void modifyImage_searchServiceNotFound_fails() throws SearchServiceException, DatabaseNotFoundException, + SearchServiceConnectionException { + final byte[] image = new byte[]{1, 2, 3, 4, 5}; + + /* mock */ + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doThrow(DatabaseNotFoundException.class) + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + assertThrows(DatabaseNotFoundException.class, () -> { + databaseService.modifyImage(DATABASE_1, image); + }); + } + + @Test + public void modifyImage_searchServiceConnection_fails() throws SearchServiceException, DatabaseNotFoundException, + SearchServiceConnectionException { + final byte[] image = new byte[]{1, 2, 3, 4, 5}; + + /* mock */ + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doThrow(SearchServiceConnectionException.class) + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + assertThrows(SearchServiceConnectionException.class, () -> { + databaseService.modifyImage(DATABASE_1, image); + }); + } + + @Test + public void updateViewMetadata_empty_succeeds() throws SearchServiceException, DataServiceException, + QueryNotFoundException, DatabaseNotFoundException, SearchServiceConnectionException, + DataServiceConnectionException, ViewNotFoundException { + + /* mock */ + when(dataServiceGateway.getViewSchemas(DATABASE_1_ID)) + .thenReturn(List.of()); + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + final Database response = databaseService.updateViewMetadata(DATABASE_1); + assertNotNull(response); + } + + @Test + public void updateViewMetadata_searchServiceConnection_fails() throws SearchServiceException, DataServiceException, + DatabaseNotFoundException, SearchServiceConnectionException, DataServiceConnectionException, + ViewNotFoundException { + + /* mock */ + when(dataServiceGateway.getViewSchemas(DATABASE_1_ID)) + .thenReturn(List.of()); + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doThrow(SearchServiceConnectionException.class) + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + assertThrows(SearchServiceConnectionException.class, () -> { + databaseService.updateViewMetadata(DATABASE_1); + }); + } + + @Test + public void updateViewMetadata_searchServiceNotFound_fails() throws SearchServiceException, DataServiceException, + DatabaseNotFoundException, SearchServiceConnectionException, DataServiceConnectionException, + ViewNotFoundException { + + /* mock */ + when(dataServiceGateway.getViewSchemas(DATABASE_1_ID)) + .thenReturn(List.of()); + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doThrow(DatabaseNotFoundException.class) + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + assertThrows(DatabaseNotFoundException.class, () -> { + databaseService.updateViewMetadata(DATABASE_1); + }); + } + + @Test + public void updateViewMetadata_oneMissing_succeeds() throws SearchServiceException, DataServiceException, + QueryNotFoundException, DatabaseNotFoundException, SearchServiceConnectionException, + DataServiceConnectionException, ViewNotFoundException { + + /* mock */ + when(dataServiceGateway.getViewSchemas(DATABASE_1_ID)) + .thenReturn(List.of(VIEW_1_DTO, VIEW_2_DTO, VIEW_3_DTO, VIEW_4_DTO)); /* <<< */ + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + final Database response = databaseService.updateViewMetadata(DATABASE_1); + assertNotNull(response); + } + + @Test + public void updateViewMetadata_allKnown_succeeds() throws SearchServiceException, DataServiceException, + QueryNotFoundException, DatabaseNotFoundException, SearchServiceConnectionException, + DataServiceConnectionException, ViewNotFoundException { + + /* mock */ + when(dataServiceGateway.getViewSchemas(DATABASE_1_ID)) + .thenReturn(List.of(VIEW_1_DTO, VIEW_2_DTO, VIEW_3_DTO)); /* <<< */ + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + final Database response = databaseService.updateViewMetadata(DATABASE_1); + assertNotNull(response); + } + + @Test + public void updateTableMetadata_empty_succeeds() throws TableNotFoundException, SearchServiceException, + MalformedException, DataServiceException, QueryNotFoundException, DatabaseNotFoundException, + SearchServiceConnectionException, DataServiceConnectionException { + + /* mock */ + when(dataServiceGateway.getTableSchemas(DATABASE_1_ID)) + .thenReturn(List.of()); + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + final Database response = databaseService.updateTableMetadata(DATABASE_1); + assertNotNull(response); + } + + @Test + public void updateTableMetadata_allKnown_succeeds() throws TableNotFoundException, SearchServiceException, + MalformedException, DataServiceException, QueryNotFoundException, DatabaseNotFoundException, + SearchServiceConnectionException, DataServiceConnectionException { + + /* mock */ + when(dataServiceGateway.getTableSchemas(DATABASE_1_ID)) + .thenReturn(List.of(TABLE_1_DTO, TABLE_2_DTO, TABLE_3_DTO, TABLE_4_DTO)); + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + final Database response = databaseService.updateTableMetadata(DATABASE_1); + assertNotNull(response); + } + + @Test + public void updateTableMetadata_oneMissing_succeeds() throws TableNotFoundException, SearchServiceException, + MalformedException, DataServiceException, QueryNotFoundException, DatabaseNotFoundException, + SearchServiceConnectionException, DataServiceConnectionException { + + /* mock */ + when(dataServiceGateway.getTableSchemas(DATABASE_1_ID)) + .thenReturn(List.of(TABLE_1_DTO, TABLE_2_DTO, TABLE_3_DTO, TABLE_4_DTO, TABLE_5_DTO)); + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + final Database response = databaseService.updateTableMetadata(DATABASE_1); + assertNotNull(response); + final Optional<Table> optional = response.getTables() + .stream() + .filter(t -> t.getInternalName().equals(TABLE_5_INTERNALNAME)) + .findFirst(); + assertTrue(optional.isPresent()); + final Table table = optional.get(); + table.getColumns() + .forEach(column -> { + assertNotNull(column.getTable()); + assertEquals(TABLE_5_ID, column.getTable().getId()); + }); + table.getConstraints() + .getUniques() + .forEach(uk -> { + assertNotNull(uk.getTable()); + assertEquals(TABLE_5_ID, uk.getTable().getId()); + }); + table.getConstraints() + .getForeignKeys() + .forEach(fk -> { + assertNotNull(fk.getTable()); + assertEquals(TABLE_5_ID, fk.getTable().getId()); + }); + table.getConstraints() + .getPrimaryKey() + .forEach(pk -> { + assertNotNull(pk.getTable()); + assertEquals(TABLE_5_ID, pk.getTable().getId()); + assertEquals(TABLE_5_COLUMNS.get(0), pk.getColumn()); + }); + } + + @Test +>>>>>>> Stashed changes public void find_succeeds() throws DatabaseNotFoundException { /* mock */ @@ -272,8 +529,14 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { ContainerNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java index 246ae7de1a4beb7a55f4cadf13f142b48ef995fd..1c44828ea73878740ee665936490ee11ddc3ba12 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java @@ -35,6 +35,7 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.when; @Log4j2 @@ -174,8 +175,14 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { /* mock */ when(dataServiceGateway.findQuery(IDENTIFIER_5_DATABASE_ID, IDENTIFIER_5_QUERY_ID)) .thenReturn(QUERY_2_DTO); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_2_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ identifierService.save(DATABASE_2, USER_2, IDENTIFIER_5_SAVE_DTO); @@ -284,8 +291,14 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { SearchServiceConnectionException { /* mock */ +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ identifierService.delete(IDENTIFIER_1); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java index 7aa22159c395046548324a714d7d8274fc8114af..59ab266765863c7e812722b14c607b10b957ac5a 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServicePersistenceTest.java @@ -1,9 +1,16 @@ package at.tuwien.service; +<<<<<<< Updated upstream import at.tuwien.api.database.table.TableCreateDto; import at.tuwien.api.database.table.columns.ColumnCreateDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; import at.tuwien.api.database.table.constraints.ConstraintsCreateDto; +======= +import at.tuwien.api.database.table.CreateTableDto; +import at.tuwien.api.database.table.columns.ColumnTypeDto; +import at.tuwien.api.database.table.columns.CreateTableColumnDto; +import at.tuwien.api.database.table.constraints.CreateTableConstraintsDto; +>>>>>>> Stashed changes import at.tuwien.entities.database.Database; import at.tuwien.entities.database.table.Table; import at.tuwien.entities.database.table.columns.TableColumn; @@ -107,8 +114,14 @@ public class TableServicePersistenceTest extends AbstractUnitTest { doNothing() .when(dataServiceGateway) .createTable(DATABASE_1_ID, request); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ final Table response = tableService.createTable(DATABASE_1, request, USER_1_PRINCIPAL); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java index 551a6c350a95e1c9a22fb55d72e04530386cb522..7bae3ac6df8f8ae5c2dabe891ffdf71fa76b36f9 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java @@ -106,12 +106,161 @@ public class TableServiceUnitTest extends AbstractUnitTest { .thenReturn(Optional.empty()); /* test */ +<<<<<<< Updated upstream +======= + assertThrows(TableNotFoundException.class, () -> { + tableService.findByName(DATABASE_3, TABLE_1_INTERNAL_NAME); + }); + } + + @Test + public void updateStatistics_succeeds() throws TableNotFoundException, DataServiceException, + DataServiceConnectionException, SearchServiceException, DatabaseNotFoundException, + SearchServiceConnectionException, MalformedException { + + /* mock */ + when(dataServiceGateway.getTableStatistics(DATABASE_3_ID, TABLE_8_ID)) + .thenReturn(TABLE_8_STATISTIC_DTO); + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + tableService.updateStatistics(TABLE_8); + } + + @Test + public void updateStatistics_searchServiceNotFound_fails() throws TableNotFoundException, DataServiceException, + DataServiceConnectionException, SearchServiceException, DatabaseNotFoundException, + SearchServiceConnectionException { + + /* mock */ + when(dataServiceGateway.getTableStatistics(DATABASE_3_ID, TABLE_8_ID)) + .thenReturn(TABLE_8_STATISTIC_DTO); + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doThrow(DatabaseNotFoundException.class) + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ +>>>>>>> Stashed changes assertThrows(DatabaseNotFoundException.class, () -> { tableService.findByName(DATABASE_3_ID, TABLE_1_INTERNALNAME); }); } @Test +<<<<<<< Updated upstream +======= + public void updateStatistics_searchServiceConnection_fails() throws TableNotFoundException, DataServiceException, + DataServiceConnectionException, SearchServiceException, DatabaseNotFoundException, + SearchServiceConnectionException { + + /* mock */ + when(dataServiceGateway.getTableStatistics(DATABASE_3_ID, TABLE_8_ID)) + .thenReturn(TABLE_8_STATISTIC_DTO); + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doThrow(SearchServiceConnectionException.class) + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + assertThrows(SearchServiceConnectionException.class, () -> { + tableService.updateStatistics(TABLE_8); + }); + } + + @Test + public void updateStatistics_columnNotFound_fails() throws TableNotFoundException, DataServiceException, + DataServiceConnectionException { + final TableStatisticDto mock = TableStatisticDto.builder() + .columns(new HashMap<>() {{ + put("unknown_column", ColumnStatisticDto.builder() + .min(BigDecimal.valueOf(11.2)) + .max(BigDecimal.valueOf(23.1)) + .mean(BigDecimal.valueOf(13.5333)) + .median(BigDecimal.valueOf(11.4)) + .stdDev(BigDecimal.valueOf(4.2952)) + .build()); + }}) + .build(); + + /* mock */ + when(dataServiceGateway.getTableStatistics(DATABASE_3_ID, TABLE_8_ID)) + .thenReturn(mock); + + /* test */ + assertThrows(MalformedException.class, () -> { + tableService.updateStatistics(TABLE_8); + }); + } + + @Test + public void update_known_succeeds() throws SearchServiceException, MalformedException, DataServiceException, + DatabaseNotFoundException, OntologyNotFoundException, SearchServiceConnectionException, + SemanticEntityNotFoundException, DataServiceConnectionException, UnitNotFoundException, + ConceptNotFoundException { + final ColumnSemanticsUpdateDto request = ColumnSemanticsUpdateDto.builder() + .unitUri(UNIT_1_URI) + .conceptUri(CONCEPT_1_URI) + .build(); + + /* mock */ + when(unitService.find(UNIT_1_URI)) + .thenReturn(UNIT_1); + when(conceptService.find(CONCEPT_1_URI)) + .thenReturn(CONCEPT_1); + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + final TableColumn response = tableService.update(TABLE_1_COLUMNS.get(0), request); + assertNotNull(response.getUnit()); + assertNotNull(response.getConcept()); + } + + @Test + public void update_unknown_succeeds() throws SearchServiceException, MalformedException, DataServiceException, + DatabaseNotFoundException, OntologyNotFoundException, SearchServiceConnectionException, + SemanticEntityNotFoundException, DataServiceConnectionException, UnitNotFoundException, + ConceptNotFoundException { + final ColumnSemanticsUpdateDto request = ColumnSemanticsUpdateDto.builder() + .unitUri(UNIT_1_URI) + .conceptUri(CONCEPT_1_URI) + .build(); + + /* mock */ + doThrow(UnitNotFoundException.class) + .when(unitService) + .find(UNIT_1_URI); + when(entityService.findOneByUri(UNIT_1_URI)) + .thenReturn(UNIT_1_ENTITY_DTO); + doThrow(ConceptNotFoundException.class) + .when(conceptService) + .find(CONCEPT_1_URI); + when(entityService.findOneByUri(CONCEPT_1_URI)) + .thenReturn(CONCEPT_1_ENTITY_DTO); + when(databaseRepository.save(any(Database.class))) + .thenReturn(DATABASE_1); + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); + + /* test */ + final TableColumn response = tableService.update(TABLE_1_COLUMNS.get(0), request); + assertNotNull(response.getUnit()); + assertNotNull(response.getConcept()); + } + + @Test +>>>>>>> Stashed changes public void createTable_succeeds() throws DataServiceException, DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException, MalformedException, OntologyNotFoundException, @@ -125,8 +274,14 @@ public class TableServiceUnitTest extends AbstractUnitTest { .createTable(eq(DATABASE_1_ID), any(TableCreateDto.class)); when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ final Table response = tableService.createTable(DATABASE_1, TABLE_3_CREATE_DTO, USER_1_PRINCIPAL); @@ -162,8 +317,14 @@ public class TableServiceUnitTest extends AbstractUnitTest { .createTable(eq(DATABASE_1_ID), any(TableCreateDto.class)); when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ final Table response = tableService.createTable(DATABASE_1, request, USER_1_PRINCIPAL); @@ -215,8 +376,14 @@ public class TableServiceUnitTest extends AbstractUnitTest { .createTable(eq(DATABASE_1_ID), any(TableCreateDto.class)); when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ assertThrows(MalformedException.class, () -> { @@ -238,8 +405,14 @@ public class TableServiceUnitTest extends AbstractUnitTest { doNothing() .when(dataServiceGateway) .createTable(DATABASE_1_ID, TABLE_3_CREATE_DTO); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ final Table response = tableService.createTable(DATABASE_1, TABLE_3_CREATE_DTO, USER_1_PRINCIPAL); @@ -259,8 +432,14 @@ public class TableServiceUnitTest extends AbstractUnitTest { doThrow(DataServiceException.class) .when(dataServiceGateway) .createTable(DATABASE_1_ID, TABLE_5_CREATE_DTO); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ assertThrows(DataServiceException.class, () -> { @@ -357,8 +536,14 @@ public class TableServiceUnitTest extends AbstractUnitTest { doNothing() .when(dataServiceGateway) .deleteTable(DATABASE_1_ID, TABLE_1_ID); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ tableService.deleteTable(TABLE_1); @@ -373,8 +558,14 @@ public class TableServiceUnitTest extends AbstractUnitTest { doNothing() .when(dataServiceGateway) .deleteTable(DATABASE_1_ID, TABLE_4_ID); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ tableService.deleteTable(TABLE_4); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java index 8ca002472a085a58ea5ee58fff8a2a0614c94fd9..c4c8b8bd8c944b8d4769c30250d59e73cf6a858e 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServicePersistenceTest.java @@ -88,8 +88,14 @@ public class ViewServicePersistenceTest extends AbstractUnitTest { doNothing() .when(dataServiceGateway) .deleteView(DATABASE_1_ID, VIEW_1_ID); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ viewService.delete(VIEW_1); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java index cd9fe03c655d33b014239af4f05f0f0ae9b6d1e9..44a0a78d9e17528616173794613edc6f49b3807f 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/ViewServiceUnitTest.java @@ -61,8 +61,14 @@ public class ViewServiceUnitTest extends AbstractUnitTest { .thenReturn(VIEW_1_DTO); when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ final View response = viewService.create(DATABASE_1, USER_1, request); @@ -116,8 +122,14 @@ public class ViewServiceUnitTest extends AbstractUnitTest { .deleteView(DATABASE_1_ID, VIEW_1_ID); when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); +<<<<<<< Updated upstream when(searchServiceGateway.update(any(Database.class))) .thenReturn(DATABASE_1_DTO); +======= + doNothing() + .when(searchServiceGateway) + .update(any(Database.class)); +>>>>>>> Stashed changes /* test */ viewService.delete(VIEW_1); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java index 0bcace730e7753b1dd21d2e1d4a91f47bda6b9f3..1559281af3462181248e492b5facb2bc89429388 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/config/GatewayConfig.java @@ -1,15 +1,27 @@ package at.tuwien.config; +import at.tuwien.api.keycloak.TokenDto; import at.tuwien.auth.InternalRequestInterceptor; +import at.tuwien.exception.AccountNotSetupException; +import at.tuwien.exception.AuthServiceConnectionException; +import at.tuwien.exception.CredentialsInvalidException; import at.tuwien.gateway.KeycloakGateway; import lombok.Getter; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.*; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; import org.springframework.web.client.RestTemplate; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.util.DefaultUriBuilderFactory; +import java.util.List; + @Log4j2 @Getter @Configuration @@ -89,4 +101,27 @@ public class GatewayConfig { return restTemplate; } + @Bean + public WebClient webClient() { + return WebClient.builder() + .baseUrl(searchEndpoint) + .filter(internalFilter()) + .build(); + } + + private ExchangeFilterFunction internalFilter() { + return (request, next) -> { + final HttpHeaders headers = request.headers(); + headers.setAccept(List.of(MediaType.APPLICATION_JSON)); + try { + final TokenDto token = keycloakGateway.obtainUserToken(getSystemUsername(), getSystemPassword()); + headers.setBearerAuth(token.getAccessToken()); + return next.exchange(request); + } catch (AuthServiceConnectionException | CredentialsInvalidException | AccountNotSetupException e) { + log.error("Failed to obtain token for internal user: {}", e.getMessage()); + } + return next.exchange(request); + }; + } + } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/SearchServiceGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/SearchServiceGateway.java index f5e2f49c02023fe9145f137089e4550c9ae5b769..16a6c731b1907eddbbed22fd5f43ddd556659ee5 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/SearchServiceGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/SearchServiceGateway.java @@ -1,12 +1,21 @@ package at.tuwien.gateway; +<<<<<<< Updated upstream import at.tuwien.api.database.DatabaseDto; +======= +>>>>>>> Stashed changes import at.tuwien.entities.database.Database; -import at.tuwien.exception.*; +import at.tuwien.exception.DatabaseNotFoundException; +import at.tuwien.exception.SearchServiceConnectionException; +import at.tuwien.exception.SearchServiceException; public interface SearchServiceGateway { +<<<<<<< Updated upstream DatabaseDto update(Database database) throws SearchServiceConnectionException, SearchServiceException, DatabaseNotFoundException; +======= + void update(Database database) throws SearchServiceConnectionException, SearchServiceException, DatabaseNotFoundException; +>>>>>>> Stashed changes void delete(Long databaseId) throws SearchServiceConnectionException, SearchServiceException, DatabaseNotFoundException; } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java index d97483beb1cac9e590b43a2cdf409067f8eb4d74..f2bed1f846476c58ba903b5ccd8d60bd48a56c0c 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/SearchServiceGatewayImpl.java @@ -11,29 +11,39 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.http.*; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.ResourceAccessException; import org.springframework.web.client.RestTemplate; +import org.springframework.web.reactive.function.client.WebClient; @Log4j2 @Service public class SearchServiceGatewayImpl implements SearchServiceGateway { + private final WebClient webClient; private final RestTemplate restTemplate; private final GatewayConfig gatewayConfig; private final MetadataMapper metadataMapper; @Autowired - public SearchServiceGatewayImpl(@Qualifier("searchServiceRestTemplate") RestTemplate restTemplate, + public SearchServiceGatewayImpl(WebClient webClient, @Qualifier("searchServiceRestTemplate") RestTemplate restTemplate, GatewayConfig gatewayConfig, MetadataMapper metadataMapper) { + this.webClient = webClient; this.restTemplate = restTemplate; this.gatewayConfig = gatewayConfig; this.metadataMapper = metadataMapper; } @Override +<<<<<<< Updated upstream public DatabaseDto update(Database database) throws SearchServiceConnectionException, SearchServiceException, DatabaseNotFoundException { +======= + @Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW) + public void update(Database database) throws SearchServiceConnectionException, SearchServiceException, DatabaseNotFoundException { +>>>>>>> Stashed changes final ResponseEntity<DatabaseDto> response; final HttpHeaders headers = new HttpHeaders(); headers.set("Accept", "application/json"); @@ -42,7 +52,11 @@ public class SearchServiceGatewayImpl implements SearchServiceGateway { log.trace("update database at endpoint {} with path {}", gatewayConfig.getSearchEndpoint(), path); try { response = restTemplate.exchange(path, HttpMethod.PUT, new HttpEntity<>( +<<<<<<< Updated upstream metadataMapper.customDatabaseToDatabaseDto(database), headers), DatabaseDto.class); +======= + metadataMapper.databaseToDatabaseDto(database), headers), DatabaseDto.class); +>>>>>>> Stashed changes } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable | HttpServerErrorException.InternalServerError e) { log.error("Failed to update database: {}", e.getMessage()); @@ -58,7 +72,6 @@ public class SearchServiceGatewayImpl implements SearchServiceGateway { log.error("Failed to update database: response code is not 202"); throw new SearchServiceException("Failed to update database: response code is not 202"); } - return response.getBody(); } @Override diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java index 4866fea2c10b8afa3bb4f93f2eedb3d2aa8f1ad7..34fd6d0fcb093fb64d2878f2dc0940e0dfbac3dc 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java @@ -2,8 +2,13 @@ package at.tuwien.service.impl; import at.tuwien.api.database.table.TableCreateDto; import at.tuwien.api.database.table.TableStatisticDto; +<<<<<<< Updated upstream import at.tuwien.api.database.table.columns.ColumnCreateDto; +======= +import at.tuwien.api.database.table.TableUpdateDto; +>>>>>>> Stashed changes import at.tuwien.api.database.table.columns.ColumnStatisticDto; +import at.tuwien.api.database.table.columns.CreateTableColumnDto; import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto; import at.tuwien.config.RabbitConfig; import at.tuwien.entities.database.Database; @@ -21,6 +26,7 @@ import at.tuwien.service.*; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import java.security.Principal; @@ -94,11 +100,15 @@ public class TableServiceImpl implements TableService { } @Override +<<<<<<< Updated upstream @Transactional public Table createTable(Database database, TableCreateDto data, Principal principal) throws DataServiceException, +======= + @Transactional(propagation = Propagation.REQUIRED) + public Table createTable(Database database, CreateTableDto data, Principal principal) throws DataServiceException, +>>>>>>> Stashed changes DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, - TableExistsException, SearchServiceException, SearchServiceConnectionException, MalformedException, - OntologyNotFoundException, SemanticEntityNotFoundException { + TableExistsException, MalformedException, OntologyNotFoundException, SemanticEntityNotFoundException { final User owner = userService.findByUsername(principal.getName()); /* map table */ final Table table = Table.builder() @@ -256,9 +266,8 @@ public class TableServiceImpl implements TableService { @Override @Transactional - public void updateStatistics(Table table) throws SearchServiceException, - DatabaseNotFoundException, SearchServiceConnectionException, MalformedException, TableNotFoundException, - DataServiceException, DataServiceConnectionException { + public void updateStatistics(Table table) throws MalformedException, TableNotFoundException, DataServiceException, + DataServiceConnectionException, DatabaseNotFoundException { final TableStatisticDto statistic = dataServiceGateway.getTableStatistics(table.getTdbid(), table.getId()); if (statistic == null) { return; @@ -289,7 +298,6 @@ public class TableServiceImpl implements TableService { /* update in open search service */ searchServiceGateway.update(database); log.info("Updated statistics for the table and {} column(s)", table.getColumns().size()); - log.trace("updated statistics: {}", table); } } diff --git a/dbrepo-search-service/Pipfile.lock b/dbrepo-search-service/Pipfile.lock index 123e864f6dd050a838ae2c7e9137a4d7b3f1e27f..e4917444da8eb3659bda8af0326e082fad0835a9 100644 --- a/dbrepo-search-service/Pipfile.lock +++ b/dbrepo-search-service/Pipfile.lock @@ -1,7 +1,11 @@ { "_meta": { "hash": { +<<<<<<< Updated upstream "sha256": "491e5f6ada48e8af417dfa7d6a0b4d98ccf9b9072df53b44d8de014b687fc80c" +======= + "sha256": "2ff9fc673f1fb1e5dc272aa711f4e730088fa0188b44449db042abf99b6c4db7" +>>>>>>> Stashed changes }, "pipfile-spec": 6, "requires": { @@ -388,9 +392,15 @@ }, "dbrepo": { "hashes": [ +<<<<<<< Updated upstream "sha256:84607677b0826bb9b2fa120aacdf56d16c8d9ae423f435b2bd2c22b1c965a33c" ], "path": "./lib/dbrepo-1.4.7.tar.gz" +======= + "sha256:7f98329f08d1da6fe45da8130cfb3ebd6e947a4101d46f92b31d7204b29a153d" + ], + "path": "./lib/dbrepo-1.6.3.tar.gz" +>>>>>>> Stashed changes }, "docker": { "hashes": [ diff --git a/dbrepo-search-service/init/lib/dbrepo-1.6.3-py3-none-any.whl b/dbrepo-search-service/init/lib/dbrepo-1.6.3-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..d9c6af3e4a3f6a722cc5d1248c9aafd04a41cbda Binary files /dev/null and b/dbrepo-search-service/init/lib/dbrepo-1.6.3-py3-none-any.whl differ diff --git a/dbrepo-search-service/init/lib/dbrepo-1.6.3.tar.gz b/dbrepo-search-service/init/lib/dbrepo-1.6.3.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..3e302ea2286d2d6548e9917019397abab93a22e0 Binary files /dev/null and b/dbrepo-search-service/init/lib/dbrepo-1.6.3.tar.gz differ diff --git a/dbrepo-search-service/lib/dbrepo-1.6.3-py3-none-any.whl b/dbrepo-search-service/lib/dbrepo-1.6.3-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..d9c6af3e4a3f6a722cc5d1248c9aafd04a41cbda Binary files /dev/null and b/dbrepo-search-service/lib/dbrepo-1.6.3-py3-none-any.whl differ diff --git a/dbrepo-search-service/lib/dbrepo-1.6.3.tar.gz b/dbrepo-search-service/lib/dbrepo-1.6.3.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..3e302ea2286d2d6548e9917019397abab93a22e0 Binary files /dev/null and b/dbrepo-search-service/lib/dbrepo-1.6.3.tar.gz differ diff --git a/dbrepo-ui/composables/table-service.ts b/dbrepo-ui/composables/table-service.ts index 3d87e68d4febed8b825a56b1aada946bd6b0f4d5..9670f16e56d61192b8be1ca8cd8380c2cbb470cc 100644 --- a/dbrepo-ui/composables/table-service.ts +++ b/dbrepo-ui/composables/table-service.ts @@ -230,13 +230,6 @@ export const useTableService = (): any => { } } - function isOwner(table: TableDto, user: UserDto) { - if (!table || !user) { - return false - } - return table.owner.id === user.id - } - function tableNameToInternalName(name: string) { return name.normalize('NFKD') .toLowerCase() @@ -271,7 +264,6 @@ export const useTableService = (): any => { suggest, prepareColumns, prepareConstraints, - isOwner, tableNameToInternalName } } diff --git a/dbrepo-ui/pages/database/[database_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/info.vue index 432b14e21a60968048440da6f0084eb535aa06a7..9d6acbcf4b2999e6c1728962c11b1691c18b7ec8 100644 --- a/dbrepo-ui/pages/database/[database_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/info.vue @@ -112,8 +112,16 @@ v-if="access" :title="$t('pages.database.connection.title')" density="compact"> +<<<<<<< Updated upstream <pre class="pb-1">{{ jdbcString }}</pre> +======= + <div> + <UserBadge + :user="database.owner" + :other-user="cacheUser" /> + </div> +>>>>>>> Stashed changes </v-list-item> <v-list-item v-if="database.contact" @@ -122,7 +130,7 @@ <div> <UserBadge :user="database.contact" - :other-user="user" /> + :other-user="cacheUser" /> </div> </v-list-item> </v-list> @@ -181,6 +189,7 @@ </div> </template> +<<<<<<< Updated upstream <script setup> const config = useRuntimeConfig() const { database_id } = useRoute().params @@ -191,6 +200,8 @@ if (data.value) { useServerSeoMeta(identifierService.databaseToServerSeoMeta(data.value)) } </script> +======= +>>>>>>> Stashed changes <script> import DatabaseToolbar from '@/components/database/DatabaseToolbar.vue' import Summary from '@/components/identifier/Summary.vue' diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/import.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/import.vue index 9da3e1c9fd9774ca61be0be90af9a7050d6fba3c..32862334e8718ab82e64e20ce6e05b1440f8e020 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/import.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/import.vue @@ -83,6 +83,9 @@ export default { table () { return this.cacheStore.getTable }, + access () { + return this.cacheStore.getAccess + }, title () { if (!this.table) { return this.$t('pages.table.import.title') diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue index 0221c64df232721f3a81b6bf2641ad37ce6fbf32..90ca284f0af300859cba5f713ce848bfdf192048 100644 --- a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/info.vue @@ -152,6 +152,8 @@ </v-card> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> + <pre>table={{ table }}</pre> + <pre>access={{ access }}</pre> </template> <script setup> @@ -234,14 +236,35 @@ export default { roles () { return this.userStore.getRoles }, + access () { + return this.cacheStore.getAccess + }, canRead () { - if (this.database && this.database.is_public) { + if (!this.database || !this.access || this.database.is_public) { return true } +<<<<<<< Updated upstream if (!this.user || !this.access) { return false } return this.access.type === 'read' || this.access.type === 'write_own' || this.access.type === 'write_all' +======= + const userService = useUserService() + return userService.hasReadAccess(this.access) + }, + canViewInfo () { + if (this.error || !this.table) { + return false + } + if (this.table.is_public || this.table.is_schema_public) { + return true + } + if (!this.access) { + return false + } + const userService = useUserService() + return userService.hasReadAccess(this.access) +>>>>>>> Stashed changes }, canWrite () { if (!this.table || !this.user || !this.access) { @@ -255,9 +278,12 @@ export default { } return formatTimestampUTCLabel(this.table.created) }, +<<<<<<< Updated upstream access () { return this.userStore.getAccess }, +======= +>>>>>>> Stashed changes hasDescription () { return this.table && this.table.description }, diff --git a/dbrepo-ui/pages/database/[database_id]/table/[table_id]/settings.vue b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/settings.vue new file mode 100644 index 0000000000000000000000000000000000000000..90a03e649b52e42e02a9b65331f653ab44d34e07 --- /dev/null +++ b/dbrepo-ui/pages/database/[database_id]/table/[table_id]/settings.vue @@ -0,0 +1,329 @@ +<template> + <div + v-if="canUpdateTable"> + <TableToolbar /> + <v-window + v-model="tab"> + <v-window-item> + <v-form + ref="form" + v-model="valid" + autocomplete="off" + @submit.prevent="submit"> + <v-card + variant="flat" + rounded="0" + :title="$t('pages.table.settings.title')" + :subtitle="$t('pages.table.settings.subtitle')"> + <v-card-text> + <v-row> + <v-col + md="8"> + <v-textarea + v-model="modify.description" + rows="2" + :rules="[ + v => max(v, 180) || ($t('validation.max-length') + 180), + ]" + clearable + counter="180" + persistent-counter + persistent-hint + :variant="inputVariant" + :hint="$t('pages.table.subpages.import.description.hint')" + :label="$t('pages.table.subpages.import.description.label')"/> + </v-col> + </v-row> + <v-row + dense> + <v-col + md="4"> + <v-select + v-model="modify.is_public" + :items="dataOptions" + persistent-hint + :variant="inputVariant" + required + :rules="[ + v => v !== null || $t('validation.required') + ]" + :label="$t('pages.database.resource.data.label')" + :hint="$t('pages.database.resource.data.hint', { resource: 'table' })" /> + </v-col> + <v-col + md="4"> + <v-select + v-model="modify.is_schema_public" + :items="schemaOptions" + persistent-hint + :variant="inputVariant" + required + :rules="[ + v => v !== null || $t('validation.required') + ]" + :label="$t('pages.database.resource.schema.label')" + :hint="$t('pages.database.resource.schema.hint', { resource: 'table', schema: 'columns' })" /> + </v-col> + </v-row> + <v-row> + <v-col> + <v-btn + id="database" + variant="flat" + size="small" + :disabled="!valid || !isChange" + :color="buttonColor" + :loading="loading" + type="submit" + :text="$t('navigation.modify')" + @click="update" /> + </v-col> + </v-row> + </v-card-text> + </v-card> + </v-form> + <v-divider + v-if="canDropTable" /> + <v-card + v-if="canDropTable" + variant="flat" + rounded="0" + :title="$t('pages.table.delete.title')" + :subtitle="$t('pages.table.delete.subtitle', { table: table.internal_name })"> + <v-card-text> + <v-row> + <v-col + md="8"> + <v-btn + size="small" + variant="flat" + color="error" + @click="askDelete"> + {{ $t('navigation.delete')}} + </v-btn> + </v-col> + </v-row> + </v-card-text> + </v-card> + </v-window-item> + </v-window> + <v-breadcrumbs + :items="items" + class="pa-0 mt-2" /> + </div> +</template> + +<script> +import TableToolbar from '@/components/table/TableToolbar.vue' +import { useCacheStore } from '@/stores/cache.js' +import { max } from '@/utils' + +export default { + components: { + TableToolbar + }, + data () { + return { + tab: 0, + valid: false, + loading: false, + modify: { + description: null, + is_public: null, + is_schema_public: null + }, + dataOptions: [ + { title: this.$t('pages.database.resource.data.enabled'), value: true }, + { title: this.$t('pages.database.resource.data.disabled'), value: false }, + ], + schemaOptions: [ + { title: this.$t('pages.database.resource.schema.enabled'), value: true }, + { title: this.$t('pages.database.resource.schema.disabled'), value: false }, + ], + items: [ + { + title: this.$t('navigation.databases'), + to: '/database' + }, + { + title: `${this.$route.params.database_id}`, + to: `/database/${this.$route.params.database_id}/info` + }, + { + title: this.$t('navigation.tables'), + to: `/database/${this.$route.params.database_id}/table` + }, + { + title: `${this.$route.params.table_id}`, + to: `/database/${this.$route.params.database_id}/table/${this.$route.params.table_id}` + }, + { + title: this.$t('navigation.settings'), + to: `/database/${this.$route.params.database_id}/table/${this.$route.params.table_id}/settings`, + disabled: true + } + ], + headers: [ + { value: 'internal_name', title: this.$t('pages.table.subpages.schema.internal-name.title') }, + { value: 'type', title: this.$t('pages.table.subpages.schema.column-type.title') }, + { value: 'extra', title: this.$t('pages.table.subpages.schema.extra.title') }, + { value: 'column_concept', title: this.$t('pages.table.subpages.schema.concept.title') }, + { value: 'column_unit', title: this.$t('pages.table.subpages.schema.unit.title') }, + { value: 'is_null_allowed', title: this.$t('pages.table.subpages.schema.nullable.title') }, + { value: 'description', title: this.$t('pages.table.subpages.schema.description.title') }, + ], + dateColumns: [], + cacheStore: useCacheStore() + } + }, + computed: { + database () { + return this.cacheStore.getDatabase + }, + table () { + return this.cacheStore.getTable + }, + access () { + return this.cacheStore.getAccess + }, + cacheUser () { + return this.cacheStore.getUser + }, + roles () { + return this.cacheStore.getRoles + }, + isChange () { + if (!this.table) { + return false + } + if (this.table.is_public !== this.modify.is_public) { + return true + } + return this.table.is_schema_public !== this.modify.is_schema_public + }, + canUpdateTable () { + if (!this.cacheUser || !this.table || !this.access || !this.roles || !this.roles.includes('update-table')) { + return false + } + const userService = useUserService() + return userService.hasReadAccess(this.access) && this.table.owner.id === this.cacheUser.uid + }, + canDropTable () { + if (!this.roles || !this.table || !this.cacheUser) { + return false + } + if (this.roles.includes('delete-foreign-table')) { + return true + } + return this.table.owner.id === this.cacheUser.uid && this.roles.includes('delete-table') && this.table.identifiers.length === 0 + }, + inputVariant () { + const runtimeConfig = useRuntimeConfig() + return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.input.contrast : runtimeConfig.public.variant.input.normal + }, + buttonVariant () { + const runtimeConfig = useRuntimeConfig() + return this.$vuetify.theme.global.name.toLowerCase().endsWith('contrast') ? runtimeConfig.public.variant.button.contrast : runtimeConfig.public.variant.button.normal + }, + buttonColor () { + return !this.isChange ? null : 'warning' + } + }, + mounted() { + if (!this.table) { + return + } + this.modify.is_public = this.table.is_public + this.modify.is_schema_public = this.table.is_schema_public + this.modify.description = this.table.description + }, + methods: { + max, + submit () { + this.$refs.form.validate() + }, + extra (column) { + if (column.type === 'float') { + return `precision=${column.size}` + } else if (['decimal', 'double'].includes(column.type)) { + let extra = '' + if (column.size !== null) { + extra += `size=${column.size}` + } + if (column.d !== null) { + if (extra.length > 0) { + extra += ', ' + } + extra += `d=${column.d}` + } + return extra + } else if (column.type === 'enum') { + return `(${column.enums.join(', ')})` + } else if (column.type === 'set') { + return `(${column.sets.join(', ')})` + } else if (['int', 'char', 'varchar', 'binary', 'varbinary', 'tinyint', 'size="small"int', 'mediumint', 'bigint'].includes(column.type)) { + return column.size !== null ? `size=${column.size}` : '' + } + return null + }, + closed (event) { + const { success } = event + console.debug('closed dialog', event) + if (success) { + const toast = useToastInstance() + toast.success(this.$t('success.table.semantics')) + this.cacheStore.reloadTable() + } + this.dialogSemantic = false + }, + update () { + this.loading = true + const tableService = useTableService() + tableService.update(this.$route.params.database_id, this.$route.params.table_id, this.modify) + .then(() => { + this.loading = false + const toast = useToastInstance() + toast.success(this.$t('success.table.updated', { table: this.table.internal_name })) + this.$emit('close', { success: true }) + this.cacheStore.reloadTable() + }) + .catch(({ code }) => { + this.loading = false + const toast = useToastInstance() + if (typeof code !== 'string') { + return + } + toast.error(this.$t(code)) + }) + .finally(() => { + this.loading = false + }) + }, + askDelete () { + if (!confirm(this.$t('pages.table.delete.subtitle', { table: this.table.internal_name }))) { + return + } + this.loadingDelete = true + const tableService = useTableService() + tableService.remove(this.database.id, this.table.id) + .then(() => { + console.info('Deleted table with id ', this.table.id) + this.cacheStore.reloadDatabase() + const toast = useToastInstance() + toast.success('Successfully deleted table with id ' + this.table.id) + this.$router.push(`/database/${this.$route.params.database_id}/table`) + }) + .catch(({code, message}) => { + const toast = useToastInstance() + if (typeof code !== 'string') { + return + } + toast.error(this.$t(code)) + }) + .finally(() => { + this.loadingDelete = false + }) + } + } +} +</script> diff --git a/dbrepo-ui/pages/database/[database_id]/view/create.vue b/dbrepo-ui/pages/database/[database_id]/view/create.vue index 839b79e243d4ceb7903e8a81ee9da0306d29697a..bdb9e4e7056ab97dbabb77abaf1be456c695d1c8 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/create.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/create.vue @@ -1,12 +1,20 @@ <template> +<<<<<<< Updated upstream <div v-if="canCreateView"> <Builder mode="view" /> +======= + <div + v-if="canCreateView"> + <Builder + mode="view" /> +>>>>>>> Stashed changes <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> </template> <script> import Builder from '@/components/subset/Builder.vue' +import { useCacheStore } from '@/stores/cache.js' export default { components: { @@ -33,7 +41,11 @@ export default { disabled: true } ], +<<<<<<< Updated upstream userStore: useUserStore() +======= + cacheStore: useCacheStore() +>>>>>>> Stashed changes } }, computed: { @@ -44,7 +56,7 @@ export default { return this.userStore.getRoles }, canCreateView () { - if (!this.roles) { + if (!this.roles || !this.access) { return false } return this.roles.includes('create-database-view') diff --git a/dbrepo-ui/pages/database/[database_id]/view/index.vue b/dbrepo-ui/pages/database/[database_id]/view/index.vue index dc87510ae887285ac36fc647e8f2a172cb708784..7ee5736216b79d84dd94eb386bafd91e6d7ed855 100644 --- a/dbrepo-ui/pages/database/[database_id]/view/index.vue +++ b/dbrepo-ui/pages/database/[database_id]/view/index.vue @@ -1,5 +1,10 @@ <template> +<<<<<<< Updated upstream <div> +======= + <div + v-if="canViewViews"> +>>>>>>> Stashed changes <DatabaseToolbar /> <v-window v-model="tab"> <ViewList /> @@ -39,8 +44,29 @@ export default { } }, computed: { +<<<<<<< Updated upstream tab () { return 1 +======= + database () { + return this.cacheStore.getDatabase + }, + access () { + return this.cacheStore.getAccess + }, + canViewViews () { + if (!this.database) { + return false + } + if (this.database.is_schema_public || this.database.is_public) { + return true + } + if (!this.access) { + return false + } + const userService = useUserService() + return userService.hasReadAccess(this.access) +>>>>>>> Stashed changes } }, mounted () { diff --git a/dbrepo-ui/pages/user/index.vue b/dbrepo-ui/pages/user/index.vue index e729d9086f2be6604c2b9d0222c00acc79297f85..d53b2f42cc8bd7966db208242ad0a8b1736b3428 100644 --- a/dbrepo-ui/pages/user/index.vue +++ b/dbrepo-ui/pages/user/index.vue @@ -2,6 +2,9 @@ <div /> </template> +<script setup> +const { loggedIn } = useOidcAuth() +</script> <script> import { useUserStore } from '@/stores/user' diff --git a/docker-compose.yml b/docker-compose.yml index 86c47b6af9cf29978dbb01b92481a586e3f3b7e0..2f6d10f1c49ffdb2b23241db3f1da3a265aaa74c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,8 +20,6 @@ services: - metadata-db-data:/bitnami/mariadb - ./dbrepo-metadata-db/1_setup-schema.sql:/docker-entrypoint-initdb.d/1_setup-schema.sql - ./dbrepo-metadata-db/2_setup-data.sql:/docker-entrypoint-initdb.d/2_setup-data.sql - ports: - - "3306:3306" environment: MARIADB_DATABASE: "${METADATA_DB:-dbrepo}" MARIADB_ROOT_PASSWORD: "${METADATA_DB_PASSWORD:-dbrepo}" @@ -118,7 +116,7 @@ services: context: ./dbrepo-metadata-service network: host ports: - - "9099:8080" + - "9099:18080" volumes: - "${SHARED_VOLUME:-/tmp}:/tmp" environment: diff --git a/helm/dbrepo/files/create-event-listener.jar b/helm/dbrepo/files/create-event-listener.jar new file mode 100644 index 0000000000000000000000000000000000000000..221bdd325f056ff953e0a44a46773470eb08e91e Binary files /dev/null and b/helm/dbrepo/files/create-event-listener.jar differ diff --git a/helm/dbrepo/templates/auth-configmap.yaml b/helm/dbrepo/templates/auth-configmap.yaml index 557d99072513ec0330848d467db2501982853c0e..5e645184f8c8ba43dd7a4439593015a5a5b7768c 100644 --- a/helm/dbrepo/templates/auth-configmap.yaml +++ b/helm/dbrepo/templates/auth-configmap.yaml @@ -4,6 +4,9 @@ kind: ConfigMap metadata: name: auth-service-config namespace: {{ include "common.names.namespace" . | quote }} +binaryData: + create-event-listener.jar: | + {{ .Files.Get "files/create-event-listener.jar" | b64enc | nindent 4 }} data: KC_HOSTNAME_PATH: "/api/auth" KC_HOSTNAME_ADMIN_URL: "{{ .Values.gateway }}/api/auth" diff --git a/helm/dbrepo/values.yaml b/helm/dbrepo/values.yaml index 68c2e4e06fed820f6c5858efdce9bcf97550fada..5adce66ac803347cefc626687b9e113364ad7c7d 100644 --- a/helm/dbrepo/values.yaml +++ b/helm/dbrepo/values.yaml @@ -115,7 +115,20 @@ authservice: ## @skip authservice.extraVolumeMounts extraVolumeMounts: - name: config-map +<<<<<<< Updated upstream mountPath: /opt/bitnami/keycloak/data/import +======= + mountPath: /opt/keycloak/data/import/dbrepo-realm.json + subPath: dbrepo-realm.json + - name: config-map + mountPath: /opt/keycloak/data/import/master-realm.json + subPath: master-realm.json + - name: config-map + mountPath: /opt/bitnami/keycloak/providers/create-event-listener.jar + subPath: create-event-listener.jar + - name: cache + mountPath: /bitnami/keycloak/ +>>>>>>> Stashed changes ## @skip authservice.replicaCount The number of replicas. replicaCount: 2 @@ -126,6 +139,7 @@ datadb: enabled: true ## @skip datadb.fullnameOverride fullnameOverride: data-db +<<<<<<< Updated upstream database: image: ## @param datadb.database.image.debug Set the logging level to `trace`. Otherwise, set to `info`. @@ -143,6 +157,46 @@ datadb: replicationUser: replication ## @param datadb.auth.replicationPassword The database replication user password replicationPassword: replication +======= + ## @param datadb.host The hostname for the microservices. + host: data-db + ## @param datadb.extraFlags Extra flags to ensure the query store works as intended, ref https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/api/data-db/#data + extraFlags: "--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci" + rootUser: + ## @param datadb.rootUser.user The root username. + user: root + ## @param datadb.rootUser.password The root user password. + password: dbrepo + db: + ## @param datadb.db.name The database name. + name: dbrepo + galera: + mariabackup: + ## @param datadb.galera.mariabackup.user The database backup username. + user: backup + ## @param datadb.galera.mariabackup.password The database backup user password + password: backup + ## @param datadb.jdbcExtraArgs The extra arguments for JDBC connections in the microservices. + jdbcExtraArgs: "" + metrics: + ## @skip datadb.metrics.enabled The Prometheus settings. + enabled: true + ## @param datadb.replicaCount The number of cluster nodes, should be uneven i.e. 2n+1 + replicaCount: 3 + resources: + resources: + limits: + cpu: 750m + ephemeral-storage: 2Gi + memory: 1536Mi + requests: + cpu: 500m + ephemeral-storage: 50Mi + memory: 1000Mi + persistence: + ## @param datadb.persistence.enabled Enable persistent storage. + enabled: true +>>>>>>> Stashed changes ## @section Search Database diff --git a/make/dev.mk b/make/dev.mk index 76c05989eb224c0ca0625f4d380f6467b8688f2f..3ede2683dfdcb62e5e5a16ce29c0de67513ae5ba 100644 --- a/make/dev.mk +++ b/make/dev.mk @@ -27,4 +27,9 @@ package-config: ## Package the config files cp ./dbrepo-gateway-service/dbrepo.conf ./.docker/config cp ./dbrepo-metric-db/prometheus.yml ./.docker/config cp ./dbrepo-storage-service/s3_config.json ./.docker/config +<<<<<<< Updated upstream +======= + cp ./dbrepo-upload-service/pre-create.sh ./.docker/config + cp ./dbrepo-auth-service/listeners/target/create-event-listener.jar ./.docker/config +>>>>>>> Stashed changes cd ./.docker && tar czf ./dist.tar.gz ./docker-compose.yml ./.env ./config