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

Merge branch 'dev-fix-bugs' into 'dev'

Fixed the query service tests

See merge request !42
parents aa052276 e3c8d910
No related branches found
No related tags found
3 merge requests!81New stable release,!47Resolve "Show error messages from response",!42Fixed the query service tests
Showing
with 262 additions and 20 deletions
#!/bin/bash
docker container stop $(docker container ls -aq -f name=^/fda-.*) || true
docker container rm $(docker container ls -aq -f name=^/fda-.*) || true
docker container stop $(docker container ls -aq) || true
docker container rm $(docker container ls -aq) || true
docker volume rm $(docker volume ls -q) || true
docker network rm fda-userdb || true
docker network rm fda-public || true
\ No newline at end of file
......@@ -53,9 +53,6 @@ services:
environment:
SPRING_PROFILES_ACTIVE: docker
TZ: Europe/Vienna
depends_on:
fda-gateway-service:
condition: service_healthy
ports:
- "9090:9090"
logging:
......@@ -73,6 +70,9 @@ services:
environment:
SPRING_PROFILES_ACTIVE: docker
TZ: Europe/Vienna
depends_on:
fda-discovery-service:
condition: service_healthy
ports:
- "9095:9095"
logging:
......@@ -133,7 +133,7 @@ services:
fda-public:
# ipv4_address: 172.29.0.14
environment:
SPRING_PROFILES_ACTIVE: docker
SPRING_PROFILES_ACTIVE: docker,seeder
TZ: Europe/Vienna
ports:
- "9097:9097"
......
......@@ -6,7 +6,7 @@ psycopg2-binary==2.8.6
py-eureka-client==0.9.1
docker==5.0.0
sqlalchemy==1.4.15
gevent==21.8.0
requests==2.26.0
gevent==21.8.0
markupsafe===2.0.1
......@@ -11,6 +11,8 @@ import io.swagger.annotations.ApiResponses;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
......@@ -24,11 +26,14 @@ import java.security.Principal;
public class AuthenticationEndpoint {
private final UserMapper userMapper;
private final UserDetailsService userDetailsServiceImpl;
private final AuthenticationService authenticationService;
@Autowired
public AuthenticationEndpoint(UserMapper userMapper, AuthenticationService authenticationService) {
public AuthenticationEndpoint(UserMapper userMapper, UserDetailsService userDetailsServiceImpl,
AuthenticationService authenticationService) {
this.userMapper = userMapper;
this.userDetailsServiceImpl = userDetailsServiceImpl;
this.authenticationService = authenticationService;
}
......@@ -49,8 +54,9 @@ public class AuthenticationEndpoint {
@ApiResponse(code = 201, message = "Successfully authenticated a user.")
})
public ResponseEntity<UserDto> authenticateUser(Principal principal) {
final UserDetails details = userDetailsServiceImpl.loadUserByUsername(principal.getName());
return ResponseEntity.accepted()
.body(userMapper.principalToUserDto(principal));
.body(userMapper.userDetailsToUserDto(details, principal));
}
}
\ No newline at end of file
package at.tuwien.config;
import at.tuwien.seeder.Seeder;
import com.google.common.io.Files;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.annotation.Configuration;
......@@ -17,8 +19,16 @@ public class ReadyConfig {
@Value("${fda.ready.path}")
private String readyPath;
private final Seeder seederImpl;
@Autowired
public ReadyConfig(Seeder seederImpl) {
this.seederImpl = seederImpl;
}
@EventListener(ApplicationReadyEvent.class)
public void init() throws IOException {
seederImpl.seed();
Files.touch(new File(readyPath));
}
......
......@@ -11,6 +11,7 @@ import org.mapstruct.Mapper;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.security.Principal;
import java.util.Objects;
......@@ -68,14 +69,18 @@ public interface UserMapper {
.build();
}
default UserDto principalToUserDto(Principal principal) {
default UserDto userDetailsToUserDto(UserDetails data, Principal principal) {
final UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) principal;
return UserDto.builder()
final UserDto user = UserDto.builder()
.username(data.getUsername())
.password(data.getPassword())
.authorities(token.getAuthorities()
.stream()
.map(this::grantedAuthorityToGrantedAuthority)
.collect(Collectors.toList()))
.build();
log.debug("mapped user and principal {}", user);
return user;
}
}
package at.tuwien.seeder;
public interface Seeder {
void seed();
}
package at.tuwien.seeder.impl;
import at.tuwien.entities.user.RoleType;
import at.tuwien.entities.user.User;
import java.util.List;
public abstract class AbstractSeeder {
public final static Long USER_1_ID = 1L;
public final static String USER_1_USERNAME = "system";
public final static String USER_1_FIRSTNAME = "System";
public final static String USER_1_LASTNAME = "Default";
public final static String USER_1_EMAIL = "system.default@example.com";
public final static String USER_1_PASSWORD = "system";
public final static List<RoleType> USER_1_ROLES = List.of(RoleType.ROLE_RESEARCHER);
public final static User USER_1 = User.builder()
.id(USER_1_ID)
.username(USER_1_USERNAME)
.firstname(USER_1_FIRSTNAME)
.lastname(USER_1_LASTNAME)
.email(USER_1_EMAIL)
.roles(USER_1_ROLES)
.build();
public final static Long USER_2_ID = 2L;
public final static String USER_2_USERNAME = "researcher";
public final static String USER_2_TITLES_BEFORE = "Dr.";
public final static String USER_2_TITLES_AFTER = "BSc";
public final static String USER_2_FIRSTNAME = "Max";
public final static String USER_2_LASTNAME = "Mustermann";
public final static String USER_2_EMAIL = "max.mustermann@example.com";
public final static String USER_2_PASSWORD = "researcher";
public final static List<RoleType> USER_2_ROLES = List.of(RoleType.ROLE_RESEARCHER);
public final static User USER_2 = User.builder()
.id(USER_2_ID)
.username(USER_2_USERNAME)
.titlesBefore(USER_2_TITLES_BEFORE)
.firstname(USER_2_FIRSTNAME)
.lastname(USER_2_LASTNAME)
.titlesBefore(USER_2_TITLES_AFTER)
.email(USER_2_EMAIL)
.roles(USER_2_ROLES)
.build();
public final static Long USER_3_ID = 3L;
public final static String USER_3_USERNAME = "developer";
public final static String USER_3_FIRSTNAME = "Maria";
public final static String USER_3_LASTNAME = "Mustermann";
public final static String USER_3_EMAIL = "maria.mustermann@example.com";
public final static String USER_3_PASSWORD = "developer";
public final static List<RoleType> USER_3_ROLES = List.of(RoleType.ROLE_DEVELOPER);
public final static User USER_3 = User.builder()
.id(USER_3_ID)
.username(USER_3_USERNAME)
.firstname(USER_3_FIRSTNAME)
.lastname(USER_3_LASTNAME)
.email(USER_3_EMAIL)
.roles(USER_3_ROLES)
.build();
public final static Long USER_4_ID = 4L;
public final static String USER_4_USERNAME = "datasteward";
public final static String USER_4_FIRSTNAME = "Eva";
public final static String USER_4_LASTNAME = "Mustermann";
public final static String USER_4_EMAIL = "eva.mustermann@example.com";
public final static String USER_4_PASSWORD = "datasteward";
public final static List<RoleType> USER_4_ROLES = List.of(RoleType.ROLE_DATA_STEWARD);
public final static User USER_4 = User.builder()
.id(USER_4_ID)
.username(USER_4_USERNAME)
.firstname(USER_4_FIRSTNAME)
.lastname(USER_4_LASTNAME)
.email(USER_4_EMAIL)
.roles(USER_4_ROLES)
.build();
}
package at.tuwien.seeder.impl;
import at.tuwien.seeder.Seeder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class SeederImpl implements Seeder {
private final Seeder userSeederImpl;
public SeederImpl(Seeder userSeederImpl) {
this.userSeederImpl = userSeederImpl;
}
@Override
public void seed() {
userSeederImpl.seed();
}
}
package at.tuwien.seeder.impl;
import at.tuwien.entities.user.User;
import at.tuwien.repositories.UserRepository;
import at.tuwien.seeder.Seeder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.Arrays;
@Slf4j
@Service
public class UserSeederImpl extends AbstractSeeder implements Seeder {
private final Environment environment;
private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
@Autowired
public UserSeederImpl(Environment environment, PasswordEncoder passwordEncoder, UserRepository userRepository) {
this.environment = environment;
this.passwordEncoder = passwordEncoder;
this.userRepository = userRepository;
}
@Override
public void seed() {
if (userRepository.findAll().size() > 0) {
log.warn("Already seeded. Skip.");
return;
}
USER_1.setPassword(passwordEncoder.encode(USER_1_PASSWORD));
final User user1 = userRepository.save(USER_1);
log.info("Created user with id {}", user1);
if (Arrays.asList(environment.getActiveProfiles()).contains("seeder")) {
USER_2.setPassword(passwordEncoder.encode(USER_2_PASSWORD));
final User user2 = userRepository.save(USER_2);
log.info("Created user with id {}", user2);
USER_3.setPassword(passwordEncoder.encode(USER_3_PASSWORD));
final User user3 = userRepository.save(USER_3);
log.info("Created user with id {}", user3);
USER_4.setPassword(passwordEncoder.encode(USER_4_PASSWORD));
final User user4 = userRepository.save(USER_4);
log.info("Created user with id {}", user4);
}
}
}
......@@ -36,14 +36,14 @@ public class UserDetailsServiceImpl implements UserDetailsService {
log.error("Failed to load user by username {}", username);
throw new UsernameNotFoundException("Failed to load user by username");
}
log.debug("loaded user {}", user);
log.trace("loaded user {}", user);
final UserDetailsDto details = userMapper.userToUserDetailsDto(user.get());
details.setAuthorities(user.get()
.getRoles()
.stream()
.map(userMapper::roleTypeToGrantedAuthority)
.collect(Collectors.toList()));
log.debug("mapped user {}", details);
log.trace("mapped user {}", details);
return details;
}
......
......@@ -18,6 +18,7 @@ import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.security.Principal;
import java.util.List;
import java.util.stream.Collectors;
......@@ -61,10 +62,10 @@ public class ContainerEndpoint {
@ApiResponse(code = 201, message = "Successfully created a new container."),
@ApiResponse(code = 400, message = "Malformed payload."),
@ApiResponse(code = 401, message = "Not authorized to create a container."),
@ApiResponse(code = 404, message = "The container was not found after creation."),
@ApiResponse(code = 404, message = "The container was not found after creation or the user was not found."),
})
public ResponseEntity<ContainerBriefDto> create(@Valid @RequestBody ContainerCreateRequestDto data)
throws ImageNotFoundException, DockerClientException, ContainerAlreadyExistsException {
throws ImageNotFoundException, DockerClientException, UserNotFoundException {
final Container container = containerService.create(data);
final ContainerBriefDto response = containerMapper.containerToDatabaseContainerBriefDto(container);
return ResponseEntity.status(HttpStatus.CREATED)
......
......@@ -25,5 +25,6 @@ eureka:
instance.hostname: fda-container-service
client.serviceUrl.defaultZone: http://fda-discovery-service:9090/eureka/
fda:
mount.path: /tmp
ready.path: /ready
gateway.endpoint: http://fda-gateway-service:9095
\ No newline at end of file
......@@ -25,5 +25,6 @@ eureka:
instance.hostname: fda-container-service
client.serviceUrl.defaultZone: http://localhost:9090/eureka/
fda:
mount.path: /tmp
ready.path: ./ready
gateway.endpoint: http://localhost:9095
\ No newline at end of file
......@@ -15,8 +15,11 @@ import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.security.test.context.support.WithUserDetails;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.security.Principal;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
......@@ -54,7 +57,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest {
}
@Test
public void create_succeeds() throws ImageNotFoundException, DockerClientException, ContainerAlreadyExistsException {
public void create_succeeds() throws ImageNotFoundException, DockerClientException, UserNotFoundException {
final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder()
.name(CONTAINER_1_NAME)
.repository(IMAGE_1.getRepository())
......@@ -72,7 +75,7 @@ public class ContainerEndpointUnitTest extends BaseUnitTest {
@Disabled
@Test
public void create_noImage_fails() throws DockerClientException, ImageNotFoundException, ContainerAlreadyExistsException {
public void create_noImage_fails() throws DockerClientException, ImageNotFoundException, UserNotFoundException {
final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder()
.name(CONTAINER_1_NAME)
.repository("image")
......@@ -88,8 +91,9 @@ public class ContainerEndpointUnitTest extends BaseUnitTest {
}
@Disabled
@WithMockUser(username = "not3x1st1ng", roles = {"ROLE_RESEARCHER"})
@Test
public void create_docker_fails() throws DockerClientException, ImageNotFoundException, ContainerAlreadyExistsException {
public void create_docker_fails() throws DockerClientException, ImageNotFoundException, UserNotFoundException {
final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder()
.name(CONTAINER_1_NAME)
.repository(IMAGE_1.getRepository())
......
......@@ -27,6 +27,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.transaction.annotation.Transactional;
import java.security.Principal;
import java.util.List;
import java.util.Map;
import java.util.Optional;
......@@ -146,7 +147,7 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest {
}
@Test
public void create_succeeds() throws DockerClientException, ImageNotFoundException, ContainerAlreadyExistsException {
public void create_succeeds() throws DockerClientException, ImageNotFoundException, UserNotFoundException {
final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder()
.repository(IMAGE_1_REPOSITORY)
.tag(IMAGE_1_TAG)
......@@ -159,7 +160,7 @@ public class ContainerServiceIntegrationTest extends BaseUnitTest {
}
@Test
public void create_conflictingNames_fails() throws DockerClientException, ImageNotFoundException, ContainerAlreadyExistsException {
public void create_conflictingNames_fails() throws DockerClientException, ImageNotFoundException, UserNotFoundException {
final ContainerCreateRequestDto request = ContainerCreateRequestDto.builder()
.repository(IMAGE_1_REPOSITORY)
.tag(IMAGE_1_TAG)
......
package at.tuwien.config;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
@Getter
@Configuration
public class MountProperties {
@Value("${fda.mount.path}")
private String mountPath;
}
package at.tuwien.exception;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "User not found")
public class UserNotFoundException extends Exception {
public UserNotFoundException(String message) {
super(message);
}
public UserNotFoundException(String message, Throwable thr) {
super(message, thr);
}
public UserNotFoundException(Throwable thr) {
super(thr);
}
}
......@@ -3,6 +3,7 @@ package at.tuwien.gateway.impl;
import at.tuwien.api.user.UserDto;
import at.tuwien.gateway.AuthenticationServiceGateway;
import at.tuwien.mapper.UserMapper;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
......@@ -12,6 +13,7 @@ import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Log4j2
@Service
public class AuthenticationServiceGatewayImpl implements AuthenticationServiceGateway {
......
package at.tuwien.repository.jpa;
import at.tuwien.entities.user.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment