Skip to content

Commit d8c0328

Browse files
Merge pull request #600 from qbicsoftware/development
Release PR
2 parents bb996a0 + 5ad1d94 commit d8c0328

File tree

244 files changed

+8681
-3059
lines changed

Some content is hidden

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

244 files changed

+8681
-3059
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@
55
Data Manager - A web-based multi-omics data management platform for the biomedical life sciences
66
that enables FAIR-compliant data access.
77

8-
**Disclaimer**: _this project is still under heavy development and not yet officially released._
9-
108
[![Build Maven Package](https://github.com/qbicsoftware/data-manager-app/actions/workflows/build_package.yml/badge.svg)](https://github.com/qbicsoftware/data-manager-app/actions/workflows/build_package.yml)
119
[![Run Maven Tests](https://github.com/qbicsoftware/data-manager-app/actions/workflows/run_tests.yml/badge.svg)](https://github.com/qbicsoftware/data-manager-app/actions/workflows/run_tests.yml)
1210
[![CodeQL](https://github.com/qbicsoftware/data-manager-app/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/qbicsoftware/data-manager-app/actions/workflows/codeql-analysis.yml)
@@ -334,3 +332,5 @@ This work is licensed under the [MIT license](https://mit-license.org/).
334332

335333
This work uses the [Vaadin Framework](https://github.com/vaadin), which is licensed
336334
under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0).
335+
336+
The University of Tübingen logo is a registered trademark and the copyright is owned by the [University of Tübingen](https://uni-tuebingen.de/).

application-commons/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,10 @@
1919
<groupId>org.springframework.data</groupId>
2020
<artifactId>spring-data-commons</artifactId>
2121
</dependency>
22+
<!-- https://mvnrepository.com/artifact/org.springframework.security/spring-security-core -->
23+
<dependency>
24+
<groupId>org.springframework.security</groupId>
25+
<artifactId>spring-security-core</artifactId>
26+
</dependency>
2227
</dependencies>
2328
</project>

application-commons/src/main/java/life/qbic/application/commons/ApplicationException.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ public static ApplicationException wrapping(Throwable e) {
104104
if (e instanceof ApplicationException applicationException) {
105105
return new ApplicationException(e, applicationException.errorCode(),
106106
applicationException.errorParameters());
107+
}
108+
if (e instanceof org.springframework.security.access.AccessDeniedException) {
109+
return new ApplicationException(e, ErrorCode.ACCESS_DENIED, ErrorParameters.empty());
107110
} else {
108111
return new ApplicationException(e.getMessage(), e);
109112
}
@@ -133,6 +136,7 @@ public String toString() {
133136
*/
134137
public enum ErrorCode {
135138
GENERAL,
139+
ACCESS_DENIED,
136140
INVALID_EXPERIMENTAL_DESIGN,
137141
INVALID_PROJECT_OBJECTIVE,
138142
INVALID_PROJECT_TITLE,

domain-concept/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
<artifactId>spock-core</artifactId>
2424
<scope>test</scope>
2525
</dependency>
26+
27+
<dependency>
28+
<groupId>com.fasterxml.jackson.core</groupId>
29+
<artifactId>jackson-annotations</artifactId>
30+
<version>2.17.1</version>
31+
</dependency>
2632
</dependencies>
2733

2834
</project>

domain-concept/src/main/java/life/qbic/domain/concepts/DomainEvent.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package life.qbic.domain.concepts;
22

3+
import com.fasterxml.jackson.annotation.JsonGetter;
34
import java.io.Serializable;
45
import java.time.Instant;
56

@@ -13,10 +14,21 @@
1314
*/
1415
public abstract class DomainEvent implements Serializable {
1516

17+
protected final Instant occurredOn;
18+
19+
protected DomainEvent() {
20+
this.occurredOn = Instant.now();
21+
}
22+
1623
/**
1724
* The instant of event creation.
1825
*
1926
* @return the instant the of event creation.
2027
*/
21-
public abstract Instant occurredOn();
28+
29+
@JsonGetter("occurredOn")
30+
public Instant occurredOn() {
31+
return occurredOn;
32+
}
33+
2234
}

domain-concept/src/main/java/life/qbic/domain/concepts/DomainEventSubscriber.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/**
44
* <b>Domain Event Subscriber</b>
55
*
6-
* <p>Clients can implement this interface to subscribe to {@link DomainEventPublisher} and get
6+
* <p>Clients can implement this interface to subscribe to {@link DomainEventDispatcher} and get
77
* informed whenever a {@link DomainEvent} of the specified type <code>T</code> happens.
88
*
99
* @since 1.0.0
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package life.qbic.domain.concepts;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
/**
7+
* <b>Local Domain Event Dispatcher</b>
8+
* <p>
9+
* Dispatches domain events to registered {@link DomainEventSubscriber}.
10+
* <p>
11+
* In contrast to the {@link DomainEventDispatcher} class, this class offers a
12+
* {@link LocalDomainEventDispatcher#reset()} method to clear all potentially existing subscribes.
13+
* This enables the domain event dispatcher to be used in an isolated local domain interaction
14+
* scope, e.g. from within an application service, when you want to ensure a successful committed
15+
* transaction first but still want to make use of broadcasting domain events within your domain.
16+
* <p>
17+
* <strong>Disclaimer</strong>
18+
* <p>The implementation runs in the main application thread and is blocking. Depending on the
19+
* number of registered subscriber and their implementation, expect the dispatching of events to
20+
* block your main app.</p>
21+
*
22+
* @since 1.0.0
23+
*/
24+
public class LocalDomainEventDispatcher {
25+
26+
private static final ThreadLocal<List<DomainEventSubscriber<?>>> subscribers = ThreadLocal.withInitial(
27+
ArrayList::new);
28+
private static LocalDomainEventDispatcher INSTANCE;
29+
30+
private LocalDomainEventDispatcher() {
31+
subscribers.set(new ArrayList<>());
32+
}
33+
34+
public static LocalDomainEventDispatcher instance() {
35+
if (INSTANCE == null) {
36+
INSTANCE = new LocalDomainEventDispatcher();
37+
}
38+
return INSTANCE;
39+
}
40+
41+
public <T extends DomainEvent> void subscribe(DomainEventSubscriber<T> subscriber) {
42+
var currentSubscribers = subscribers.get();
43+
currentSubscribers.add(subscriber);
44+
subscribers.set(currentSubscribers);
45+
}
46+
47+
public <T extends DomainEvent> void dispatch(T domainEvent) {
48+
subscribers.get().stream()
49+
.filter(subscriber -> subscriber.subscribedToEventType() == domainEvent.getClass())
50+
.map(subscriber -> (DomainEventSubscriber<T>) subscriber)
51+
.forEach(subscriber -> subscriber.handleEvent(domainEvent));
52+
}
53+
54+
/**
55+
* Removes all existing {@link DomainEventSubscriber}s of the dispatcher instance.
56+
*
57+
* @since 1.0.0
58+
*/
59+
public void reset() {
60+
subscribers.remove();
61+
}
62+
63+
}

domain-concept/src/test/groovy/life/qbic/domain/concepts/TestEvent.groovy

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@ class TestEvent extends DomainEvent {
1616

1717
private String test = "TEST"
1818

19-
@Override
20-
Instant occurredOn() {
21-
return Instant.now()
22-
}
23-
2419
boolean equals(o) {
2520
if (this.is(o)) return true
2621
if (o == null || getClass() != o.class) return false

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
*
88
* @since 1.0.0
99
*/
10-
public record UserInfo(String id, String fullName, String emailAddress, String userName, String encryptedPassword,
10+
public record UserInfo(String id, String fullName, String emailAddress, String platformUserName,
11+
String encryptedPassword,
1112
boolean isActive) {
1213

1314
}

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,28 @@ public ApplicationResponse requestPasswordReset(String userEmailAddress) {
150150
return ApplicationResponse.successResponse();
151151
}
152152

153+
public ApplicationResponse requestUserNameChange(String userId, String userName) {
154+
if (isNull(userName) || userName.isBlank()) {
155+
return ApplicationResponse.failureResponse(new EmptyUserNameException());
156+
}
157+
UserId id = UserId.from(userId);
158+
var optionalUser = userRepository.findById(id);
159+
if (optionalUser.isEmpty()) {
160+
return ApplicationResponse.failureResponse(new UserNotFoundException("User not found"));
161+
}
162+
// get user
163+
var user = optionalUser.get();
164+
if (user.userName().equals(userName)) {
165+
return ApplicationResponse.successResponse();
166+
}
167+
if (userRepository.findByUserName(userName).isPresent()) {
168+
return ApplicationResponse.failureResponse(new UserNameNotAvailableException());
169+
}
170+
user.setNewUserName(userName);
171+
userRepository.updateUser(user);
172+
return ApplicationResponse.successResponse();
173+
}
174+
153175
/**
154176
* Sets a new password for a given user.
155177
* <p>

0 commit comments

Comments
 (0)