fix: app_key backfill on re-registration + notify after tx commit
- LicenseDeviceService: update app_key on re-registration if blank, fixing devices that registered before the app_key column was added - FeatureServiceManager: send activation IM notification in afterCommit() hook so the frontend refresh sees the committed DB state Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
父节点
8443af4818
当前提交
57ad8f7f25
@ -56,6 +56,9 @@ public class DeviceService {
|
|||||||
// Re-issue token
|
// Re-issue token
|
||||||
String token = licenseAuthService.generateToken(appKey, deviceId, existing.getId());
|
String token = licenseAuthService.generateToken(appKey, deviceId, existing.getId());
|
||||||
String tokenHash = hashToken(token);
|
String tokenHash = hashToken(token);
|
||||||
|
if (existing.getAppKey() == null || existing.getAppKey().isBlank()) {
|
||||||
|
existing.setAppKey(appKey);
|
||||||
|
}
|
||||||
existing.setDeviceName(firstNonBlank(deviceName, existing.getDeviceName()));
|
existing.setDeviceName(firstNonBlank(deviceName, existing.getDeviceName()));
|
||||||
existing.setDeviceModel(firstNonBlank(deviceModel, existing.getDeviceModel()));
|
existing.setDeviceModel(firstNonBlank(deviceModel, existing.getDeviceModel()));
|
||||||
existing.setDeviceVendor(firstNonBlank(deviceVendor, existing.getDeviceVendor()));
|
existing.setDeviceVendor(firstNonBlank(deviceVendor, existing.getDeviceVendor()));
|
||||||
|
|||||||
@ -11,8 +11,12 @@ import com.xuqm.tenant.entity.ServiceActivationRequestEntity.Status;
|
|||||||
import com.xuqm.tenant.repository.AppRepository;
|
import com.xuqm.tenant.repository.AppRepository;
|
||||||
import com.xuqm.tenant.repository.FeatureServiceRepository;
|
import com.xuqm.tenant.repository.FeatureServiceRepository;
|
||||||
import com.xuqm.tenant.repository.ServiceActivationRequestRepository;
|
import com.xuqm.tenant.repository.ServiceActivationRequestRepository;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.transaction.support.TransactionSynchronization;
|
||||||
|
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@ -22,22 +26,27 @@ import java.util.UUID;
|
|||||||
@Service
|
@Service
|
||||||
public class FeatureServiceManager {
|
public class FeatureServiceManager {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(FeatureServiceManager.class);
|
||||||
|
|
||||||
private final FeatureServiceRepository repository;
|
private final FeatureServiceRepository repository;
|
||||||
private final ServiceActivationRequestRepository requestRepository;
|
private final ServiceActivationRequestRepository requestRepository;
|
||||||
private final AppRepository appRepository;
|
private final AppRepository appRepository;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
private final LicenseServiceClient licenseServiceClient;
|
private final LicenseServiceClient licenseServiceClient;
|
||||||
|
private final ImPlatformEventService imPlatformEventService;
|
||||||
|
|
||||||
public FeatureServiceManager(FeatureServiceRepository repository,
|
public FeatureServiceManager(FeatureServiceRepository repository,
|
||||||
ServiceActivationRequestRepository requestRepository,
|
ServiceActivationRequestRepository requestRepository,
|
||||||
AppRepository appRepository,
|
AppRepository appRepository,
|
||||||
ObjectMapper objectMapper,
|
ObjectMapper objectMapper,
|
||||||
LicenseServiceClient licenseServiceClient) {
|
LicenseServiceClient licenseServiceClient,
|
||||||
|
ImPlatformEventService imPlatformEventService) {
|
||||||
this.repository = repository;
|
this.repository = repository;
|
||||||
this.requestRepository = requestRepository;
|
this.requestRepository = requestRepository;
|
||||||
this.appRepository = appRepository;
|
this.appRepository = appRepository;
|
||||||
this.objectMapper = objectMapper;
|
this.objectMapper = objectMapper;
|
||||||
this.licenseServiceClient = licenseServiceClient;
|
this.licenseServiceClient = licenseServiceClient;
|
||||||
|
this.imPlatformEventService = imPlatformEventService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<FeatureServiceEntity> listByApp(String appKey) {
|
public List<FeatureServiceEntity> listByApp(String appKey) {
|
||||||
@ -173,6 +182,7 @@ public class FeatureServiceManager {
|
|||||||
appRepository.findByAppKey(normalizedAppId).ifPresent(app ->
|
appRepository.findByAppKey(normalizedAppId).ifPresent(app ->
|
||||||
licenseServiceClient.syncAppLicense(app.getAppKey(), app.getName(), 1, expiresAt));
|
licenseServiceClient.syncAppLicense(app.getAppKey(), app.getName(), 1, expiresAt));
|
||||||
}
|
}
|
||||||
|
sendActivationImNotification(req.getAppKey(), req.getServiceType().name(), "APPROVED", reviewNote);
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,6 +199,7 @@ public class FeatureServiceManager {
|
|||||||
});
|
});
|
||||||
entity.setEnabled(true);
|
entity.setEnabled(true);
|
||||||
repository.save(entity);
|
repository.save(entity);
|
||||||
|
sendActivationImNotification(req.getAppKey(), req.getServiceType().name(), "APPROVED", reviewNote);
|
||||||
return req;
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +216,9 @@ public class FeatureServiceManager {
|
|||||||
req.setStatus(Status.REJECTED);
|
req.setStatus(Status.REJECTED);
|
||||||
req.setReviewNote(reviewNote);
|
req.setReviewNote(reviewNote);
|
||||||
req.setReviewedAt(LocalDateTime.now());
|
req.setReviewedAt(LocalDateTime.now());
|
||||||
return requestRepository.save(req);
|
requestRepository.save(req);
|
||||||
|
sendActivationImNotification(req.getAppKey(), req.getServiceType().name(), "REJECTED", reviewNote);
|
||||||
|
return req;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ServiceActivationRequestEntity> listRequestsByApp(String appKey) {
|
public List<ServiceActivationRequestEntity> listRequestsByApp(String appKey) {
|
||||||
@ -619,4 +632,28 @@ public class FeatureServiceManager {
|
|||||||
node.put(field, value.trim());
|
node.put(field, value.trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendActivationImNotification(String appKey, String serviceType, String status, String reviewNote) {
|
||||||
|
// Send after transaction commits so the frontend refresh sees the updated DB state.
|
||||||
|
if (TransactionSynchronizationManager.isActualTransactionActive()) {
|
||||||
|
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
|
||||||
|
@Override
|
||||||
|
public void afterCommit() {
|
||||||
|
doSendActivationImNotification(appKey, serviceType, status, reviewNote);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
doSendActivationImNotification(appKey, serviceType, status, reviewNote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doSendActivationImNotification(String appKey, String serviceType, String status, String reviewNote) {
|
||||||
|
try {
|
||||||
|
imPlatformEventService.notifyServiceActivationChange(
|
||||||
|
new ImPlatformEventService.ServiceActivationEventRequest(appKey, serviceType, status, reviewNote));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Failed to send service activation IM notification appKey={} serviceType={} status={}: {}",
|
||||||
|
appKey, serviceType, status, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
正在加载...
在新工单中引用
屏蔽一个用户