I am new to spring boot and testing and I have spring boot app (generated with JHipster) that uses authentication. I need to get the id of the current user.
so this method inside userRepository returns the current user
#Query(value = "select u.* from user u where u.username=?#{principal.username}", nativeQuery = true)
User findConnectedUser();
here is the method I want to test in my controller:
#PostMapping("/rdvs")
public ResponseEntity<Rdv> createRdv(#RequestBody Rdv rdv) throws URISyntaxException {
log.debug("REST request to save Rdv : {}", rdv);
if (rdv.getId() != null) {
throw new BadRequestAlertException("A new rdv cannot already have an ID", ENTITY_NAME, "idexists");
}
User user = userRepository.findConnectedUser();
rdv.setIdUser(user.getId());
Rdv result = rdvRepository.save(rdv);
return ResponseEntity
.created(new URI("/api/rdvs/" + result.getId()))
.headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, result.getId().toString()))
.body(result);
}
here is my test method
#Autowired
private RdvRepository rdvRepository;
#Autowired
private UserRepository userRepository;
....
#Test
#Transactional
void createRdv() throws Exception {
int databaseSizeBeforeCreate = rdvRepository.findAll().size();
// Create the Rdv
restRdvMockMvc
.perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(TestUtil.convertObjectToJsonBytes(rdv)))
.andExpect(status().isCreated());
// Validate the Rdv in the database
User user = userRepository.findConnectedUser();// this generate the NullPointer exception
List<Rdv> rdvList = rdvRepository.findAll();
assertThat(rdvList).hasSize(databaseSizeBeforeCreate + 1);
Rdv testRdv = rdvList.get(rdvList.size() - 1);
assertThat(testRdv.getDescription()).isEqualTo(DEFAULT_DESCRIPTION);
assertThat(testRdv.getIdUser()).isEqualTo(user.getId());
}
So this method generate a NullPointer, I guess because the method can't find the current user which should be authenticated first. So how can I authenticate a user inside that test method please I spend a lot of time with it but nothing seems to be working
note: I tried to call this api that authenticate users
#PostMapping("/authenticate")
public ResponseEntity<JWTToken> authorize(#Valid #RequestBody LoginVM loginVM) {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
loginVM.getUsername(),
loginVM.getPassword()
);
Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = tokenProvider.createToken(authentication, loginVM.isRememberMe());
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer " + jwt);
return new ResponseEntity<>(new JWTToken(jwt), httpHeaders, HttpStatus.OK);
}
like this in test method
User user = new User();
user.setLogin("user-jwt-controller");
user.setEmail("user-jwt-controller#example.com");
user.setActivated(true);
user.setPassword(passwordEncoder.encode("test"));
userRepository.saveAndFlush(user);
LoginVM loginVM = new LoginVM();
loginVM.setUsername("user-jwt-controller");
loginVM.setPassword("test");
//I don't know how to call the api #PostMapping("/authenticate")
Thanks in advance
Have a look at #WithMockUser annotation, see https://docs.spring.io/spring-security/site/docs/5.0.x/reference/html/test-method.html
You can see an example in the project that was generated by JHipster:
#AutoConfigureMockMvc
#WithMockUser(value = TEST_USER_LOGIN)
#IntegrationTest
class AccountResourceIT {
Related
I have to write a test function for findInContextUser based on JUnit Mock in Spring Boot but I have no idea how to write it.
How can I write findInContextUser for Junit Test?
Here are my code defined in UserService shown below.
public UserDto getUserDto(String username) {
var user = findUserByUsername(username);
return UserDto.builder()
.id(user.getId())
.username(user.getUsername())
.role(user.getRole())
.build();
}
public UserDto findInContextUser() {
final Authentication authentication = Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication()).orElseThrow(notFoundUser(HttpStatus.UNAUTHORIZED));
final UserDetails details = Optional.ofNullable((UserDetails) authentication.getPrincipal()).orElseThrow(notFoundUser(HttpStatus.UNAUTHORIZED));
return getUserDto(details.getUsername());
}
private static Supplier<GenericException> notFoundUser(HttpStatus unauthorized) {
return () -> GenericException.builder().httpStatus(unauthorized).errorMessage("user not found!").build();
}
Here is my test class shown below.
#Test
void itShouldFindInContextUser(){
// given - precondition or setup
User user = User.builder()
.username("username")
.password("password")
.role(Role.USER)
.build();
UserDto expected = UserDto.builder()
.id(user.getId())
.username(user.getUsername())
.role(user.getRole())
.build();
var roles = Stream.of(user.getRole())
.map(x -> new SimpleGrantedAuthority(x.name()))
.collect(Collectors.toList());
UserDetails details = new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), roles);
Authentication authentication = Mockito.mock(Authentication.class);
SecurityContext securityContext = Mockito.mock(SecurityContext.class);
// when - action or the behaviour that we are going test
when(securityContext.getAuthentication()).thenReturn(authentication);
when(securityContext.getAuthentication().getPrincipal()).thenReturn(details);
// then - verify the output
UserDto actual = userService.findInContextUser(); // ERROR IS HERE
assertEquals(expected, actual);
assertEquals(expected.getUsername(), actual.getUsername());
verify(userService, times(1)).findInContextUser();
}
Here is the error message shown below.
com.example.lib.exception.GenericException
Debug Part : 401 UNAUTHORIZED
I also added #WithMockUser(username = "username", password = "password", roles = "USER") but nothing changed.
Here is the solution shown below.
Add this line shown below underneath when parts
SecurityContextHolder.setContext(securityContext);
I have developed integration tests using MockMvc to send requests to the API server.
When I run each test individually they pass, but if I run the entire test class, the first passes and the rest fail due to:
DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["PUBLIC.UK_SB8BBOUER5WAK8VYIIY4PF2BX_INDEX_2 ON PUBLIC.USER(USERNAME) VALUES 4"; SQL statement:
I understand that this means the tests are trying to add another User entity to the repo where one already exists, but I don't understand why the repo is not being reset after each test?
The tests rely on methods to avoid repeated code in each test, and this must be having an effect because only my test classes with these methods are failing like this, but I cannot think why or how to fix it.
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureMockMvc
public class GameControllerTest {
#Autowired
MockMvc mvc;
#Autowired
GameService gameService;
#Autowired
GameRepository gameRepository;
#Autowired
UserRepository userRepository;
#Autowired
UserService userService;
public String username1 = "ss";
public String username2 = "dd";
public String username3 = "ff";
public String location = "London";
public String password = "Password72-";
public String apiVersion = "v1";
public final String gamesUrl = "/api/" + apiVersion + "/games/";
public final String addGameUrl = gamesUrl + "add-game";
public final String gameHistoryUrl = gamesUrl + "your-game-history";
public final String signupUrl = "/api/" + apiVersion + "/users/signup";
public final String loginUrl = "/api/" + apiVersion + "/login";
#Test
#Transactional
public void addGameTest() throws Exception {
String token = signupAndLogin();
Set<User> users = new HashSet<>();
User user = userRepository.findByUsername(username1);
User user2 = userRepository.findByUsername(username2);
users.add(user);
users.add(user2);
Game game = new Game(users, username1, username2, ResultForWhite.LOSE.getUrl(), "1.e4e5", username2);
MvcResult mvcResult = mvc.perform(post(addGameUrl)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(asJsonString(game)).header("Authorization", token))
.andExpect(status().isOk()).andReturn();
//Test JSON response is correct.
String jsonResult = mvcResult.getResponse().getContentAsString();
assertThat(jsonResult.contains(username1));
assertThat(jsonResult.contains(username2));
//Test that Game stored in DB correctly.
Optional<Game> savedGame = gameRepository.findById(1L);
assertThat(savedGame.get().getGameId() == 1);
//Test that user victories and defeats have been incremented correctly.
//Should be 1.
User savedUser = userRepository.findByUsername(username1);
User savedUser2 = userRepository.findByUsername(username2);
UserStats savedUserStats = savedUser.getUserStats().get(0);
UserStats savedUserStats2 = savedUser2.getUserStats().get(0);
Integer user1Victories = savedUserStats.getVictories();
Integer user1Defeats = savedUserStats.getDefeats();
Integer user2Victories = savedUserStats2.getVictories();
Integer user2Defeats = savedUserStats2.getDefeats();
//Assert that magnus lost the game and his defeats was incremented, and victories unchanged.
assertThat(user1Victories == 0 && user1Defeats == 1);
//Assert that hikaru won the game and his victories was incremented, and defeats unchanged.
assertThat(user2Victories == 1 && user2Defeats == 0);
}
#Test
#Transactional
public void getAUsersCompleteGameHistory() throws Exception {
String token = signupAndLogin();
createGames(token);
String content = "{\"keyword\":\"null\"}";
MvcResult mvcResult = mvc.perform(post(gameHistoryUrl)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(content).header("Authorization", token))
.andExpect(status().isOk()).andReturn();
String jsonResult = mvcResult.getResponse().getContentAsString();
System.out.println(jsonResult);
//Ensure the JSON object returned contains all the game entities.
assertTrue(jsonResult.contains("{\"gameId\":1") || jsonResult.contains("{\"gameId\":2") || jsonResult.contains("{\"gameId\":3") || jsonResult.contains("{\"gameId\":4") || jsonResult.contains("{\"gameId\":5") || jsonResult.contains("{\"gameId\":6"));
}
public String signupAndLogin() throws Exception {
User user = new User(1L, username1, password, location);
mvc.perform(post(signupUrl)
.contentType(MediaType.APPLICATION_JSON)
.content(asJsonString(user)))
.andExpect(status().isOk());
Optional<User> savedUser = userService.getUser(1L);
System.out.println(savedUser.toString());
//2nd User
User user2 = new User(2L, username2, password, location);
mvc.perform(post(signupUrl)
.contentType(MediaType.APPLICATION_JSON)
.content(asJsonString(user2)))
.andExpect(status().isOk());
Optional<User> savedUser2 = userService.getUser(2L);
System.out.println(savedUser2.toString());
//3rd User
User user3 = new User(3L, username3, password, "Bristol");
mvc.perform(post(signupUrl)
.contentType(MediaType.APPLICATION_JSON)
.content(asJsonString(user3)))
.andExpect(status().isOk());
Optional<User> savedUser3 = userService.getUser(3L);
System.out.println(savedUser3.toString());
//LOGIN
MvcResult mvcResult = mvc.perform(post(loginUrl)
.contentType(MediaType.APPLICATION_JSON)
.content(asJsonString(user)))
.andExpect(status().isOk())
.andReturn();
String token = mvcResult.getResponse().getHeader("Authorization");
System.out.println("Bearer Token: " + token);
return token;
}
#Transactional
public void createGames(String token) throws Exception {
Set<User> users = new HashSet<>();
Set<User> users2 = new HashSet<>();
User user = userRepository.findByUsername(username1);
User user2 = userRepository.findByUsername(username2);
User user3 = userRepository.findByUsername(username3);
System.out.println("ss: " + username1 + " dd " + username2 + " ff: " + username3);
//Add the User objects
users.add(user);
users.add(user2);
//Add the User objects
users2.add(user);
users2.add(user3);
System.out.println(users2.toString());
//Create 4 new Game objec
Game game = new Game(users, username1, username2username2);
Game game2 = new Game(users, username1, username2, username2);
Game game3 = new Game(users, username2, username1, username2);
Game game4 = new Game(users, username2, username1,username2);
//Create 2 new Game objects
Game game5 = new Game(users2, username3, username1, username3);
Game game6 = new Game(users2, username1, username3, username3);
mvc.perform(post(addGameUrl)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(asJsonString(game)).header("Authorization", token))
.andExpect(status().isOk());
System.out.println("DEFEATS TEST : //////// :" + userRepository.findByUsername(username2).getUserStats().get(0).getDefeats());
mvc.perform(post(addGameUrl)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(asJsonString(game2)).header("Authorization", token))
.andExpect(status().isOk());
System.out.println(userRepository.findByUsername(username2).getUserStats().get(0).getVictoryScore());
mvc.perform(post(addGameUrl)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(asJsonString(game3)).header("Authorization", token))
.andExpect(status().isOk());
System.out.println(userRepository.findByUsername(username2).getUserStats().get(0).getVictoryScore());
mvc.perform(post(addGameUrl)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(asJsonString(game4)).header("Authorization", token))
.andExpect(status().isOk());
System.out.println(userRepository.findByUsername(username2).getUserStats().get(0).getVictoryScore());
mvc.perform(post(addGameUrl)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(asJsonString(game5)).header("Authorization", token))
.andExpect(status().isOk());
mvc.perform(post(addGameUrl)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(asJsonString(game6)).header("Authorization", token))
.andExpect(status().isOk());
}
I am not sure but perchance if I refactored this to use #BeforeEach it would work? I just don't know if it will work though.
I have looked into #BeforeEach and I am unsure how I could get the token from the signUp method call e.g:
#BeforeEach
void setup( WebApplicationContext wac) throws Exception {
this.mvc = MockMvcBuilders.webAppContextSetup( wac )
.apply(SecurityMockMvcConfigurers.springSecurity())
.alwaysDo( signupAndLogin() )
.build();
}
Thanks
Edit:
I have added this to the 2nd test:
#Test
public void getAUsersCompleteGameHistory() throws Exception {
userRepository.deleteAll();
gameRepository.deleteAll();
//This doesn't print anything.
for (User u: userRepository.findAll()
) {
System.out.println();
System.out.println(u.getUsername());
System.out.println();
}
//This passes, user Repo.findAll IS empty
assertTrue(userRepository.findAll().isEmpty());
assertTrue(gameRepository.findAll().isEmpty());
String token = signupAndLogin();
createGames(token);
ETC...
}
So the repo are empty, it must be something in signUpAndLogin?
You can put #Transactional on your test class, instead of every test case, if all of the test require a rollback. I am not sure why it doesn't work in your case, so i will offer you some workarounds.
You can do a cleanup after every test:
#AfterEach
public void cleanup() {
gameRepository.deleteAll();
userRepository.deleteAll();
}
That is assuming that your repositories do not contain previous data required to run tests correctly. Or create custom method to delete by username in your repo, to delete only users created for tests, for example:
userRepository.deleteByUsername(username);
In order to initialize the token in BeforeEach method, and then access it, you need to keep it in an instance variable:
#BeforeEach
public void setup() throws Exception {
//instance variable
this.token = signupAndLogin();
}
But that will also lead to constraint violation if the DB is not cleared. If it's the username constraint which causes the problem, you can somewhat hack it by assigning random values to usernames in tests - UUID.randomUUID().toString() for example.
As a side note, i believe assertions using assertThat should look like that:
assertThat(user2Victories == 1 && user2Defeats == 0).isEqualTo(true);
assertThat(user2Victories == 1 && user2Defeats == 0); actually does not assert anything.
I try some tests on my UserController for updating the email field like this :
#Test
public void testUpdateUserNominal() throws Exception {
savedUser.setEmail(EMAIL_2);
UserDTORequest updatedUserDTORequest = modelMapper.map(savedUser, UserDTORequest.class);
String jsonMessage = gson.toJson(updatedUserDTORequest);
mvc.perform(put(USER_ROUTE)
.contentType(APPLICATION_JSON)
.accept(APPLICATION_JSON)
.content(jsonMessage))
.andExpect(status().isOk())
.andReturn();
assertThat(userService.findAll().size()).isEqualTo(1);
assertThat(userService.findAll().get(0).getEmail()).isEqualTo(EMAIL_2);
}
Here is the code on my controller :
#Override
public ResponseEntity<UserDTOResponse> update(UserDTORequest userDTORequest) throws ParseException {
Optional<User> optUser = userService.findByUri(userDTORequest.getUri());
if(optUser.isEmpty()){
return ResponseEntity
.notFound()
.build();
}
User user = convertToEntity(userDTORequest);
User userUpdated = userService.save(user);
UserDTOResponse userDTOResponse = convertToDto(userUpdated);
return ResponseEntity
.ok(userDTOResponse);
}
The response from the mockMvc is correct : the new email set is the good one.
But on the second assertThat :
assertThat(userService.findAll().get(0).getEmail()).isEqualTo(EMAIL_2);
The email is not the good one, the email is not updated.
What I do wrong ?
Thanks :)
In my micro service, I have a ResourceServer and an AuthServer at port 19000.
In ResourceServer here is the part of the application.yml
security:
oauth2:
resource:
id: gateway
user-info-uri: http://localhost:19000/user
prefer-token-info: false
the /user end point is simple like this
#RestController
#RequestMapping("/")
public class UserController {
#GetMapping(value = "/user")
public Principal getUser(Principal user) {
return user;
}
}
and I will get UserDetail in the ResourceServer , use this code
void me(Principal principal) {
String name = principal.getName();
}
At the beginning ,the name is always the right name . but If userA and userB access the interface with their token at the almost same time, Things go wrong. Sometimes I will get userA's name when I except userB' name.
I check out the spring security source code , In UserInfoTokenServices.java , I found this code probably cause the mistake. When many querys come in, they multi-threads operate the same this.restTemplate , and the logical of accessToken and existingToken , when they equals, but other thread maybe will change the this.restTemplate before it calls restTemplate.getForEntity
private Map<String, Object> getMap(String path, String accessToken) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Getting user info from: " + path);
}
try {
OAuth2RestOperations restTemplate = this.restTemplate;
if (restTemplate == null) {
BaseOAuth2ProtectedResourceDetails resource = new BaseOAuth2ProtectedResourceDetails();
resource.setClientId(this.clientId);
restTemplate = new OAuth2RestTemplate(resource);
}
OAuth2AccessToken existingToken = restTemplate.getOAuth2ClientContext()
.getAccessToken();
if (existingToken == null || !accessToken.equals(existingToken.getValue())) {
DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(
accessToken);
token.setTokenType(this.tokenType);
restTemplate.getOAuth2ClientContext().setAccessToken(token);
}
return restTemplate.getForEntity(path, Map.class).getBody();
}
catch (Exception ex) {
this.logger.warn("Could not fetch user details: " + ex.getClass() + ", "
+ ex.getMessage());
return Collections.<String, Object>singletonMap("error",
"Could not fetch user details");
}
}
}
I think this will cause the wrong Principal info.
And In fact. When I use this code
Principal principal = SecurityContextHolder.getContext().getAuthentication();
String name = principal.getName();
the name will suddenly go wrong ,then next time be right again.
Are you guys ever confused with this situation?
What to do I can get the right username all the time.
Thanks for your attention.
when server started,
step 1 if there is not a bean of AuthorizationServerEndpointsConfiguration.class , will goto step 2
step 2: if there is not a bean of ResourceServerTokenServices.class
,run the code below:
#Bean
#ConditionalOnMissingBean(ResourceServerTokenServices.class)
public UserInfoTokenServices userInfoTokenServices() {
UserInfoTokenServices services = new UserInfoTokenServices(
this.sso.getUserInfoUri(), this.sso.getClientId());
services.setRestTemplate(this.restTemplate);
services.setTokenType(this.sso.getTokenType());
if (this.authoritiesExtractor != null) {
services.setAuthoritiesExtractor(this.authoritiesExtractor);
}
if (this.principalExtractor != null) {
services.setPrincipalExtractor(this.principalExtractor);
}
return services;
}
so ResourceServerTokenServices is singleton, and so its restTemplate,
when program run into this code below , multi-thread will concurrent operate restTemplate. Something wrong will come out.
private Map<String, Object> getMap(String path, String accessToken) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Getting user info from: " + path);
}
try {
OAuth2RestOperations restTemplate = this.restTemplate;
if (restTemplate == null) {
BaseOAuth2ProtectedResourceDetails resource = new BaseOAuth2ProtectedResourceDetails();
resource.setClientId(this.clientId);
restTemplate = new OAuth2RestTemplate(resource);
}
OAuth2AccessToken existingToken = restTemplate.getOAuth2ClientContext()
.getAccessToken();
if (existingToken == null || !accessToken.equals(existingToken.getValue())) {
DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(
accessToken);
token.setTokenType(this.tokenType);
restTemplate.getOAuth2ClientContext().setAccessToken(token);
}
return restTemplate.getForEntity(path, Map.class).getBody();
}
catch (Exception ex) {
this.logger.warn("Could not fetch user details: " + ex.getClass() + ", "
+ ex.getMessage());
return Collections.<String, Object>singletonMap("error",
"Could not fetch user details");
}
}
the right way is : If ResourceServer there is no AuthorizationServerEndpointsConfiguration, you'd better provide an implement of ResourceServerTokenServices.class. This will be controlled better.
I had same problem: concurrent requests mashed up principals.
Today applied advice from this article: https://www.baeldung.com/spring-security-oauth2-authentication-with-reddit .
1) Added #EnableOAuth2Client annotation,
2) Added OAuth2ClientContext clientContext to rest remplate.
Me final RestTemplate bean looks this way:
#Bean
#LoadBalanced
public OAuth2RestOperations restTemplate(UserInfoTokenServices remoteTokenServices,
OAuth2ClientContext clientContext) {
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setClientId(securityProperties.getServiceClientId());
resourceDetails.setClientSecret(securityProperties.getServiceClientSecret());
OAuth2RestOperations restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);
remoteTokenServices.setRestTemplate(restTemplate);
return restTemplate;
}
And my tests show that bug has gone and no mash happens in principals.
So a have a blueprint code of a web app which allows different accounts with logins to upload simple files. However, there are security flaws that allow non-admin accounts to enter database configurations and direct object referencing (download files of other accounts by URL tampering). I was recommended a solution whereby I check if the owner of the uploaded file is the same one trying to download it. But doing that in a spring #controller posed a few problems. If you look at my get statement to get a specific file, you see that I got the file object and the account object. Then I just check if the name is the same of file owner. But how do I "return" something in a controller while in an "if" statement?
#Controller
public class FileController {
#Autowired
private FileRepository fileRepository;
#Autowired
private AccountRepository accountRepository;
#RequestMapping(value = "/files", method = RequestMethod.GET)
public String list(Authentication authentication, Model model) {
model.addAttribute("files", accountRepository.findByUsername(authentication.getName()).getFileObjects());
return "files";
}
#RequestMapping(value = "/files/{id}", method = RequestMethod.GET)
public ResponseEntity<byte[]> viewFile(#PathVariable Long id) {
//1. get object or name account name
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();
//2. check if the file account is of the same name
FileObject fo = fileRepository.findOne(id);
if((fo.getAccount().getUsername()).equals(currentPrincipalName)) {
System.out.println("WHAT AM I SUPPOSED TO DO!?");
}
final HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType(fo.getContentType()));
headers.add("Content-Disposition", "attachment; filename=" + fo.getName());
headers.setContentLength(fo.getContentLength());
return new ResponseEntity<>(fo.getContent(), headers, HttpStatus.CREATED);
}
#RequestMapping(value = "/files", method = RequestMethod.POST)
public String addFile(Authentication authentication, #RequestParam("file") MultipartFile file) throws IOException {
Account account = accountRepository.findByUsername(authentication.getName());
FileObject fileObject = new FileObject();
fileObject.setContentType(file.getContentType());
fileObject.setContent(file.getBytes());
fileObject.setName(file.getOriginalFilename());
fileObject.setContentLength(file.getSize());
fileObject.setAccount(account);
fileRepository.save(fileObject);
return "redirect:/files";
}
#RequestMapping(value = "/files/{id}", method = RequestMethod.DELETE)
public String delete(#PathVariable Long id) {
fileRepository.delete(id);
return "redirect:/files";
}
}