Aggiornate componenti per gestione token.
All checks were successful
IntegryManagementSystem_Multi/pipeline/head This commit looks good

This commit is contained in:
2025-02-12 16:27:53 +01:00
parent ddd5cbaf77
commit 7265f32b3d
9 changed files with 139 additions and 110 deletions

View File

@@ -2,14 +2,15 @@ package it.integry.ems.license;
import com.fasterxml.jackson.core.type.TypeReference;
import it.integry.annotations.PostContextAutowired;
import it.integry.annotations.PostContextConstruct;
import it.integry.ems.json.ResponseJSONObjectMapper;
import it.integry.ems.looper.service.LooperService;
import it.integry.ems.response.EsitoType;
import it.integry.ems.response.ServiceRestResponse;
import it.integry.ems.service.HttpRestWrapper;
import it.integry.ems.settings.Model.AvailableConnectionsModel;
import it.integry.ems.settings.Model.SettingsModel;
import it.integry.ems.sync.MultiDBTransaction.AdvancedDataSource;
import it.integry.ems.sync.MultiDBTransaction.MultiDBTransactionManager;
import it.integry.ems.utility.UtilityDebug;
import it.integry.ems_model.config.EmsRestConstants;
@@ -19,10 +20,12 @@ import org.apache.http.entity.ContentType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
@Component
public class LicenseComponent {
@@ -32,27 +35,46 @@ public class LicenseComponent {
@Autowired
private SettingsModel settingsModel;
@Autowired
private LooperService looperService;
@Autowired
private ResponseJSONObjectMapper jsonObjectMapper;
@PostContextAutowired
private MultiDBTransactionManager multiDBTransactionManager;
private final HashMap<String, LicenseStatusDTO> cachedLicenseStatus = new HashMap<>();
boolean canStart = false;
@PostContextConstruct(priority = 10)
public void init() {
logger.info("Initializing license checker service");
if(UtilityDebug.isDebugExecution() || UtilityDebug.isIntegryServer())
return;
logger.debug("isDebug: " + (UtilityDebug.isDebugExecution() ? "yes" : "no"));
logger.debug("isIntegryServer: " + (UtilityDebug.isIntegryServer() ? "yes" : "no"));
if (!UtilityDebug.isDebugExecution() && !UtilityDebug.isIntegryServer())
looperService.add(this::syncLicense, 60 * 60 * 1000, LicenseComponent.class.getName());
// else
// looperService.add(this::syncLicense, 15 * 1000, LicenseComponent.class.getName());
canStart = true;
this.syncLicense(multiDBTransactionManager);
}
private void syncLicense() {
@Scheduled(fixedDelay = 1, timeUnit = TimeUnit.HOURS)
private void syncLicenseScheduled() {
if (!canStart)
return;
List<AvailableConnectionsModel> availableConnectionsModels = settingsModel.getAvailableConnections(true);
try (MultiDBTransactionManager multiDBTransactionManager = new MultiDBTransactionManager()) {
for (AvailableConnectionsModel model : availableConnectionsModels) {
multiDBTransactionManager.addConnection(model);
}
syncLicense(multiDBTransactionManager);
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
}
private void syncLicense(MultiDBTransactionManager multiDBTransactionManager) {
try {
String url = "https://services.studioml.it/ems-api" + EmsRestConstants.PATH_GET_LICENSE_STATUS;
@@ -60,15 +82,13 @@ public class LicenseComponent {
final HashMap<String, String> listAziende = new HashMap<>();
for (AvailableConnectionsModel model : settingsModel.getAvailableConnections(true)) {
try (MultiDBTransactionManager multiDBTransactionManager = new MultiDBTransactionManager(model)) {
for (AdvancedDataSource model : multiDBTransactionManager.getActiveConnections()) {
String sql = "SELECT part_iva FROM azienda WHERE part_iva is not null";
String partIva = UtilityDB.executeSimpleQueryOnlyFirstRowFirstColumn(multiDBTransactionManager.getPrimaryConnection(), sql);
String partIva = UtilityDB.executeSimpleQueryOnlyFirstRowFirstColumn(model.getConnection(), sql);
if (!UtilityString.isNullOrEmpty(partIva))
listAziende.put(model.getProfileName(), partIva);
}
}
String jsonBody = jsonObjectMapper.writeValueAsString(listAziende.values());

View File

@@ -61,7 +61,7 @@ public class ConfigActivityRules extends QueryRules {
}
}
if (blocca)
throw new Exception("Impossibile modificare\\inserire un'attività in un periodo fatturato.");
throw new Exception("Impossibile modificare/inserire un'attività in un periodo fatturato.");
return false;
}

View File

@@ -11,6 +11,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
@@ -55,9 +56,10 @@ public class UserController {
}
@PreAuthorize("isAnonymous()")
@RequestMapping(value = "availableProfiles", method = RequestMethod.GET)
public ServiceRestResponse changePassword(@RequestParam String username) throws Exception {
return ServiceRestResponse.createPositiveResponse(userService.retrieveAvailableProfiles(username));
public ServiceRestResponse availableProfiles(@RequestParam String username, @RequestParam String password) {
return ServiceRestResponse.createPositiveResponse(userService.retrieveAvailableProfiles(username, password));
}
}

View File

@@ -87,7 +87,7 @@ public class UserCacheService {
users.add(user);
}
public List<String> retrieveProfilesOfUserByUsername(String username) {
public List<String> retrieveProfilesOfUser(String username, String password) {
ArrayList<String> profiles = new ArrayList<>();
for (Map.Entry<String, List<UserDTO>> users : cachedUsers.entrySet()) {

View File

@@ -104,16 +104,16 @@ public class UserService {
return UtilityDB.executeSimpleQueryOnlyFirstRowFirstColumn(multiDBTransactionManager.getPrimaryConnection(), sql);
}
public List<String> retrieveAvailableProfiles(String username) {
public List<String> retrieveAvailableProfiles(String username, String password) {
List<String> profiles;
profiles = userCacheService.retrieveProfilesOfUserByUsername(username);
profiles = userCacheService.retrieveProfilesOfUser(username, password);
if (profiles.isEmpty()) {
// SELEZIONE CICLICA IN TUTTI I DB SPECIFICATI
userCacheService.invalidateCache();
profiles = userCacheService.retrieveProfilesOfUserByUsername(username);
profiles = userCacheService.retrieveProfilesOfUser(username, password);
}
return profiles;

View File

@@ -1,10 +1,9 @@
package it.integry.security.cache;
import it.integry.annotations.PostContextAutowired;
import it.integry.annotations.PostContextConstruct;
import it.integry.ems.looper.service.LooperService;
import it.integry.ems.settings.Model.AvailableConnectionsModel;
import it.integry.ems.settings.Model.SettingsModel;
import it.integry.ems.settings.SettingsController;
import it.integry.ems.sync.MultiDBTransaction.AdvancedDataSource;
import it.integry.ems.sync.MultiDBTransaction.MultiDBTransactionManager;
import it.integry.ems_model.entity.StbAuthToken;
@@ -15,7 +14,6 @@ import it.integry.ems_model.utility.UtilityLocalDate;
import it.integry.security.event.InvalidateTokenCacheEvent;
import it.integry.security.event.TokenCreateEvent;
import it.integry.security.event.TokenExpireEvent;
import it.integry.security.jwt.AccessTokenProvider;
import net.jodah.expiringmap.ExpiringMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -23,6 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.Instant;
@@ -34,40 +33,44 @@ import java.util.concurrent.TimeUnit;
public class JwtTokenCacheComponent implements ApplicationListener {
Logger logger = LogManager.getLogger();
@Autowired
private AccessTokenProvider accessTokenProvider;
@Autowired
private SecretKeyCacheComponent secretKeyCacheComponent;
@Autowired
private SettingsModel settingsModel;
@Autowired
private ApplicationEventPublisher applicationEventPublisher;
@Autowired
private LooperService looperService;
@Autowired
private SettingsController settingsController;
@PostContextAutowired
private MultiDBTransactionManager multiDBTransactionManager;
private final HashMap<String, ExpiringMap<String, StbAuthToken>> tokenEventMap = new HashMap<>();
boolean canStart = false;
@PostContextConstruct(priority = 20)
public void init() throws Exception {
updateCache(multiDBTransactionManager);
canStart = true;
}
@Scheduled(fixedDelay = 5, timeUnit = TimeUnit.MINUTES)
private void updateCacheScheduled() {
if (!settingsModel.isEnableTokenCaching()) return;
List<AvailableConnectionsModel> availableConnectionsModels = settingsModel.getAvailableConnections(true);
looperService.add(() -> {
try {
refreshCache();
} catch (Exception e) {
//throw new RuntimeException(e);
logger.error("Caching JWTSessions", e);
}
}, 5 * 60 * 1000, JwtTokenCacheComponent.class.getName());
try (MultiDBTransactionManager multiDBTransactionManager = new MultiDBTransactionManager()) {
for (AvailableConnectionsModel model : availableConnectionsModels) {
multiDBTransactionManager.addConnection(model);
}
updateCache(multiDBTransactionManager);
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
}
}
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
@@ -90,7 +93,7 @@ public class JwtTokenCacheComponent implements ApplicationListener {
}
} else if (applicationEvent instanceof InvalidateTokenCacheEvent) {
try {
refreshCache();
updateCacheScheduled();
} catch (Exception e) {
logger.error("Errore durante il refresh della cache dei token", e);
}
@@ -98,7 +101,7 @@ public class JwtTokenCacheComponent implements ApplicationListener {
}
private void refreshCache() throws Exception {
private void updateCache(MultiDBTransactionManager multiDBTransactionManager) throws Exception {
if(!settingsModel.isEnableTokenCaching()) return;
tokenEventMap.clear();
@@ -106,20 +109,6 @@ public class JwtTokenCacheComponent implements ApplicationListener {
String sql = "SELECT * " +
"FROM " + StbAuthToken.ENTITY;
MultiDBTransactionManager multiDBTransactionManager = new MultiDBTransactionManager();
for (AvailableConnectionsModel availableConnectionsModel : settingsModel.getAvailableConnections()) {
if (!availableConnectionsModel.getInternalDb())
continue;
try {
multiDBTransactionManager.addConnection(
availableConnectionsModel.getProfileName());
} catch (Exception ex) {
logger.error("Database connection error", ex);
}
}
boolean shouldCloseConnections = true;
for (AdvancedDataSource advancedDataSource : multiDBTransactionManager.getActiveConnections()) {

View File

@@ -2,65 +2,79 @@ package it.integry.security.cache;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import it.integry.annotations.PostContextConstruct;
import it.integry.ems.looper.service.LooperService;
import it.integry.ems.settings.Model.AvailableConnectionsModel;
import it.integry.ems.settings.Model.SettingsModel;
import it.integry.ems.sync.MultiDBTransaction.MultiDBTransactionManager;
import it.integry.ems.utility.UtilityDebug;
import it.integry.ems_model.entity.Azienda;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.crypto.SecretKey;
import java.util.HashMap;
import java.util.List;
@Component
public class SecretKeyCacheComponent {
private final Logger logger = LogManager.getLogger();
@Autowired
private LooperService looperService;
@Autowired
private SettingsModel settingsModel;
private final HashMap<String, SecretKey> internalCache = new HashMap<>();
private final String SIGNING_KEY = "gICy3bjD56i/YFnBZZKe5ibiz3Snsp08nybGGziCV4ZcvyXBbyqWUnJ2wTrRXhOuf/xdljPXX0yBaqdAgvKthQ==";
// private final Logger logger = LogManager.getLogger();
@PostContextConstruct(priority = 10)
public void init() throws Exception {
// @Autowired
// private SettingsModel settingsModel;
if (!UtilityDebug.isDebugExecution())
looperService.add(this::updateInternalCache, 5 * 60 * 1000, SecretKeyCacheComponent.class.getName()); //Ogni 5 minuti
else this.updateInternalCache();
// @PostContextAutowired
// private MultiDBTransactionManager multiDBTransactionManager;
}
private void updateInternalCache() {
List<AvailableConnectionsModel> availableConnectionsModels = settingsModel.getAvailableConnections(true);
for (AvailableConnectionsModel model : availableConnectionsModels) {
try (MultiDBTransactionManager multiDBTransactionManager = new MultiDBTransactionManager(model)) {
// private final HashMap<String, SecretKey> internalCache = new HashMap<>();
Azienda azienda = Azienda.getDefaultAzienda(multiDBTransactionManager.getPrimaryConnection());
internalCache.put(model.getDbName().toLowerCase(), Keys.hmacShaKeyFor(Decoders.BASE64.decode(azienda.getJwtSecretKey())));
// boolean canStart = false;
} catch (Exception ex) {
logger.info(String.format("Cannot find %s database", model.getDbName()), ex);
}
}
}
// @PostContextConstruct(priority = 10)
// public void init() throws SQLException {
// canStart = true;
// this.updateCache(multiDBTransactionManager);
// }
// @Scheduled(fixedDelay = 5, timeUnit = TimeUnit.MINUTES)
// private void updateCacheScheduled() {
// if (!canStart || UtilityDebug.isDebugExecution())
// return;
//
// List<AvailableConnectionsModel> availableConnectionsModels = settingsModel.getAvailableConnections(true);
//
// try (MultiDBTransactionManager multiDBTransactionManager = new MultiDBTransactionManager()) {
//
// for (AvailableConnectionsModel model : availableConnectionsModels) {
// multiDBTransactionManager.addConnection(model);
// }
//
// updateCache(multiDBTransactionManager);
//
// } catch (Exception ex) {
// logger.error(ex.getMessage(), ex);
// }
//
// }
//
//
// private void updateCache(MultiDBTransactionManager multiDBTransactionManager) throws SQLException {
//
// for (AdvancedDataSource dataSource : multiDBTransactionManager.getActiveConnections()) {
// try {
// Azienda azienda = Azienda.getDefaultAzienda(dataSource.getConnection());
// internalCache.put(dataSource.getDataSource().getDbName().toLowerCase(), Keys.hmacShaKeyFor(Decoders.BASE64.decode(azienda.getJwtSecretKey())));
// } catch (Exception ex) {
// logger.error(String.format("Cannot find %s database", dataSource.getDataSource().getDbName()), ex);
// }
// }
// }
// public SecretKey getKey(String dbName) {
// if (internalCache.containsKey(dbName.toLowerCase()))
// return internalCache.get(dbName.toLowerCase());
//
// return null;
// }
public SecretKey getKey(String dbName) {
if(internalCache.containsKey(dbName.toLowerCase()))
return internalCache.get(dbName.toLowerCase());
return null;
return Keys.hmacShaKeyFor(Decoders.BASE64.decode(SIGNING_KEY));
}
}

View File

@@ -60,6 +60,10 @@ public class AuthService {
@Autowired
private RequestDataDTO requestDataDTO;
public JwtResponse login(String profileDb, LoginRequestDTO loginRequestDTO) throws Exception {
if (UtilityString.isNullOrEmpty(loginRequestDTO.getUsername())) {
throw new Exception("Username mancante.");
@@ -130,7 +134,7 @@ public class AuthService {
.setExpireIn(ChronoUnit.SECONDS.between(UtilityLocalDate.getNowTime(), stbAuthToken.getExpiryDate()));
}
public void logout(String profileDb, LogoutRequestDTO logoutRequestDTO) throws Exception {
public void logout(String profileDb, LogoutRequestDTO logoutRequestDTO) {
TokenExpireEvent tokenExpireEvent = new TokenExpireEvent(profileDb, logoutRequestDTO.getToken());
applicationEventPublisher.publishEvent(tokenExpireEvent);

View File

@@ -316,7 +316,7 @@ public class SystemService {
List<String> profiles = null;
profiles = userCacheService.retrieveProfilesOfUserByUsername(username);
profiles = userCacheService.retrieveProfilesOfUser(username, password);
if (profiles.isEmpty()) {
// SELEZIONE CICLICA IN TUTTI I DB SPECIFICATI