Skip to content
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,7 @@ build/
.vscode/

.env

application-*.properties
application-*.yml
application-*.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,10 @@ public ResponseEntity<Map<String, String>> handleEntityNotFoundException(EntityN

@ExceptionHandler(AggregateException.class)
public ResponseEntity<Map<String, String>> handleAggregateException(AggregateException exception) {
LOGGER.error(exception.getMessage(), exception);
for (var ex : exception.getExceptions()) {
LOGGER.error(ex.getLocalizedMessage(), ex);
}

Throwable cause = exception.getExceptions().getFirst();
LOGGER.debug("AggregateException contains {} exceptions, handling the first one: {}", exception.getExceptions().size(), cause.getMessage());
return handleGeneralException(cause);
Expand Down
27 changes: 27 additions & 0 deletions framework/src/main/java/io/theurl/framework/core/BeanScope.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.theurl.framework.core;

public class BeanScope {
public final static String APPLICATION = "application";
public final static String PROTOTYPE = "prototype";
public final static String REQUEST = "request";
public final static String SESSION = "session";
public final static String SINGLETON = "singleton";
public final static String WEB_SOCKET = "websocket";
// APPLICATION("application"),
// PROTOTYPE("prototype"),
// REQUEST("request"),
// SESSION("session"),
// SINGLETON("singleton"),
// WEB_SOCKET("websocket");
//
// private final String name;
//
// BeanScope(String name) {
// this.name = name;
// }
//
// @Override
// public String toString() {
// return name;
// }
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,9 @@ public boolean equals(Object obj) {
ObjectId objectId = (ObjectId) obj;
return value.equals(objectId.value);
}

@Override
public String toString() {
return value.toString();
}
}
11 changes: 11 additions & 0 deletions identity/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@
<artifactId>jjwt-api</artifactId>
<version>0.13.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.13.0</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.13.0</version>
<scope>runtime</scope>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-amqp</artifactId>-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import io.theurl.framework.domain.ApplicationEvent;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@EqualsAndHashCode(callSuper = true)
Expand All @@ -14,13 +16,14 @@ public final class UserAuthSuccessEvent extends ApplicationEvent implements Even
private final String grantType;
private final Long userId;


public UserAuthSuccessEvent(String grantType, Long userId) {
this.grantType = grantType;
this.userId = userId;
}

private String username;
private LocalDateTime grantTime;
private Map<String, String> data;

@Getter
private Map<String, String> data = new HashMap<>();
}
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package io.theurl.identity.application.handler;

import com.neroyun.mediator.Handler;
import io.theurl.framework.core.BeanScope;
import io.theurl.identity.application.command.TokenCreateCommand;
import io.theurl.identity.domain.aggregate.Token;
import io.theurl.identity.domain.repository.TokenRepository;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;
import org.springframework.web.context.WebApplicationContext;

import java.util.concurrent.CompletableFuture;

@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
@Scope(BeanScope.PROTOTYPE)
//@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class TokenCreateCommandHandler implements Handler<TokenCreateCommand, Void> {

@Resource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public CompletableFuture<TokenGrantResponseDto> grant(TokenGrantRequestDto reque
throw new CredentialNotFoundException(request.username(), "Invalid username or password.");
}

if (userInfo.getLockedUntil().isAfter(LocalDateTime.now())) {
if (userInfo.getLockedUntil() != null && userInfo.getLockedUntil().isAfter(LocalDateTime.now())) {
throw new AccountLockedException(request.username(), "Account is locked until " + userInfo.getLockedUntil());
}

Expand All @@ -92,13 +92,17 @@ public CompletableFuture<TokenGrantResponseDto> grant(TokenGrantRequestDto reque
}
}

events.add(new UserAuthSuccessEvent(request.grantType(), userInfo.getId()));

var jwtId = ObjectId.guid().toString();
var iat = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
var exp = LocalDateTime.now().plusHours(24).toEpochSecond(ZoneOffset.UTC);
var accessToken = generateToken(jwtId, userInfo, iat, exp);

var event = new UserAuthSuccessEvent(request.grantType(), userInfo.getId());
event.setGrantTime(LocalDateTime.now());
event.getData().put("jti", jwtId);
event.getData().put("jwt", accessToken);
events.add(event);

return new TokenGrantResponseDto(accessToken, jwtId, "Bearer", 3600 * 24, iat, userInfo.getUsername(), userInfo.getId());

} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package io.theurl.identity.application.subscriber;

import com.neroyun.mediator.Mediator;
import io.theurl.framework.core.BeanScope;
import io.theurl.identity.application.command.TokenCreateCommand;
import io.theurl.identity.application.event.UserAuthSuccessEvent;
import org.springframework.context.annotation.Scope;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Component
@Scope(BeanScope.PROTOTYPE)
public class TokenEventSubscriber {
private final Mediator mediator;

Expand All @@ -20,7 +23,7 @@ public TokenEventSubscriber(Mediator mediator) {
public void handleUserAuthSucceedEvent(UserAuthSuccessEvent event) {
var command = new TokenCreateCommand() {{
setJti(event.getData().get("jti"));
setContent(event.getData().get("content"));
setContent(event.getData().get("jwt"));
setSubject(event.getUserId());
}};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

@SuppressWarnings({"LombokGetterMayBeUsed"})
public class Token extends AggregateRoot<Long> {
private String jti;
private String content;
private Long subject;
private final String jti;
private final String content;
private final Long subject;
private LocalDateTime issuedAt;
private LocalDateTime expiresAt;

Expand All @@ -20,6 +20,9 @@ public class Token extends AggregateRoot<Long> {
*/
public Token(Long id, String jti, String content, Long subject) {
super(id);
this.jti = jti;
this.content = content;
this.subject = subject;
}

public LocalDateTime getIssuedAt() {
Expand All @@ -30,15 +33,27 @@ public LocalDateTime getExpiresAt() {
return expiresAt;
}

public String getContent() {
return content;
}

public String getJti() {
return jti;
}

public Long getSubject() {
return subject;
}

public void setIssuedAt(LocalDateTime issuedAt) {
if (issuedAt.isBefore(LocalDateTime.now())) {
if (issuedAt != null && issuedAt.isBefore(LocalDateTime.now())) {
throw new IllegalArgumentException("issuedAt must be in the future");
}
this.issuedAt = issuedAt;
}

public void setExpiresAt(LocalDateTime expiresAt) {
if (expiresAt.isBefore(LocalDateTime.now())) {
if (expiresAt != null && expiresAt.isBefore(LocalDateTime.now())) {
throw new IllegalArgumentException("expiresAt must be in the future");
}
this.expiresAt = expiresAt;
Expand Down
5 changes: 0 additions & 5 deletions identity/src/main/resources/application-dev.yaml

This file was deleted.

5 changes: 0 additions & 5 deletions message/src/main/resources/application-dev.yaml

This file was deleted.

Loading