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

Updated some more tests

parent 64e4aa69
Branches
Tags
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 register or to comment