package com.cloudhandson.vpdbackoffice.web; import com.cloudhandson.vpdbackoffice.domain.probe.ProbeCommand; import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedObject; import com.cloudhandson.vpdbackoffice.domain.vector.VectorQueryEmbedding; import com.cloudhandson.vpdbackoffice.service.AppException; import com.cloudhandson.vpdbackoffice.service.BearerTokenService; import com.cloudhandson.vpdbackoffice.service.OrdsProbeService; import com.cloudhandson.vpdbackoffice.service.ProtectedObjectService; import com.cloudhandson.vpdbackoffice.service.VectorKnowledgeService; import com.cloudhandson.vpdbackoffice.service.VpdPolicyService; import com.cloudhandson.vpdbackoffice.mapper.UserMapper; import java.util.Comparator; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; @Controller public class ProbeController { private final OrdsProbeService probeService; private final ProtectedObjectService protectedObjectService; private final BearerTokenService tokenService; private final VpdPolicyService vpdPolicyService; private final UserMapper userMapper; private final VectorKnowledgeService vectorKnowledgeService; public ProbeController( OrdsProbeService probeService, ProtectedObjectService protectedObjectService, BearerTokenService tokenService, VpdPolicyService vpdPolicyService, UserMapper userMapper, VectorKnowledgeService vectorKnowledgeService ) { this.probeService = probeService; this.protectedObjectService = protectedObjectService; this.tokenService = tokenService; this.vpdPolicyService = vpdPolicyService; this.userMapper = userMapper; this.vectorKnowledgeService = vectorKnowledgeService; } @GetMapping("/probe") public String probe(Model model) { Set defaultObjectKeys = defaultPermissionObjectKeys(); List objects = protectedObjectService.findEnabled().stream() .sorted(Comparator .comparing((ProtectedObject object) -> !defaultObjectKeys.contains(object.displayName())) .thenComparing(ProtectedObject::displayName)) .toList(); model.addAttribute("objects", objects); model.addAttribute("defaultObjectKeys", defaultObjectKeys); model.addAttribute("users", userMapper.findAll()); model.addAttribute("aiEmbeddingConfigured", vectorKnowledgeService.aiEmbeddingConfigured()); return "probe"; } @PostMapping("/probe") public String run( @RequestParam long objectId, @RequestParam(defaultValue = "") String bearerToken, @RequestParam(required = false) Long tempUserId, @RequestParam(defaultValue = "50") int limit, @RequestParam(required = false) String requestBody, @RequestParam(defaultValue = "DEMO") String embeddingMode, Model model ) { String normalizedToken = bearerToken == null ? "" : bearerToken.trim(); ProtectedObject selectedObject = protectedObjectService.findEnabled().stream() .filter(object -> object.objectId() == objectId) .findFirst() .orElse(null); boolean vectorSearch = selectedObject != null && VectorKnowledgeService.VECTOR_OBJECT.equalsIgnoreCase(selectedObject.objectName()); model.addAttribute("vectorSearch", vectorSearch); Long temporaryKeyId = null; if (tempUserId != null) { var issued = tokenService.issueTemporaryToken(tempUserId, "ORDS 검증 임시 실행"); normalizedToken = issued.plainToken(); temporaryKeyId = issued.keyId(); } try { if (vectorSearch) { VectorQueryEmbedding vectorQuery = vectorKnowledgeService.vectorizeQuery(requestBody, embeddingMode); requestBody = vectorQuery.requestBody(); model.addAttribute("vectorQuery", vectorQuery.query()); model.addAttribute("vectorEmbeddingMode", vectorQuery.embeddingMode()); model.addAttribute("vectorEmbeddingModel", vectorQuery.embeddingModel()); } model.addAttribute("result", probeService.runProbe( new ProbeCommand(temporaryKeyId, objectId, normalizedToken, limit, requestBody))); model.addAttribute("tokenContext", tokenService.findTokenContextByPlainToken(normalizedToken)); } catch (AppException exception) { model.addAttribute("errorMessage", exception.getMessage()); } finally { if (temporaryKeyId != null) { tokenService.revokeToken(temporaryKeyId, "temporary probe completed"); } } model.addAttribute("selectedObject", selectedObject); return "fragments/probe-result :: result"; } private Set defaultPermissionObjectKeys() { Set result = new LinkedHashSet<>(); vpdPolicyService.findPolicies().stream() .filter(policy -> policy.permissionSystemDefault() && "YES".equalsIgnoreCase(policy.enabled())) .map(policy -> policy.objectDisplayName().toUpperCase()) .forEach(result::add); return result; } }