diff --git a/clearing-parent/backend-api/pom.xml b/clearing-parent/backend-api/pom.xml index 1875a33b2..18b29f7d1 100644 --- a/clearing-parent/backend-api/pom.xml +++ b/clearing-parent/backend-api/pom.xml @@ -49,6 +49,10 @@ io.springfox springfox-swagger-ui + + ru.spcex.clearing + classes + diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/KeycloakRestTemplateAuthenticationProvider.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/KeycloakRestTemplateAuthenticationProvider.java index 5999a8cbf..67e5c07f1 100644 --- a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/KeycloakRestTemplateAuthenticationProvider.java +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/security/KeycloakRestTemplateAuthenticationProvider.java @@ -24,6 +24,7 @@ import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; +import ru.spcex.clearing.backendapi.service.UserAutoCreateService; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -39,13 +40,15 @@ public class KeycloakRestTemplateAuthenticationProvider implements Authenticatio private final HttpServletRequest currentHttpRequest; private final HttpServletResponse currentHttpResponse; private final RestTemplate restTemplate; + private final UserAutoCreateService userAutoCreation; public KeycloakRestTemplateAuthenticationProvider(KeycloakConfigResolver resolver, HttpServletRequest currentHttpRequest, HttpServletResponse currentHttpResponse, - @Qualifier("clearing-rest") RestTemplate restTemplate) { + @Qualifier("clearing-rest") RestTemplate restTemplate, UserAutoCreateService userAutoCreation) { this.resolver = resolver; this.currentHttpRequest = currentHttpRequest; this.currentHttpResponse = currentHttpResponse; this.restTemplate = restTemplate; + this.userAutoCreation = userAutoCreation; } @Override @@ -83,11 +86,11 @@ public class KeycloakRestTemplateAuthenticationProvider implements Authenticatio RefreshableKeycloakSecurityContext skSession = new RefreshableKeycloakSecurityContext(deployment, null, accessTokenString, accessToken, null, null, refreshTokenString); String principalName = AdapterUtils.getPrincipalName(deployment, accessToken); final KeycloakPrincipal principal = new KeycloakPrincipal<>(principalName, skSession); - final Set roles = AdapterUtils.getRolesFromSecurityContext(skSession); final KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, skSession); KeycloakAuthenticationToken keycloakAuthenticationToken = new KeycloakAuthenticationToken(account, false, realmRoles); keycloakAuthenticationToken.setAuthenticated(true); + checkRightsAndCreate(principalName, roles); return keycloakAuthenticationToken; } catch (VerificationException vex) { @@ -97,6 +100,13 @@ public class KeycloakRestTemplateAuthenticationProvider implements Authenticatio } } + private void checkRightsAndCreate(String username, Set roles) { + //todo remove hardcode + if (roles.contains("admin") || roles.contains("default-roles-master")) { + userAutoCreation.createUserIfNeeded(username); + } + } + @Override public boolean supports(Class type) { return UsernamePasswordAuthenticationToken.class.equals(type); diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/UserAutoCreateService.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/UserAutoCreateService.java new file mode 100644 index 000000000..19e9e6ffb --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/service/UserAutoCreateService.java @@ -0,0 +1,36 @@ +package ru.spcex.clearing.backendapi.service; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import ru.clearing.classes.statics.data.user.ClearingUser; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.platform.imdg.api.Imdg; +import ru.spcex.platform.imdg.api.ImdgProvider; + +import java.time.Instant; +import java.util.Map; + +@Service +public class UserAutoCreateService { + + private final Imdg userMap; + + @Autowired + public UserAutoCreateService(ImdgProvider imdgProvider) { + this.userMap = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingUser, ClearingUser.class); + } + + /** + * при необходимости переделать на отдельный поток + * todo transactional? + */ + public void createUserIfNeeded(String userName) { + ClearingUser username = userMap.getSingleObjectByFieldValues(Map.of("username", userName)); + if (username == null) { + username = new ClearingUser(); + username.setUsername(userName); + username.setCreated(Instant.now()); + userMap.insert(username); + } + } +} diff --git a/clearing-parent/classes/src/main/java/ru/clearing/classes/statics/data/user/ClearingUser.java b/clearing-parent/classes/src/main/java/ru/clearing/classes/statics/data/user/ClearingUser.java index 50fbff743..2f751c07b 100644 --- a/clearing-parent/classes/src/main/java/ru/clearing/classes/statics/data/user/ClearingUser.java +++ b/clearing-parent/classes/src/main/java/ru/clearing/classes/statics/data/user/ClearingUser.java @@ -9,6 +9,15 @@ import ru.clearing.classes.objects.BusinessObject; */ public class ClearingUser extends BusinessObject { private static final long serialVersionUID = ConstSerializable.serialVersionUID; + private String username; + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } // private String idpUuid; // diff --git a/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/object/ClearingUserMapStore.java b/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/object/ClearingUserMapStore.java new file mode 100644 index 000000000..6b00310c5 --- /dev/null +++ b/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/object/ClearingUserMapStore.java @@ -0,0 +1,61 @@ +package ru.spcex.clearing.imdg.object; + +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.stereotype.Component; +import ru.clearing.classes.statics.data.user.ClearingUser; +import ru.spcex.clearing.imdg.IMDGDistributedNames; +import ru.spcex.clearing.imdg.base.AutoconfiguredMap; +import ru.spcex.clearing.imdg.base.SimpleObjectMapStore; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +//todo rewrite +@Component +public class ClearingUserMapStore extends SimpleObjectMapStore implements AutoconfiguredMap { + + public ClearingUserMapStore(JdbcTemplate jdbcTemplate) { + super(jdbcTemplate); + //super(jdbcTemplate); + } + + @Override + public String getTableName() { + + return "COMPANY"; + } + + @Override + public String[] getFields() { + return new String[0]; + } + + @Override + public void store(Map map) {} + + @Override + public String getMapName() { + return IMDGDistributedNames.Map_ClearingUser; + } + + @Override + public String[] getIndexingField() { + return new String[] {"username"}; + } + + @Override + public ClearingUser load(Long key) { + return null; + } + + @Override + public Map loadAll(Collection keys) { + return null; + } + + @Override + public Iterable loadAllKeys() { + return Collections.emptyList(); + } +} diff --git a/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/adapter/ImdgHazelcast.java b/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/adapter/ImdgHazelcast.java index 9bdfaf9a7..ab51b6132 100644 --- a/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/adapter/ImdgHazelcast.java +++ b/platform-parent/platform-imdg-api-hazelcast-impl/src/main/java/ru/spcex/platform/imdg/iml/hazelcast/adapter/ImdgHazelcast.java @@ -2,9 +2,12 @@ package ru.spcex.platform.imdg.iml.hazelcast.adapter; import com.hazelcast.core.IMap; import com.hazelcast.core.IdGenerator; +import com.hazelcast.query.Predicate; +import com.hazelcast.query.Predicates; import ru.spcex.platform.classes.base.SpcexObjectBase; import ru.spcex.platform.imdg.api.Imdg; +import java.util.*; public class ImdgHazelcast implements Imdg { private IdGenerator idGenerator; @@ -46,4 +49,52 @@ public class ImdgHazelcast implements Imdg { public T getSingleObjectByID(Long paramLong) { return map.get(paramLong); } + + /** + * возвращает объект удовлетворяющий условиям + * не проверяет, если удовлетворяющих условиям > 1 + */ + @SuppressWarnings("unchecked") + @Override + public T getSingleObjectByFieldValues(Map> conditions) { + Predicate[] predicates = new Predicate[conditions.size()]; + final int[] i = {0}; + conditions.forEach((key, value) -> { + predicates[i[0]] = Predicates.equal(key, value); + i[0]++; + }); + Predicate or = Predicates.or(predicates); + Set> found = map.entrySet(or); + Iterator> allFoundByCondition = found.iterator(); + if (allFoundByCondition.hasNext()) { + return allFoundByCondition.next().getValue(); + } else { + return null; + } + } + + /** + * возвращает коллекцию объектов, удовлетворяющий условиям на поля + */ + @SuppressWarnings("unchecked") + @Override + public Collection getCollectionObjectsByFieldValues(Map> conditions) { + Predicate[] predicates = new Predicate[conditions.size()]; + final int[] i = {0}; + conditions.forEach((key, value) -> { + predicates[i[0]] = Predicates.equal(key, value); + i[0]++; + }); + Predicate or = Predicates.or(predicates); + Set ids = map.keySet(or); + Iterator idIterator = ids.iterator(); + Collection searchResult = new ArrayList<>(); + while(idIterator.hasNext()) { + T element = map.get(idIterator.next()); + if (element != null) { + searchResult.add(element); + } + } + return searchResult; + } } diff --git a/platform-parent/platform-imdg-api/src/main/java/ru/spcex/clearing/imdg/IMDGDistributedNames.java b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/clearing/imdg/IMDGDistributedNames.java index 86597f7e4..908a3cdfd 100644 --- a/platform-parent/platform-imdg-api/src/main/java/ru/spcex/clearing/imdg/IMDGDistributedNames.java +++ b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/clearing/imdg/IMDGDistributedNames.java @@ -38,6 +38,7 @@ public final class IMDGDistributedNames { public static final String Map_SDf08 = "Map_SDf08"; public static final String Map_SDf02 = "Map_SDf02"; public static final String Map_SDf01 = "Map_SDf01"; + public static final String Map_ClearingUser = "Map_ClearingUser"; // public static final String Map_InterestStatusDictionary = "Map_InterestStatusDictionary"; future public static final String Map_AllowedDictionary = "Map_AllowedDictionary"; diff --git a/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/Imdg.java b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/Imdg.java index 259d607b6..49b9ddf94 100644 --- a/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/Imdg.java +++ b/platform-parent/platform-imdg-api/src/main/java/ru/spcex/platform/imdg/api/Imdg.java @@ -3,6 +3,7 @@ package ru.spcex.platform.imdg.api; import ru.spcex.platform.classes.base.SpcexObjectBase; import java.util.Collection; +import java.util.Map; public interface Imdg { default void insert(T paramT) { @@ -29,6 +30,14 @@ public interface Imdg { throw new UnsupportedOperationException("not implemented getSingleObjectBySQL"); } + default T getSingleObjectByFieldValues(Map> conditions) { + throw new UnsupportedOperationException("not implemented getSingleObjectByFieldValues"); + } + + default Collection getCollectionObjectsByFieldValues(Map> conditions) { + throw new UnsupportedOperationException("not implemented getCollectionObjectsByFieldValues"); + } + default T getSingleObjectByID(Long paramLong) { throw new UnsupportedOperationException("not implemented getSingleObjectByID"); }