Skip to content

Commit cb4ad7e

Browse files
Merge pull request #540 from qbicsoftware/development
Release 0.39.0
2 parents 266d40a + 5a11d5e commit cb4ad7e

File tree

173 files changed

+7230
-2281
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

173 files changed

+7230
-2281
lines changed

application-commons/pom.xml

+4
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,9 @@
1515
<artifactId>spock-core</artifactId>
1616
<scope>test</scope>
1717
</dependency>
18+
<dependency>
19+
<groupId>org.springframework.data</groupId>
20+
<artifactId>spring-data-commons</artifactId>
21+
</dependency>
1822
</dependencies>
1923
</project>
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package life.qbic.projectmanagement.infrastructure;
1+
package life.qbic.application.commons;
22

33
import java.util.Objects;
44
import org.springframework.data.domain.Pageable;

project-management/src/main/java/life/qbic/projectmanagement/application/SortOrder.java application-commons/src/main/java/life/qbic/application/commons/SortOrder.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package life.qbic.projectmanagement.application;
1+
package life.qbic.application.commons;
22

33
/**
44
* A sort order to be consumed by a data providing service.

identity-api/pom.xml

+8
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,13 @@
1717
<maven.compiler.target>17</maven.compiler.target>
1818
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
1919
</properties>
20+
<dependencies>
21+
<dependency>
22+
<groupId>life.qbic</groupId>
23+
<artifactId>application-commons</artifactId>
24+
<version>0.38.2</version>
25+
<scope>compile</scope>
26+
</dependency>
27+
</dependencies>
2028

2129
</project>

identity-api/src/main/java/life/qbic/identity/api/PersonalAccessTokenService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ RawToken create(String userId, String description, Duration duration)
3131
* @return a collection of personal access token entries associated with a user id
3232
* @since 1.0.0
3333
*/
34-
Collection<PersonalAccessToken> find(String userId);
34+
Collection<PersonalAccessToken> findAll(String userId);
3535

3636
/**
3737
* Deletes a personal access token with a given token id for a user

identity-api/src/main/java/life/qbic/identity/api/UserInformationService.java

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package life.qbic.identity.api;
22

3+
import java.util.List;
34
import java.util.Optional;
5+
import life.qbic.application.commons.SortOrder;
46

57
/**
68
* <b>User information service</b>
@@ -42,4 +44,5 @@ public interface UserInformationService {
4244
*/
4345
boolean userNameAvailable(String userName);
4446

47+
List<UserInfo> findAllActive(String filter, int offset, int limit, List<SortOrder> sortOrders);
4548
}

identity-infrastructure/src/main/java/life/qbic/identity/infrastructure/QbicUserRepo.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import life.qbic.identity.domain.model.EmailAddress;
66
import life.qbic.identity.domain.model.User;
77
import life.qbic.identity.domain.model.UserId;
8+
import org.springframework.data.domain.Pageable;
9+
import org.springframework.data.jpa.repository.JpaRepository;
810
import org.springframework.data.repository.CrudRepository;
911

1012
/**
@@ -18,7 +20,7 @@
1820
*
1921
* @since 1.0.0
2022
*/
21-
public interface QbicUserRepo extends CrudRepository<User, UserId> {
23+
public interface QbicUserRepo extends JpaRepository<User, UserId> {
2224

2325
/**
2426
* Find users by mail address in the persistent data storage
@@ -46,4 +48,6 @@ public interface QbicUserRepo extends CrudRepository<User, UserId> {
4648
List<User> findUsersByActiveTrue();
4749

4850
User findUserByUserName(String userName);
51+
52+
List<User> findAllByUserNameContainingIgnoreCaseAndActiveTrue(String username, Pageable pageable);
4953
}

identity-infrastructure/src/main/java/life/qbic/identity/infrastructure/UserJpaRepository.java

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import life.qbic.identity.domain.model.UserId;
88
import life.qbic.identity.domain.repository.UserDataStorage;
99
import org.springframework.beans.factory.annotation.Autowired;
10+
import org.springframework.data.domain.Pageable;
1011
import org.springframework.stereotype.Component;
1112

1213

@@ -57,4 +58,10 @@ public List<User> findAllActiveUsers() {
5758
public Optional<User> findUserByUserName(String userName) {
5859
return Optional.ofNullable(userRepo.findUserByUserName(userName));
5960
}
61+
62+
@Override
63+
public List<User> findByUserNameContainingIgnoreCaseAndActiveTrue(String userName,
64+
Pageable pageable) {
65+
return userRepo.findAllByUserNameContainingIgnoreCaseAndActiveTrue(userName, pageable);
66+
}
6067
}

identity/src/main/java/life/qbic/identity/application/service/BasicUserInformationService.java

+25
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22

33
import static life.qbic.logging.service.LoggerFactory.logger;
44

5+
import java.util.List;
56
import java.util.Objects;
67
import java.util.Optional;
8+
import life.qbic.application.commons.OffsetBasedRequest;
9+
import life.qbic.application.commons.SortOrder;
710
import life.qbic.identity.api.UserInfo;
811
import life.qbic.identity.api.UserInformationService;
912
import life.qbic.identity.domain.model.EmailAddress;
@@ -12,6 +15,8 @@
1215
import life.qbic.identity.domain.model.UserId;
1316
import life.qbic.identity.domain.repository.UserRepository;
1417
import life.qbic.logging.api.Logger;
18+
import org.springframework.data.domain.Sort;
19+
import org.springframework.data.domain.Sort.Order;
1520

1621
/**
1722
* <b>Basic user information service</b>
@@ -58,6 +63,26 @@ public boolean userNameAvailable(String userName) {
5863
return userRepository.findByUserName(userName).isEmpty();
5964
}
6065

66+
@Override
67+
public List<UserInfo> findAllActive(String filter, int offset, int limit,
68+
List<SortOrder> sortOrders) {
69+
List<Order> orders = sortOrders.stream().map(it -> {
70+
Order order;
71+
if (it.isDescending()) {
72+
order = Order.desc(it.propertyName());
73+
} else {
74+
order = Order.asc(it.propertyName());
75+
}
76+
return order;
77+
}).toList();
78+
return userRepository.findByUserNameContainingIgnoreCaseAndActiveTrue(
79+
filter, new OffsetBasedRequest(offset, limit, Sort.by(orders)))
80+
.stream()
81+
.map(user -> new UserInfo(user.id().get(), user.fullName().get(), user.emailAddress().get(),
82+
user.userName(), user.getEncryptedPassword().get(), user.isActive()))
83+
.toList();
84+
}
85+
6186
private UserInfo convert(User user) {
6287
return new UserInfo(user.id().get(), user.fullName().get(), user.emailAddress().get(),
6388
user.userName(),

identity/src/main/java/life/qbic/identity/application/token/PersonalAccessTokenServiceImpl.java

+15-9
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package life.qbic.identity.application.token;
22

3+
import static java.util.Objects.requireNonNull;
4+
35
import java.time.Duration;
46
import java.util.Collection;
57
import life.qbic.identity.api.PersonalAccessToken;
68
import life.qbic.identity.api.PersonalAccessTokenService;
79
import life.qbic.identity.api.RawToken;
810
import life.qbic.identity.api.UnknownUserIdException;
911
import life.qbic.identity.api.UserInformationService;
12+
import life.qbic.identity.domain.model.token.TokenEncoder;
1013
import life.qbic.identity.domain.model.token.TokenGenerator;
1114
import life.qbic.identity.domain.model.token.TokenRepository;
1215
import org.springframework.stereotype.Service;
@@ -22,13 +25,16 @@
2225
public class PersonalAccessTokenServiceImpl implements PersonalAccessTokenService {
2326

2427
private final UserInformationService userInformationService;
25-
2628
private final TokenRepository tokenRepository;
29+
private final TokenEncoder tokenEncoder;
2730

2831
public PersonalAccessTokenServiceImpl(UserInformationService basicUserInformationService,
29-
TokenRepository tokenRepository) {
30-
this.userInformationService = basicUserInformationService;
31-
this.tokenRepository = tokenRepository;
32+
TokenRepository tokenRepository,
33+
TokenEncoder tokenEncoder) {
34+
this.userInformationService = requireNonNull(basicUserInformationService,
35+
"basicUserInformationService must not be null");
36+
this.tokenRepository = requireNonNull(tokenRepository, "tokenRepository must not be null");
37+
this.tokenEncoder = requireNonNull(tokenEncoder, "tokenEncoder must not be null");
3238
}
3339

3440
private static PersonalAccessToken convert(
@@ -49,16 +55,16 @@ public RawToken create(String userId, String description, Duration duration)
4955
}
5056

5157
private RawToken processTokenRequest(String userId, String description, Duration duration) {
52-
TokenGenerator tokenGenerator = new TokenGenerator();
53-
String rawToken = tokenGenerator.token();
54-
var token = life.qbic.identity.domain.model.token.PersonalAccessToken.create(userId,
55-
description, duration, rawToken);
58+
String rawToken = TokenGenerator.token();
59+
String encodedToken = tokenEncoder.encode(rawToken.toCharArray());
60+
var token = new life.qbic.identity.domain.model.token.PersonalAccessToken(userId, description,
61+
duration, encodedToken);
5662
tokenRepository.save(token);
5763
return new RawToken(rawToken);
5864
}
5965

6066
@Override
61-
public Collection<PersonalAccessToken> find(String userId) {
67+
public Collection<PersonalAccessToken> findAll(String userId) {
6268
return tokenRepository.findAllByUserId(userId).stream()
6369
.map(PersonalAccessTokenServiceImpl::convert).toList();
6470
}

identity/src/main/java/life/qbic/identity/application/user/IdentityService.java

+18-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package life.qbic.identity.application.user;
22

3+
import static java.util.Objects.isNull;
4+
35
import java.io.Serial;
46
import java.util.ArrayList;
57
import java.util.Arrays;
@@ -55,7 +57,7 @@ public IdentityService(UserRepository userRepository) {
5557
public ApplicationResponse registerUser(final String fullName, String userName, final String email,
5658
final char[] rawPassword) {
5759

58-
var registrationResponse = validateInput(fullName, email, rawPassword);
60+
var registrationResponse = validateInput(fullName, userName, email, rawPassword);
5961
if (registrationResponse.hasFailures()) {
6062
return registrationResponse;
6163
}
@@ -86,7 +88,8 @@ public ApplicationResponse registerUser(final String fullName, String userName,
8688
return ApplicationResponse.successResponse();
8789
}
8890

89-
private ApplicationResponse validateInput(String fullName, String email, char[] rawPassword) {
91+
private ApplicationResponse validateInput(String fullName, String userName, String email,
92+
char[] rawPassword) {
9093
List<RuntimeException> failures = new ArrayList<>();
9194

9295
try {
@@ -99,6 +102,9 @@ private ApplicationResponse validateInput(String fullName, String email, char[]
99102
} catch (FullNameValidationException e) {
100103
failures.add(e);
101104
}
105+
if (isNull(userName) || userName.isBlank()) {
106+
failures.add(new EmptyUserNameException());
107+
}
102108
try {
103109
EncryptedPassword.from(rawPassword);
104110
} catch (PasswordValidationException e) {
@@ -185,6 +191,16 @@ private Result<EncryptedPassword, RuntimeException> attemptPasswordEncryption(
185191
}
186192
}
187193

194+
public static class EmptyUserNameException extends ApplicationException {
195+
196+
@Serial
197+
private static final long serialVersionUID = -150902871229730428L;
198+
199+
public EmptyUserNameException() {
200+
super();
201+
}
202+
}
203+
188204
public static class UserExistsException extends ApplicationException {
189205

190206
@Serial

identity/src/main/java/life/qbic/identity/application/user/registration/Registration.java

+14-10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import life.qbic.application.commons.ApplicationResponse;
44
import life.qbic.identity.application.user.IdentityService;
5+
import life.qbic.identity.application.user.IdentityService.EmptyUserNameException;
56
import life.qbic.identity.application.user.IdentityService.UserExistsException;
67
import life.qbic.identity.application.user.IdentityService.UserNameNotAvailableException;
78
import life.qbic.identity.domain.model.EmailAddress.EmailValidationException;
@@ -83,16 +84,19 @@ private UserRegistrationException build(ApplicationResponse applicationResponse)
8384
var builder = UserRegistrationException.builder();
8485

8586
for (RuntimeException e : applicationResponse.failures()) {
86-
if (e instanceof EmailValidationException) {
87-
builder.withEmailFormatException((EmailValidationException) e);
88-
} else if (e instanceof PasswordValidationException) {
89-
builder.withInvalidPasswordException((PasswordValidationException) e);
90-
} else if (e instanceof FullNameValidationException) {
91-
builder.withFullNameException((FullNameValidationException) e);
92-
} else if (e instanceof UserExistsException) {
93-
builder.withUserExistsException((UserExistsException) e);
94-
} else if (e instanceof UserNameNotAvailableException) {
95-
builder.withUserNameNotAvailableException((UserNameNotAvailableException) e);
87+
88+
if (e instanceof EmailValidationException emailValidationException) {
89+
builder.withEmailFormatException(emailValidationException);
90+
} else if (e instanceof PasswordValidationException passwordValidationException) {
91+
builder.withInvalidPasswordException(passwordValidationException);
92+
} else if (e instanceof FullNameValidationException fullNameValidationException) {
93+
builder.withFullNameException(fullNameValidationException);
94+
} else if (e instanceof UserExistsException userExistsException) {
95+
builder.withUserExistsException(userExistsException);
96+
} else if (e instanceof UserNameNotAvailableException userNameNotAvailableException) {
97+
builder.withUserNameNotAvailableException(userNameNotAvailableException);
98+
} else if (e instanceof EmptyUserNameException emptyUserNameException) {
99+
builder.withEmptyUserNameException(emptyUserNameException);
96100
} else {
97101
builder.withUnexpectedException(e);
98102
}

identity/src/main/java/life/qbic/identity/application/user/registration/UserRegistrationException.java

+13
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.Serial;
44
import java.util.Optional;
55
import life.qbic.application.commons.ApplicationException;
6+
import life.qbic.identity.application.user.IdentityService.EmptyUserNameException;
67
import life.qbic.identity.application.user.IdentityService.UserExistsException;
78
import life.qbic.identity.application.user.IdentityService.UserNameNotAvailableException;
89
import life.qbic.identity.domain.model.EmailAddress.EmailValidationException;
@@ -32,6 +33,7 @@ public class UserRegistrationException extends ApplicationException {
3233
private final transient FullNameValidationException fullNameException;
3334

3435
private final transient UserNameNotAvailableException userNameNotAvailableException;
36+
private final transient EmptyUserNameException emptyUserNameException;
3537

3638
private final transient UserExistsException userExistsException;
3739
private final transient RuntimeException unexpectedException;
@@ -51,6 +53,7 @@ public static class Builder {
5153
private UserExistsException userExistsException;
5254
private RuntimeException unexpectedException;
5355
private UserNameNotAvailableException userNameNotAvailableException;
56+
private EmptyUserNameException emptyUserNameException;
5457

5558
protected Builder() {
5659

@@ -89,6 +92,11 @@ public Builder withUserNameNotAvailableException(UserNameNotAvailableException e
8992
this.userNameNotAvailableException = e;
9093
return this;
9194
}
95+
96+
public Builder withEmptyUserNameException(EmptyUserNameException emptyUserNameException) {
97+
this.emptyUserNameException = emptyUserNameException;
98+
return this;
99+
}
92100
}
93101

94102
private UserRegistrationException(Builder builder) {
@@ -98,6 +106,7 @@ private UserRegistrationException(Builder builder) {
98106
userExistsException = builder.userExistsException;
99107
unexpectedException = builder.unexpectedException;
100108
userNameNotAvailableException = builder.userNameNotAvailableException;
109+
emptyUserNameException = builder.emptyUserNameException;
101110
}
102111

103112
public Optional<EmailValidationException> emailFormatException() {
@@ -120,6 +129,10 @@ public Optional<UserNameNotAvailableException> userNameNotAvailableException() {
120129
return Optional.ofNullable(userNameNotAvailableException);
121130
}
122131

132+
public Optional<EmptyUserNameException> emptyUserNameException() {
133+
return Optional.ofNullable(emptyUserNameException);
134+
}
135+
123136
public Optional<RuntimeException> unexpectedException() {
124137
return Optional.ofNullable(unexpectedException);
125138
}

0 commit comments

Comments
 (0)