ialbert 2022-09-16 19:11:07 +03:00
parent d124da97b8
commit cefcd14fda
20 changed files with 663 additions and 11 deletions

View file

@ -10,6 +10,7 @@ import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.servlet.config.annotation.*; import org.springframework.web.servlet.config.annotation.*;
import java.util.List; import java.util.List;
@ -69,4 +70,9 @@ public class WebConfig implements WebMvcConfigurer {
public void addCorsMappings(CorsRegistry registry) { public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedMethods("*"); registry.addMapping("/**").allowedMethods("*");
} }
@Bean
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
} }

View file

@ -0,0 +1,43 @@
package ru.spcex.clearing.backendapi.controller.request.cud.utilities;
import ru.spcex.clearing.backendapi.domain.actions.IAction;
import ru.spcex.clearing.backendapi.errors.BackEndError;
import ru.spcex.clearing.platform.messaging.domain.ActionType;
import ru.spcex.clearing.platform.messaging.domain.cud.utilities.UserAuthRequest;
import ru.spcex.platform.utils.enumeration.EnumMessage;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class UserAuthAction implements IAction<UserAuthRequest> {
private final UserAuthRequest authRequest;
public UserAuthAction() {
this.authRequest = new UserAuthRequest();
}
public UserAuthRequest getAuthRequest() {
return authRequest;
}
@Override
public Collection<EnumMessage> validate() {
long count = authRequest.getRoles().stream().distinct().count();
if (count != authRequest.getRoles().size()) {
return List.of(new EnumMessage(BackEndError.KeycloakRepeatedRoles));
}
return Collections.emptyList();
}
@Override
public UserAuthRequest toRequest() {
return authRequest;
}
@Override
public ActionType getActionType() {
return ActionType.SYSTEM;
}
}

View file

@ -5,7 +5,8 @@ import ru.spcex.platform.utils.enumeration.IEnumId;
public enum BackEndError implements IEnumId { public enum BackEndError implements IEnumId {
ValidationError(3000L), ValidationError(3000L),
UnknownJsonProperty(3001L), UnknownJsonProperty(3001L),
FailedToReadHttpMessage(3002L); FailedToReadHttpMessage(3002L),
KeycloakRepeatedRoles(3003L);
private final Long id; private final Long id;
BackEndError(Long id) { BackEndError(Long id) {

View file

@ -11,6 +11,8 @@ import org.keycloak.adapters.springsecurity.account.SimpleKeycloakAccount;
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
import org.keycloak.common.VerificationException; import org.keycloak.common.VerificationException;
import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessToken;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.*; import org.springframework.http.*;
import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.AuthenticationProvider;
@ -24,7 +26,7 @@ import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap; import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import ru.spcex.clearing.backendapi.service.UserAutoCreateService; import ru.spcex.clearing.backendapi.service.UserAuthProcessor;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -36,14 +38,15 @@ import java.util.stream.Collectors;
@Component("keycloakRestAuthenticationProvider") @Component("keycloakRestAuthenticationProvider")
public class KeycloakRestTemplateAuthenticationProvider implements AuthenticationProvider { public class KeycloakRestTemplateAuthenticationProvider implements AuthenticationProvider {
private final Logger log = LoggerFactory.getLogger(getClass());
private final KeycloakConfigResolver resolver; private final KeycloakConfigResolver resolver;
private final HttpServletRequest currentHttpRequest; private final HttpServletRequest currentHttpRequest;
private final HttpServletResponse currentHttpResponse; private final HttpServletResponse currentHttpResponse;
private final RestTemplate restTemplate; private final RestTemplate restTemplate;
private final UserAutoCreateService userAutoCreation; private final UserAuthProcessor userAutoCreation;
public KeycloakRestTemplateAuthenticationProvider(KeycloakConfigResolver resolver, HttpServletRequest currentHttpRequest, HttpServletResponse currentHttpResponse, public KeycloakRestTemplateAuthenticationProvider(KeycloakConfigResolver resolver, HttpServletRequest currentHttpRequest, HttpServletResponse currentHttpResponse,
@Qualifier("clearing-rest") RestTemplate restTemplate, UserAutoCreateService userAutoCreation) { @Qualifier("clearing-rest") RestTemplate restTemplate, UserAuthProcessor userAutoCreation) {
this.resolver = resolver; this.resolver = resolver;
this.currentHttpRequest = currentHttpRequest; this.currentHttpRequest = currentHttpRequest;
this.currentHttpResponse = currentHttpResponse; this.currentHttpResponse = currentHttpResponse;
@ -79,8 +82,6 @@ public class KeycloakRestTemplateAuthenticationProvider implements Authenticatio
AccessToken accessToken = AdapterTokenVerifier.verifyToken(accessTokenString, deployment); AccessToken accessToken = AdapterTokenVerifier.verifyToken(accessTokenString, deployment);
//todo cors settings //todo cors settings
accessToken.setAllowedOrigins(Collections.singleton("*")); accessToken.setAllowedOrigins(Collections.singleton("*"));
System.out.println("login successful");
List<SimpleGrantedAuthority> realmRoles = accessToken.getRealmAccess().getRoles().stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()); List<SimpleGrantedAuthority> realmRoles = accessToken.getRealmAccess().getRoles().stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
RefreshableKeycloakSecurityContext skSession = new RefreshableKeycloakSecurityContext(deployment, null, accessTokenString, accessToken, null, null, refreshTokenString); RefreshableKeycloakSecurityContext skSession = new RefreshableKeycloakSecurityContext(deployment, null, accessTokenString, accessToken, null, null, refreshTokenString);
@ -90,7 +91,7 @@ public class KeycloakRestTemplateAuthenticationProvider implements Authenticatio
final KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, skSession); final KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, skSession);
KeycloakAuthenticationToken keycloakAuthenticationToken = new KeycloakAuthenticationToken(account, false, realmRoles); KeycloakAuthenticationToken keycloakAuthenticationToken = new KeycloakAuthenticationToken(account, false, realmRoles);
keycloakAuthenticationToken.setAuthenticated(true); keycloakAuthenticationToken.setAuthenticated(true);
checkRightsAndCreate(principalName, roles); checkRightsAndCreate(principalName, accessToken.getId(), roles);
return keycloakAuthenticationToken; return keycloakAuthenticationToken;
} catch (VerificationException vex) { } catch (VerificationException vex) {
@ -100,10 +101,14 @@ public class KeycloakRestTemplateAuthenticationProvider implements Authenticatio
} }
} }
private void checkRightsAndCreate(String username, Set<String> roles) { private void checkRightsAndCreate(String username, String id, Set<String> roles) {
log.debug("login successful: login {}, roles {}", username, String.join(";", roles));
//todo remove hardcode //todo remove hardcode
if (roles.contains("admin") || roles.contains("default-roles-master")) { if (roles.contains("admin") || roles.contains("default-roles-master")) {
userAutoCreation.createUserIfNeeded(username); String clientIp = currentHttpRequest != null ? currentHttpRequest.getRemoteAddr() : null;
String serverIp = currentHttpRequest != null ? currentHttpRequest.getLocalAddr() : null;
userAutoCreation.sendUserInfo(username, id, roles, clientIp, serverIp);
} }
} }

View file

@ -0,0 +1,75 @@
package ru.spcex.clearing.backendapi.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import ru.spcex.clearing.backendapi.controller.request.cud.utilities.UserAuthAction;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.utilities.UserAuthRequest;
import ru.spcex.platform.utils.log.ExceptionUtils;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
@Service
public class UserAuthProcessor {
private final Logger log = LoggerFactory.getLogger(getClass());
private final IOperator operator;
private String serverAddress;
@Value("${server.port}")
private String serverPort;
@Autowired
public UserAuthProcessor(IOperator operator) {
this.operator = operator;
}
public void sendUserInfo(String username, String identifier, Collection<String> roles, String userIp, String serverIp) {
UserAuthAction authEvent = new UserAuthAction();
UserAuthRequest requestData = authEvent.getAuthRequest();
requestData.setUsername(username);
requestData.setIdentifier(identifier);
requestData.setTime(Instant.now());
requestData.setRoles(new ArrayList<>(roles));
requestData.setServerIp(serverIp + ":" + serverPort); //getServerAddress() + ":" + serverPort
requestData.setClientIp(userIp);
try {
operator.sendRequestToQueue(Consts.USER_AUTH_SUCCESS, authEvent);
} catch (Throwable e) { //ExecutionException | InterruptedException
log.error(ExceptionUtils.getStackTrace(e));
}
}
private String getServerAddress() {
if (serverAddress != null) {
return serverAddress;
}
try {
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = networkInterfaces.nextElement();
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
while(inetAddresses.hasMoreElements()) {
InetAddress inetAddress = inetAddresses.nextElement();
if (inetAddress != null) {
serverAddress = inetAddress.getHostAddress();
return serverAddress;
}
}
}
serverAddress = "unknown";
return serverAddress;
} catch (Throwable e) {
log.error("cannot retrieve server address {}", ExceptionUtils.getStackTrace(e));
serverAddress = "unknown";
return serverAddress;
}
}
}

View file

@ -20,6 +20,10 @@
<groupId>ru.spcex.platform</groupId> <groupId>ru.spcex.platform</groupId>
<artifactId>platform-messaging</artifactId> <artifactId>platform-messaging</artifactId>
</dependency> </dependency>
<dependency>
<groupId>ru.spcex.platform</groupId>
<artifactId>platform-enum</artifactId>
</dependency>
<dependency> <dependency>
<groupId>ru.spcex.platform</groupId> <groupId>ru.spcex.platform</groupId>
<artifactId>platform-imdg-api-hazelcast-impl</artifactId> <artifactId>platform-imdg-api-hazelcast-impl</artifactId>
@ -36,6 +40,28 @@
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
</dependency> </dependency>
<!-- TEST -->
<!-- <dependency>-->
<!-- <groupId>org.springframework</groupId>-->
<!-- <artifactId>spring-test</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.mockito</groupId>-->
<!-- <artifactId>mockito-core</artifactId>-->
<!-- <scope>test</scope>-->
<!-- </dependency>-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View file

@ -2,8 +2,10 @@ package ru.spcex.clearing.utility.config;
import org.apache.kafka.clients.consumer.Consumer; import org.apache.kafka.clients.consumer.Consumer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import ru.spcex.clearing.platform.messaging.config.KafkaConsumerFactory; import ru.spcex.clearing.platform.messaging.config.KafkaConsumerFactory;
import ru.spcex.clearing.utility.config.settings.UtilityServiceSettings; import ru.spcex.clearing.utility.config.settings.UtilityServiceSettings;
@ -11,6 +13,7 @@ import ru.spcex.clearing.utility.config.settings.UtilityServiceSettings;
public class KafkaConfig { public class KafkaConfig {
@Autowired @Autowired
@Bean @Bean
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public Consumer<String, Object> createProducer(UtilityServiceSettings settings) { public Consumer<String, Object> createProducer(UtilityServiceSettings settings) {
return KafkaConsumerFactory.consumer(settings.getKafka()); return KafkaConsumerFactory.consumer(settings.getKafka());
} }

View file

@ -0,0 +1,176 @@
package ru.spcex.clearing.utility.service;
import org.apache.kafka.clients.consumer.Consumer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.user.User;
import ru.clearing.classes.statics.data.user.UserConnect;
import ru.clearing.classes.statics.data.user.UserRoleSession;
import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
import ru.spcex.clearing.platform.messaging.domain.Consts;
import ru.spcex.clearing.platform.messaging.domain.cud.utilities.UserAuthRequest;
import ru.spcex.clearing.platform.messaging.service.QueueConsumer;
import ru.spcex.platform.enumeration.ConnectionState;
import ru.spcex.platform.enumeration.Status;
import ru.spcex.platform.imdg.api.Imdg;
import ru.spcex.platform.imdg.api.ImdgProvider;
import ru.spcex.platform.utils.time.TimeUtil;
import java.time.Instant;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Stream;
@Service
public class UserService extends QueueConsumer implements InitializingBean {
private final Logger log = LoggerFactory.getLogger(getClass());
private final Imdg<User> userMap;
private final Imdg<UserRoleSession> userRoleSessionImdg;
private final Imdg<UserConnect> userConnectImdg;
@Autowired
public UserService(Consumer<String, Object> kafkaQueue, ImdgProvider imdgProvider) {
super(kafkaQueue);
this.userMap = imdgProvider.getImdg(IMDGDistributedNames.Map_User, User.class);
this.userRoleSessionImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_UserRoleSession, UserRoleSession.class);
this.userConnectImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_UserConnect, UserConnect.class);
}
@Override
public void afterPropertiesSet() {
callback(UserAuthRequest.class)
.setConsumer(this::userAuthSuccess)
.forDestination(Consts.USER_AUTH_SUCCESS, callbacks::put);
init();
}
private void userAuthSuccess(BaseRequest<UserAuthRequest> authEvent) {
UserAuthRequest authInfo = authEvent.getRequestPayload();
log.debug("user id={} authenticated", authInfo.getUsername());
UserInfo userInfo = createUserIfNeeded(authInfo.getUsername());
changeRoles(userInfo.userId, userInfo.isNew, authInfo.getRoles());
connected(userInfo.userId, authInfo.getTime(), authInfo.getClientIp(), authInfo.getServerIp());
}
private UserInfo createUserIfNeeded(String username) {
User user = userMap.getSingleObjectByFieldValues(Map.of("identifier", username));
if (user == null) {
user = new User();
user.setCreated(Instant.now());
user.setIdentifier(username);
userMap.insert(user);
return new UserInfo(true, user.getId());
} else {
return new UserInfo(false, user.getId());
}
}
private void changeRoles(Long userId, boolean isNew, Collection<String> authRoles) {
Collection<UserRoleSession> presentRoles;
if (isNew) {
presentRoles = Collections.emptyList();
} else {
presentRoles = userRoleSessionImdg.getCollectionObjectsByFieldValues(Map.of("userId", userId));
}
Collection<RoleAction> roleActions = defineAllRoleChanges(presentRoles, authRoles);
if (roleActions.size() > 0) {
for (RoleAction roleAction : roleActions) {
UserRoleSession role;
if (roleAction.create()) {
role = new UserRoleSession();
role.setUserRole(roleAction.roleName);
role.setUserId(userId);
role.setStatus(Status.Active.getKey());
userRoleSessionImdg.insert(role);
} else {
role = roleAction.roleToChange;
role.setStatus(roleAction.newStatus.getKey());
userRoleSessionImdg.update(role);
}
}
}
}
private void connected(Long userId, Instant time, String clientIp, String serverIp) {
UserConnect userConnect = userConnectImdg.getSingleObjectByFieldValues(Map.of("userId", userId));
boolean isNew = false;
if (userConnect == null) {
userConnect = new UserConnect();
userConnect.setUserId(userId);
isNew = true;
}
userConnect.setConnectionTime(time);
userConnect.setServerIP(serverIp);
userConnect.setClientIP(clientIp);
userConnect.setConnectionState(ConnectionState.Connected.getKey());
userConnect.setClearingDate(TimeUtil.today());
if (isNew) {
userConnectImdg.insert(userConnect);
} else {
userConnectImdg.update(userConnect);
}
}
static Collection<RoleAction> defineAllRoleChanges(Collection<UserRoleSession> presentRoles, Collection<String> authRoles) {
return Stream.concat(
presentRoles
.stream()
.filter(presentRole -> !(Status.Active.equalsByKey(presentRole.getStatus()) && contain(presentRole, authRoles)))
.filter(presentRole -> !(Status.Blocked.equalsByKey(presentRole.getStatus()) && !contain(presentRole, authRoles)))
.map(role -> {
RoleAction roleAction = new RoleAction();
roleAction.roleToChange = role;
if (Status.Active.equalsByKey(role.getStatus())) {
roleAction.newStatus = Status.Blocked;
} else {
roleAction.newStatus = Status.Active;
}
return roleAction;
}),
authRoles
.stream()
.filter(authRole -> !contain(authRole, presentRoles))
.map(authRole -> {
RoleAction action = new RoleAction();
action.newStatus = Status.Active;
action.roleName = authRole;
return action;
})
).toList();
}
private static boolean contain(UserRoleSession role, Collection<String> authRoles) {
return authRoles.stream().anyMatch(authRole -> authRole.equalsIgnoreCase(role.getUserRole()));
}
private static boolean contain(String authRole, Collection<UserRoleSession> presentRoles) {
return presentRoles.stream().anyMatch(role -> role.getUserRole().equalsIgnoreCase(authRole));
}
public static class RoleAction {
String roleName;
//------поля при обновления-----
Status newStatus;
UserRoleSession roleToChange;
boolean create() {
return roleToChange == null;
}
}
private static class UserInfo {
boolean isNew;
Long userId;
public UserInfo(boolean isNew, Long userId) {
this.isNew = isNew;
this.userId = userId;
}
}
}

View file

@ -5,7 +5,7 @@ utility-service.hazelcast.login=dev
utility-service.hazelcast.password=dev-pass utility-service.hazelcast.password=dev-pass
utility-service.kafka.bootstrap-servers=localhost:9092 utility-service.kafka.bootstrap-servers=localhost:9092
utility-service.kafka.group-id=dev-group utility-service.kafka.group-id=dev-group-utility-service
utility-service.kafka.enable-auto-commit=false utility-service.kafka.enable-auto-commit=false
utility-service.kafka.session-timeout-ms=30000 utility-service.kafka.session-timeout-ms=30000
utility-service.kafka.auto-offset-reset=latest utility-service.kafka.auto-offset-reset=latest

View file

@ -0,0 +1,94 @@
package ru.spcex.clearing.utility.service;
import org.junit.jupiter.api.Test;
import ru.clearing.classes.statics.data.user.UserRoleSession;
import ru.spcex.platform.enumeration.Status;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
class UserServiceChangeRolesTest {
private static final AtomicLong idGenerator = new AtomicLong();
@Test
public void testTwoNewRoles() {
Collection<UserRoleSession> userRoles = new ArrayList<>();
userRoles.add(generate("admin", Status.Active));
userRoles.add(generate("broker", Status.Active));
userRoles.add(generate("manager", Status.Blocked));
Collection<String> methodsFromAuth = List.of("admin", "broker", "makler", "user");
Collection<UserService.RoleAction> roleActions = UserService.defineAllRoleChanges(userRoles, methodsFromAuth);
assertEquals(2, roleActions.size());
assertTrue(roleActions.stream().anyMatch(roleAction -> roleAction.create()
&& "makler".equals(roleAction.roleName)));
assertTrue(roleActions.stream().anyMatch(roleAction -> roleAction.create()
&& "user".equals(roleAction.roleName)));
}
@Test
public void testOneMissingTwoNew() {
Collection<UserRoleSession> userRoles = new ArrayList<>();
userRoles.add(generate("admin", Status.Active));
userRoles.add(generate("broker", Status.Active));
userRoles.add(generate("manager", Status.Active));
Collection<String> methodsFromAuth = List.of("admin", "broker", "makler", "user");
Collection<UserService.RoleAction> roleActions = UserService.defineAllRoleChanges(userRoles, methodsFromAuth);
assertEquals(3, roleActions.size());
assertTrue(roleActions.stream().anyMatch(roleAction -> !roleAction.create()
&& roleAction.roleToChange.getUserRole().equals("manager")
&& roleAction.newStatus.equals(Status.Blocked)));
assertTrue(roleActions.stream().anyMatch(roleAction -> roleAction.create()
&& "makler".equals(roleAction.roleName)));
assertTrue(roleActions.stream().anyMatch(roleAction -> roleAction.create()
&& "user".equals(roleAction.roleName)));
}
@Test
public void testAllNew() {
Collection<UserRoleSession> userRoles = new ArrayList<>();
Collection<String> methodsFromAuth = List.of("admin", "broker", "makler", "user");
Collection<UserService.RoleAction> roleActions = UserService.defineAllRoleChanges(userRoles, methodsFromAuth);
assertEquals(4, roleActions.size());
assertTrue(roleActions.stream().anyMatch(roleAction -> roleAction.create()
&& "admin".equals(roleAction.roleName)));
assertTrue(roleActions.stream().anyMatch(roleAction -> roleAction.create()
&& "broker".equals(roleAction.roleName)));
assertTrue(roleActions.stream().anyMatch(roleAction -> roleAction.create()
&& "makler".equals(roleAction.roleName)));
assertTrue(roleActions.stream().anyMatch(roleAction -> roleAction.create()
&& "user".equals(roleAction.roleName)));
}
@Test
public void testTwoNewRolesDifferentCase() {
Collection<UserRoleSession> userRoles = new ArrayList<>();
userRoles.add(generate("AdMin", Status.Active));
userRoles.add(generate("broKer", Status.Active));
userRoles.add(generate("MANAGER", Status.Blocked));
Collection<String> methodsFromAuth = List.of("admin", "broker", "makler", "user");
Collection<UserService.RoleAction> roleActions = UserService.defineAllRoleChanges(userRoles, methodsFromAuth);
assertEquals(2, roleActions.size());
assertTrue(roleActions.stream().anyMatch(roleAction -> roleAction.create()
&& "makler".equalsIgnoreCase(roleAction.roleName)));
assertTrue(roleActions.stream().anyMatch(roleAction -> roleAction.create()
&& "user".equalsIgnoreCase(roleAction.roleName)));
}
private static UserRoleSession generate(String roleName, Status roleStatus) {
UserRoleSession userRoleSession = new UserRoleSession();
userRoleSession.setId(idGenerator.incrementAndGet());
userRoleSession.setUserId(1L);
userRoleSession.setUserRole(roleName);
userRoleSession.setStatus(roleStatus.getKey());
return userRoleSession;
}
}

View file

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>platform-enum</artifactId>
<name>Platform enumerations</name>
<packaging>jar</packaging>
<version>1.0.0</version>
<parent>
<artifactId>platform-parent</artifactId>
<groupId>ru.spcex.platform</groupId>
<version>1.0.0</version>
</parent>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>ru.spcex.platform</groupId>
<artifactId>platform-utils</artifactId>
</dependency>
</dependencies>
</project>

View file

@ -0,0 +1,18 @@
package ru.spcex.platform.enumeration;
import ru.spcex.platform.utils.enumeration.IEnumKey;
public enum ConnectionState implements IEnumKey {
Connected("CNCT"), Disconnected("DSBL");
private final String key;
ConnectionState(String key) {
this.key = key;
}
@Override
public String getKey() {
return key;
}
}

View file

@ -0,0 +1,18 @@
package ru.spcex.platform.enumeration;
import ru.spcex.platform.utils.enumeration.IEnumKey;
public enum Status implements IEnumKey {
Active("ACTV"), Blocked("BLKD");
private final String key;
Status(String key) {
this.key = key;
}
@Override
public String getKey() {
return key;
}
}

View file

@ -1,5 +1,6 @@
package ru.spcex.clearing.platform.messaging.domain; package ru.spcex.clearing.platform.messaging.domain;
public enum ActionType { public enum ActionType {
NEW, UPDATE, DELETE; NEW, UPDATE, DELETE,
SYSTEM;
} }

View file

@ -22,4 +22,6 @@ public interface Consts {
String DESTINATION_SDF08_NEW = "s-df-08-new"; String DESTINATION_SDF08_NEW = "s-df-08-new";
String DESTINATION_SDF02_NEW = "s-df-02-new"; String DESTINATION_SDF02_NEW = "s-df-02-new";
String USER_AUTH_SUCCESS = "user-auth-success";
} }

View file

@ -0,0 +1,76 @@
package ru.spcex.clearing.platform.messaging.domain.cud.utilities;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import ru.spcex.clearing.platform.messaging.domain.json.deserialize.InstantDeserializer;
import ru.spcex.clearing.platform.messaging.domain.json.serialize.InstantSerializer;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
public class UserAuthRequest {
@JsonProperty
private String username;
@JsonProperty
private String identifier;
@JsonProperty
private List<String> roles = new ArrayList<>();
@JsonSerialize(using = InstantSerializer.class)
@JsonDeserialize(using = InstantDeserializer.class)
@JsonProperty
private Instant time;
@JsonProperty
private String serverIp;
@JsonProperty
private String clientIp;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public List<String> getRoles() {
return roles;
}
public void setRoles(List<String> roles) {
this.roles = roles;
}
public Instant getTime() {
return time;
}
public void setTime(Instant time) {
this.time = time;
}
public String getServerIp() {
return serverIp;
}
public void setServerIp(String serverIp) {
this.serverIp = serverIp;
}
public String getClientIp() {
return clientIp;
}
public void setClientIp(String clientIp) {
this.clientIp = clientIp;
}
}

View file

@ -0,0 +1,64 @@
package ru.spcex.platform.utils.enumeration;
import java.io.Serializable;
import java.util.Objects;
public interface IEnumKey extends Serializable {
String getKey();
default boolean equalsByKey(String key) {
return key != null && getKey().equalsIgnoreCase(key);
}
/**
* Проверяет что среди данного набора Enum, присутствует элемент с данным id
* id может быть null
*/
static <T extends Enum<T> & IEnumKey> boolean contains(String id, T... enumSet) {
for (T e : enumSet) {
if (Objects.equals(id, e.getKey()))
return true;
}
return false;
}
static <T extends Enum<T> & IEnumKey> boolean contains(T e, T... enumSet) {
for (T enumEl : enumSet) {
if (enumEl.equals(e))
return true;
}
return false;
}
/**
* Проверяет что среди всех Enum данного класса, присутствует элемент с данным id
* id может быть null
*/
static <T extends Enum<T> & IEnumKey> boolean contains(Class<T> enumClass, String key) {
for (T e : enumClass.getEnumConstants()) {
if (Objects.equals(key, e.getKey()))
return true;
}
return false;
}
/**
* Возвращает Enum по id, если в заданном классе такой определен
* id может быть null
*
* @return Enum если нашел, иначе <tt>null</tt>
*/
static <T extends Enum<T> & IEnumKey> T getEnumByKey(Class<T> enumClass, String key) {
for (T e : enumClass.getEnumConstants()) {
if (Objects.equals(key, e.getKey()))
return e;
}
return null;
}
static String getKeyOrNull(IEnumKey enumVal) {
return enumVal == null ? null : enumVal.getKey();
}
String UNDEFINED_VALUE = "_Undefined";
}

View file

@ -19,4 +19,12 @@ public class TimeUtil {
if (date == null) return null; if (date == null) return null;
return formatter.format(date.atZone(zone)); return formatter.format(date.atZone(zone));
} }
public static Instant today() {
return localDateToInstant(LocalDate.now());
}
public static Instant localDateToInstant(LocalDate date) {
return date.atStartOfDay(zone).toInstant();
}
} }

View file

@ -22,6 +22,7 @@
<module>platform-classes-base</module> <module>platform-classes-base</module>
<module>platform-imdg-api-hazelcast-impl</module> <module>platform-imdg-api-hazelcast-impl</module>
<module>platform-utils</module> <module>platform-utils</module>
<module>platform-enum</module>
<module>platform-messaging</module> <module>platform-messaging</module>
</modules> </modules>
</project> </project>

View file

@ -103,6 +103,12 @@
<version>1.0.0</version> <version>1.0.0</version>
</dependency> </dependency>
<dependency>
<groupId>ru.spcex.platform</groupId>
<artifactId>platform-enum</artifactId>
<version>1.0.0</version>
</dependency>
<dependency> <dependency>
<groupId>ru.spcex.platform</groupId> <groupId>ru.spcex.platform</groupId>
<artifactId>platform-imdg-api</artifactId> <artifactId>platform-imdg-api</artifactId>