Introduction of WindowsUpdate endpoint, allows for /api/patch-compliance to accept POSTS
This commit is contained in:
6895
scripts/cve-sync.log
6895
scripts/cve-sync.log
File diff suppressed because it is too large
Load Diff
@@ -2,12 +2,15 @@ package com.psg.dlsysinfo.dl_sysinfo_server.controller;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.dto.InstalledAppDTO;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.dto.PatchComplianceDTO;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.dto.SystemInfoDTO;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.entity.Client;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.entity.Devices;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.entity.InstalledSoftware;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.entity.WindowsUpdate;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.repository.ClientRepository;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.repository.InstalledSoftwareRepository;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.repository.WindowsUpdateRepository;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.security.EncryptionService;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.security.JwtUtil;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.security.TokenResolver;
|
||||
@@ -42,6 +45,7 @@ public class SystemInfoController {
|
||||
|
||||
@Autowired private ClientRepository clientRepository;
|
||||
@Autowired private InstalledSoftwareRepository installedSoftwareRepository;
|
||||
@Autowired private WindowsUpdateRepository windowsUpdateRepository;
|
||||
@Autowired private DeviceService deviceService;
|
||||
@Autowired private ObjectMapper objectMapper;
|
||||
|
||||
@@ -67,18 +71,25 @@ public class SystemInfoController {
|
||||
|
||||
String decryptedData = encryptionService.decryptData(encryptedData);
|
||||
System.out.println("🔓 Decrypted payload size: " + decryptedData.length());
|
||||
System.out.println("🔓 Decrypted payload content: " + decryptedData);
|
||||
|
||||
SystemInfoDTO dto;
|
||||
|
||||
try {
|
||||
dto = objectMapper.readValue(decryptedData, SystemInfoDTO.class);
|
||||
System.out.println("✅ Successfully deserialized SystemInfoDTO");
|
||||
} catch (Exception ex) {
|
||||
System.out.println("❌ Failed to deserialize SystemInfoDTO: " + ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
return errorResponse(response, "Failed to parse payload.", 400);
|
||||
}
|
||||
|
||||
System.out.println("🔍 DTO clientIdentifier: " + dto.getClientIdentifier());
|
||||
System.out.println("🔍 DTO hostname: " + dto.getHostname());
|
||||
System.out.println("🔍 DTO drives: " + (dto.getDrives() != null ? dto.getDrives().size() : "null"));
|
||||
|
||||
if (dto.getClientIdentifier() == null || dto.getHostname() == null) {
|
||||
System.out.println("❌ Missing required fields");
|
||||
return errorResponse(response, "Missing clientIdentifier or hostname in payload.", 400);
|
||||
}
|
||||
|
||||
@@ -132,6 +143,69 @@ public class SystemInfoController {
|
||||
}
|
||||
}
|
||||
|
||||
@PreAuthorize("isAuthenticated()")
|
||||
@PostMapping("/patch-compliance")
|
||||
public ResponseEntity<Map<String, String>> receivePatchCompliance(
|
||||
@AuthenticationPrincipal Object currentUser,
|
||||
HttpServletRequest request,
|
||||
@RequestBody List<PatchComplianceDTO> patchData) {
|
||||
|
||||
Map<String, String> response = new HashMap<>();
|
||||
|
||||
try {
|
||||
String token = tokenResolver.resolveToken(request);
|
||||
if (!jwtUtil.validateToken(token)) {
|
||||
return errorResponse(response, "Invalid or expired token.", 403);
|
||||
}
|
||||
|
||||
if (patchData == null || patchData.isEmpty()) {
|
||||
return errorResponse(response, "No patch data found in request body.", 400);
|
||||
}
|
||||
|
||||
String clientIdentifier = jwtUtil.extractClientIdentifier(token);
|
||||
System.out.println("🔍 Receiving patch compliance data for client: " + clientIdentifier);
|
||||
|
||||
Client client = clientRepository.findByClientIdentifier(clientIdentifier)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Client not registered"));
|
||||
|
||||
// Get the device associated with this client
|
||||
// Since we need to know which device this is for, we'll need the hostname
|
||||
// For now, we'll assume the most recently checked-in device for this client
|
||||
Devices device = deviceService.getMostRecentDeviceForClient(client);
|
||||
if (device == null) {
|
||||
return errorResponse(response, "No device found for this client.", 404);
|
||||
}
|
||||
|
||||
System.out.println("🔍 Processing " + patchData.size() + " Windows updates for device: " + device.getDeviceId());
|
||||
|
||||
// Delete existing updates for this device to replace with fresh data
|
||||
windowsUpdateRepository.deleteByDevice(device);
|
||||
|
||||
// Save new updates
|
||||
for (PatchComplianceDTO dto : patchData) {
|
||||
if (dto.getUpdateId() == null) continue;
|
||||
|
||||
WindowsUpdate update = new WindowsUpdate();
|
||||
update.setDevice(device);
|
||||
update.setDate(dto.getDate());
|
||||
update.setTitle(dto.getTitle());
|
||||
update.setUpdateId(dto.getUpdateId());
|
||||
|
||||
windowsUpdateRepository.save(update);
|
||||
}
|
||||
|
||||
response.put("status", "success");
|
||||
response.put("message", "Patch compliance data received and stored successfully.");
|
||||
response.put("updatesProcessed", String.valueOf(patchData.size()));
|
||||
return ResponseEntity.ok(response);
|
||||
|
||||
} catch (Exception e) {
|
||||
System.out.println("❌ Unexpected exception in patch-compliance: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
return errorResponse(response, "Server error occurred: " + e.getMessage(), 500);
|
||||
}
|
||||
}
|
||||
|
||||
private ResponseEntity<Map<String, String>> errorResponse(Map<String, String> response, String message, int statusCode) {
|
||||
response.put("status", "error");
|
||||
response.put("message", message);
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.psg.dlsysinfo.dl_sysinfo_server.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class PatchComplianceDTO {
|
||||
private String date;
|
||||
private String title;
|
||||
private String updateId;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.psg.dlsysinfo.dl_sysinfo_server.entity;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Entity
|
||||
@Table(name = "windows_updates")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class WindowsUpdate {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "device_id", nullable = false)
|
||||
private Devices device;
|
||||
|
||||
@Column(name = "update_date")
|
||||
private String date;
|
||||
|
||||
@Column(name = "title", length = 1000)
|
||||
private String title;
|
||||
|
||||
@Column(name = "update_id")
|
||||
private String updateId;
|
||||
|
||||
@Column(name = "recorded_at", nullable = false)
|
||||
private LocalDateTime recordedAt = LocalDateTime.now();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.psg.dlsysinfo.dl_sysinfo_server.repository;
|
||||
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.entity.Devices;
|
||||
import com.psg.dlsysinfo.dl_sysinfo_server.entity.WindowsUpdate;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface WindowsUpdateRepository extends JpaRepository<WindowsUpdate, Long> {
|
||||
|
||||
List<WindowsUpdate> findByDevice(Devices device);
|
||||
|
||||
Optional<WindowsUpdate> findByDeviceAndUpdateId(Devices device, String updateId);
|
||||
|
||||
void deleteByDevice(Devices device);
|
||||
}
|
||||
@@ -293,6 +293,16 @@ public class DeviceService {
|
||||
System.out.println("🔄 Reassigned device " + deviceId + " to client " + newClientId);
|
||||
}
|
||||
|
||||
public Devices getMostRecentDeviceForClient(Client client) {
|
||||
List<Devices> devices = devicesRepository.findByClient_ClientId(client.getClientId());
|
||||
if (devices.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return devices.stream()
|
||||
.max(Comparator.comparing(Devices::getLastCheckedIn))
|
||||
.orElse(null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user