Merge branch 'release/1.9.12'

This commit is contained in:
Zaripov Emil 2025-04-24 10:03:28 +03:00
commit f306fef748
75 changed files with 497 additions and 1029 deletions

View file

@ -5,7 +5,7 @@
<parent>
<groupId>ru.micord.ervu</groupId>
<artifactId>account-applications</artifactId>
<version>1.9.11</version>
<version>1.9.12-SNAPSHOT</version>
</parent>
<groupId>ru.micord.ervu.account_applications</groupId>
<artifactId>backend</artifactId>

View file

@ -0,0 +1,43 @@
package ru.micord.ervu.account_applications.component.rpc;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import ru.micord.ervu.account_applications.dao.UserApplicationListDao;
import ru.micord.ervu.account_applications.service.RoleServiceImpl;
import ru.cg.webbpm.modules.webkit.annotations.RpcCall;
import ru.cg.webbpm.modules.webkit.annotations.RpcService;
import ru.cg.webbpm.modules.webkit.beans.Behavior;
/**
* @author gulnaz
*/
@RpcService
public class UserApplicationListRpcService extends Behavior {
private static final Logger LOGGER = LoggerFactory.getLogger(UserApplicationListRpcService.class);
@Autowired
private UserApplicationListDao applicationListDao;
@Autowired
private RoleServiceImpl roleService;
@RpcCall
public void saveTraceId(String traceId, long appNumber) {
LOGGER.info("saving traceId {} for application {}", traceId, appNumber);
applicationListDao.saveTraceId(traceId, appNumber);
}
@RpcCall
public void saveAgreedStatus(long appNumber) {
applicationListDao.saveAgreedStatus(appNumber);
}
@RpcCall
public List<String> getRemovedRoleIds(String accountId, Set<String> roleIds) {
return roleService.fetchRemovedRoleIds(accountId, roleIds);
}
}

View file

@ -1,197 +1,29 @@
package ru.micord.ervu.account_applications.controller;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.validation.Valid;
import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
import ru.micord.ervu.account_applications.dto.Account;
import ru.micord.ervu.account_applications.dto.ProcessRequest;
import ru.micord.ervu.account_applications.dto.create.CreateProcessRequest;
import ru.micord.ervu.account_applications.dto.create.CreateUserDto;
import ru.micord.ervu.account_applications.dto.create.Credential;
import ru.micord.ervu.account_applications.dto.create.CreateData;
import ru.micord.ervu.account_applications.dto.Person;
import ru.micord.ervu.account_applications.dto.ProcessResponse;
import ru.micord.ervu.account_applications.dto.Role;
import ru.micord.ervu.account_applications.dto.Roles;
import ru.micord.ervu.account_applications.dto.activation.ChangeActivationData;
import ru.micord.ervu.account_applications.dto.activation.ChangeActivationDto;
import ru.micord.ervu.account_applications.dto.activation.ChangeActivationProcessRequest;
import ru.micord.ervu.account_applications.dto.edit.EditAccountDto;
import ru.micord.ervu.account_applications.dto.edit.EditData;
import ru.micord.ervu.account_applications.dto.edit.EditRolesDto;
import ru.micord.ervu.account_applications.dto.edit.EditPersonDto;
import ru.micord.ervu.account_applications.dto.edit.EditPersonProcessRequest;
import ru.micord.ervu.account_applications.dto.password.ResetPasswordData;
import ru.micord.ervu.account_applications.dto.password.ResetPasswordDto;
import ru.micord.ervu.account_applications.dto.password.ResetPasswordProcessRequest;
import ru.micord.ervu.account_applications.dto.password.UserIdInfo;
import ru.micord.ervu.account_applications.security.context.SecurityContext;
import ru.micord.ervu.account_applications.service.RoleServiceImpl;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import ru.micord.ervu.account_applications.service.UserApplicationListService;
import static ru.micord.ervu.account_applications.enums.ProcessKey.*;
/**
* @author gulnaz
*/
@RestController
@RequestMapping("/user")
public class AdminController {
private static final Logger LOGGER = LoggerFactory.getLogger(AdminController.class);
private static final String PROCESS_START_PATH = "/service/wf/service/start";
private final RestTemplate restTemplate;
private final SecurityContext securityContext;
private final UserApplicationListService applicationListService;
private final RoleServiceImpl roleService;
@Value("${ervu.url}")
private String ervuUrl;
public AdminController(RestTemplate restTemplate, SecurityContext securityContext,
UserApplicationListService applicationListService, RoleServiceImpl roleService) {
this.restTemplate = restTemplate;
this.securityContext = securityContext;
public AdminController(UserApplicationListService applicationListService) {
this.applicationListService = applicationListService;
this.roleService = roleService;
}
@PostMapping(value = "", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> create(@RequestBody @Valid CreateUserDto dto) {
Credential credential = new Credential(dto.username());
Account account = new Account(dto.userDomain(), dto.position());
Person person = new Person(dto.surname(), dto.firstname(), dto.middlename(), dto.sex(),
dto.email(), dto.birthdate(), dto.snils(), dto.ipAddresses());
List<Role> rolesList = dto.roles()
.stream()
.map(Role::new)
.collect(Collectors.toList());
Roles roles = new Roles(rolesList);
CreateProcessRequest request = new CreateProcessRequest(
CREATE.getValue(), getUserId(), new CreateData(credential, account, person, roles));
return doRequestAndSaveTraceId(request, dto.appNumber());
}
@PostMapping(value = "/person", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> editPerson(@RequestBody @Valid EditPersonDto dto) {
Person person = new Person(dto.id(), dto.surname(), dto.firstname(), dto.middlename(), dto.sex(),
dto.email(), dto.birthdate(), dto.snils(), dto.ipAddresses());
EditPersonProcessRequest request = new EditPersonProcessRequest(EDIT_PERSON.getValue(),
getUserId(), new EditData(dto.accountId(), person));
return doRequestAndSaveTraceId(request, dto.appNumber());
}
@PostMapping(value = "/account", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> editAccount(@RequestBody @Valid EditAccountDto dto) {
Account account = new Account(dto.accountId(), dto.userDomain(), dto.position());
EditPersonProcessRequest request = new EditPersonProcessRequest(EDIT_ACCOUNT.getValue(),
getUserId(), new EditData(account));
return doRequestAndSaveTraceId(request, dto.appNumber());
}
@PostMapping(value = "/roles", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> editRoles(@RequestBody @Valid EditRolesDto dto) {
List<Role> rolesList = dto.roles()
.stream()
.map(Role::new)
.collect(Collectors.toList());
List<String> removedRoleIds = roleService.fetchRemovedRoleIds(dto.accountId(), dto.roles());
Account account = new Account(dto.accountId(), removedRoleIds, rolesList);
EditPersonProcessRequest request = new EditPersonProcessRequest(EDIT_ROLES.getValue(),
getUserId(), new EditData(account));
return doRequestAndSaveTraceId(request, dto.appNumber());
}
@PostMapping(value = "/deactivation", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> deactivate(@RequestBody @Valid ChangeActivationDto dto) {
ChangeActivationProcessRequest request = new ChangeActivationProcessRequest(DEACTIVATE.getValue(),
getUserId(), new ChangeActivationData(Collections.singletonList(dto.accountId())));
return doRequestAndSaveTraceId(request, dto.appNumber());
}
@PostMapping(value = "/activation", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> activate(@RequestBody @Valid ChangeActivationDto dto) {
ChangeActivationProcessRequest request = new ChangeActivationProcessRequest(ACTIVATE.getValue(),
getUserId(), new ChangeActivationData(Collections.singletonList(dto.accountId())));
return doRequestAndSaveTraceId(request, dto.appNumber());
}
//TODO SUPPORT-9109 move to front
@GetMapping("/exists")
public ResponseEntity<Boolean> userExists(@RequestParam(name = "login") String login) {
boolean result = applicationListService.userExists(login);
return ResponseEntity.ok(result);
}
@PostMapping(value = "/password/reset")
public ResponseEntity<?> resetPassword(@RequestBody @Valid ResetPasswordDto dto) {
UserIdInfo userIdInfo = new UserIdInfo(dto.accountId());
ResetPasswordData resetPasswordData = new ResetPasswordData(userIdInfo);
ResetPasswordProcessRequest request = new ResetPasswordProcessRequest(
RESET_PASSWORD.getValue(),
getUserId(), resetPasswordData
);
return doRequestAndSaveTraceId(request, dto.appNumber());
}
private <R> ResponseEntity<?> doRequestAndSaveTraceId(ProcessRequest<R> request, long appNumber) {
LOGGER.info("making request for application {} with {}", appNumber, new Gson().toJson(request));
ResponseEntity<?> responseEntity = doRequest(request);
if (responseEntity.getStatusCode().equals(HttpStatus.OK)) {
String traceId = ((ProcessResponse) Objects.requireNonNull(responseEntity.getBody())).traceId();
LOGGER.info("saving traceId {}", traceId);
applicationListService.saveTraceId(traceId, appNumber);
}
return responseEntity;
}
private <R> ResponseEntity<?> doRequest(ProcessRequest<R> request) {
HttpEntity<ProcessRequest<R>> entity = setEntity(getToken(), request);
URI uri = UriComponentsBuilder.fromHttpUrl(ervuUrl)
.path(PROCESS_START_PATH)
.build()
.toUri();
try {
return restTemplate.postForEntity(uri, entity, ProcessResponse.class);
}
catch (HttpClientErrorException | HttpServerErrorException e) {
return new ResponseEntity<>(e.getMessage(), e.getStatusCode());
}
}
private <R> HttpEntity<R> setEntity(String token, R body) {
HttpHeaders headers = new HttpHeaders();
headers.setBearerAuth(token);
headers.setContentType(MediaType.APPLICATION_JSON);
return new HttpEntity<>(body, headers);
}
private String getUserId() {
return securityContext.getUserId();
}
private String getToken() {
return securityContext.getToken();
}
}

View file

@ -0,0 +1,54 @@
package ru.micord.ervu.account_applications.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import ru.micord.ervu.account_applications.security.service.EncryptionService;
import ru.micord.ervu.account_applications.service.UserApplicationListService;
import ru.micord.ervu.account_applications.websocket.dto.ProcessResponseDto;
/**
* @author gulnaz
*/
@RestController
public class UserApplicationController {
private static final Logger LOGGER = LoggerFactory.getLogger(UserApplicationController.class);
private final UserApplicationListService applicationService;
private final EncryptionService encryptionService;
public UserApplicationController(UserApplicationListService applicationService,
EncryptionService encryptionService) {
this.applicationService = applicationService;
this.encryptionService = encryptionService;
}
@PutMapping(value = "/status", consumes = MediaType.APPLICATION_JSON_VALUE)
public void updateStatus(@RequestBody ProcessResponseDto data) {
String traceId = data.traceId();
switch (data.className()) {
case UPDATE -> {
LOGGER.info("update by traceId = {}", traceId);
String tempPass = data.body().tempPass();
if (StringUtils.hasText(tempPass)) {
String encryptedPassword = encryptionService.encrypt(tempPass);
applicationService.savePassword(traceId, encryptedPassword);
}
else {
applicationService.saveAcceptedStatus(traceId);
}
}
case PROCESS_ERROR -> {
String msg = data.body().msg().message();
LOGGER.error("error by traceId = {}, message: {}", traceId, msg);
applicationService.saveError(traceId, msg);
}
}
}
}

View file

@ -69,4 +69,11 @@ public class UserApplicationListDao {
Timestamp.valueOf(LocalDateTime.now().minusMinutes(minutes)))))
.execute();
}
public void saveAgreedStatus(long appNumber) {
dslContext.update(USER_APPLICATION_LIST)
.set(USER_APPLICATION_LIST.APPLICATION_STATUS, AGREED.name())
.where(USER_APPLICATION_LIST.NUMBER_APP.eq(appNumber))
.execute();
}
}

View file

@ -1,143 +0,0 @@
package ru.micord.ervu.account_applications.dto;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
/**
* @author Emir Suleimanov
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class Account {
private final String schema = "Account";
@JsonProperty("user-domain")
private String userDomain;
private String position;
private boolean enabled = true;
private boolean esiaAccount;
private String start;
private String finish;
private String id;
private String accountId;
private List<String> removeRoles;
private List<Role> rolesList;
public Account(String userDomain, String position) {
this.userDomain = userDomain;
this.position = position;
}
public Account(String id, String userDomain, String position) {
this(userDomain, position);
this.id = id;
}
public Account(String accountId, List<String> removeRoles, List<Role> rolesList) {
this.accountId = accountId;
this.removeRoles = removeRoles;
this.rolesList = rolesList;
}
public String getSchema() {
return schema;
}
public String getUserDomain() {
return userDomain;
}
public void setUserDomain(String userDomain) {
this.userDomain = userDomain;
}
public String getPosition() {
return position;
}
public void setPosition(String position) {
this.position = position;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isEsiaAccount() {
return esiaAccount;
}
public void setEsiaAccount(boolean esiaAccount) {
this.esiaAccount = esiaAccount;
}
public String getStart() {
return start;
}
public void setStart(String start) {
this.start = start;
}
public String getFinish() {
return finish;
}
public void setFinish(String finish) {
this.finish = finish;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getAccountId() {
return accountId;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public List<String> getRemoveRoles() {
return removeRoles;
}
public void setRemoveRoles(List<String> removeRoles) {
this.removeRoles = removeRoles;
}
public List<Role> getRolesList() {
return rolesList;
}
public void setRolesList(List<Role> rolesList) {
this.rolesList = rolesList;
}
@Override
public String toString() {
return "Account{" +
"schema='" + schema + '\'' +
", userDomain='" + userDomain + '\'' +
", position='" + position + '\'' +
", enabled=" + enabled +
", esiaAccount=" + esiaAccount +
", start='" + start + '\'' +
", finish='" + finish + '\'' +
", id='" + id + '\'' +
", accountId='" + accountId + '\'' +
", removeRoles=" + removeRoles +
", rolesList=" + rolesList +
'}';
}
}

View file

@ -1,21 +0,0 @@
package ru.micord.ervu.account_applications.dto;
import java.util.List;
/**
* @author gulnaz
*/
public record Person(String id, String surname, String firstname, String middlename, String sex,
String email, String birthdate, String snils, List<String> ipAddresses,
boolean secondFactorEnabled) {
public Person(String surname, String firstname, String middlename, String sex, String email,
String birthdate, String snils, List<String> ipAddresses) {
this("", surname, firstname, middlename, sex, email, birthdate, snils, ipAddresses);
}
public Person(String id, String surname, String firstname, String middlename, String sex,
String email, String birthdate, String snils, List<String> ipAddresses) {
this(id, surname, firstname, middlename, sex, email, birthdate, snils, ipAddresses, false);
}
}

View file

@ -1,38 +0,0 @@
package ru.micord.ervu.account_applications.dto;
/**
* @author gulnaz
*/
public abstract class ProcessRequest<T> {
protected final String processKey;
protected final String userId;
protected final T data;
public ProcessRequest(String processKey, String userId, T data) {
this.processKey = processKey;
this.userId = userId;
this.data = data;
}
public String getProcessKey() {
return processKey;
}
public String getUserId() {
return userId;
}
public T getData() {
return data;
}
@Override
public String toString() {
return "ProcessRequest{" +
"processKey='" + processKey + '\'' +
", userId='" + userId + '\'' +
", data=" + data +
'}';
}
}

View file

@ -1,7 +0,0 @@
package ru.micord.ervu.account_applications.dto;
/**
* @author gulnaz
*/
public record ProcessResponse(String code, String msg, String traceId) {
}

View file

@ -1,10 +0,0 @@
package ru.micord.ervu.account_applications.dto;
/**
* @author gulnaz
*/
public record Role(String id, String finish) {
public Role(String id) {
this(id, "");
}
}

View file

@ -1,9 +0,0 @@
package ru.micord.ervu.account_applications.dto;
import java.util.List;
/**
* @author gulnaz
*/
public record Roles(List<Role> rolesList) {
}

View file

@ -1,9 +0,0 @@
package ru.micord.ervu.account_applications.dto.activation;
import java.util.List;
/**
* @author gulnaz
*/
public record ChangeActivationData(List<String> accountIdList) {
}

View file

@ -1,12 +0,0 @@
package ru.micord.ervu.account_applications.dto.activation;
import javax.validation.constraints.NotNull;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* @author gulnaz
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public record ChangeActivationDto(@NotNull long appNumber, @NotNull String accountId) {
}

View file

@ -1,13 +0,0 @@
package ru.micord.ervu.account_applications.dto.activation;
import ru.micord.ervu.account_applications.dto.ProcessRequest;
/**
* @author gulnaz
*/
public class ChangeActivationProcessRequest extends ProcessRequest<ChangeActivationData> {
public ChangeActivationProcessRequest(String processKey, String userId, ChangeActivationData data) {
super(processKey, userId, data);
}
}

View file

@ -1,11 +0,0 @@
package ru.micord.ervu.account_applications.dto.create;
import ru.micord.ervu.account_applications.dto.Account;
import ru.micord.ervu.account_applications.dto.Person;
import ru.micord.ervu.account_applications.dto.Roles;
/**
* @author gulnaz
*/
public record CreateData(Credential credential, Account account, Person person, Roles roles) {
}

View file

@ -1,13 +0,0 @@
package ru.micord.ervu.account_applications.dto.create;
import ru.micord.ervu.account_applications.dto.ProcessRequest;
/**
* @author gulnaz
*/
public class CreateProcessRequest extends ProcessRequest<CreateData> {
public CreateProcessRequest(String processKey, String userId, CreateData data) {
super(processKey, userId, data);
}
}

View file

@ -1,20 +0,0 @@
package ru.micord.ervu.account_applications.dto.create;
import java.util.List;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* @author gulnaz
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public record CreateUserDto(@NotNull long appNumber, @NotNull String firstname,
@NotNull String surname, String middlename,
String birthdate, String sex, String position, String email,
@NotNull String username, @NotNull String snils,
@NotNull @NotEmpty String userDomain,
String start, String finish,
List<String> roles, List<String> ipAddresses) {
}

View file

@ -1,7 +0,0 @@
package ru.micord.ervu.account_applications.dto.create;
/**
* @author gulnaz
*/
public record Credential(String userName) {
}

View file

@ -1,14 +0,0 @@
package ru.micord.ervu.account_applications.dto.edit;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* @author Emir Suleimanov
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public record EditAccountDto(@NotNull long appNumber, String username, @NotNull String position,
@NotNull @NotEmpty String accountId, @NotNull @NotEmpty String userDomain) {
}

View file

@ -1,57 +0,0 @@
package ru.micord.ervu.account_applications.dto.edit;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import ru.micord.ervu.account_applications.dto.Account;
import ru.micord.ervu.account_applications.dto.Person;
/**
* @author gulnaz
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public class EditData {
private String accountId;
private Person personData;
private Account account;
public EditData(String accountId, Person personData) {
this.accountId = accountId;
this.personData = personData;
}
public EditData(Account account) {
this.account = account;
}
public String getAccountId() {
return accountId;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public Person getPersonData() {
return personData;
}
public void setPersonData(Person personData) {
this.personData = personData;
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
@Override
public String toString() {
return "EditData{" +
"accountId='" + accountId + '\'' +
", personData=" + personData +
", account=" + account +
'}';
}
}

View file

@ -1,16 +0,0 @@
package ru.micord.ervu.account_applications.dto.edit;
import java.util.List;
import javax.validation.constraints.NotNull;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* @author gulnaz
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public record EditPersonDto(@NotNull long appNumber, @NotNull String accountId, @NotNull String id,
@NotNull String firstname, @NotNull String surname, String middlename,
String birthdate, String sex, String position, String email,
@NotNull String snils, List<String> ipAddresses) {
}

View file

@ -1,13 +0,0 @@
package ru.micord.ervu.account_applications.dto.edit;
import ru.micord.ervu.account_applications.dto.ProcessRequest;
/**
* @author gulnaz
*/
public class EditPersonProcessRequest extends ProcessRequest<EditData> {
public EditPersonProcessRequest(String processKey, String userId, EditData data) {
super(processKey, userId, data);
}
}

View file

@ -1,13 +0,0 @@
package ru.micord.ervu.account_applications.dto.edit;
import java.util.Set;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import javax.validation.constraints.NotNull;
/**
* @author Emir Suleimanov
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public record EditRolesDto(@NotNull long appNumber, @NotNull String accountId, Set<String> roles) {
}

View file

@ -1,8 +0,0 @@
package ru.micord.ervu.account_applications.dto.password;
/**
* @author Adel Kalimullin
*/
public record ResetPasswordData(UserIdInfo account) {
}

View file

@ -1,13 +0,0 @@
package ru.micord.ervu.account_applications.dto.password;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
/**
* @author Adel Kalimullin
*/
@JsonIgnoreProperties(ignoreUnknown = true)
public record ResetPasswordDto(@NotNull long appNumber, @NotNull @NotEmpty String accountId) {
}

View file

@ -1,13 +0,0 @@
package ru.micord.ervu.account_applications.dto.password;
import ru.micord.ervu.account_applications.dto.ProcessRequest;
/**
* @author Adel Kalimullin
*/
public class ResetPasswordProcessRequest extends ProcessRequest<ResetPasswordData> {
public ResetPasswordProcessRequest(String processKey, String userId, ResetPasswordData data) {
super(processKey, userId, data);
}
}

View file

@ -1,7 +0,0 @@
package ru.micord.ervu.account_applications.dto.password;
/**
* @author Adel Kalimullin
*/
public record UserIdInfo(String id){
}

View file

@ -1,24 +0,0 @@
package ru.micord.ervu.account_applications.enums;
/**
* @author gulnaz
*/
public enum ProcessKey {
CREATE("milBaseCreateAccountProcess"),
EDIT_PERSON("milBaseEditAccountPersonIDMProcess"),
EDIT_ACCOUNT("milBaseEditAccountIDMProcess"),
EDIT_ROLES("milBaseEditAccountRolesIDMSubProcess"),
DEACTIVATE("milBaseMassDeActivateAccountIDMProcess"),
ACTIVATE("milBaseMassActivateAccountIDMProcess"),
RESET_PASSWORD("milBaseResetPasswordProcess");
private final String value;
ProcessKey(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}

View file

@ -14,6 +14,7 @@ import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.config.ConcurrentKafkaListenerContainerFactory;
import org.springframework.kafka.core.ConsumerFactory;
import org.springframework.kafka.core.DefaultKafkaConsumerFactory;
import org.springframework.kafka.support.serializer.JsonDeserializer;
/**
* @author Eduard Tihomirov

View file

@ -19,7 +19,6 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import ru.micord.ervu.account_applications.security.model.jwt.authentication.JwtTokenDummy;
import ru.micord.ervu.account_applications.websocket.service.WebSocketService;
@Component
@ -28,12 +27,9 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
MethodHandles.lookup().lookupClass());
private final AuthenticationManager authenticationManager;
private final WebSocketService webSocketService;
public JwtAuthenticationFilter(AuthenticationManager authenticationManager,
WebSocketService webSocketService) {
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
this.webSocketService = webSocketService;
}
@Override

View file

@ -1,34 +0,0 @@
package ru.micord.ervu.account_applications.security.listener;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.stereotype.Component;
import ru.micord.ervu.account_applications.security.model.jwt.UserSession;
import ru.micord.ervu.account_applications.security.model.jwt.authentication.JwtTokenAuthentication;
import ru.micord.ervu.account_applications.websocket.service.WebSocketService;
/**
* @author gulnaz
*/
@Component
public class SuccessfulAuthListener implements ApplicationListener<AuthenticationSuccessEvent> {
private static final String ADMIN_ROLE = "security_administrator";
private final WebSocketService webSocketService;
public SuccessfulAuthListener(WebSocketService webSocketService) {
this.webSocketService = webSocketService;
}
@Override
public void onApplicationEvent(AuthenticationSuccessEvent event) {
JwtTokenAuthentication authentication = (JwtTokenAuthentication) event.getAuthentication();
UserSession userSession = authentication.getUserSession();
boolean isAdmin = userSession.roles().stream()
.anyMatch(ervuRoleAuthority -> ervuRoleAuthority.getAuthority().equals(ADMIN_ROLE));
if (isAdmin) {
webSocketService.connectToSocket(userSession.userId(), authentication.getCredentials().toString());
}
}
}

View file

@ -22,7 +22,7 @@ public class ErvuDirectoriesDaoService {
@Autowired
private ErvuDirectoriesDao ervuDirectoriesDao;
@Cacheable(value = "role-ids", unless = "#result == null")
@Cacheable(value = "role-ids", unless = "#result == null")
public List<String> getRoleIds() {
return ervuDirectoriesDao.getRoleIds();
}

View file

@ -38,8 +38,8 @@ public class RoleServiceImpl extends AbstractUserDataService {
public List<String> fetchRemovedRoleIds(String accountId, Set<String> newRoleIds) {
try {
return fetchRolesByAccountId(accountId).stream()
.filter(role -> role.isErvuRole() && !newRoleIds.contains(role.getId()))
.map(Role::getId)
.filter(id -> !newRoleIds.contains(id))
.toList();
}
catch (Exception e) {

View file

@ -32,6 +32,10 @@ public class UserApplicationListService {
dao.saveAcceptedStatus(traceId);
}
public void saveAgreedStatus(long appNumber) {
dao.saveAgreedStatus(appNumber);
}
public void saveError(String traceId, String errorMsg) {
dao.saveError(traceId, errorMsg);
}

View file

@ -1,29 +0,0 @@
package ru.micord.ervu.account_applications.websocket;
import java.util.HashMap;
import java.util.Map;
import javax.net.ssl.SSLContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.client.WebSocketClient;
import org.springframework.web.socket.client.standard.StandardWebSocketClient;
/**
* @author gulnaz
*/
@Configuration
public class WebSocketConfig {
@Autowired
private SSLContext sslContext;
@Bean
public WebSocketClient webSocketClient() {
Map<String, Object> userProperties = new HashMap<>();
userProperties.put("org.apache.tomcat.websocket.SSL_CONTEXT", sslContext);
StandardWebSocketClient webSocketClient = new StandardWebSocketClient();
webSocketClient.setUserProperties(userProperties);
return webSocketClient;
}
}

View file

@ -1,11 +0,0 @@
package ru.micord.ervu.account_applications.websocket.exception;
/**
* @author gulnaz
*/
public class WebSocketConnectionException extends RuntimeException {
public WebSocketConnectionException(String message) {
super(message);
}
}

View file

@ -1,123 +0,0 @@
package ru.micord.ervu.account_applications.websocket.handler;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import ru.micord.ervu.account_applications.security.service.EncryptionService;
import ru.micord.ervu.account_applications.service.UserApplicationListService;
import ru.micord.ervu.account_applications.websocket.dto.ProcessResponseDto;
import ru.micord.ervu.account_applications.websocket.service.WebSocketService;
/**
* @author gulnaz
*/
@Component
public class ClientSocketHandler extends TextWebSocketHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(TextWebSocketHandler.class);
private static final Map<String, WebSocketSession> sessionByUserId = new ConcurrentHashMap<>();
private static final Map<String, UserData> userDataBySessionId = new ConcurrentHashMap<>();
private final ObjectMapper objectMapper;
private final UserApplicationListService applicationService;
private final EncryptionService encryptionService;
private final WebSocketService webSocketService;
public ClientSocketHandler(ObjectMapper objectMapper,
UserApplicationListService applicationService,
EncryptionService encryptionService,
@Lazy WebSocketService webSocketService) {
this.objectMapper = objectMapper;
this.applicationService = applicationService;
this.encryptionService = encryptionService;
this.webSocketService = webSocketService;
}
@Override
public void afterConnectionEstablished(WebSocketSession session) {
LOGGER.info("established connection {}", session);
}
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message)
throws JsonProcessingException {
ProcessResponseDto dto = objectMapper.readValue(message.getPayload().toString(),
ProcessResponseDto.class);
String traceId = dto.traceId();
switch (dto.className()) {
case UPDATE -> {
LOGGER.info("update by traceId = {}", traceId);
String tempPass = dto.body().tempPass();
if (StringUtils.hasText(tempPass)) {
String encryptedPassword = encryptionService.encrypt(tempPass);
applicationService.savePassword(traceId, encryptedPassword);
}
else {
applicationService.saveAcceptedStatus(traceId);
}
}
case PROCESS_ERROR -> {
String msg = dto.body().msg().message();
LOGGER.error("error by traceId = {}, message: {}", traceId, msg);
applicationService.saveError(traceId, msg);
}
}
}
@Override
public void handleTransportError(WebSocketSession session, Throwable exception) {
LOGGER.error("Transport error {}", exception.getMessage());
try {
session.close();
}
catch (IOException e) {
LOGGER.error("Failed to close session on handleTransportError ", e);
}
}
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
LOGGER.info("Connection closed");
if (!status.equals(CloseStatus.NORMAL)) {
try {
session.close();
}
catch (IOException e) {
LOGGER.error("Failed to close session on afterConnectionClosed ", e);
}
}
String sessionId = session.getId();
UserData userData = userDataBySessionId.get(sessionId);
userDataBySessionId.remove(sessionId);
webSocketService.connectToSocket(userData.userId(), userData.token());
}
public boolean isSessionOpen(String userId) {
return sessionByUserId.get(userId) != null && sessionByUserId.get(userId).isOpen();
}
public void putSession(String userId, WebSocketSession session) {
sessionByUserId.put(userId, session);
}
public void putUserData(String sessionId, String userId, String token) {
userDataBySessionId.put(sessionId, new UserData(userId, token));
}
private record UserData(String userId, String token) {}
}

View file

@ -1,75 +0,0 @@
package ru.micord.ervu.account_applications.websocket.service;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.retry.annotation.Retryable;
import org.springframework.retry.support.RetrySynchronizationManager;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketHttpHeaders;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.client.WebSocketClient;
import ru.micord.ervu.account_applications.websocket.exception.WebSocketConnectionException;
import ru.micord.ervu.account_applications.websocket.handler.ClientSocketHandler;
/**
* @author gulnaz
*/
@Service
public class WebSocketService {
private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketService.class);
private final WebSocketClient webSocketClient;
private final WebSocketHandler webSocketHandler;
@Value("${ervu.url}")
private String ervuUrl;
@Value("${ervu.socket.queue:/service/notifier/gateway/notify/notifier.message.send.push}")
private String socketQueue;
@Value("${ervu.socket.connection_timeout:30}")
private long timeout;
public WebSocketService(WebSocketClient webSocketClient, WebSocketHandler webSocketHandler) {
this.webSocketClient = webSocketClient;
this.webSocketHandler = webSocketHandler;
}
@Retryable(
retryFor = {WebSocketConnectionException.class},
maxAttemptsExpression = "${socket.connect.max_attempts:3}")
public void connectToSocket(String userId, String token) {
ClientSocketHandler socketHandler = (ClientSocketHandler) this.webSocketHandler;
if (socketHandler.isSessionOpen(userId)) {
return;
}
WebSocketHttpHeaders headers = new WebSocketHttpHeaders();
headers.set("Content-Type", "application/json");
headers.add("Authorization", "Bearer " + token);
headers.add("Cookie", "JWT=" + token); // to listen private messages
try {
String host = new URI(ervuUrl).getHost();
WebSocketSession session = webSocketClient.doHandshake(this.webSocketHandler, headers,
URI.create("wss://" + host + socketQueue)).get(timeout, TimeUnit.SECONDS);
socketHandler.putSession(userId, session);
socketHandler.putUserData(session.getId(), userId, token);
}
catch (InterruptedException | ExecutionException | TimeoutException e) {
LOGGER.error("Failed to connect socket", e);
LOGGER.error("Failed to connect socket on retry {}",
RetrySynchronizationManager.getContext().getRetryCount());
throw new WebSocketConnectionException(e.getMessage());
}
catch (URISyntaxException e) {
LOGGER.error("Failed to parse url: {}", ervuUrl, e);
}
}
}

View file

@ -21,10 +21,11 @@ KAFKA_PASS=Blfi9d2OFG
KAFKA_CONSUMER_GROUP_ID=1
KAFKA_DOMAIN_GROUP_ID=ervu-account-applications-backend-domain
KAFKA_ROLE_GROUP_ID=ervu-account-applications-backend-role
IDM_URL=http://idm
ERVU_URL=https://ervu-dev.pgs.rtlabs.ru
ERVU_HTTP_TIMEOUT=30
ERVU_PWD_SIGN_SECRET_KEY=xoL2Y3VRdQ4phXG85o6dRqcgqb4bk6ULdkJJdlRLhZM=
KAFKA_ROLE_RECONCILIATION=idmv2.role.reconciliation
KAFKA_DOMAIN_RECONCILIATION=idmv2.domain.reconciliation
IDM_URL=http://idm
ERVU_ROLE_ADMIN=security_administrator

View file

@ -4,7 +4,7 @@
<parent>
<groupId>ru.micord.ervu</groupId>
<artifactId>account-applications</artifactId>
<version>1.9.11</version>
<version>1.9.12-SNAPSHOT</version>
</parent>
<groupId>ru.micord.ervu.account_applications</groupId>

View file

@ -4,7 +4,7 @@
<parent>
<groupId>ru.micord.ervu</groupId>
<artifactId>account-applications</artifactId>
<version>1.9.11</version>
<version>1.9.12-SNAPSHOT</version>
</parent>
<groupId>ru.micord.ervu.account_applications</groupId>

View file

@ -4,16 +4,41 @@ import {
NotNull,
ObjectRef,
SaveButton,
TextField, Visible
TextField,
Visible
} from "@webbpm/base-package";
import {HttpClient} from "@angular/common/http";
import {FormField} from "../field/FormField";
import {AuthorizationService} from "../../../modules/app/service/authorization.service";
import {ApplicationKind} from "../enum/ApplicationKind";
import {ProcessKey} from "../enum/ProcessKey";
import {ProcessResponse} from "./response/ProcessResponse";
import {UserApplicationListRpcService} from "../../../generated/ru/micord/ervu/account_applications/component/rpc/UserApplicationListRpcService";
import {Account} from "./dto/Account";
import {Person} from "./dto/Person";
import {Credential} from "./dto/create/Credential";
import {Roles} from "./dto/create/Roles";
import {CreateAccountRequest} from "./dto/create/CreateAccountRequest";
import {CreateAccountData} from "./dto/create/CreateAccountData";
import {Role} from "./dto/Role";
import {EditPersonData} from "./dto/edit/EditPersonData";
import {EditPersonRequest} from "./dto/edit/EditPersonRequest";
import {EditAccountData} from "./dto/edit/EditAccountData";
import {EditAccountRequest} from "./dto/edit/EditAccountRequest";
import {ChangeActivationData} from "./dto/activation/ChangeActivationData";
import {ChangeActivationRequest} from "./dto/activation/ChangeActivationRequest";
import {EditRolesAccount} from "./dto/edit/EditRolesAccount";
import {EditRolesData} from "./dto/edit/EditRolesData";
import {EditRolesRequest} from "./dto/edit/EditRolesRequest";
import {ResetPasswordAccount} from "./dto/password/ResetPasswordAccount";
import {ResetPasswordData} from "./dto/password/ResetPasswordData";
import {ResetPasswordRequest} from "./dto/password/ResetPasswordRequest";
@AnalyticalScope(SaveButton)
export class UserManagementService extends Behavior {
private static PROCESS_START_PATH = '/service/wf/service/start';
@NotNull()
@ObjectRef()
public applicationKind: TextField;
@ -22,43 +47,109 @@ export class UserManagementService extends Behavior {
private httpClient: HttpClient;
private onClickFunction: Function;
private sendToErvu: boolean = false;
private rpc: UserApplicationListRpcService;
private authService: AuthorizationService;
initialize() {
super.initialize();
this.button = this.getScript(SaveButton);
this.httpClient = this.injector.get(HttpClient);
let authService = this.injector.get(AuthorizationService);
this.rpc = this.getScript(UserApplicationListRpcService);
this.authService = this.injector.get(AuthorizationService);
this.onClickFunction = () => {
if (!authService.hasRole('security_administrator') || !this.sendToErvu) {
if (!this.authService.hasRole('security_administrator') || !this.sendToErvu) {
return;
}
let jsonObj = this.collectData();
let kind = this.applicationKind.getValue();
let formJson = this.collectData();
let request;
switch (kind) {
case ApplicationKind.CREATE_USER:
this.doRequest("user", jsonObj);
let createData = new CreateAccountData();
createData.credential = this.populateDto(new Credential(), formJson);
createData.account = this.populateDto(new Account(), formJson);
createData.person = this.populateDto(new Person(), formJson);
let roles = new Roles();
roles.rolesList = formJson['rolesList'].map(id => {
let role = new Role();
role.id = id;
return role;
});
createData.roles = roles;
request = new CreateAccountRequest();
request.data = createData;
request.processKey = ProcessKey.CREATE;
this.doRequest(request, formJson['appNumber']);
break;
case ApplicationKind.EDIT_USER_MAIN:
this.doRequest("user/person", jsonObj);
let editPersonData = new EditPersonData();
editPersonData.accountId = formJson['accountId'];
editPersonData.personData = this.populateDto(new Person(), formJson);
request = new EditPersonRequest();
request.data = editPersonData;
request.processKey = ProcessKey.EDIT_PERSON;
this.doRequest(request, formJson['appNumber']);
break;
case ApplicationKind.EDIT_USER_ACCOUNT:
this.doRequest("user/account", jsonObj);
let editAccountData = new EditAccountData();
let account = this.populateDto(new Account(), formJson);
account.id = formJson['accountId'];
editAccountData.account = account;
request = new EditAccountRequest();
request.data = editAccountData;
request.processKey = ProcessKey.EDIT_ACCOUNT;
this.doRequest(request, formJson['appNumber']);
break;
case ApplicationKind.EDIT_USER_ROLES:
this.doRequest("user/roles", jsonObj);
let editRolesAccount = new EditRolesAccount();
let accountId = formJson['accountId'];
let rolesList = formJson['rolesList'];
editRolesAccount.accountId = accountId;
editRolesAccount.rolesList = rolesList.map(id => {
let role = new Role();
role.id = id;
return role;
});
this.rpc.getRemovedRoleIds(accountId, rolesList)
.then(list => {
editRolesAccount.removeRoles = list;
let editRolesData = new EditRolesData();
editRolesData.account = editRolesAccount;
request = new EditRolesRequest();
request.data = editRolesData;
request.processKey = ProcessKey.EDIT_ROLES;
this.doRequest(request, formJson['appNumber']);
});
break;
case ApplicationKind.BLOCK_USER:
this.doRequest("user/deactivation", jsonObj);
let deactivationData = new ChangeActivationData();
deactivationData.accountIdList = [formJson['accountId']];
request = new ChangeActivationRequest();
request.data = deactivationData;
request.processKey = ProcessKey.DEACTIVATE;
this.doRequest(request, formJson['appNumber']);
break;
case ApplicationKind.UNBLOCK_USER:
this.doRequest("user/activation", jsonObj);
let activationData = new ChangeActivationData();
activationData.accountIdList = [formJson['accountId']];
request = new ChangeActivationRequest();
request.data = activationData;
request.processKey = ProcessKey.ACTIVATE;
this.doRequest(request, formJson['appNumber']);
break;
case ApplicationKind.RESET_PASSWORD:
this.doRequest("user/password/reset", jsonObj);
let resetPasswordAccount = new ResetPasswordAccount();
resetPasswordAccount.id = formJson['accountId'];
let resetPasswordData = new ResetPasswordData();
resetPasswordData.account = resetPasswordAccount;
request = new ResetPasswordRequest();
request.data = resetPasswordData;
request.processKey = ProcessKey.RESET_PASSWORD;
this.doRequest(request, formJson['appNumber']);
break;
}
}
};
}
@Visible()
@ -76,11 +167,32 @@ export class UserManagementService extends Behavior {
return jsonObj;
}
private doRequest(url: string, jsonObj: any): void {
this.httpClient.post(url, jsonObj).toPromise()
private populateDto(dto: any, jsonObj: any): any {
Object.keys(dto).forEach(key => {
if (jsonObj[key]) {
dto[key] = jsonObj[key]
}
});
return dto;
}
private doRequest(request: any, appNumber: number): void {
const url = window.location.origin + UserManagementService.PROCESS_START_PATH;
request.userId = this.authService.getUserId();
this.httpClient.post(url, request).toPromise()
.then((response: ProcessResponse) => {
let code = response.code;
if (code === '200') {
this.rpc.saveTraceId(response.traceId, appNumber);
}
else {
this.rpc.saveAgreedStatus(appNumber);
}
})
.catch(reason => {
//TODO change status
console.error("Error while executing request:", reason.toString());
this.rpc.saveAgreedStatus(appNumber);
});
}

View file

@ -0,0 +1,10 @@
export class Account {
public id: string;
public schema: string = "Account";
public "user-domain": string = "";
public position: string = "";
public enabled: boolean = true;
public esiaAccount: boolean = false;
public start: string = "";
public finish: string = "";
}

View file

@ -0,0 +1,12 @@
export class Person {
public id: string = "";
public surname: string = "";
public firstname: string = "";
public middlename: string = "";
public email: string = "";
public birthdate: string = "";
public snils: string = "";
public ipAddresses: string[] = [];
public secondFactorEnabled: boolean = false;
public sex: string = "";
}

View file

@ -0,0 +1,4 @@
export class Role {
public id: string;
public finish: string = "";
}

View file

@ -0,0 +1,3 @@
export class ChangeActivationData {
public accountIdList: string[];
}

View file

@ -0,0 +1,7 @@
import {ChangeActivationData} from "./ChangeActivationData";
export class ChangeActivationRequest {
public processKey: string;
public userId: string;
public data: ChangeActivationData;
}

View file

@ -0,0 +1,11 @@
import {Credential} from "./Credential";
import {Account} from "../Account";
import {Roles} from "./Roles";
import {Person} from "../Person";
export class CreateAccountData {
public credential: Credential;
public account: Account;
public person: Person;
public roles: Roles;
}

View file

@ -0,0 +1,7 @@
import {CreateAccountData} from "./CreateAccountData";
export class CreateAccountRequest {
public processKey: string;
public userId: string;
public data: CreateAccountData;
}

View file

@ -0,0 +1,3 @@
export class Credential {
public userName: string = "";
}

View file

@ -0,0 +1,6 @@
import {Role} from "../Role";
export class Roles {
public rolesList: Role[] = [];
public removeRoles: string[] = [];
}

View file

@ -0,0 +1,5 @@
import {Account} from "../Account";
export class EditAccountData {
public account: Account;
}

View file

@ -0,0 +1,7 @@
import {EditAccountData} from "./EditAccountData";
export class EditAccountRequest {
public processKey: string;
public userId: string;
public data: EditAccountData;
}

View file

@ -0,0 +1,6 @@
import {Person} from "../Person";
export class EditPersonData {
public accountId: string;
public personData: Person;
}

View file

@ -0,0 +1,7 @@
import {EditPersonData} from "./EditPersonData";
export class EditPersonRequest {
public processKey: string;
public userId: string;
public data: EditPersonData;
}

View file

@ -0,0 +1,7 @@
import {Role} from "../Role";
export class EditRolesAccount {
public accountId: string;
public rolesList: Role[] = [];
public removeRoles: string[] = [];
}

View file

@ -0,0 +1,5 @@
import {EditRolesAccount} from "./EditRolesAccount";
export class EditRolesData {
public account: EditRolesAccount;
}

View file

@ -0,0 +1,7 @@
import {EditRolesData} from "./EditRolesData";
export class EditRolesRequest {
public processKey: string;
public userId: string;
public data: EditRolesData;
}

View file

@ -0,0 +1,3 @@
export class ResetPasswordAccount {
public id: string;
}

View file

@ -0,0 +1,5 @@
import {ResetPasswordAccount} from "./ResetPasswordAccount";
export class ResetPasswordData {
public account: ResetPasswordAccount;
}

View file

@ -0,0 +1,7 @@
import {ResetPasswordData} from "./ResetPasswordData";
export class ResetPasswordRequest {
public processKey: string;
public userId: string;
public data: ResetPasswordData;
}

View file

@ -0,0 +1,5 @@
export interface ProcessResponse {
code: string,
msg: string,
traceId: string
}

View file

@ -0,0 +1,9 @@
export enum ProcessKey {
CREATE= "milBaseCreateAccountProcess",
EDIT_PERSON = "milBaseEditAccountPersonIDMProcess",
EDIT_ACCOUNT = "milBaseEditAccountIDMProcess",
EDIT_ROLES = "milBaseEditAccountRolesIDMSubProcess",
DEACTIVATE = "milBaseMassDeActivateAccountIDMProcess",
ACTIVATE = "milBaseMassActivateAccountIDMProcess",
RESET_PASSWORD = "milBaseResetPasswordProcess"
}

View file

@ -1,3 +0,0 @@
export class SocketProvider {
public getSocket(): Promise<any> { return null }
}

View file

@ -1,7 +1,7 @@
import {Injectable} from "@angular/core";
import {Subject} from "rxjs";
import {HttpClient} from "@angular/common/http";
import {SocketProvider} from "../provider/socket.provider";
import {WebsocketService} from "../websocket/websocket.service";
export interface UserSession {
userId: string,
@ -18,28 +18,32 @@ export class AuthorizationService {
public onSessionUpdate: Subject<UserSession> = new Subject<UserSession>();
constructor(protected httpClient: HttpClient, protected socketProvider: SocketProvider) {}
constructor(protected httpClient: HttpClient, protected websocketService: WebsocketService) {}
public getCurrentSession(): Promise<any> {
if (this.session) return new Promise(resolve => resolve(this.session));
//TODO remove after test
this.listenSocket();
return this.httpClient.get('session')
.toPromise()
.then((session: UserSession) => {
this.session = session;
this.onSessionUpdate.next(session);
if (this.hasRole('security_administrator')) {
this.websocketService.listen(({data}) => {
let parsedObj = JSON.parse(data);
if (parsedObj && parsedObj.traceId) {
if (parsedObj.className === 'update' || parsedObj.className === 'processError') {
this.httpClient.put('status', parsedObj).toPromise()
.catch(err => console.log('failed to update application status', err));
}
}
});
}
return session;
})
}
private async listenSocket(): Promise<void> {
const webSocketPlugin = await this.socketProvider.getSocket();
webSocketPlugin.addListener((e: MessageEvent) => {
console.log('socket msg!!!', JSON.parse(e.data));
});
}
isAuthorized(): boolean {
return !!this.session;
}

View file

@ -0,0 +1,25 @@
import {Injectable} from "@angular/core";
@Injectable({providedIn: 'root'})
export class WebsocketService {
public listen(fn){
let property = Object.getOwnPropertyDescriptor(MessageEvent.prototype, "data");
const data = property.get;
// wrapper that replaces getter
function lookAtMessage() {
let socket = this.currentTarget instanceof WebSocket;
if (!socket) {
return data.call(this);
}
let msg = data.call(this);
Object.defineProperty(this, "data", { value: msg }); //anti-loop
fn({ data: msg, socket: this.currentTarget, event: this });
return msg;
}
property.get = lookAtMessage;
Object.defineProperty(MessageEvent.prototype, "data", property);
}
}

View file

@ -28,8 +28,6 @@ import {TokenProvider} from "../app/provider/token.provider";
import {MfeTokenProvider} from "./provider/mfe-token.provider";
import {DEFAULT_HTTP_INTERCEPTOR_PROVIDERS} from "./interceptor/mfe-default-interceptors.prod";
import {MfeOverlayContainer} from "./overlay/mfe-overlay-container.service";
import {MfeSocketProvider} from "./provider/mfe-socket-provider";
import {SocketProvider} from "../app/provider/socket.provider";
let IMPORTS = [
@ -63,7 +61,6 @@ let IMPORTS = [
{provide: RolesGuard, useClass: MfeRolesGuard},
{provide: TokenProvider, useClass: MfeTokenProvider},
{provide: OverlayContainer, useClass: MfeOverlayContainer},
{provide: SocketProvider, useClass: MfeSocketProvider},
DEFAULT_HTTP_INTERCEPTOR_PROVIDERS
],
bootstrap: [

View file

@ -1,8 +0,0 @@
import {fireMfeEventToContainer} from "../../../mfe-app-tools";
import {SocketProvider} from "../../app/provider/socket.provider";
export class MfeSocketProvider extends SocketProvider {
getSocket(): Promise<any> {
return fireMfeEventToContainer('ws-request', {});
}
}

66
pom.xml
View file

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>ru.micord.ervu</groupId>
<artifactId>account-applications</artifactId>
<version>1.9.11</version>
<version>1.9.12-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>backend</module>
@ -44,88 +44,88 @@
<version>3.192.6</version>
<exclusions>
<exclusion>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<groupId>xerces</groupId>
</exclusion>
<exclusion>
<groupId>ru.micord.fias</groupId>
<artifactId>client</artifactId>
<groupId>ru.micord.fias</groupId>
</exclusion>
<exclusion>
<groupId>ru.micord.gar</groupId>
<artifactId>gar-client</artifactId>
<groupId>ru.micord.gar</groupId>
</exclusion>
<exclusion>
<groupId>org.mnode.ical4j</groupId>
<artifactId>ical4j</artifactId>
<groupId>org.mnode.ical4j</groupId>
</exclusion>
<exclusion>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<groupId>org.apache.commons</groupId>
</exclusion>
<exclusion>
<groupId>org.springframework.ldap</groupId>
<artifactId>spring-ldap-core</artifactId>
<groupId>org.springframework.ldap</groupId>
</exclusion>
<exclusion>
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
<artifactId>bpmn-workflow-api</artifactId>
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
</exclusion>
<exclusion>
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
<artifactId>bpmn-workflow-jbpm-api</artifactId>
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
</exclusion>
<exclusion>
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
<artifactId>bpmn-workflow-jbpm</artifactId>
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
</exclusion>
<exclusion>
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
<artifactId>bpmn-deploy</artifactId>
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
</exclusion>
<exclusion>
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
<artifactId>bpmn-beans</artifactId>
</exclusion>
<exclusion>
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
</exclusion>
<exclusion>
<artifactId>bpmn-variable-condition-adapter</artifactId>
<groupId>ru.cg.webbpm.modules.bpmn</groupId>
</exclusion>
<exclusion>
<groupId>ru.cg.webbpm.modules.security</groupId>
<artifactId>security-esia</artifactId>
<groupId>ru.cg.webbpm.modules.security</groupId>
</exclusion>
<exclusion>
<groupId>ru.cg.webbpm.modules.security</groupId>
<artifactId>security-api</artifactId>
<groupId>ru.cg.webbpm.modules.security</groupId>
</exclusion>
<exclusion>
<groupId>ru.cg.webbpm.modules.security</groupId>
<artifactId>security-beans</artifactId>
<groupId>ru.cg.webbpm.modules.security</groupId>
</exclusion>
<exclusion>
<groupId>ru.cg.webbpm.modules.security</groupId>
<artifactId>security-db-synchronization-api</artifactId>
<groupId>ru.cg.webbpm.modules.security</groupId>
</exclusion>
<exclusion>
<groupId>ru.cg.webbpm.modules.security</groupId>
<artifactId>security-db-synchronization-ldap-impl</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.security.kerberos</groupId>
<artifactId>spring-security-kerberos-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.security.kerberos</groupId>
<artifactId>spring-security-kerberos-web</artifactId>
</exclusion>
<exclusion>
<groupId>ru.cg.webbpm.modules.security</groupId>
<artifactId>security-adapter</artifactId>
</exclusion>
<exclusion>
<groupId>ru.cg.webbpm.modules.integration</groupId>
<artifactId>spring-security-kerberos-core</artifactId>
<groupId>org.springframework.security.kerberos</groupId>
</exclusion>
<exclusion>
<artifactId>spring-security-kerberos-web</artifactId>
<groupId>org.springframework.security.kerberos</groupId>
</exclusion>
<exclusion>
<artifactId>security-adapter</artifactId>
<groupId>ru.cg.webbpm.modules.security</groupId>
</exclusion>
<exclusion>
<artifactId>telegram</artifactId>
<groupId>ru.cg.webbpm.modules.integration</groupId>
</exclusion>
</exclusions>
</dependency>
@ -329,8 +329,8 @@
<version>${spring-kafka.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<groupId>org.apache.kafka</groupId>
</exclusion>
</exclusions>
</dependency>
@ -340,8 +340,8 @@
<version>3.9.0</version>
<exclusions>
<exclusion>
<groupId>org.xerial.snappy</groupId>
<artifactId>snappy-java</artifactId>
<groupId>org.xerial.snappy</groupId>
</exclusion>
</exclusions>
</dependency>

View file

@ -4,7 +4,7 @@
<parent>
<groupId>ru.micord.ervu</groupId>
<artifactId>account-applications</artifactId>
<version>1.9.11</version>
<version>1.9.12-SNAPSHOT</version>
</parent>
<groupId>ru.micord.ervu.account_applications</groupId>

View file

@ -3057,7 +3057,7 @@
<entry>
<key>name</key>
<value>
<simple>"username"</simple>
<simple>"userName"</simple>
</value>
</entry>
</properties>
@ -3466,7 +3466,7 @@
<entry>
<key>name</key>
<value>
<simple>"userDomain"</simple>
<simple>"user-domain"</simple>
</value>
</entry>
</properties>
@ -3682,7 +3682,7 @@
<entry>
<key>name</key>
<value>
<simple>"roles"</simple>
<simple>"rolesList"</simple>
</value>
</entry>
</properties>
@ -8722,6 +8722,14 @@
</entry>
</properties>
</scripts>
<scripts id="ae7e90d1-0db9-4cc1-9202-e2dc273ae66d">
<classRef type="JAVA">
<className>UserApplicationListRpcService</className>
<packageName>ru.micord.ervu.account_applications.component.rpc</packageName>
</classRef>
<enabled>true</enabled>
<expanded>true</expanded>
</scripts>
</children>
<children id="7ed531bc-a941-43a9-8cf7-31d32dd6e0cd">
<prototypeId>c8dfe691-a84a-48da-b79e-6298d90db71d</prototypeId>

View file

@ -2688,7 +2688,7 @@
<entry>
<key>name</key>
<value>
<simple>"username"</simple>
<simple>"userName"</simple>
</value>
</entry>
</properties>
@ -2891,7 +2891,7 @@
<entry>
<key>name</key>
<value>
<simple>"userDomain"</simple>
<simple>"user-domain"</simple>
</value>
</entry>
</properties>
@ -3112,7 +3112,7 @@
<entry>
<key>name</key>
<value>
<simple>"roles"</simple>
<simple>"rolesList"</simple>
</value>
</entry>
</properties>
@ -3391,7 +3391,6 @@
<componentRootId>2ee6f91b-c4a2-461d-8428-c3a6a13c9244</componentRootId>
<name>hidden</name>
<container>true</container>
<expanded>false</expanded>
<childrenReordered>false</childrenReordered>
<scripts id="bf098f19-480e-44e4-9084-aa42955c4d0f">
<properties>
@ -7780,6 +7779,14 @@
</entry>
</properties>
</scripts>
<scripts id="55ae453e-60e1-4988-83b0-36b73289e533">
<classRef type="JAVA">
<className>UserApplicationListRpcService</className>
<packageName>ru.micord.ervu.account_applications.component.rpc</packageName>
</classRef>
<enabled>true</enabled>
<expanded>true</expanded>
</scripts>
</children>
<children id="7ed531bc-a941-43a9-8cf7-31d32dd6e0cd">
<prototypeId>c8dfe691-a84a-48da-b79e-6298d90db71d</prototypeId>

View file

@ -2465,6 +2465,7 @@
<componentRootId>9bfac70b-fd5e-4cdc-84fa-50190bde76d1</componentRootId>
<name>Связанная таблица</name>
<container>false</container>
<expanded>false</expanded>
<childrenReordered>false</childrenReordered>
<scripts id="e6553d24-6c92-461b-b0ab-f7a400836302">
<properties>

View file

@ -8866,6 +8866,13 @@
<container>false</container>
<removed>true</removed>
</children>
<children id="5b8c5ac4-549d-411f-80ff-d29293638e5f">
<prototypeId>887d2044-9e34-46a5-852c-e9ce07b42f30</prototypeId>
<componentRootId>5b8c5ac4-549d-411f-80ff-d29293638e5f</componentRootId>
<name>Пол</name>
<container>false</container>
<removed>true</removed>
</children>
<children id="39040b94-4780-4067-864e-64ad3d22a2a3">
<prototypeId>4d981f15-5535-45f7-882b-3647b251ad05</prototypeId>
<componentRootId>39040b94-4780-4067-864e-64ad3d22a2a3</componentRootId>

View file

@ -8867,6 +8867,13 @@
<container>false</container>
<removed>true</removed>
</children>
<children id="5b8c5ac4-549d-411f-80ff-d29293638e5f">
<prototypeId>887d2044-9e34-46a5-852c-e9ce07b42f30</prototypeId>
<componentRootId>5b8c5ac4-549d-411f-80ff-d29293638e5f</componentRootId>
<name>Пол</name>
<container>false</container>
<removed>true</removed>
</children>
<children id="39040b94-4780-4067-864e-64ad3d22a2a3">
<prototypeId>4d981f15-5535-45f7-882b-3647b251ad05</prototypeId>
<componentRootId>39040b94-4780-4067-864e-64ad3d22a2a3</componentRootId>