diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java index 31ab0b765de2ccd488d40e289d9c2b6066dbc083..a3fb6833ce05abf5cd8c2dd4f5842722e17785a2 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java @@ -68,17 +68,37 @@ public class EndpointValidator { if (data == null) { throw new MalformedException("Validation failed: table data is null"); } + final List<ColumnTypeDto> needSize = List.of(ColumnTypeDto.VARCHAR, ColumnTypeDto.BINARY, ColumnTypeDto.VARBINARY); final List<ColumnTypeDto> canHaveSize = List.of(ColumnTypeDto.CHAR, ColumnTypeDto.VARCHAR, ColumnTypeDto.BINARY, ColumnTypeDto.VARBINARY, ColumnTypeDto.BIT, ColumnTypeDto.TINYINT, ColumnTypeDto.SMALLINT, ColumnTypeDto.MEDIUMINT, ColumnTypeDto.INT); final List<ColumnTypeDto> canHaveSizeAndD = List.of(ColumnTypeDto.DOUBLE, ColumnTypeDto.DECIMAL); /* check size */ final Optional<ColumnCreateDto> optional0 = data.getColumns() + .stream() + .filter(c -> Objects.isNull(c.getSize())) + .filter(c -> needSize.contains(c.getType())) + .findFirst(); + if (optional0.isPresent()) { + log.error("Validation failed: column {} need size parameter", optional0.get().getName()); + throw new MalformedException("Validation failed: column " + optional0.get().getName() + " need size parameter"); + } + final Optional<ColumnCreateDto> optional0a = data.getColumns() + .stream() + .filter(c -> !Objects.isNull(c.getSize())) + .filter(c -> canHaveSize.contains(c.getType())) + .filter(c -> c.getSize() < 0) + .findFirst(); + if (optional0a.isPresent()) { + log.error("Validation failed: column {} needs positive size parameter", optional0a.get().getName()); + throw new MalformedException("Validation failed: column " + optional0a.get().getName() + " needs positive size parameter"); + } + final Optional<ColumnCreateDto> optional0b = data.getColumns() .stream() .filter(c -> !Objects.isNull(c.getSize())) .filter(c -> !canHaveSize.contains(c.getType())) .findFirst(); - if (optional0.isPresent()) { - log.error("Validation failed: column {} cannot have size parameter", optional0.get().getName()); - throw new MalformedException("Validation failed: column " + optional0.get().getName() + " cannot have size parameter"); + if (optional0b.isPresent()) { + log.error("Validation failed: column {} cannot have size parameter", optional0b.get().getName()); + throw new MalformedException("Validation failed: column " + optional0b.get().getName() + " cannot have size parameter"); } /* check size and d */ final Optional<ColumnCreateDto> optional1 = data.getColumns() diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java index 69d817afb763fa47b878b71fb315bb8dbb02f750..41de319fef328626ab21501a4f7a9c556f6d11ee 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java @@ -1,16 +1,16 @@ package at.tuwien.endpoints; -import at.tuwien.mapper.MetadataMapper; -import at.tuwien.test.AbstractUnitTest; import at.tuwien.api.database.AccessTypeDto; import at.tuwien.api.database.DatabaseAccessDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.entities.user.User; import at.tuwien.exception.*; +import at.tuwien.mapper.MetadataMapper; import at.tuwien.repository.DatabaseRepository; import at.tuwien.repository.UserRepository; import at.tuwien.service.AccessService; +import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -57,7 +57,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - generic_create(null, USER_2_ID, null, null); + generic_create(null, null, null, null); }); } @@ -67,7 +67,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - generic_create(USER_2_PRINCIPAL, USER_4_ID, USER_4_USERNAME, USER_4); + generic_create(USER_2_PRINCIPAL, USER_2, USER_4_ID, USER_4); }); } @@ -82,7 +82,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1_USER_1_READ_ACCESS); /* test */ - generic_create(USER_2_PRINCIPAL, USER_2_ID, USER_2_USERNAME, USER_2); + generic_create(USER_1_PRINCIPAL, USER_1, USER_2_ID, USER_2); } @Test @@ -129,7 +129,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - generic_update(null, USER_4_USERNAME, USER_4, null, null); + generic_update(null, null, null, null, null); }); } @@ -138,8 +138,8 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { public void update_hasRoleNoAccess_fails() { /* test */ - assertThrows(NotAllowedException.class, () -> { - generic_update(null, USER_4_USERNAME, USER_4, USER_1_PRINCIPAL, USER_1); + assertThrows(AccessNotFoundException.class, () -> { + generic_update(USER_1_PRINCIPAL, USER_1, USER_4_ID, USER_4, null); }); } @@ -149,7 +149,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - generic_update(null, USER_4_USERNAME, USER_4, USER_4_PRINCIPAL, USER_4); + generic_update(USER_4_PRINCIPAL, USER_4, USER_1_ID, USER_1, null); }); } @@ -165,7 +165,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { .update(eq(DATABASE_1), eq(USER_2), any(AccessTypeDto.class)); /* test */ - generic_update(DATABASE_1_USER_2_WRITE_OWN_ACCESS, USER_2_USERNAME, USER_2, USER_2_PRINCIPAL, USER_2); + generic_update(USER_1_PRINCIPAL, USER_1, USER_2_ID, USER_2, DATABASE_1_USER_2_WRITE_OWN_ACCESS); } @Test @@ -174,7 +174,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - generic_revoke(USER_1_PRINCIPAL, USER_1); + generic_revoke(null, null, USER_1_ID, USER_1); }); } @@ -184,7 +184,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - generic_revoke(USER_4_PRINCIPAL, USER_4); + generic_revoke(USER_4_PRINCIPAL, USER_4, USER_1_ID, USER_1); }); } @@ -200,14 +200,14 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { .delete(DATABASE_1, USER_2); /* test */ - generic_revoke(USER_1_PRINCIPAL, USER_1); + generic_revoke(USER_1_PRINCIPAL, USER_1, USER_2_ID, USER_2); } /* ################################################################################################### */ /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ - protected void generic_create(Principal principal, UUID userId, String username, User user) + protected void generic_create(Principal principal, User principalUser, UUID userId, User user) throws NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { @@ -218,11 +218,18 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { doThrow(AccessNotFoundException.class) .when(accessService) .find(DATABASE_1, user); + if (principalUser != null) { + when(userRepository.findByUsername(principal.getName())) + .thenReturn(Optional.of(principalUser)); + } else { + when(userRepository.findByUsername(anyString())) + .thenReturn(Optional.empty()); + } if (user != null) { - when(userRepository.findByUsername(username)) + when(userRepository.findById(userId)) .thenReturn(Optional.of(user)); } else { - when(userRepository.findByUsername(anyString())) + when(userRepository.findById(any(UUID.class))) .thenReturn(Optional.empty()); } @@ -268,61 +275,62 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } } - protected void generic_update(DatabaseAccess access, String otherUsername, User otherUser, Principal principal, - User user) throws NotAllowedException, DataServiceException, DataServiceConnectionException, - AccessNotFoundException, UserNotFoundException, DatabaseNotFoundException, SearchServiceException, - SearchServiceConnectionException { + protected void generic_update(Principal principal, User principalUser, UUID userId, User user, + DatabaseAccess access) throws NotAllowedException, DataServiceException, + DataServiceConnectionException, AccessNotFoundException, UserNotFoundException, DatabaseNotFoundException, + SearchServiceException, SearchServiceConnectionException { /* mock */ when(databaseRepository.findById(DATABASE_1_ID)) .thenReturn(Optional.of(DATABASE_1)); if (access != null) { - log.trace("mock access {} for user with id {} for database with id {}", access.getType(), USER_1_ID, DATABASE_1_ID); - when(accessService.find(DATABASE_1, USER_1)) + log.trace("mock access {} for user with id {} for database with id {}", access.getType(), userId, DATABASE_1_ID); + when(accessService.find(DATABASE_1, user)) .thenReturn(access); } else { - log.trace("mock no access for user with id {} for database with id {}", USER_1_ID, DATABASE_1_ID); + log.trace("mock no access for user with id {} for database with id {}", userId, DATABASE_1_ID); doThrow(AccessNotFoundException.class) .when(accessService) - .find(DATABASE_1, USER_1); + .find(DATABASE_1, user); } - if (otherUsername != null) { - when(userRepository.findByUsername(otherUsername)) - .thenReturn(Optional.of(otherUser)); + if (userId != null) { + when(userRepository.findById(userId)) + .thenReturn(Optional.of(user)); } else { - when(userRepository.findByUsername(anyString())) + when(userRepository.findById(any(UUID.class))) .thenReturn(Optional.empty()); } if (principal != null) { when(userRepository.findByUsername(principal.getName())) - .thenReturn(Optional.of(user)); + .thenReturn(Optional.of(principalUser)); } else { when(userRepository.findByUsername(anyString())) .thenReturn(Optional.empty()); } /* test */ - final ResponseEntity<?> response = accessEndpoint.update(DATABASE_1_ID, USER_1_ID, UPDATE_DATABASE_ACCESS_READ_DTO, principal); + final ResponseEntity<?> response = accessEndpoint.update(DATABASE_1_ID, userId, UPDATE_DATABASE_ACCESS_READ_DTO, principal); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); assertNull(response.getBody()); } - protected void generic_revoke(Principal principal, User user) throws DataServiceConnectionException, - NotAllowedException, DataServiceException, UserNotFoundException, DatabaseNotFoundException, - AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { + protected void generic_revoke(Principal principal, User principalUser, UUID userId, User user) + throws DataServiceConnectionException, NotAllowedException, DataServiceException, UserNotFoundException, + DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, + SearchServiceConnectionException { /* mock */ - when(accessService.find(any(Database.class), eq(user))) - .thenReturn(DATABASE_1_USER_1_READ_ACCESS); when(databaseRepository.findById(DATABASE_1_ID)) .thenReturn(Optional.of(DATABASE_1)); if (principal != null) { when(userRepository.findByUsername(principal.getName())) - .thenReturn(Optional.of(user)); + .thenReturn(Optional.of(principalUser)); } + when(userRepository.findById(userId)) + .thenReturn(Optional.of(user)); /* test */ - final ResponseEntity<?> response = accessEndpoint.revoke(DATABASE_1_ID, USER_1_ID, principal); + final ResponseEntity<?> response = accessEndpoint.revoke(DATABASE_1_ID, userId, principal); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); assertNull(response.getBody()); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java index 154ebda86c3a32554c2c83a3330846ebdee8f939..69f9a8dadd385f2a679b855b839be24f3b8101ef 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java @@ -167,101 +167,6 @@ public class TableEndpointUnitTest extends AbstractUnitTest { }); } - @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_publicDecimalColumnSizeMissing_fails() { - final TableCreateDto request = TableCreateDto.builder() - .name("Some Table") - .description("Some Description") - .columns(List.of(ColumnCreateDto.builder() - .name("ID") - .type(ColumnTypeDto.DECIMAL) - .build())) - .constraints(null) - .build(); - - /* test */ - assertThrows(MalformedException.class, () -> { - generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS); - }); - } - - @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_publicDateFormatMissing_fails() { - final TableCreateDto request = TableCreateDto.builder() - .name("Some Table") - .description("Some Description") - .columns(List.of(ColumnCreateDto.builder() - .name("timestamp") - .type(ColumnTypeDto.DATE) - .build())) - .constraints(null) - .build(); - - /* test */ - assertThrows(MalformedException.class, () -> { - generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS); - }); - } - - @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_publicDateTimeFormatMissing_fails() { - final TableCreateDto request = TableCreateDto.builder() - .name("Some Table") - .description("Some Description") - .columns(List.of(ColumnCreateDto.builder() - .name("timestamp") - .type(ColumnTypeDto.DATETIME) - .build())) - .constraints(null) - .build(); - - /* test */ - assertThrows(MalformedException.class, () -> { - generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS); - }); - } - - @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_publicTimeFormatMissing_fails() { - final TableCreateDto request = TableCreateDto.builder() - .name("Some Table") - .description("Some Description") - .columns(List.of(ColumnCreateDto.builder() - .name("timestamp") - .type(ColumnTypeDto.TIME) - .build())) - .constraints(null) - .build(); - - /* test */ - assertThrows(MalformedException.class, () -> { - generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS); - }); - } - - @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) - public void create_publicTimestampFormatMissing_fails() { - final TableCreateDto request = TableCreateDto.builder() - .name("Some Table") - .description("Some Description") - .columns(List.of(ColumnCreateDto.builder() - .name("timestamp") - .type(ColumnTypeDto.TIMESTAMP) - .build())) - .constraints(null) - .build(); - - /* test */ - assertThrows(MalformedException.class, () -> { - generic_create(DATABASE_3_ID, DATABASE_3, request, USER_1_PRINCIPAL, USER_1, DATABASE_3_USER_1_WRITE_OWN_ACCESS); - }); - } - @Test @WithMockUser(username = USER_3_USERNAME, authorities = {"create-table"}) public void create_publicDecimalColumnSizeTooSmall_fails() { diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java index 66ae6777e9c26d113d70dba48b536c8fa5d6a58e..8528d29f07d267bd4dcbe94de5379e47e13f1cef 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java @@ -53,22 +53,9 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { public static Stream<Arguments> needSize_parameters() { return Stream.of( - Arguments.arguments(ColumnTypeDto.CHAR), Arguments.arguments(ColumnTypeDto.VARCHAR), Arguments.arguments(ColumnTypeDto.BINARY), - Arguments.arguments(ColumnTypeDto.VARBINARY), - Arguments.arguments(ColumnTypeDto.BIT), - Arguments.arguments(ColumnTypeDto.TINYINT), - Arguments.arguments(ColumnTypeDto.SMALLINT), - Arguments.arguments(ColumnTypeDto.MEDIUMINT), - Arguments.arguments(ColumnTypeDto.INT) - ); - } - - public static Stream<Arguments> needSizeAndD_parameters() { - return Stream.of( - Arguments.arguments(ColumnTypeDto.DOUBLE), - Arguments.arguments(ColumnTypeDto.DECIMAL) + Arguments.arguments(ColumnTypeDto.VARBINARY) ); } @@ -300,23 +287,6 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { }); } - @ParameterizedTest - @MethodSource("needSizeAndD_parameters") - public void validateColumnCreateConstraints_needSizeAndD_fails(ColumnTypeDto type) { - final TableCreateDto request = TableCreateDto.builder() - .columns(List.of(ColumnCreateDto.builder() - .type(type) - .size(10L) - .d(null) // <<<<<<< - .build())) - .build(); - - /* test */ - assertThrows(MalformedException.class, () -> { - endpointValidator.validateColumnCreateConstraints(request); - }); - } - @Test public void validateColumnCreateConstraints_needEnum_fails() { final TableCreateDto request = TableCreateDto.builder() diff --git a/dbrepo-ui/composables/query-service.ts b/dbrepo-ui/composables/query-service.ts index a0b4427e015a1362cc00320ece0e55800160a7b2..00d661788d3116c879dc32e91cefbcca2369614b 100644 --- a/dbrepo-ui/composables/query-service.ts +++ b/dbrepo-ui/composables/query-service.ts @@ -196,6 +196,9 @@ export const useQueryService = (): any => { return {timestamp, page, size} } + /** + * data types with non-null defaultSize values require size to be set + */ function mySql8DataTypes(): MySql8DataType[] { return [ {value: 'bigint', text: 'BIGINT(size)', defaultSize: null, defaultD: null, signed: null, zerofill: false, quoted: false, isBuildable: true, hint: null},