Skip to content
This repository was archived by the owner on Apr 5, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ CommandLineRunner initUserDataBaseProd(UserRepository repository) {
.builder()
.userId(0L)
.username("admin")
.lowercaseUsername("admin")
.password("admin")
.refreshToken("refreshToken1234")
.groupIds(new long[]{0, 1})
Expand All @@ -90,6 +91,7 @@ CommandLineRunner initUserDataBaseDev(UserRepository repository) {
.builder()
.userId(0)
.username("user")
.lowercaseUsername("user")
.password("1234")
.refreshToken("rft1234")
.groupIds(new long[]{0})
Expand All @@ -98,6 +100,7 @@ CommandLineRunner initUserDataBaseDev(UserRepository repository) {
.builder()
.userId(1)
.username("user1")
.lowercaseUsername("user1")
.password("12345")
.refreshToken("rft")
.groupIds(new long[]{-1})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import de.filefighter.rest.domain.token.exceptions.AccessTokenNotFoundException;
import de.filefighter.rest.domain.user.data.dto.User;
import de.filefighter.rest.domain.user.exceptions.UserNotAuthenticatedException;
import de.filefighter.rest.rest.exceptions.RequestDidntMeetFormalRequirementsException;
import org.springframework.stereotype.Service;

import java.time.Instant;
Expand Down Expand Up @@ -59,7 +60,7 @@ public AccessToken getValidAccessTokenForUser(User user) {

public AccessToken findAccessTokenByValueAndUserId(String accessTokenValue, long userId) {
if (!stringIsValid(accessTokenValue))
throw new IllegalArgumentException("Value of AccessToken was not valid.");
throw new RequestDidntMeetFormalRequirementsException("Value of AccessToken was not valid.");

AccessTokenEntity accessTokenEntity = accessTokenRepository.findByUserIdAndValue(userId, accessTokenValue);
if (null == accessTokenEntity)
Expand All @@ -68,13 +69,24 @@ public AccessToken findAccessTokenByValueAndUserId(String accessTokenValue, long
return accessTokenDtoService.createDto(accessTokenEntity);
}

public AccessToken findAccessTokenByValue(String accessTokenValue) {
if (!stringIsValid(accessTokenValue))
throw new RequestDidntMeetFormalRequirementsException("Value of AccessToken was not valid.");

AccessTokenEntity accessTokenEntity = accessTokenRepository.findByValue(accessTokenValue);
if (null == accessTokenEntity)
throw new UserNotAuthenticatedException("AccessToken not found.");

return accessTokenDtoService.createDto(accessTokenEntity);
}

public String generateRandomTokenValue() {
return UUID.randomUUID().toString();
}

public String checkBearerHeader(String accessTokenValue) {
if (!accessTokenValue.matches("^" + AUTHORIZATION_BEARER_PREFIX + "[^\\s](.*)$"))
throw new UserNotAuthenticatedException("Header does not contain '" + AUTHORIZATION_BEARER_PREFIX + "', or format is invalid.");
throw new RequestDidntMeetFormalRequirementsException("Header does not contain '" + AUTHORIZATION_BEARER_PREFIX + "', or format is invalid.");
return accessTokenValue.split(AUTHORIZATION_BEARER_PREFIX)[1];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class AccessTokenNotFoundAdvise {
@ResponseStatus(HttpStatus.BAD_REQUEST)

ResponseEntity<ServerResponse> tokenNotFoundAdvise(AccessTokenNotFoundException ex) {
LoggerFactory.getLogger(UserAlreadyExistsAdvise.class).warn(ex.getMessage());
LoggerFactory.getLogger(AccessTokenNotFoundException.class).warn(ex.getMessage());
return new ResponseEntity<>(new ServerResponse("denied", ex.getMessage()), HttpStatus.BAD_REQUEST);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import de.filefighter.rest.domain.user.data.persistance.UserRepository;
import de.filefighter.rest.domain.user.exceptions.UserNotAuthenticatedException;
import de.filefighter.rest.domain.user.exceptions.UserNotFoundException;
import de.filefighter.rest.rest.exceptions.RequestDidntMeetFormalRequirementsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -39,11 +40,11 @@ public long getUserCount() {

public User getUserByUsernameAndPassword(String base64encodedUserAndPasswordWithHeaderPrefix) {
if (!stringIsValid(base64encodedUserAndPasswordWithHeaderPrefix))
throw new UserNotAuthenticatedException("Header was empty.");
throw new RequestDidntMeetFormalRequirementsException("Header was empty.");

//TODO: maybe filter unsupported characters?
if (!base64encodedUserAndPasswordWithHeaderPrefix.matches("^" + AUTHORIZATION_BASIC_PREFIX + "[^\\s](.*)$"))
throw new UserNotAuthenticatedException("Header does not contain '" + AUTHORIZATION_BASIC_PREFIX + "', or format is invalid.");
throw new RequestDidntMeetFormalRequirementsException("Header does not contain '" + AUTHORIZATION_BASIC_PREFIX + "', or format is invalid.");

String[] split = base64encodedUserAndPasswordWithHeaderPrefix.split(AUTHORIZATION_BASIC_PREFIX);

Expand All @@ -60,22 +61,22 @@ public User getUserByUsernameAndPassword(String base64encodedUserAndPasswordWith
split = decodedUsernameUndPassword.strip().split(":");

if (split.length != 2)
throw new UserNotAuthenticatedException("Credentials didnt meet formal requirements.");
throw new RequestDidntMeetFormalRequirementsException("Credentials didnt meet formal requirements.");

String username = split[0];
String password = split[1];

UserEntity userEntity = userRepository.findByUsernameAndPassword(username, password);
if (null == userEntity)
throw new UserNotFoundException("No User found with this username and password.");
throw new UserNotAuthenticatedException("No User found with this username and password.");

return userDtoService.createDto(userEntity);
}

public RefreshToken getRefreshTokenForUser(User user) {
UserEntity userEntity = userRepository.findByUserIdAndUsername(user.getId(), user.getUsername());
if (null == userEntity)
throw new UserNotFoundException();
throw new UserNotAuthenticatedException(user.getId());

String refreshTokenValue = userEntity.getRefreshToken();

Expand All @@ -91,11 +92,11 @@ public RefreshToken getRefreshTokenForUser(User user) {

public User getUserByRefreshTokenAndUserId(String refreshToken, long userId) {
if (!stringIsValid(refreshToken))
throw new UserNotAuthenticatedException("RefreshToken was not valid.");
throw new RequestDidntMeetFormalRequirementsException("RefreshToken was not valid.");

UserEntity userEntity = userRepository.findByRefreshTokenAndUserId(refreshToken, userId);
if (null == userEntity)
throw new UserNotFoundException(userId);
throw new UserNotAuthenticatedException(userId);

return userDtoService.createDto(userEntity);
}
Expand All @@ -110,4 +111,17 @@ public User getUserByAccessTokenAndUserId(AccessToken accessToken, long userId)

return userDtoService.createDto(userEntity);
}

public User findUserByUsername(String username) {
if (!stringIsValid(username))
throw new RequestDidntMeetFormalRequirementsException("Username was not valid.");

String lowercaseUsername = username.toLowerCase().replace(" ","");

UserEntity entity = userRepository.findByLowercaseUsername(lowercaseUsername);
if (null == entity)
throw new UserNotFoundException("User with username '" + username + "' not found.");

return userDtoService.createDto(entity);
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
package de.filefighter.rest.domain.user.data.persistance;

import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.ToString;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoId;

@Document(collection = "user")
@Data
@Getter
@ToString
@Builder
public class UserEntity {

@MongoId
private String _id;
private long userId;
private String username;
private String password;
private String refreshToken; //TODO: add valid_until for refreshToken
private long[] groupIds;
private final String _id;
private final long userId;
private final String username;
private final String lowercaseUsername; // Redundancy for performance tradeoff.
private final String password;
private final String refreshToken; //TODO: add valid_until for refreshToken
private final long[] groupIds;

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ public interface UserRepository extends MongoRepository<UserEntity, String> {
UserEntity findByUsernameAndPassword(String username, String password);
UserEntity findByRefreshTokenAndUserId(String refreshToken, long userId);
UserEntity findByUserId(long userId);
UserEntity findByLowercaseUsername(String lowercaseUsername);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class UserAlreadyExistsAdvise {
@ResponseStatus(HttpStatus.BAD_REQUEST)

ResponseEntity<ServerResponse> userAlreadyExistsAdvise(UserAlreadyExistsException ex) {
LoggerFactory.getLogger(UserAlreadyExistsAdvise.class).warn(ex.getMessage());
LoggerFactory.getLogger(UserAlreadyExistsException.class).warn(ex.getMessage());
return new ResponseEntity<>(new ServerResponse("denied", ex.getMessage()), HttpStatus.BAD_REQUEST);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class UserNotAuthenticatedAdvise {
@ExceptionHandler(UserNotAuthenticatedException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
ResponseEntity<ServerResponse> userNotAuthenticatedHandler(UserNotAuthenticatedException ex) {
LoggerFactory.getLogger(UserAlreadyExistsAdvise.class).warn(ex.getMessage());
LoggerFactory.getLogger(UserNotAuthenticatedException.class).warn(ex.getMessage());
return new ResponseEntity<>(new ServerResponse("denied", ex.getMessage()), HttpStatus.UNAUTHORIZED);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ public UserNotAuthenticatedException(String reason){
super("User could not be authenticated. "+reason);
}

// public UserNotAuthenticatedException() {
// super("User could not be authenticated.");
// }

public UserNotAuthenticatedException(long id){
super("User with the id "+id+" could not be authenticated.");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class UserNotFoundAdvice {
@ExceptionHandler(UserNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
ResponseEntity<ServerResponse> userNotFoundHandler(UserNotFoundException ex) {
LoggerFactory.getLogger(UserAlreadyExistsAdvise.class).warn(ex.getMessage());
return new ResponseEntity<>(new ServerResponse("denied", ex.getMessage()), HttpStatus.NOT_FOUND);
LoggerFactory.getLogger(UserNotFoundException.class).warn(ex.getMessage());
return new ResponseEntity<>(new ServerResponse("not found", ex.getMessage()), HttpStatus.NOT_FOUND);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public UserNotFoundException(long id) {
super("Could not find user " + id);
}

public UserNotFoundException(String string) {
super(string);
public UserNotFoundException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ public ResponseEntity<User> registerNewUserWithAccessToken(UserRegisterForm newU

@Override
public ResponseEntity<User> findUserByUsernameAndAccessToken(String username, String accessToken) {
return null;
String cleanValue = accessTokenBusinessService.checkBearerHeader(accessToken);
AccessToken token = accessTokenBusinessService.findAccessTokenByValue(cleanValue);
User foundUser = userBusinessService.findUserByUsername(username);
return new ResponseEntity<>(foundUser, HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package de.filefighter.rest.rest.exceptions;

import de.filefighter.rest.rest.ServerResponse;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
public class RequestDidntMeetFormalRequirementsAdvise {

@ResponseBody
@ExceptionHandler(RequestDidntMeetFormalRequirementsException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
ResponseEntity<ServerResponse> requestDidntMeetFormalRequirements(RequestDidntMeetFormalRequirementsException ex) {
LoggerFactory.getLogger(RequestDidntMeetFormalRequirementsException.class).warn(ex.getMessage());
return new ResponseEntity<>(new ServerResponse("denied", ex.getMessage()), HttpStatus.BAD_REQUEST);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package de.filefighter.rest.rest.exceptions;

public class RequestDidntMeetFormalRequirementsException extends RuntimeException{

public RequestDidntMeetFormalRequirementsException() {
super("Request didnt meet formal requirements.");
}

public RequestDidntMeetFormalRequirementsException(String message) {
super("Request didnt meet formal requirements. "+message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import io.cucumber.java.en.And;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
Expand All @@ -22,6 +24,7 @@

public class CommonCucumberSteps extends RestApplicationIntegrationTest {

private static final Logger LOG = LoggerFactory.getLogger(CommonCucumberSteps.class);
private final UserRepository userRepository;
private final AccessTokenRepository accessTokenRepository;
private final FileSystemRepository fileSystemRepository;
Expand All @@ -44,21 +47,33 @@ public void databaseIsEmpty() {

@And("user {long} exists")
public void userExists(long userId) {
userRepository.save(UserEntity
LOG.info("Creating User: " + userRepository.save(UserEntity
.builder()
.userId(userId)
.build());
.build()));
}

@And("user with id {long} exists and has username {string}, password {string} and refreshToken {string}")
public void userWithIdExistsAndHasUsernamePasswordAndRefreshToken(long userId, String username, String password, String refreshTokenValue) {
userRepository.save(UserEntity
LOG.info("Creating User: " + userRepository.save(UserEntity
.builder()
.userId(userId)
.username(username)
.lowercaseUsername(username.toLowerCase())
.password(password)
.refreshToken(refreshTokenValue)
.build());
.build()));
}

@And("user with id {long} exists and has username {string}, password {string}")
public void userWithIdExistsAndHasUsernamePassword(long userId, String username, String password) {
LOG.info("Creating User: " + userRepository.save(UserEntity
.builder()
.userId(userId)
.username(username)
.lowercaseUsername(username.toLowerCase())
.password(password)
.build()));
}

// This step almost needs a unit test.
Expand All @@ -81,17 +96,17 @@ public void fileOrFolderExistsWithIdAndPath(String fileOrFolder, long fsItemId,
for (int i = 0; i < names.length; i++) {
if (!names[i].isEmpty() && !names[i].isBlank()) {
boolean isLastOne = i == names.length - 1;
if(!isLastOne){
if (!isLastOne) {
//is obviously a folder.
completeFilePath.append(names[i]).append("/");
fileSystemRepository.save(FileSystemEntity
.builder()
.isFile(false)
.path(completeFilePath.toString())
.build());
System.out.println("folder: "+completeFilePath.toString());
}else{
System.out.println("last one: "+names[i]);
System.out.println("folder: " + completeFilePath.toString());
} else {
System.out.println("last one: " + names[i]);
if (fileOrFolder.equals("file")) {
fileSystemRepository.save(FileSystemEntity
.builder()
Expand Down
22 changes: 22 additions & 0 deletions src/test/java/de/filefighter/rest/cucumber/FindUserSteps.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package de.filefighter.rest.cucumber;

import de.filefighter.rest.RestApplicationIntegrationTest;
import io.cucumber.java.en.When;
import org.springframework.http.HttpMethod;

import java.util.HashMap;

import static de.filefighter.rest.configuration.RestConfiguration.*;

public class FindUserSteps extends RestApplicationIntegrationTest {
@When("user with accessToken {string} searches user with search-value {string}")
public void userWithAccessTokenSearchesUserWithSearchValue(String accessToken, String search_value) {
String authHeaderString = AUTHORIZATION_BEARER_PREFIX + accessToken;
String url = BASE_API_URI + USER_BASE_URI + "/find?username="+search_value;

HashMap<String, String> authHeader = new HashMap<>();
authHeader.put("Authorization", authHeaderString);

executeRestApiCall(HttpMethod.GET, url, authHeader);
}
}
Loading