Skip to content
Snippets Groups Projects
Unverified Commit 3991315b authored by Martin Weise's avatar Martin Weise
Browse files

Updated some more tests

parent 64e4aa69
No related branches found
No related tags found
2 merge requests!163Relase 1.3.0,!155Added readme to authentication service and added eureka service
Showing
with 495 additions and 707 deletions
package at.tuwien.endpoint;
import at.tuwien.SortType;
import at.tuwien.api.database.query.ExecuteStatementDto;
import at.tuwien.config.QueryConfig;
import at.tuwien.entities.database.AccessType;
import at.tuwien.entities.database.Database;
import at.tuwien.entities.database.DatabaseAccess;
import at.tuwien.entities.database.table.Table;
import at.tuwien.entities.identifier.Identifier;
import at.tuwien.exception.*;
import at.tuwien.service.AccessService;
import at.tuwien.service.DatabaseService;
import at.tuwien.service.IdentifierService;
import at.tuwien.service.TableService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import java.security.Principal;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static at.tuwien.entities.identifier.VisibilityType.EVERYONE;
@Slf4j
public abstract class AbstractEndpoint {
private final QueryConfig queryConfig;
private final TableService tableService;
private final AccessService accessService;
private final DatabaseService databaseService;
private final IdentifierService identifierService;
@Autowired
protected AbstractEndpoint(TableService tableService, AccessService accessService, DatabaseService databaseService,
IdentifierService identifierService, QueryConfig queryConfig) {
this.queryConfig = queryConfig;
this.tableService = tableService;
this.accessService = accessService;
this.databaseService = databaseService;
this.identifierService = identifierService;
}
protected Boolean hasDatabasePermission(Long containerId, Long databaseId, String permissionCode,
Principal principal) throws NotAllowedException {
log.trace("validate database permission, containerId={}, databaseId={}, permissionCode={}, principal={}",
containerId, databaseId, permissionCode, principal);
final Database database;
try {
database = databaseService.find(containerId, databaseId);
} catch (DatabaseNotFoundException e) {
log.error("Failed to find database with id {}", databaseId);
return false;
}
/* view-only operations are allowed on public databases */
if (database.getIsPublic() && List.of("DATA_VIEW", "DATA_HISTORY", "QUERY_VIEW_ALL").contains(permissionCode)) {
log.debug("grant permission {} because database is public", permissionCode);
return true;
}
if (List.of("LIST_VIEWS", "FIND_VIEW", "DATA_VIEW").contains(permissionCode)) {
log.debug("grant permission {} because it is allowed on public/private databases", permissionCode);
return true;
}
if (principal == null) {
log.error("Failed to grant permission {} because principal is null", permissionCode);
return false;
}
final DatabaseAccess access = accessService.find(databaseId, principal.getName());
/* check view access */
if (List.of("QUERY_EXECUTE").contains(permissionCode)) {
log.debug("grant permission {} because user has access {}", permissionCode, access.getType());
return true;
}
if (List.of("CREATE_VIEW").contains(permissionCode) && database.getOwner().getId().equals(access.getHuserid())) {
log.debug("grant permission {} because user is owner {}", permissionCode, access.getType());
return true;
}
/* has role researcher */
final Authentication authentication = (Authentication) principal /* with pre-authorization this always holds */;
if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("ROLE_RESEARCHER"))) {
log.error("Failed to grant permission {} because current user misses authority 'ROLE_RESEARCHER'",
permissionCode);
return false;
}
return false;
}
protected void validateDataParams(Long page, Long size) throws PaginationException {
log.trace("validate data params, page={}, size={}", page, size);
if ((page == null && size != null) || (page != null && size == null)) {
log.error("Failed to validate page and/or size number, either both are present or none");
throw new PaginationException("Failed to validate page and/or size number");
}
if (page != null && page < 0) {
log.error("Failed to validate page number, is lower than zero");
throw new PaginationException("Failed to validate page number");
}
if (size != null && size <= 0) {
log.error("Failed to validate size number, is lower or equal than zero");
throw new PaginationException("Failed to validate size number");
}
}
protected void validateDataParams(Long page, Long size, SortType sortDirection, String sortColumn)
throws PaginationException, SortException {
log.trace("validate data params, page={}, size={}, sortDirection={}, sortColumn={}", page, size,
sortDirection, sortColumn);
validateDataParams(page, size);
if ((sortDirection == null && sortColumn != null) || (sortDirection != null && sortColumn == null)) {
log.error("Failed to validate sort direction and/or sort column, either both are present or none");
throw new SortException("Failed to validate sort direction and/or sort column");
}
}
/**
* Do not allow aggregate functions and comments
* https://mariadb.com/kb/en/aggregate-functions/
*/
protected void validateForbiddenStatements(ExecuteStatementDto data) throws QueryMalformedException {
final List<String> words = new LinkedList<>();
Arrays.stream(queryConfig.getNotSupportedKeywords())
.forEach(keyword -> {
final Pattern pattern = Pattern.compile(keyword);
final Matcher matcher = pattern.matcher(data.getStatement());
final boolean found = matcher.find();
if (found) {
words.add(keyword);
}
});
if (words.size() == 0) {
return;
}
log.error("Query contains forbidden keyword(s): {}", words);
log.debug("forbidden keywords: {}", words);
throw new QueryMalformedException("Query contains forbidden keyword(s): " + Arrays.toString(words.toArray()));
}
protected Boolean hasTablePermission(Long containerId, Long databaseId, Long tableId, String permissionCode,
Principal principal) throws NotAllowedException {
log.trace("validate queue permission, containerId={}, databaseId={}, tableId={}, permissionCode={}, principal={}",
containerId, databaseId, tableId, permissionCode, principal);
final Database database;
try {
database = databaseService.find(containerId, databaseId);
} catch (DatabaseNotFoundException e) {
log.error("Failed to find database with id {}", databaseId);
return false;
}
final Table table;
try {
table = tableService.find(containerId, databaseId, tableId);
} catch (TableNotFoundException e) {
log.error("Failed to find table with id {} in database with id {}", tableId, databaseId);
return false;
} catch (DatabaseNotFoundException e) {
/* can never occur here */
return false;
}
/* view-only operations are allowed on public databases */
if (database.getIsPublic() && List.of("TABLE_EXPORT", "DATA_VIEW", "DATA_HISTORY").contains(permissionCode)) {
log.debug("grant permission {} because database is public", permissionCode);
return true;
}
if (principal == null) {
log.error("Failed to grant permission {} because principal is null", permissionCode);
return false;
}
final Authentication authentication = (Authentication) principal /* with pre-authorization this always holds */;
if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("ROLE_RESEARCHER"))) {
log.error("Failed to grant permission {} because current user misses authority 'ROLE_RESEARCHER'",
permissionCode);
return false;
}
final DatabaseAccess access = accessService.find(databaseId, principal.getName());
/* check view access */
if (List.of("TABLE_EXPORT", "DATA_VIEW", "DATA_HISTORY", "QUERY_VIEW_ALL", "QUERY_RE_EXECUTE", "QUERY_VIEW", "FIND_VIEW").contains(permissionCode)) {
log.trace("grant permission {} because user has access {}", permissionCode, access.getType());
return true;
}
if (List.of("DATA_INSERT", "DATA_UPDATE", "DATA_DELETE").contains(permissionCode) && access.getType().equals(AccessType.WRITE_ALL)) {
/* write own is already effective with creator check above */
log.debug("grant permission {} because user {} is has table write permission {}", permissionCode, principal.getName(),
access.getType());
return true;
}
if (List.of("QUERY_PERSIST").contains(permissionCode) && access != null) {
/* write own is already effective with creator check above */
log.debug("grant permission {} because user {} is has database read/write permission {}", permissionCode, principal.getName(),
access.getType());
return true;
}
log.debug("failed to grant permission {} because database is not owner by the current user and also has not appropriate access", permissionCode);
return false;
}
protected Boolean hasQueryPermission(Long containerId, Long databaseId, Long queryId, String permissionCode,
Principal principal) throws NotAllowedException {
log.trace("validate query permission, containerId={}, databaseId={}, queryId={}, permissionCode={}, principal={}",
containerId, databaseId, queryId, permissionCode, principal);
final Database database;
try {
database = databaseService.find(containerId, databaseId);
} catch (DatabaseNotFoundException e) {
log.error("Failed to find database with id {}", databaseId);
return false;
}
if (hasPublicIdentifier(databaseId, queryId, permissionCode)) {
return true;
}
/* modification operations are limited to the creator */
if (isMyPrivateIdentifier(databaseId, queryId, principal, permissionCode)) {
return true;
}
/* view-only operations are allowed on public databases */
if (database.getIsPublic() && List.of("QUERY_VIEW_ALL", "QUERY_VIEW", "QUERY_EXPORT", "QUERY_RE_EXECUTE").contains(
permissionCode)) {
log.debug("grant permission {} because database is public", permissionCode);
return true;
}
if (principal == null) {
log.error("Failed to grant permission {} because principal is null", permissionCode);
return false;
}
final DatabaseAccess access = accessService.find(databaseId, principal.getName());
/* check view access */
if (List.of("DATA_VIEW", "DATA_HISTORY", "QUERY_VIEW_ALL", "QUERY_RE_EXECUTE", "QUERY_VIEW", "FIND_VIEW", "QUERY_EXPORT").contains(permissionCode)) {
log.trace("grant permission {} because user has access {}", permissionCode, access.getType());
return true;
}
/* has role researcher */
final Authentication authentication = (Authentication) principal /* with pre-authorization this always holds */;
if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("ROLE_RESEARCHER"))) {
log.error("Failed to grant permission {} because current user misses authority 'ROLE_RESEARCHER'",
permissionCode);
return false;
}
if (access.getType().equals(AccessType.WRITE_ALL)) {
log.trace("grant permission {} because user has access {}", permissionCode, access.getType());
return true;
}
log.debug("failed to grant permission {} because database is not owner by the current user and also has not appropriate access", permissionCode);
return false;
}
protected Boolean hasPublicIdentifier(Long databaseId, Long queryId, String permissionCode) {
log.trace("validate has public identifier, databaseId={}, queryId={}, permissionCode={}", databaseId, queryId,
permissionCode);
final Identifier identifier;
try {
identifier = identifierService.findByDatabaseIdAndQueryId(databaseId, queryId);
} catch (IdentifierNotFoundException e) {
return false;
}
if (identifier.getVisibility().equals(EVERYONE)) {
log.debug("grant permission {} because identifier visibility is public", permissionCode);
return true;
}
log.error("Failed to grant permission {} because identifier visibility is not public", permissionCode);
return false;
}
protected Boolean isMyPrivateIdentifier(Long databaseId, Long queryId, Principal principal, String permissionCode) {
log.trace("validate is my private identifier, databaseId={}, queryId={}, permissionCode={}", databaseId, queryId,
permissionCode);
final Identifier identifier;
try {
identifier = identifierService.findByDatabaseIdAndQueryId(databaseId, queryId);
} catch (IdentifierNotFoundException e) {
return false;
}
if (identifier.getDatabase().getIsPublic()) {
log.debug("grant permission {} because database is public", permissionCode);
return true;
}
if (principal == null) {
log.error("Failed to grant permission {} because database is private and principal is null",
permissionCode);
return false;
}
if (identifier.getCreator().getUsername().equals(principal.getName())) {
log.debug("grant permission {} because database is private and identifier creator is the current user",
permissionCode);
return true;
}
log.error("Failed to grant permission {} because database is private and identifier creator is not the current user", permissionCode);
return false;
}
}
package at.tuwien.endpoint;
import at.tuwien.ExportResource;
import at.tuwien.config.QueryConfig;
import at.tuwien.entities.database.Database;
import at.tuwien.exception.*;
import at.tuwien.service.*;
import io.micrometer.core.annotation.Timed;
......@@ -12,7 +12,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
......@@ -27,10 +27,12 @@ import java.time.Instant;
public class ExportEndpoint {
private final QueryService queryService;
private final DatabaseService databaseService;
@Autowired
public ExportEndpoint(QueryService queryService) {
public ExportEndpoint(QueryService queryService, DatabaseService databaseService) {
this.queryService = queryService;
this.databaseService = databaseService;
}
@GetMapping
......@@ -44,10 +46,21 @@ public class ExportEndpoint {
Principal principal)
throws TableNotFoundException, DatabaseConnectionException, TableMalformedException,
DatabaseNotFoundException, ImageNotSupportedException, PaginationException, ContainerNotFoundException,
FileStorageException, QueryMalformedException, UserNotFoundException {
// TODO: check if authority 'export-table'
FileStorageException, QueryMalformedException, UserNotFoundException, NotAllowedException {
log.debug("endpoint export table, id={}, databaseId={}, tableId={}, timestamp={}, principal={}", containerId, databaseId,
tableId, timestamp, principal);
final Database database = databaseService.find(containerId, databaseId);
if (!database.getIsPublic()) {
if (principal == null) {
log.error("Failed to export private table: principal is null");
throw new NotAllowedException("Failed to export private table: principal is null");
}
final Authentication authentication = (Authentication) principal;
if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("export-table-data"))) {
log.error("Failed to export private table: role missing");
throw new NotAllowedException("Failed to export private table: role missing");
}
}
final HttpHeaders headers = new HttpHeaders();
final ExportResource resource = queryService.tableFindAll(containerId, databaseId, tableId, timestamp, principal);
headers.add("Content-Disposition", "attachment; filename=\"" + resource.getFilename() + "\"");
......
......@@ -3,6 +3,7 @@ package at.tuwien.endpoint;
import at.tuwien.ExportResource;
import at.tuwien.SortType;
import at.tuwien.api.database.query.*;
import at.tuwien.entities.database.Database;
import at.tuwien.querystore.Query;
import at.tuwien.exception.*;
import at.tuwien.service.*;
......@@ -16,6 +17,7 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
......@@ -31,11 +33,13 @@ public class QueryEndpoint {
private final QueryService queryService;
private final StoreService storeService;
private final DatabaseService databaseService;
private final EndpointValidator endpointValidator;
@Autowired
public QueryEndpoint(QueryService queryService, StoreService storeService,
EndpointValidator endpointValidator) {
DatabaseService databaseService, EndpointValidator endpointValidator) {
this.databaseService = databaseService;
this.endpointValidator = endpointValidator;
this.queryService = queryService;
this.storeService = storeService;
......@@ -44,7 +48,7 @@ public class QueryEndpoint {
@PostMapping
@Transactional(readOnly = true)
@Timed(value = "query.execute", description = "Time needed to execute a query")
@PreAuthorize("hasAuthority('execute-query')")
@PreAuthorize("isAuthenticated()")
@Operation(summary = "Execute query", security = @SecurityRequirement(name = "bearerAuth"))
public ResponseEntity<QueryResultDto> execute(@NotNull @PathVariable("id") Long containerId,
@NotNull @PathVariable("databaseId") Long databaseId,
......@@ -56,7 +60,7 @@ public class QueryEndpoint {
@RequestParam(required = false) String sortColumn)
throws DatabaseNotFoundException, ImageNotSupportedException, QueryStoreException, QueryMalformedException,
ContainerNotFoundException, ColumnParseException, UserNotFoundException, TableMalformedException,
NotAllowedException, DatabaseConnectionException, SortException, PaginationException {
DatabaseConnectionException, SortException, PaginationException, NotAllowedException {
log.debug("endpoint execute query, containerId={}, databaseId={}, data={}, page={}, size={}, principal={}, sortDirection={}, sortColumn={}",
containerId, databaseId, data, page, size, principal, sortDirection, sortColumn);
/* check */
......@@ -66,6 +70,18 @@ public class QueryEndpoint {
}
endpointValidator.validateForbiddenStatements(data);
endpointValidator.validateDataParams(page, size, sortDirection, sortColumn);
final Database database = databaseService.find(containerId, databaseId);
if (!database.getIsPublic()) {
if (principal == null) {
log.error("Failed to execute private query: principal is null");
throw new NotAllowedException("Failed to re-execute private query: principal is null");
}
final Authentication authentication = (Authentication) principal;
if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("execute-query"))) {
log.error("Failed to execute private query: role missing");
throw new NotAllowedException("Failed to re-execute private query: role missing");
}
}
/* execute */
final QueryResultDto result = queryService.execute(containerId, databaseId, data, principal, page, size,
sortDirection, sortColumn);
......@@ -76,7 +92,6 @@ public class QueryEndpoint {
@GetMapping("/{queryId}/data")
@Transactional(readOnly = true)
@PreAuthorize("hasAuthority('re-execute-query')")
@Timed(value = "query.reexecute", description = "Time needed to re-execute a query")
@Operation(summary = "Re-execute some query", security = @SecurityRequirement(name = "bearerAuth"))
public ResponseEntity<QueryResultDto> reExecute(@NotNull @PathVariable("id") Long containerId,
......@@ -88,11 +103,23 @@ public class QueryEndpoint {
@RequestParam(required = false) SortType sortDirection,
@RequestParam(required = false) String sortColumn)
throws QueryStoreException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
QueryMalformedException, TableMalformedException, ColumnParseException, NotAllowedException,
DatabaseConnectionException, SortException, PaginationException, UserNotFoundException {
QueryMalformedException, TableMalformedException, ColumnParseException,
DatabaseConnectionException, SortException, PaginationException, UserNotFoundException, NotAllowedException {
log.debug("endpoint re-execute query, containerId={}, databaseId={}, queryId={}, principal={}, page={}, size={}, sortDirection={}, sortColumn={}",
containerId, databaseId, queryId, principal, page, size, sortDirection, sortColumn);
endpointValidator.validateDataParams(page, size, sortDirection, sortColumn);
final Database database = databaseService.find(containerId, databaseId);
if (!database.getIsPublic()) {
if (principal == null) {
log.error("Failed to re-execute private query: principal is null");
throw new NotAllowedException("Failed to re-execute private query: principal is null");
}
final Authentication authentication = (Authentication) principal;
if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("re-execute-query"))) {
log.error("Failed to re-execute private query: role missing");
throw new NotAllowedException("Failed to re-execute private query: role missing");
}
}
/* execute */
final Query query = storeService.findOne(containerId, databaseId, queryId, principal);
final QueryResultDto result = queryService.reExecute(containerId, databaseId, query, page, size,
......@@ -105,7 +132,6 @@ public class QueryEndpoint {
@GetMapping("/{queryId}/data/count")
@Transactional(readOnly = true)
@PreAuthorize("hasAuthority('re-execute-query')")
@Timed(value = "query.reexecute.count", description = "Time needed to re-execute a query")
@Operation(summary = "Re-execute some query", security = @SecurityRequirement(name = "bearerAuth"))
public ResponseEntity<Long> reExecuteCount(@NotNull @PathVariable("id") Long containerId,
......@@ -117,6 +143,18 @@ public class QueryEndpoint {
DatabaseConnectionException, UserNotFoundException {
log.debug("endpoint re-execute query count, containerId={}, databaseId={}, queryId={}, principal={}",
containerId, databaseId, queryId, principal);
final Database database = databaseService.find(containerId, databaseId);
if (!database.getIsPublic()) {
if (principal == null) {
log.error("Failed to re-execute private query: principal is null");
throw new NotAllowedException("Failed to re-execute private query: principal is null");
}
final Authentication authentication = (Authentication) principal;
if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("re-execute-query"))) {
log.error("Failed to re-execute private query: role missing");
throw new NotAllowedException("Failed to re-execute private query: role missing");
}
}
/* execute */
final Query query = storeService.findOne(containerId, databaseId, queryId, principal);
final Long result = queryService.reExecuteCount(containerId, databaseId, query, principal);
......@@ -136,10 +174,21 @@ public class QueryEndpoint {
Principal principal)
throws QueryStoreException, QueryNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
ContainerNotFoundException, TableMalformedException, FileStorageException, QueryMalformedException,
DatabaseConnectionException, UserNotFoundException {
// TODO: check if authority 'export-query-data'
DatabaseConnectionException, UserNotFoundException, NotAllowedException {
log.debug("endpoint export query, containerId={}, databaseId={}, queryId={}, accept={}, principal={}",
containerId, databaseId, queryId, accept, principal);
final Database database = databaseService.find(containerId, databaseId);
if (!database.getIsPublic()) {
if (principal == null) {
log.error("Failed to export private query: principal is null");
throw new NotAllowedException("Failed to export private query: principal is null");
}
final Authentication authentication = (Authentication) principal;
if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("export-query-data"))) {
log.error("Failed to export private query: role missing");
throw new NotAllowedException("Failed to export private query: role missing");
}
}
final Query query = storeService.findOne(containerId, databaseId, queryId, principal);
log.trace("querystore returned query {}", query);
final ExportResource resource = queryService.findOne(containerId, databaseId, queryId, principal);
......
......@@ -50,7 +50,7 @@ public class TableDataEndpoint {
@NotNull @Valid @RequestBody TableCsvDto data,
@NotNull Principal principal)
throws TableNotFoundException, DatabaseNotFoundException, TableMalformedException,
ImageNotSupportedException, ContainerNotFoundException, NotAllowedException, DatabaseConnectionException,
ImageNotSupportedException, ContainerNotFoundException, DatabaseConnectionException,
UserNotFoundException {
log.debug("endpoint insert data, containerId={}, databaseId={}, tableId={}, data={}, principal={}", containerId,
databaseId, tableId, data, principal);
......@@ -91,7 +91,7 @@ public class TableDataEndpoint {
@NotNull @Valid @RequestBody TableCsvDeleteDto data,
@NotNull Principal principal)
throws TableNotFoundException, DatabaseNotFoundException, TableMalformedException,
ImageNotSupportedException, TupleDeleteException, ContainerNotFoundException,
ImageNotSupportedException, ContainerNotFoundException,
DatabaseConnectionException, QueryMalformedException, UserNotFoundException {
log.debug("endpoint delete data, containerId={}, databaseId={}, tableId={}, data={}, principal={}", containerId,
databaseId, tableId, data, principal);
......
package at.tuwien.auth;
import at.tuwien.BaseUnitTest;
import at.tuwien.config.H2Utils;
import at.tuwien.config.IndexConfig;
import at.tuwien.config.ReadyConfig;
import at.tuwien.repository.jpa.UserRepository;
import com.rabbitmq.client.Channel;
import lombok.extern.log4j.Log4j2;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.junit.jupiter.api.Assertions.*;
@Log4j2
@SpringBootTest
@ExtendWith(SpringExtension.class)
public class AuthTokenFilterTest extends BaseUnitTest {
@MockBean
private Channel channel;
@MockBean
private IndexConfig indexConfig;
@MockBean
private ReadyConfig readyConfig;
@MockBean
private UserRepository userRepository;
@Autowired
private AuthTokenFilter authTokenFilter;
@Autowired
private H2Utils h2Utils;
@Test
public void parseJwt_fails() {
final MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Authorization", "Basic dXNlcjpwYXNz");
/* test */
final String response = authTokenFilter.parseJwt(request);
assertNull(response);
}
@Test
public void parseJwt_noAuthenticationHeader_fails() {
final MockHttpServletRequest request = new MockHttpServletRequest();
/* test */
final String response = authTokenFilter.parseJwt(request);
assertNull(response);
}
}
......@@ -20,12 +20,16 @@ import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
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.web.client.RestTemplate;
import java.io.File;
import java.io.IOException;
......@@ -51,11 +55,9 @@ public class ExportEndpointUnitTest extends BaseUnitTest {
@MockBean
private IndexConfig indexInitializer;
/* keep */
@MockBean
private RabbitMqListenerImpl rabbitMqListener;
/* keep */
@MockBean
private BrokerServiceGateway brokerServiceGateway;
......@@ -75,75 +77,56 @@ public class ExportEndpointUnitTest extends BaseUnitTest {
private ExportEndpoint exportEndpoint;
@Test
public void export_publicAnonymous_succeeds() throws TableNotFoundException, DatabaseConnectionException,
TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException,
UserNotFoundException, IOException {
@WithAnonymousUser
public void export_anonymous_succeeds() {
/* test */
assertThrows(NotAllowedException.class, () -> {
export_generic(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, null, null, null);
});
}
@Test
public void export_publicRead_succeeds() throws TableNotFoundException, DatabaseConnectionException,
TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException,
UserNotFoundException, IOException {
/* test */
export_generic(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, USER_2_PRINCIPAL, USER_2_USERNAME, DATABASE_1_RESEARCHER_READ_ACCESS);
}
@Test
public void export_publicWriteOwn_succeeds() throws TableNotFoundException, DatabaseConnectionException,
TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException,
UserNotFoundException, IOException {
/* test */
export_generic(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, USER_2_PRINCIPAL, USER_2_USERNAME, DATABASE_1_RESEARCHER_WRITE_OWN_ACCESS);
}
@Test
public void export_publicWriteAll_succeeds() throws TableNotFoundException, DatabaseConnectionException,
@WithMockUser(username = USER_1_USERNAME, authorities = {"export-table-data"})
public void export_publicHasRoleNoAccess_succeeds() throws TableNotFoundException, DatabaseConnectionException,
TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException,
UserNotFoundException, IOException {
/* test */
export_generic(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, USER_2_PRINCIPAL, USER_2_USERNAME, DATABASE_1_RESEARCHER_WRITE_ALL_ACCESS);
export_generic(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, USER_1_PRINCIPAL, USER_1_USERNAME, null);
}
@Test
public void export_publicOwner_succeeds() throws TableNotFoundException, DatabaseConnectionException,
@WithMockUser(username = USER_1_USERNAME, authorities = {"export-table-data"})
public void export_publicHasRoleReadAccess_succeeds() throws TableNotFoundException, DatabaseConnectionException,
TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException,
UserNotFoundException, IOException {
/* test */
export_generic(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, USER_1_PRINCIPAL, USER_1_USERNAME, DATABASE_1_RESEARCHER_WRITE_ALL_ACCESS);
export_generic(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, USER_1_PRINCIPAL, USER_1_USERNAME, DATABASE_1_RESEARCHER_READ_ACCESS);
}
@Test
public void export_publicReadWithTimestamp_succeeds() throws TableNotFoundException, DatabaseConnectionException,
TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException,
UserNotFoundException, IOException {
@WithAnonymousUser
public void export_publicReadWithTimestamp_succeeds() {
final Instant timestamp = Instant.now();
/* test */
export_generic(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, timestamp, USER_2_PRINCIPAL, USER_2_USERNAME, DATABASE_1_RESEARCHER_READ_ACCESS);
assertThrows(NotAllowedException.class, () -> {
export_generic(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, timestamp, null, null, null);
});
}
@Test
public void export_publicReadWithTimestampInFuture_succeeds() throws TableNotFoundException, DatabaseConnectionException,
TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException,
UserNotFoundException, IOException {
public void export_publicReadWithTimestampInFuture_succeeds() {
final Instant timestamp = Instant.now().plus(10, ChronoUnit.DAYS);
/* test */
export_generic(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, timestamp, USER_2_PRINCIPAL, USER_2_USERNAME, DATABASE_1_RESEARCHER_READ_ACCESS);
assertThrows(NotAllowedException.class, () -> {
export_generic(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, timestamp, null, null, null);
});
}
/* ################################################################################################### */
......@@ -151,6 +134,7 @@ public class ExportEndpointUnitTest extends BaseUnitTest {
/* ################################################################################################### */
@Test
@WithAnonymousUser
public void export_privateAnonymous_fails() {
/* test */
......@@ -160,17 +144,19 @@ public class ExportEndpointUnitTest extends BaseUnitTest {
}
@Test
public void export_privateRead_succeeds() throws TableNotFoundException, DatabaseConnectionException,
@WithMockUser(username = USER_2_USERNAME, authorities = {"export-table-data"})
public void export_privateHasRoleNoAccess_fails() throws TableNotFoundException, DatabaseConnectionException,
TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException,
UserNotFoundException, IOException {
/* test */
export_generic(CONTAINER_2_ID, DATABASE_2_ID, TABLE_1_ID, DATABASE_2, null, USER_2_PRINCIPAL, USER_2_USERNAME, DATABASE_2_RESEARCHER_READ_ACCESS);
export_generic(CONTAINER_2_ID, DATABASE_2_ID, TABLE_1_ID, DATABASE_2, null, USER_2_PRINCIPAL, USER_2_USERNAME, null);
}
@Test
public void export_privateWriteOwn_succeeds() throws TableNotFoundException, DatabaseConnectionException,
@WithMockUser(username = USER_2_USERNAME, authorities = {"export-table-data"})
public void export_HasRoleReadAccess_succeeds() throws TableNotFoundException, DatabaseConnectionException,
TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException,
UserNotFoundException, IOException {
......@@ -180,26 +166,7 @@ public class ExportEndpointUnitTest extends BaseUnitTest {
}
@Test
public void export_privateWriteAll_succeeds() throws TableNotFoundException, DatabaseConnectionException,
TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException,
UserNotFoundException, IOException {
/* test */
export_generic(CONTAINER_2_ID, DATABASE_2_ID, TABLE_1_ID, DATABASE_2, null, USER_2_PRINCIPAL, USER_2_USERNAME, DATABASE_2_RESEARCHER_WRITE_ALL_ACCESS);
}
@Test
public void export_privateOwner_succeeds() throws TableNotFoundException, DatabaseConnectionException,
TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException,
UserNotFoundException, IOException {
/* test */
export_generic(CONTAINER_2_ID, DATABASE_2_ID, TABLE_1_ID, DATABASE_2, null, USER_1_PRINCIPAL, USER_1_USERNAME, DATABASE_2_RESEARCHER_WRITE_ALL_ACCESS);
}
@Test
@WithMockUser(username = USER_2_USERNAME, authorities = {"export-table-data"})
public void export_privateReadWithTimestamp_succeeds() throws TableNotFoundException, DatabaseConnectionException,
TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException,
......@@ -211,6 +178,7 @@ public class ExportEndpointUnitTest extends BaseUnitTest {
}
@Test
@WithMockUser(username = USER_2_USERNAME, authorities = {"export-table-data"})
public void export_privateReadWithTimestampInFuture_succeeds() throws TableNotFoundException, DatabaseConnectionException,
TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException, FileStorageException,
PaginationException, ContainerNotFoundException, NotAllowedException, QueryMalformedException,
......
......@@ -12,6 +12,7 @@ import at.tuwien.exception.*;
import at.tuwien.gateway.BrokerServiceGateway;
import at.tuwien.listener.impl.RabbitMqListenerImpl;
import at.tuwien.querystore.Query;
import at.tuwien.repository.jpa.DatabaseAccessRepository;
import at.tuwien.repository.jpa.IdentifierRepository;
import at.tuwien.service.AccessService;
import at.tuwien.service.DatabaseService;
......@@ -32,6 +33,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.security.Principal;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.*;
......@@ -63,73 +65,89 @@ public class StoreEndpointUnitTest extends BaseUnitTest {
@Autowired
private StoreEndpoint storeEndpoint;
@MockBean
private QueryService queryService;
@MockBean
private StoreServiceImpl storeService;
@MockBean
private IdentifierRepository identifierRepository;
private DatabaseService databaseService;
@MockBean
private DatabaseService databaseService;
private DatabaseAccessRepository accessRepository;
@MockBean
private AccessService accessService;
@Test
@WithAnonymousUser
public void findAll_anonymous_succeeds() throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException,
ContainerNotFoundException, NotAllowedException, DatabaseConnectionException, TableMalformedException, UserNotFoundException {
ContainerNotFoundException, DatabaseConnectionException, TableMalformedException, UserNotFoundException {
/* test */
findAll_generic(CONTAINER_1_ID, DATABASE_1_ID, DATABASE_1, null, null);
findAll_generic(CONTAINER_1_ID, DATABASE_1_ID, DATABASE_1, null);
}
@Test
@WithAnonymousUser
public void findAll_anonymous2_succeeds() throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException,
ContainerNotFoundException, NotAllowedException, DatabaseConnectionException, TableMalformedException, UserNotFoundException {
@WithMockUser(username = USER_1_USERNAME)
public void findAll_noRole_succeeds() throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException,
ContainerNotFoundException, DatabaseConnectionException, TableMalformedException, UserNotFoundException {
/* test */
findAll_generic(CONTAINER_1_ID, DATABASE_1_ID, DATABASE_1, null, null);
findAll_generic(CONTAINER_1_ID, DATABASE_1_ID, DATABASE_1, USER_1_PRINCIPAL);
}
@Test
@WithMockUser(username = USER_1_USERNAME)
public void findAll_researcher_succeeds() throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException,
ContainerNotFoundException, NotAllowedException, DatabaseConnectionException, TableMalformedException, UserNotFoundException {
@WithMockUser(username = USER_1_USERNAME, authorities = {"list-queries"})
public void findAll_hasRole_succeeds() throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException,
ContainerNotFoundException, DatabaseConnectionException, TableMalformedException, UserNotFoundException {
/* test */
findAll_generic(CONTAINER_1_ID, DATABASE_1_ID, DATABASE_1, USER_1, USER_1_PRINCIPAL);
findAll_generic(CONTAINER_1_ID, DATABASE_1_ID, DATABASE_1, USER_1_PRINCIPAL);
}
@Test
@WithMockUser(username = USER_1_USERNAME)
public void findAll_researcherPrivateNoAccess_fails() {
@WithMockUser(username = USER_1_USERNAME, authorities = {"list-queries"})
public void findAll_noAccess_fails() {
/* mock */
when(accessRepository.findByDatabaseIdAndUsername(DATABASE_2_ID, USER_1_USERNAME))
.thenReturn(Optional.of(DATABASE_1_RESEARCHER_READ_ACCESS));
/* test */
assertThrows(NotAllowedException.class, () -> {
findAll_generic(CONTAINER_2_ID, DATABASE_2_ID, DATABASE_2, USER_1, USER_1_PRINCIPAL);
findAll_generic(CONTAINER_2_ID, DATABASE_2_ID, DATABASE_2, USER_1_PRINCIPAL);
});
}
@Test
@WithMockUser(username = USER_1_USERNAME, authorities = {"list-queries"})
public void findAll_hasAccess_succeeds() throws UserNotFoundException, QueryStoreException,
DatabaseConnectionException, TableMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
ContainerNotFoundException {
/* mock */
when(accessRepository.findByDatabaseIdAndUsername(DATABASE_2_ID, USER_1_USERNAME))
.thenReturn(Optional.of(DATABASE_1_RESEARCHER_READ_ACCESS));
/* test */
findAll_generic(CONTAINER_2_ID, DATABASE_2_ID, DATABASE_2, USER_1_PRINCIPAL);
}
@Test
@WithMockUser(username = USER_2_USERNAME)
public void findAll_dataSteward_succeeds() throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException,
ContainerNotFoundException, NotAllowedException, DatabaseConnectionException, TableMalformedException, UserNotFoundException {
ContainerNotFoundException, DatabaseConnectionException, TableMalformedException, UserNotFoundException {
/* test */
findAll_generic(CONTAINER_1_ID, DATABASE_1_ID, DATABASE_1, USER_2, USER_2_PRINCIPAL);
findAll_generic(CONTAINER_1_ID, DATABASE_1_ID, DATABASE_1, USER_2_PRINCIPAL);
}
@Test
@WithMockUser(username = USER_3_USERNAME)
public void findAll_developer_succeeds() throws QueryStoreException, DatabaseNotFoundException, ImageNotSupportedException,
ContainerNotFoundException, NotAllowedException, DatabaseConnectionException, TableMalformedException, UserNotFoundException {
ContainerNotFoundException, DatabaseConnectionException, TableMalformedException, UserNotFoundException {
/* test */
findAll_generic(CONTAINER_1_ID, DATABASE_1_ID, DATABASE_1, USER_3, USER_3_PRINCIPAL);
findAll_generic(CONTAINER_1_ID, DATABASE_1_ID, DATABASE_1, USER_3_PRINCIPAL);
}
@Test
......@@ -298,9 +316,9 @@ public class StoreEndpointUnitTest extends BaseUnitTest {
return response.getBody();
}
protected void findAll_generic(Long containerId, Long databaseId, Database database, User user, Principal principal)
protected void findAll_generic(Long containerId, Long databaseId, Database database, Principal principal)
throws UserNotFoundException, QueryStoreException, DatabaseConnectionException, TableMalformedException,
DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException, NotAllowedException {
DatabaseNotFoundException, ImageNotSupportedException, ContainerNotFoundException {
/* mock */
doReturn(List.of(QUERY_1)).when(storeService)
......
......@@ -4,6 +4,7 @@ import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.support.BasicAuthenticationInterceptor;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.DefaultUriBuilderFactory;
......@@ -14,6 +15,12 @@ public class GatewayConfig {
@Value("${fda.gateway.endpoint}")
private String gatewayEndpoint;
@Value("${spring.rabbitmq.username}")
private String brokerUsername;
@Value("${spring.rabbitmq.password}")
private String brokerPassword;
@Bean
public RestTemplate restTemplate() {
final RestTemplate restTemplate = new RestTemplate();
......@@ -21,4 +28,13 @@ public class GatewayConfig {
return restTemplate;
}
@Bean("brokerRestTemplate")
public RestTemplate brokerRestTemplate() {
final RestTemplate restTemplate = new RestTemplate();
restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(gatewayEndpoint));
restTemplate.getInterceptors()
.add(new BasicAuthenticationInterceptor(brokerUsername, brokerPassword));
return restTemplate;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment