diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/QueryMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/QueryMapper.java index a96053ee95bd3e07c91b3d1a6217d702497d524d..fb186a6474df5cddc19fe8fed680c220d8833cfb 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/QueryMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/QueryMapper.java @@ -72,9 +72,7 @@ public interface QueryMapper { String nowhitespace = WHITESPACE.matcher(data).replaceAll("_"); String normalized = Normalizer.normalize(nowhitespace, Normalizer.Form.NFD); String slug = NONLATIN.matcher(normalized).replaceAll(""); - final String name = slug.toLowerCase(Locale.ENGLISH); - log.trace("mapped name {} to name {}", data, name); - return name; + return slug.toLowerCase(Locale.ENGLISH); } default QueryResultDto resultListToQueryResultDto(List<TableColumn> columns, ResultSet result) throws SQLException { diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/TableMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/TableMapper.java index fbdb04f252d9a99e14ba3ccb0b81d92b230cc373..9f91dd3bc28b461e2b3981ab658242d194528b01 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/TableMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/TableMapper.java @@ -219,14 +219,14 @@ public interface TableMapper { @Mappings({ @Mapping(source = "table", target = "table"), @Mapping(target = "id", ignore = true), - @Mapping(target = "autoGenerated", expression = "java(data.getInternalName() == \"id\" && query.getGenerated())"), + @Mapping(target = "autoGenerated", ignore = true), @Mapping(source = "data.name", target = "name"), @Mapping(source = "data.internalName", target = "internalName"), @Mapping(source = "data.created", target = "created"), @Mapping(source = "data.dateFormat", target = "dateFormat"), @Mapping(source = "data.lastModified", target = "lastModified"), }) - TableColumn tableColumnToTableColumn(Table table, TableColumn data, TableCreateRawQuery query); + TableColumn tableColumnToTableColumn(Table table, TableColumn data); @Named("internalMapping") default String nameToInternalName(String data) { @@ -239,9 +239,7 @@ public interface TableMapper { String normalized = Normalizer.normalize(nowhitespace, Normalizer.Form.NFD); String slug = NONLATIN.matcher(normalized).replaceAll("_") .replaceAll("-", "_"); - final String name = slug.toLowerCase(Locale.ENGLISH); - log.trace("mapped name {} to internal name {}", data, name); - return name; + return slug.toLowerCase(Locale.ENGLISH); } @Mappings({ @@ -332,13 +330,12 @@ public interface TableMapper { } /** - * Map the table to a create table query - * TODO for e.g. postgres image + * Map the table to a create table and eventual create sequence query. * * @param data The table * @return The create table query */ - default TableCreateRawQuery tableToCreateTableRawQuery(Connection connection, TableCreateDto data) + default PreparedStatement tableToCreateTableRawQuery(Connection connection, TableCreateDto data) throws TableMalformedException, QueryMalformedException { final StringBuilder query = new StringBuilder("CREATE TABLE `") .append(nameToInternalName(data.getName())) @@ -359,9 +356,10 @@ public interface TableMapper { .build(); log.trace("attempt to create id column {}", idColumn); if (data.getColumns().stream().anyMatch(c -> c.getName().equals("id"))) { - log.error("Cannot create id column, it already exists"); - throw new TableMalformedException("Cannot create id column"); + log.error("Cannot create id column: it already exists"); + throw new TableMalformedException("Cannot create id column: it already exists"); } + /* metadata */ final List<ColumnCreateDto> columns = new LinkedList<>(); columns.add(idColumn); columns.addAll(data.getColumns()); @@ -378,8 +376,7 @@ public interface TableMapper { /* null expressions */ .append(column.getNullAllowed() != null && column.getNullAllowed() ? " NULL" : " NOT NULL") /* default expressions */ - .append(!primaryColumnExists && column.getName().equals( - "id") ? " DEFAULT NEXTVAL(`" + tableCreateDtoToSequenceName(data) + "`)" : ""); + .append(!primaryColumnExists && column.getName().equals("id") ? " AUTO_INCREMENT" : ""); } /* create primary key index */ query.append(", PRIMARY KEY (") @@ -432,62 +429,14 @@ public interface TableMapper { query.append(") WITH SYSTEM VERSIONING;"); log.trace("create table query built with {} columns and system versioning", data.getColumns().size()); try { - final PreparedStatement pstmt = connection.prepareStatement(query.toString()); - log.trace("prepared create table statement {}", query); - return TableCreateRawQuery.builder() - .preparedStatement(pstmt) - .generated(!primaryColumnExists) - .build(); + log.trace("mapped create table statement: {}", query); + return connection.prepareStatement(query.toString()); } catch (SQLException e) { log.error("Failed to prepare statement {}, reason: {}", query, e.getMessage()); throw new QueryMalformedException("Failed to prepare statement", e); } } - default String tableCreateDtoToSequenceName(TableCreateDto data) { - final String name = "seq_" + nameToInternalName(data.getName()) + "_id"; - log.trace("mapped name {} to internal name {}", data.getName(), name); - return name; - } - - default PreparedStatement tableToCreateSequenceRawQuery(Connection connection, Database database, TableCreateDto data) - throws ImageNotSupportedException, QueryMalformedException { - if (!database.getContainer().getImage().getName().equals("mariadb")) { - log.error("Currently only MariaDB is supported"); - throw new ImageNotSupportedException("Currently only MariaDB is supported"); - } - final StringBuilder statement = new StringBuilder("CREATE SEQUENCE `") - .append(tableCreateDtoToSequenceName(data)) - .append("` START WITH 1 INCREMENT BY 1 NOCACHE;"); - try { - final PreparedStatement pstmt = connection.prepareStatement(statement.toString()); - log.trace("prepared create sequence statement {}", statement); - return pstmt; - } catch (SQLException e) { - log.error("Failed to prepare statement {}, reason: {}", statement, e.getMessage()); - throw new QueryMalformedException("Failed to prepare statement", e); - } - } - - default PreparedStatement tableToDropSequenceRawQuery(Connection connection, Database database, TableCreateDto data) - throws ImageNotSupportedException, QueryMalformedException { - if (!database.getContainer().getImage().getName().equals("mariadb")) { - log.error("Currently only MariaDB is supported"); - throw new ImageNotSupportedException("Currently only MariaDB is supported"); - } - final StringBuilder statement = new StringBuilder("DROP SEQUENCE `") - .append(tableCreateDtoToSequenceName(data)) - .append("`;"); - try { - final PreparedStatement pstmt = connection.prepareStatement(statement.toString()); - log.trace("prepared drop sequence statement {}", statement); - return pstmt; - } catch (SQLException e) { - log.error("Failed to prepare statement {}, reason: {}", statement, e.getMessage()); - throw new QueryMalformedException("Failed to prepare statement", e); - } - } - default PreparedStatement tableToCreateHistoryViewRawQuery(Connection connection, Table data) throws QueryMalformedException { final StringBuilder statement = new StringBuilder("CREATE VIEW `hs_") .append(data.getInternalName()) diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/ViewMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/ViewMapper.java index a864436151ec128c4a3effd1416a3d5baff04da2..ad8ee0e23eee9139485fcf9b014a11082cd040c6 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/ViewMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/ViewMapper.java @@ -32,9 +32,7 @@ public interface ViewMapper { String nowhitespace = WHITESPACE.matcher(data).replaceAll("_"); String normalized = Normalizer.normalize(nowhitespace, Normalizer.Form.NFD); String slug = NONLATIN.matcher(normalized).replaceAll(""); - final String name = slug.toLowerCase(Locale.ENGLISH); - log.trace("mapped name {} to internal name {}", data, name); - return name; + return slug.toLowerCase(Locale.ENGLISH); } @Mappings({ 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 3b29e987bcca3b23a06fc663e793d7069c93db1d..10d0ae805ff6e6fbe1303571d469e0e5d35c2fb9 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 @@ -14,6 +14,7 @@ import at.tuwien.service.TableService; import at.tuwien.utils.PrincipalUtil; import at.tuwien.validation.EndpointValidator; import io.micrometer.core.annotation.Timed; +import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -59,7 +60,7 @@ public class TableEndpoint { @GetMapping @Transactional(readOnly = true) - @Timed(value = "table.list", description = "Time needed to list the tables") + @Observed(name = "dbr_tables_findall") @Operation(summary = "List all tables", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -95,7 +96,7 @@ public class TableEndpoint { @PostMapping @Transactional @PreAuthorize("hasAuthority('create-table')") - @Timed(value = "table.create", description = "Time needed to create a table") + @Observed(name = "dbr_table_create") @Operation(summary = "Create a table", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "201", @@ -141,6 +142,11 @@ public class TableEndpoint { TableNameExistsException, ContainerNotFoundException, UserNotFoundException, QueryMalformedException, NotAllowedException, AccessDeniedException { log.debug("endpoint create table, databaseId={}, createDto={}, {}", databaseId, createDto, PrincipalUtil.formatForDebug(principal)); + /* checks */ + if (createDto.getName().isBlank()) { + log.error("Failed create table: table name is blank"); + throw new TableMalformedException("Failed create table: table name is blank"); + } endpointValidator.validateOnlyAccess(databaseId, principal, true); endpointValidator.validateColumnCreateConstraints(createDto); final Table table = tableService.createTable(databaseId, createDto, principal); @@ -153,7 +159,7 @@ public class TableEndpoint { @GetMapping("/{tableId}") @Transactional(readOnly = true) - @Timed(value = "table.find", description = "Time needed to find a table") + @Observed(name = "dbr_tables_find") @Operation(summary = "Get information about table", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -196,7 +202,7 @@ public class TableEndpoint { @DeleteMapping("/{tableId}") @Transactional @PreAuthorize("hasAuthority('delete-table')") - @Timed(value = "table.delete", description = "Time needed to delete a table") + @Observed(name = "dbr_table_delete") @Operation(summary = "Delete a table", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "202", diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableHistoryEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableHistoryEndpoint.java index 90a61181ba259160d6c208da198c2782ebd59f8e..8e8c79d3f41f57f2f0175a8d2cba98f0cce579e2 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableHistoryEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableHistoryEndpoint.java @@ -6,6 +6,7 @@ import at.tuwien.exception.*; import at.tuwien.service.TableService; import at.tuwien.utils.PrincipalUtil; import io.micrometer.core.annotation.Timed; +import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -38,7 +39,7 @@ public class TableHistoryEndpoint { @RequestMapping(method = {RequestMethod.GET, RequestMethod.HEAD}) @Transactional(readOnly = true) - @Timed(value = "history.list", description = "Time needed to retrieve table history") + @Observed(name = "dbr_table_history_findall") @Operation(summary = "Find all history", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "200", diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java index 5ea977c641d54c9339b7f79e9eb7cffa191dbb37..9e3f3d71e7b59e91fbc1e318ff49a61d2c47ba20 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java @@ -13,6 +13,7 @@ import at.tuwien.service.UserService; import at.tuwien.utils.PrincipalUtil; import at.tuwien.utils.UserUtil; import io.micrometer.core.annotation.Timed; +import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -58,7 +59,7 @@ public class UserEndpoint { @GetMapping @Transactional(readOnly = true) - @Timed(value = "user.list", description = "Time needed to list all users in the metadata database") + @Observed(name = "dbr_users_findall") @Operation(summary = "Find all users") @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -80,7 +81,7 @@ public class UserEndpoint { @PostMapping @Transactional(rollbackFor = Exception.class) @PreAuthorize("!isAuthenticated()") - @Timed(value = "user.create", description = "Time needed to create a user in the metadata database") + @Observed(name = "dbr_user_create") @Operation(summary = "Create user") @ApiResponses(value = { @ApiResponse(responseCode = "201", @@ -146,7 +147,7 @@ public class UserEndpoint { @GetMapping("/{id}") @Transactional @PreAuthorize("isAuthenticated() or hasAuthority('find-user')") - @Timed(value = "user.info", description = "Time needed to get information of a user in the metadata database") + @Observed(name = "dbr_user_find") @Operation(summary = "Get a user info", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -188,7 +189,7 @@ public class UserEndpoint { @PutMapping("/{id}") @Transactional @PreAuthorize("hasAuthority('modify-user-information')") - @Timed(value = "user.modify", description = "Time needed to modify a user in the metadata database") + @Observed(name = "dbr_user_modify") @Operation(summary = "Modify user information", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -230,7 +231,7 @@ public class UserEndpoint { @PutMapping("/{id}/theme") @Transactional @PreAuthorize("hasAuthority('modify-user-theme')") - @Timed(value = "user.theme", description = "Time needed to modify a user theme in the metadata database") + @Observed(name = "dbr_user_theme_modify") @Operation(summary = "Modify user theme", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "202", @@ -270,7 +271,7 @@ public class UserEndpoint { @PutMapping("/{id}/password") @Transactional @PreAuthorize("isAuthenticated()") - @Timed(value = "user.password", description = "Time needed to modify a user password in the metadata database") + @Observed(name = "dbr_user_password_modify") @Operation(summary = "Modify user password", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "202", diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index 365d991997f238840f22dd3e14de14bcc02813b7..5dbf52cd292dafaf49441a687ac440cdd1758001 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -16,6 +16,7 @@ import at.tuwien.utils.PrincipalUtil; import at.tuwien.utils.UserUtil; import at.tuwien.validation.EndpointValidator; import io.micrometer.core.annotation.Timed; +import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -61,7 +62,7 @@ public class ViewEndpoint { @GetMapping @Transactional(readOnly = true) - @Timed(value = "view.list", description = "Time needed to list all views in a database") + @Observed(name = "dbr_views_findall") @Operation(summary = "Find all views", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -97,7 +98,7 @@ public class ViewEndpoint { @PostMapping @Transactional @PreAuthorize("hasAuthority('create-database-view')") - @Timed(value = "view.create", description = "Time needed to create a view") + @Observed(name = "dbr_view_create") @Operation(summary = "Create a view", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "201", @@ -164,7 +165,7 @@ public class ViewEndpoint { @GetMapping("/{viewId}") @Transactional(readOnly = true) - @Timed(value = "view.find", description = "Time needed to find a view") + @Observed(name = "dbr_view_find") @Operation(summary = "Find one view", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -198,7 +199,7 @@ public class ViewEndpoint { @DeleteMapping("/{viewId}") @Transactional @PreAuthorize("hasAuthority('delete-database-view')") - @Timed(value = "view.delete", description = "Time needed to delete a view") + @Observed(name = "dbr_view_delete") @Operation(summary = "Delete one view", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -259,7 +260,7 @@ public class ViewEndpoint { @GetMapping("/{viewId}/data") @Transactional(readOnly = true) - @Timed(value = "view.data", description = "Time needed to retrieve data from a view") + @Observed(name = "dbr_view_data_findall") @Operation(summary = "Find view data", security = @SecurityRequirement(name = "bearerAuth")) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -352,7 +353,7 @@ public class ViewEndpoint { @GetMapping("/{viewId}/data/count") @Transactional(readOnly = true) - @Timed(value = "view.data.count", description = "Time needed to retrieve data count from a view") + @Observed(name = "dbr_view_data_count") @Operation(summary = "Find view data count", security = @SecurityRequirement(name = "bearerAuth")) public ResponseEntity<Long> count(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("viewId") Long viewId, diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java index afd229f5a1206a9d54bf5ff5def0bf38cb13a348..95043859e12ab016b3a23f537c909a673f126a3b 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java @@ -24,6 +24,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; +import org.springframework.security.test.context.support.WithAnonymousUser; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; @@ -99,6 +100,18 @@ public class PrometheusEndpointMvcTest extends BaseUnitTest { @Autowired private TableDataEndpoint tableDataEndpoint; + @Autowired + private TableEndpoint tableEndpoint; + + @Autowired + private TableHistoryEndpoint tableHistoryEndpoint; + + @Autowired + private UserEndpoint userEndpoint; + + @Autowired + private ViewEndpoint viewEndpoint; + @TestConfiguration static class ObservationTestConfiguration { @@ -641,4 +654,150 @@ public class PrometheusEndpointMvcTest extends BaseUnitTest { } } + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"create-table", "delete-table"}) + public void prometheusTableEndpoint_succeeds() { + + /* mock */ + try { + tableEndpoint.list(DATABASE_1_ID, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + try { + tableEndpoint.create(DATABASE_1_ID, TABLE_3_CREATE_DTO, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + try { + tableEndpoint.findById(DATABASE_1_ID, TABLE_1_ID, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + try { + tableEndpoint.delete(DATABASE_1_ID, TABLE_1_ID, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + + /* test */ + for (String metric : List.of("dbr_tables_findall", "dbr_table_create", "dbr_tables_find", "dbr_table_delete")) { + assertThat(registry) + .hasObservationWithNameEqualTo(metric); + } + } + + @Test + @WithMockUser(username = USER_1_USERNAME) + public void prometheusTableHistoryEndpoint_succeeds() { + + /* mock */ + try { + tableHistoryEndpoint.getAll(DATABASE_1_ID, TABLE_1_ID, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + + /* test */ + assertThat(registry) + .hasObservationWithNameEqualTo("dbr_table_history_findall"); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"find-user", "modify-user-information", "modify-user-theme"}) + public void prometheusUserEndpoint_succeeds() { + + /* mock */ + try { + userEndpoint.findAll(); + } catch (Exception e) { + /* ignore */ + } + try { + userEndpoint.find(USER_1_ID, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + try { + userEndpoint.modify(USER_1_ID, USER_1_UPDATE_DTO, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + try { + userEndpoint.theme(USER_1_ID, USER_1_THEME_SET_DTO, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + try { + userEndpoint.password(USER_1_ID, USER_1_PASSWORD_DTO, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + + /* test */ + for (String metric : List.of("dbr_users_findall", "dbr_user_find", "dbr_user_modify", "dbr_user_theme_modify", "dbr_user_password_modify")) { + assertThat(registry) + .hasObservationWithNameEqualTo(metric); + } + } + + @Test + @WithAnonymousUser + public void prometheusUserEndpoint2_succeeds() { + + /* mock */ + try { + userEndpoint.create(USER_1_SIGNUP_REQUEST_DTO); + } catch (Exception e) { + /* ignore */ + } + + /* test */ + assertThat(registry) + .hasObservationWithNameEqualTo("dbr_user_create"); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"create-database-view", "delete-database-view"}) + public void prometheusViewEndpoint_succeeds() { + + /* mock */ + try { + viewEndpoint.findAll(DATABASE_1_ID, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + try { + viewEndpoint.create(DATABASE_1_ID, VIEW_1_CREATE_DTO, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + try { + viewEndpoint.find(DATABASE_1_ID, VIEW_1_ID, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + try { + viewEndpoint.delete(DATABASE_1_ID, VIEW_1_ID, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + try { + viewEndpoint.data(DATABASE_1_ID, VIEW_1_ID, USER_1_PRINCIPAL, null, null); + } catch (Exception e) { + /* ignore */ + } + try { + viewEndpoint.count(DATABASE_1_ID, VIEW_1_ID, USER_1_PRINCIPAL); + } catch (Exception e) { + /* ignore */ + } + + /* test */ + for (String metric : List.of("dbr_views_findall", "dbr_view_create", "dbr_view_find", "dbr_view_delete", "dbr_view_data_findall", "dbr_view_data_count")) { + assertThat(registry) + .hasObservationWithNameEqualTo(metric); + } + } + } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationWriteTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationWriteTest.java index 11fb73a8e07ca567de5155118b96d3643b2f3408..c3149bd713ea0fe616724f72468e7d7774dc7417 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationWriteTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationWriteTest.java @@ -114,31 +114,6 @@ public class TableServiceIntegrationWriteTest extends BaseUnitTest { tableService.createTable(DATABASE_1_ID, TABLE_3_CREATE_DTO, USER_1_PRINCIPAL); } - @Test - public void create_failedBefore_succeeds() throws UserNotFoundException, TableMalformedException, - QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException, TableNameExistsException, - ContainerNotFoundException, SQLException { - - /* mock */ - when(tableidxRepository.save(any(TableDto.class))) - .thenReturn(null); - when(tableColumnidxRepository.saveAll(anyList())) - .thenReturn(List.of()); - - /* test */ - try { - tableService.createTable(DATABASE_1_ID, TABLE_3_INVALID_CREATE_DTO, USER_1_PRINCIPAL); - } catch (TableMalformedException e) { - /* ignore */ - } - assertFalse(MariaDbConfig.tableExists(DATABASE_1, "traffic_zu_rich")); - final Table response = tableService.createTable(DATABASE_1_ID, TABLE_3_CREATE_DTO, USER_1_PRINCIPAL); - assertTrue(MariaDbConfig.tableExists(DATABASE_1, "traffic_zu_rich")); - assertEquals(TABLE_3_NAME, response.getName()); - assertEquals(TABLE_3_INTERNALNAME, response.getInternalName()); - assertEquals(TABLE_3_DESCRIPTION, response.getDescription()); - } - @Test public void create_withConstraints_succeeds() throws UserNotFoundException, TableMalformedException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException, TableNameExistsException, diff --git a/dbrepo-metadata-service/rest-service/src/test/resources/application.properties b/dbrepo-metadata-service/rest-service/src/test/resources/application.properties index 7c4376e9dcb7f15176aecfe79a6b971c1d690010..cc1a895c65c7189221a4e062dcfdb20370b6e5fb 100644 --- a/dbrepo-metadata-service/rest-service/src/test/resources/application.properties +++ b/dbrepo-metadata-service/rest-service/src/test/resources/application.properties @@ -17,7 +17,7 @@ spring.jpa.hibernate.ddl-auto=create # logging logging.level.root=error logging.level.at.tuwien.=debug -logging.level.at.tuwien.gateway.impl.=trace +logging.level.at.tuwien.mapper.=trace # rabbitmq spring.rabbitmq.host=localhost 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 2bb3da5b1c5d8f521eb8b91af1b24793e1514487..33769e83399068dd90c23204aadec8c9d28e9fc4 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 @@ -158,11 +158,6 @@ public class TableServiceImpl extends HibernateConnector implements TableService public Table createTable(Long databaseId, TableCreateDto createDto, Principal principal) throws ImageNotSupportedException, DatabaseNotFoundException, TableMalformedException, TableNameExistsException, QueryMalformedException { - /* checks */ - if (createDto.getName().isBlank()) { - log.error("Failed create table: table name is blank"); - throw new TableMalformedException("Failed create table: table name is blank"); - } /* find */ final Database database = databaseService.find(databaseId); if (!database.getContainer().getImage().getName().equals("mariadb")) { @@ -177,27 +172,11 @@ public class TableServiceImpl extends HibernateConnector implements TableService } /* run query */ final ComboPooledDataSource dataSource = getPrivilegedDataSource(database.getContainer().getImage(), database.getContainer(), database); - final TableCreateRawQuery query; try { final Connection connection = dataSource.getConnection(); - query = tableMapper.tableToCreateTableRawQuery(connection, createDto); - if (query.getGenerated()) { - /* in case the id column needs to be generated, we need to generate the sequence too */ - final PreparedStatement preparedStatement10 = tableMapper.tableToCreateSequenceRawQuery(connection, database, createDto); - preparedStatement10.executeUpdate(); - log.debug("created id sequence"); - } - final PreparedStatement preparedStatement11 = query.getPreparedStatement(); - preparedStatement11.executeUpdate(); + final PreparedStatement preparedStatement = tableMapper.tableToCreateTableRawQuery(connection, createDto); + preparedStatement.executeUpdate(); } catch (Exception e) { - try { - final Connection connection = dataSource.getConnection(); - final PreparedStatement preparedStatement11 = tableMapper.tableToDropSequenceRawQuery(connection, database, createDto); - preparedStatement11.executeUpdate(); - log.debug("successfully rolled back creation of id sequence"); - } catch (SQLException ex) { - log.error("Failed to rollback creation of id sequence"); - } log.error("Failed to create table, reason: {}", e.getMessage()); throw new TableMalformedException("Failed to create table", e); } finally { @@ -219,7 +198,7 @@ public class TableServiceImpl extends HibernateConnector implements TableService entity.setColumns(createDto.getColumns() .stream() .map(column -> tableMapper.columnCreateDtoToTableColumn(column, database.getContainer().getImage())) - .map(column -> tableMapper.tableColumnToTableColumn(entity, column, query)) + .map(column -> tableMapper.tableColumnToTableColumn(entity, column)) .toList()); /* set the ordinal position for the columns */ entity.getColumns()