content;
- private Pagination pagination;
-
- @Data
- @Builder
- @NoArgsConstructor
- @AllArgsConstructor
- public static class Pagination implements Serializable {
- private long total;
- private int limit;
- private int page;
- private int pages;
- }
-}
-
diff --git a/rag-service/src/main/java/com/balex/rag/model/response/RagResponse.java b/rag-service/src/main/java/com/balex/rag/model/response/RagResponse.java
deleted file mode 100644
index 148d6b9..0000000
--- a/rag-service/src/main/java/com/balex/rag/model/response/RagResponse.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.balex.rag.model.response;
-
-import com.balex.rag.model.constants.ApiMessage;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
-import lombok.NoArgsConstructor;
-import lombok.Setter;
-import org.apache.commons.lang3.StringUtils;
-
-import java.io.Serializable;
-
-@Getter
-@Setter
-@NoArgsConstructor
-@AllArgsConstructor
-
-public class RagResponse implements Serializable {
- private String message;
- private P payload;
- private boolean success;
-
- public static
RagResponse
createSuccessful(P payload) {
- return new RagResponse<>(StringUtils.EMPTY, payload, true);
- }
-
- public static
RagResponse
createSuccessfulWithNewToken(P payload) {
- return new RagResponse<>(ApiMessage.TOKEN_CREATED_OR_UPDATED.getMessage(), payload, true);
- }
-
-}
-
-
diff --git a/rag-service/src/main/java/com/balex/rag/repo/ChatEntryRepository.java b/rag-service/src/main/java/com/balex/rag/repo/ChatEntryRepository.java
deleted file mode 100644
index 96cb33b..0000000
--- a/rag-service/src/main/java/com/balex/rag/repo/ChatEntryRepository.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.balex.rag.repo;
-
-import com.balex.rag.model.entity.ChatEntry;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.stereotype.Repository;
-
-import java.util.List;
-
-@Repository
-public interface ChatEntryRepository extends JpaRepository {
-
- List findByChatIdOrderByCreatedAtAsc(Long chatId);
-}
diff --git a/rag-service/src/main/java/com/balex/rag/repo/ChatRepository.java b/rag-service/src/main/java/com/balex/rag/repo/ChatRepository.java
deleted file mode 100644
index 901a49e..0000000
--- a/rag-service/src/main/java/com/balex/rag/repo/ChatRepository.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.balex.rag.repo;
-
-import com.balex.rag.model.entity.Chat;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-import java.util.List;
-
-public interface ChatRepository extends JpaRepository {
- List findByIdOwnerOrderByCreatedAtDesc(Long idOwner);
-}
-
diff --git a/rag-service/src/main/java/com/balex/rag/repo/DocumentRepository.java b/rag-service/src/main/java/com/balex/rag/repo/DocumentRepository.java
deleted file mode 100644
index a7ea5fd..0000000
--- a/rag-service/src/main/java/com/balex/rag/repo/DocumentRepository.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.balex.rag.repo;
-
-import com.balex.rag.model.LoadedDocument;
-import org.springframework.data.jpa.repository.JpaRepository;
-
-import java.util.List;
-
-public interface DocumentRepository extends JpaRepository {
-
- boolean existsByFilenameAndContentHash(String filename, String contentHash);
-
- List findByUserId(Integer userId);
-
-}
-
diff --git a/rag-service/src/main/java/com/balex/rag/repo/UserRepository.java b/rag-service/src/main/java/com/balex/rag/repo/UserRepository.java
deleted file mode 100644
index 3db7437..0000000
--- a/rag-service/src/main/java/com/balex/rag/repo/UserRepository.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.balex.rag.repo;
-
-import com.balex.rag.model.entity.User;
-import org.springframework.data.jpa.repository.JpaRepository;
-import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
-import org.springframework.stereotype.Repository;
-
-import java.util.Optional;
-
-@Repository
-public interface UserRepository extends JpaRepository, JpaSpecificationExecutor {
-
- boolean existsByEmail(String email);
-
- boolean existsByUsername(String username);
-
- Optional findByIdAndDeletedFalse (Integer id);
-
- Optional findUserByEmailAndDeletedFalse(String email);
-
- Optional findByEmail(String email);
-
- Optional findByUsername(String username);
-
-}
-
-
diff --git a/rag-service/src/main/java/com/balex/rag/repo/VectorStoreRepository.java b/rag-service/src/main/java/com/balex/rag/repo/VectorStoreRepository.java
deleted file mode 100644
index 89d4c37..0000000
--- a/rag-service/src/main/java/com/balex/rag/repo/VectorStoreRepository.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.balex.rag.repo;
-
-import org.springframework.stereotype.Repository;
-
-import java.util.List;
-
-@Repository
-public interface VectorStoreRepository {
-
- void deleteBySourceIn(List sources);
-
- void deleteByUserId(Long userId);
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/repo/impl/VectorStoreRepositoryImpl.java b/rag-service/src/main/java/com/balex/rag/repo/impl/VectorStoreRepositoryImpl.java
deleted file mode 100644
index 48c8826..0000000
--- a/rag-service/src/main/java/com/balex/rag/repo/impl/VectorStoreRepositoryImpl.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.balex.rag.repo.impl;
-
-import com.balex.rag.repo.VectorStoreRepository;
-import lombok.RequiredArgsConstructor;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.stereotype.Repository;
-
-import java.util.List;
-
-@Repository
-@RequiredArgsConstructor
-public class VectorStoreRepositoryImpl implements VectorStoreRepository {
-
- private final JdbcTemplate jdbcTemplate;
-
- @Override
- public void deleteBySourceIn(List sources) {
- if (sources == null || sources.isEmpty()) {
- return;
- }
-
- String placeholders = String.join(",", sources.stream()
- .map(s -> "?")
- .toList());
-
- String sql = "DELETE FROM vector_store WHERE metadata->>'source' IN (" + placeholders + ")";
-
- jdbcTemplate.update(sql, sources.toArray());
- }
-
- @Override
- public void deleteByUserId(Long userId) {
- String sql = "DELETE FROM vector_store WHERE (metadata->>'user_id')::bigint = ?";
- jdbcTemplate.update(sql, userId);
- }
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/security/validation/AccessValidator.java b/rag-service/src/main/java/com/balex/rag/security/validation/AccessValidator.java
deleted file mode 100644
index c035964..0000000
--- a/rag-service/src/main/java/com/balex/rag/security/validation/AccessValidator.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.balex.rag.security.validation;
-
-import com.balex.rag.model.constants.ApiErrorMessage;
-import com.balex.rag.repo.UserRepository;
-import lombok.RequiredArgsConstructor;
-import lombok.SneakyThrows;
-import org.springframework.stereotype.Component;
-
-import java.nio.file.AccessDeniedException;
-
-@Component
-@RequiredArgsConstructor
-public class AccessValidator {
- private final UserRepository userRepository;
-
- @SneakyThrows
- public void validateOwnerAccess(Integer ownerId, Integer currentUserId) {
- if (!currentUserId.equals(ownerId)) {
- throw new AccessDeniedException(ApiErrorMessage.HAVE_NO_ACCESS.getMessage());
- }
- }
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/service/ChatEntryService.java b/rag-service/src/main/java/com/balex/rag/service/ChatEntryService.java
deleted file mode 100644
index be9723e..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/ChatEntryService.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.balex.rag.service;
-
-import com.balex.rag.model.entity.ChatEntry;
-
-import java.util.List;
-
-public interface ChatEntryService {
-
- List getEntriesByChatId(Long chatId);
-
- ChatEntry addUserEntry(Long chatId, String content, boolean onlyContext, double topP, Long userId);
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/service/ChatService.java b/rag-service/src/main/java/com/balex/rag/service/ChatService.java
deleted file mode 100644
index e07fc5f..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/ChatService.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.balex.rag.service;
-
-import com.balex.rag.model.entity.Chat;
-import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
-
-import java.util.List;
-
-public interface ChatService {
-
- Chat createNewChat(String title, Long ownerId);
-
- List getAllChatsByOwner(Long ownerId);
-
- Chat getChat(Long chatId, Long ownerId);
-
- void deleteChat(Long chatId, Long ownerId);
-
- SseEmitter proceedInteractionWithStreaming(Long chatId, String userPrompt);
-}
diff --git a/rag-service/src/main/java/com/balex/rag/service/EventPublisher.java b/rag-service/src/main/java/com/balex/rag/service/EventPublisher.java
deleted file mode 100644
index 3d5825c..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/EventPublisher.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.balex.rag.service;
-
-public interface EventPublisher {
-
- void publishChatCreated(String userId, String chatId);
-
- void publishChatDeleted(String userId, String chatId);
-
- void publishQuerySent(String userId, String chatId);
-
- void publishUserCreated(String userId);
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/service/PostgresChatMemory.java b/rag-service/src/main/java/com/balex/rag/service/PostgresChatMemory.java
deleted file mode 100644
index 3076d1b..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/PostgresChatMemory.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.balex.rag.service;
-
-import com.balex.rag.model.entity.Chat;
-import com.balex.rag.model.entity.ChatEntry;
-import com.balex.rag.repo.ChatRepository;
-import lombok.Builder;
-import org.springframework.ai.chat.memory.ChatMemory;
-import org.springframework.ai.chat.messages.Message;
-
-import java.util.List;
-
-@Builder
-public class PostgresChatMemory implements ChatMemory {
-
- private ChatRepository chatMemoryRepository;
-
- private int maxMessages;
-
- @Override
- public void add(String conversationId, List messages) {
-// Chat chat = chatMemoryRepository.findById(Long.valueOf(conversationId)).orElseThrow();
-// for (Message message : messages) {
-// chat.addChatEntry(ChatEntry.toChatEntry(message));
-// }
-// chatMemoryRepository.save(chat);
-
- // No-op: messages are saved manually in ChatEntryServiceImpl
-
- }
-
-
- @Override
- public List get(String conversationId) {
- Chat chat = chatMemoryRepository.findById(Long.valueOf(conversationId)).orElseThrow();
- Long messagesToSkip= (long) Math.max(0, chat.getHistory().size() - maxMessages);
- return chat.getHistory().stream()
- .skip(messagesToSkip)
- //.sorted(Comparator.comparing(ChatEntry::getCreatedAt))
- //.sorted(Comparator.comparing(ChatEntry::getCreatedAt).reversed())
- .map(ChatEntry::toMessage)
- .limit(maxMessages)
- .toList();
-
- }
-
- @Override
- public void clear(String conversationId) {
- //not implemented
- }
-}
-
diff --git a/rag-service/src/main/java/com/balex/rag/service/UserDocumentService.java b/rag-service/src/main/java/com/balex/rag/service/UserDocumentService.java
deleted file mode 100644
index a789393..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/UserDocumentService.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.balex.rag.service;
-
-import org.springframework.web.multipart.MultipartFile;
-import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
-
-import java.util.List;
-
-public interface UserDocumentService {
- SseEmitter processUploadedFilesWithSse(List files, Long userId);
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/service/UserService.java b/rag-service/src/main/java/com/balex/rag/service/UserService.java
deleted file mode 100644
index 87a8db1..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/UserService.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.balex.rag.service;
-
-import com.balex.rag.model.dto.UserDTO;
-import com.balex.rag.model.dto.UserSearchDTO;
-import com.balex.rag.model.entity.UserInfo;
-import com.balex.rag.model.request.user.NewUserRequest;
-import com.balex.rag.model.request.user.UpdateUserRequest;
-import com.balex.rag.model.response.PaginationResponse;
-import com.balex.rag.model.response.RagResponse;
-import jakarta.validation.constraints.NotNull;
-import org.springframework.data.domain.Pageable;
-
-public interface UserService {
-
- RagResponse getById(@NotNull Integer userId);
-
- RagResponse createUser(@NotNull NewUserRequest request);
-
- RagResponse updateUser(@NotNull Integer postId, @NotNull UpdateUserRequest request);
-
- void softDeleteUser(Integer userId, Integer currentUserId);
-
- RagResponse> findAllUsers(Pageable pageable);
-
- RagResponse getUserInfo(Integer userId);
-
- RagResponse deleteUserDocuments(Integer userId);
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/service/autostart/DocumentLoaderService.java b/rag-service/src/main/java/com/balex/rag/service/autostart/DocumentLoaderService.java
deleted file mode 100644
index b779d7a..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/autostart/DocumentLoaderService.java
+++ /dev/null
@@ -1,85 +0,0 @@
-//package com.balex.rag.service.autostart;
-//
-//import com.balex.rag.model.LoadedDocument;
-//import com.balex.rag.repo.DocumentRepository;
-//import lombok.SneakyThrows;
-//import org.springframework.ai.document.Document;
-//import org.springframework.ai.reader.TextReader;
-//import org.springframework.ai.transformer.splitter.TokenTextSplitter;
-//import org.springframework.ai.vectorstore.VectorStore;
-//import org.springframework.beans.factory.annotation.Autowired;
-//import org.springframework.boot.CommandLineRunner;
-//import org.springframework.core.io.Resource;
-//import org.springframework.core.io.support.ResourcePatternResolver;
-//import org.springframework.data.util.Pair;
-//import org.springframework.stereotype.Service;
-//import org.springframework.util.DigestUtils;
-//
-//import java.util.Arrays;
-//import java.util.List;
-//
-//@Service
-//public class DocumentLoaderService implements CommandLineRunner {
-//
-// @Autowired
-// private DocumentRepository documentRepository;
-//
-// @Autowired
-// private ResourcePatternResolver resolver;
-//
-// @Autowired
-// private VectorStore vectorStore;
-//
-//
-// @SneakyThrows
-// public void loadDocuments() {
-// List resources = Arrays.stream(resolver.getResources("classpath:/knowledgebase/**/*.txt")).toList();
-//
-// resources.stream()
-// .map(r -> Pair.of(r, calcContentHash(r)))
-// .filter(p -> !documentRepository.existsByFilenameAndContentHash(p.getFirst().getFilename(), p.getSecond()))
-// .forEach(p -> {
-// Resource resource = p.getFirst();
-// List docs = new TextReader(resource).get();
-// TokenTextSplitter splitter = TokenTextSplitter.builder().withChunkSize(200).build();
-// List chunks = splitter.apply(docs);
-//
-// for (Document c : chunks) {
-// acceptWithRetry(vectorStore, List.of(c), 3, 1500);
-// }
-//
-// LoadedDocument loaded = LoadedDocument.builder()
-// .documentType("txt")
-// .chunkCount(chunks.size())
-// .filename(resource.getFilename())
-// .contentHash(p.getSecond())
-// .build();
-// documentRepository.save(loaded);
-// });
-//
-// }
-//
-// private static void acceptWithRetry(VectorStore vs, List part, int attempts, long sleepMs) {
-// RuntimeException last = null;
-// for (int i = 0; i < attempts; i++) {
-// try {
-// vs.accept(part);
-// return;
-// } catch (RuntimeException e) {
-// last = e;
-// try { Thread.sleep(sleepMs); } catch (InterruptedException ignored) {}
-// }
-// }
-// throw last;
-// }
-//
-// @SneakyThrows
-// private String calcContentHash(Resource resource) {
-// return DigestUtils.md5DigestAsHex(resource.getInputStream());
-// }
-//
-// @Override
-// public void run(String... args) {
-// loadDocuments();
-// }
-//}
diff --git a/rag-service/src/main/java/com/balex/rag/service/impl/ChatEntryServiceImpl.java b/rag-service/src/main/java/com/balex/rag/service/impl/ChatEntryServiceImpl.java
deleted file mode 100644
index f61ea94..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/impl/ChatEntryServiceImpl.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.balex.rag.service.impl;
-
-import com.balex.rag.model.entity.Chat;
-import com.balex.rag.model.entity.ChatEntry;
-import com.balex.rag.model.enums.Role;
-import com.balex.rag.repo.ChatEntryRepository;
-import com.balex.rag.repo.ChatRepository;
-import com.balex.rag.service.ChatEntryService;
-import jakarta.persistence.EntityNotFoundException;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.ai.chat.client.ChatClient;
-import org.springframework.ai.chat.memory.ChatMemory;
-import org.springframework.ai.openai.OpenAiChatOptions;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import com.balex.rag.config.RagDefaultsProperties;
-
-import java.util.List;
-
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class ChatEntryServiceImpl implements ChatEntryService {
-
- private final ChatEntryRepository chatEntryRepository;
- private final ChatRepository chatRepository;
- private final ChatClient chatClient;
- private final RagDefaultsProperties ragDefaults;
-
- @Override
- public List getEntriesByChatId(Long chatId) {
- return chatEntryRepository.findByChatIdOrderByCreatedAtAsc(chatId);
- }
-
- @Override
- @Transactional
- public ChatEntry addUserEntry(Long chatId, String content, boolean onlyContext, double topP, Long userId) {
- Chat chat = chatRepository.findById(chatId)
- .orElseThrow(() -> new EntityNotFoundException("Chat not found with id: " + chatId));
-
- ChatEntry userEntry = ChatEntry.builder()
- .chat(chat)
- .content(content)
- .role(Role.USER)
- .build();
- chatEntryRepository.save(userEntry);
-
- String systemPrompt = onlyContext
- ? """
- The question may be about a CONSEQUENCE of a fact from Context.
- ALWAYS connect: Context fact → question.
- No connection, even indirect = answer ONLY: "The request is not related to the uploaded context."
- Connection exists = answer using ONLY the context.
- Do NOT use any knowledge outside the provided context.
- """
- : """
- The question may be about a CONSEQUENCE of a fact from Context.
- ALWAYS connect: Context fact → question.
- If context contains relevant information, use it in your answer.
- If context does not contain relevant information, answer using your general knowledge.
- """;
-
- String response = chatClient.prompt()
- .system(systemPrompt)
- .user(content)
- .advisors(a -> a
- .param(ChatMemory.CONVERSATION_ID, String.valueOf(chatId))
- .param("USER_ID", userId))
- .options(OpenAiChatOptions.builder()
- .model(ragDefaults.model())
- .topP(topP)
- .build())
- .call()
- .content();
-
- ChatEntry assistantEntry = ChatEntry.builder()
- .chat(chat)
- .content(response)
- .role(Role.ASSISTANT)
- .build();
-
- return chatEntryRepository.save(assistantEntry);
- }
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/service/impl/ChatServiceImpl.java b/rag-service/src/main/java/com/balex/rag/service/impl/ChatServiceImpl.java
deleted file mode 100644
index cde046f..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/impl/ChatServiceImpl.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package com.balex.rag.service.impl;
-
-import com.balex.rag.model.entity.Chat;
-import com.balex.rag.repo.ChatRepository;
-import com.balex.rag.service.ChatService;
-import lombok.RequiredArgsConstructor;
-import lombok.SneakyThrows;
-import org.springframework.ai.chat.client.ChatClient;
-import org.springframework.ai.chat.memory.ChatMemory;
-import org.springframework.ai.chat.model.ChatResponse;
-import org.springframework.http.HttpStatus;
-import org.springframework.stereotype.Service;
-import org.springframework.web.server.ResponseStatusException;
-import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
-
-import java.util.List;
-
-@Service
-@RequiredArgsConstructor
-public class ChatServiceImpl implements ChatService {
-
- private final ChatRepository chatRepo;
- private final ChatClient chatClient;
-
- public List getAllChatsByOwner(Long ownerId) {
- return chatRepo.findByIdOwnerOrderByCreatedAtDesc(ownerId);
- }
-
- public Chat createNewChat(String title, Long ownerId) {
- Chat chat = Chat.builder().title(title).idOwner(ownerId).build();
- chatRepo.save(chat);
- return chat;
- }
-
- public Chat getChat(Long chatId, Long ownerId) {
- Chat chat = chatRepo.findById(chatId).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Chat not found"));
- if (!chat.getIdOwner().equals(ownerId)) {
- throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Access denied");
- }
- return chat;
- }
-
- public void deleteChat(Long chatId, Long ownerId) {
- Chat chat = getChat(chatId, ownerId);
- chatRepo.deleteById(chat.getId());
- }
-
- public SseEmitter proceedInteractionWithStreaming(Long chatId, String userPrompt) {
- SseEmitter sseEmitter = new SseEmitter(0L);
- final StringBuilder answer = new StringBuilder();
-
- chatClient.prompt(userPrompt).advisors(advisorSpec -> advisorSpec.param(ChatMemory.CONVERSATION_ID, chatId)).stream().chatResponse().subscribe((ChatResponse response) -> processToken(response, sseEmitter, answer), sseEmitter::completeWithError, sseEmitter::complete);
- return sseEmitter;
- }
-
- @SneakyThrows
- private static void processToken(ChatResponse response, SseEmitter emitter, StringBuilder answer) {
- var token = response.getResult().getOutput();
- emitter.send(token);
- answer.append(token.getText());
- }
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/service/impl/DocumentTransactionalHelper.java b/rag-service/src/main/java/com/balex/rag/service/impl/DocumentTransactionalHelper.java
deleted file mode 100644
index af3523d..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/impl/DocumentTransactionalHelper.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.balex.rag.service.impl;
-
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.multipart.MultipartFile;
-
-/**
- * Helper component to handle transactional file processing.
- *
- * This separate bean is necessary because Spring's @Transactional relies on proxies,
- * and self-invocation within the same class bypasses the proxy, causing transactions
- * to not be applied.
- */
-@Component
-public class DocumentTransactionalHelper {
-
- /**
- * Processes a single file within a transaction boundary.
- *
- * @param file the file to process
- * @param userId the user ID
- * @param filename the filename
- * @param processor the processing function to execute
- * @return true if file was processed, false if skipped
- */
- @Transactional
- public boolean processFileInTransaction(MultipartFile file,
- Long userId,
- String filename,
- FileProcessor processor) {
- return processor.process(file, userId, filename);
- }
-
- @FunctionalInterface
- public interface FileProcessor {
- boolean process(MultipartFile file, Long userId, String filename);
- }
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/service/impl/EventPublisherImpl.java b/rag-service/src/main/java/com/balex/rag/service/impl/EventPublisherImpl.java
deleted file mode 100644
index 042c377..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/impl/EventPublisherImpl.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.balex.rag.service.impl;
-
-import com.balex.rag.model.dto.UserEvent;
-import com.balex.rag.model.dto.UserEvent.EventType;
-import com.balex.rag.service.EventPublisher;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.kafka.core.KafkaTemplate;
-import org.springframework.stereotype.Service;
-
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class EventPublisherImpl implements EventPublisher {
-
- private final KafkaTemplate kafkaTemplate;
-
- @Value("${analytics.kafka.topic:user-events}")
- private String topic;
-
- @Override
- public void publishChatCreated(String userId, String chatId) {
- publish(UserEvent.builder()
- .type(EventType.CHAT_CREATED)
- .userId(userId)
- .chatId(chatId)
- .build());
- }
-
- @Override
- public void publishChatDeleted(String userId, String chatId) {
- publish(UserEvent.builder()
- .type(EventType.CHAT_DELETED)
- .userId(userId)
- .chatId(chatId)
- .build());
- }
-
- @Override
- public void publishQuerySent(String userId, String chatId) {
- publish(UserEvent.builder()
- .type(EventType.QUERY_SENT)
- .userId(userId)
- .chatId(chatId)
- .build());
- }
-
-
- private void publish(UserEvent event) {
- kafkaTemplate.send(topic, event.getUserId(), event)
- .whenComplete((result, ex) -> {
- if (ex != null) {
- log.error("Failed to send event {}: {}", event.getType(), ex.getMessage());
- } else {
- log.info("Event sent: type={}, userId={}", event.getType(), event.getUserId());
- }
- });
- }
-
- @Override
- public void publishUserCreated(String userId) {
- publish(UserEvent.builder()
- .type(EventType.USER_CREATED)
- .userId(userId)
- .build());
- }
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/service/impl/UserDocumentServiceImpl.java b/rag-service/src/main/java/com/balex/rag/service/impl/UserDocumentServiceImpl.java
deleted file mode 100644
index ca25460..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/impl/UserDocumentServiceImpl.java
+++ /dev/null
@@ -1,256 +0,0 @@
-package com.balex.rag.service.impl;
-
-import com.balex.rag.model.LoadedDocument;
-import com.balex.rag.model.UploadProgress;
-import com.balex.rag.model.constants.ApiLogMessage;
-import com.balex.rag.model.exception.UploadException;
-import com.balex.rag.repo.DocumentRepository;
-import com.balex.rag.service.UserDocumentService;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.ai.document.Document;
-import org.springframework.ai.reader.TextReader;
-import org.springframework.ai.transformer.splitter.TokenTextSplitter;
-import org.springframework.ai.vectorstore.VectorStore;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.core.io.ByteArrayResource;
-import org.springframework.core.io.Resource;
-import org.springframework.retry.annotation.Backoff;
-import org.springframework.retry.annotation.Retryable;
-import org.springframework.stereotype.Service;
-import org.springframework.web.multipart.MultipartFile;
-import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
-import org.springframework.ai.reader.tika.TikaDocumentReader;
-
-import java.io.IOException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.util.HexFormat;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import static com.balex.rag.model.constants.ApiConstants.EMPTY_FILENAME;
-import static com.balex.rag.model.constants.ApiErrorMessage.UPLOADED_FILENAME_EMPTY;
-import static com.balex.rag.model.constants.ApiErrorMessage.UPLOAD_FILE_READ_ERROR;
-
-@Slf4j
-@Service
-@RequiredArgsConstructor
-public class UserDocumentServiceImpl implements UserDocumentService {
-
- private final DocumentRepository documentRepository;
- private final VectorStore vectorStore;
- private final DocumentTransactionalHelper transactionalHelper;
-
- private static final String TXT_EXTENSION = "txt";
- private static final String USER_ID_FIELD_NAME = "user_id";
-
- private static final String STATUS_PROCESSING = "processing";
- private static final String STATUS_COMPLETED = "completed";
- private static final String STATUS_SKIPPED = "skipped";
- private static final Long SSE_EMITTER_TIMEOUT_IN_MILLIS = 120000L;
-
- @Value("${app.document.chunk-size:200}")
- private int chunkSize;
-
- public SseEmitter processUploadedFilesWithSse(List files, Long userId) {
- SseEmitter emitter = new SseEmitter(SSE_EMITTER_TIMEOUT_IN_MILLIS);
-
- AtomicBoolean isCompleted = new AtomicBoolean(false);
-
- emitter.onCompletion(() -> {
- log.debug("SSE completed");
- isCompleted.set(true);
- });
- emitter.onTimeout(() -> {
- log.debug("SSE timeout");
- isCompleted.set(true);
- });
- emitter.onError(e -> {
- log.debug("SSE client disconnected: {}", e.getMessage());
- isCompleted.set(true);
- });
-
- List validFiles = files.stream()
- .filter(f -> !f.isEmpty())
- .toList();
-
- CompletableFuture.runAsync(() -> {
- try {
- int totalFiles = validFiles.size();
- int processedCount = 0;
-
- for (MultipartFile file : validFiles) {
- if (isCompleted.get()) {
- log.debug("Upload cancelled, stopping at file: {}", processedCount);
- return;
- }
-
- String filename = getFilename(file);
-
- sendProgress(emitter, isCompleted, processedCount, totalFiles, filename, STATUS_PROCESSING);
-
- if (isCompleted.get()) return; // Проверка после отправки
-
- boolean processed = transactionalHelper.processFileInTransaction(
- file, userId, filename, this::processFileInternal);
-
- processedCount++;
- String status = processed ? STATUS_PROCESSING : STATUS_SKIPPED;
- sendProgress(emitter, isCompleted, processedCount, totalFiles, filename, status);
- }
-
- if (!isCompleted.get()) {
- try {
- emitter.send(SseEmitter.event()
- .data(UploadProgress.builder()
- .percent(100)
- .processedFiles(processedCount)
- .totalFiles(totalFiles)
- .currentFile("")
- .status(STATUS_COMPLETED)
- .build()));
- emitter.complete();
- } catch (IOException | IllegalStateException e) {
- log.debug("Could not send completion: {}", e.getMessage());
- }
- }
-
- } catch (Exception e) {
- if (!isCompleted.get()) {
- log.error("SSE processing error", e);
- emitter.completeWithError(e);
- }
- }
- });
-
- return emitter;
- }
-
- private void sendProgress(SseEmitter emitter, AtomicBoolean isCompleted,
- int processed, int total, String filename, String status) {
- if (isCompleted.get()) {
- return;
- }
-
- try {
- int percent = total > 0 ? (int) Math.round((double) processed / total * 100) : 0;
-
- emitter.send(SseEmitter.event()
- .data(UploadProgress.builder()
- .percent(percent)
- .processedFiles(processed)
- .totalFiles(total)
- .currentFile(filename)
- .status(status)
- .build()));
- } catch (IOException | IllegalStateException e) {
- // Client disconnected - this is normal for cancel
- log.debug("Client disconnected: {}", e.getMessage());
- isCompleted.set(true);
- }
- }
- boolean processFileInternal(MultipartFile file, Long userId, String filename) {
- byte[] content;
- try {
- content = file.getBytes();
- } catch (IOException e) {
- throw new UploadException(UPLOAD_FILE_READ_ERROR + filename, e);
- }
-
- String contentHash = computeSha256Hash(content);
-
- if (documentRepository.existsByFilenameAndContentHash(filename, contentHash)) {
- log.debug("Skipping duplicate file: {} with hash: {}", filename, contentHash);
- return false;
- }
-
- processTextAndStore(userId, filename, content, contentHash);
- return true;
- }
-
- private void processTextAndStore(Long userId, String filename, byte[] content, String contentHash) {
- Resource resource = new ByteArrayResource(content) {
- @Override
- public String getFilename() {
- return filename;
- }
- };
-
- List docs;
- String ext = getExtensionOrTxt(filename);
- if (ext.equals("txt")) {
- docs = new TextReader(resource).get();
- } else {
- docs = new TikaDocumentReader(resource).get();
- }
-
- TokenTextSplitter splitter = TokenTextSplitter.builder()
- .withChunkSize(chunkSize)
- .build();
- List chunks = splitter.apply(docs);
-
- for (Document chunk : chunks) {
- chunk.getMetadata().put(USER_ID_FIELD_NAME, userId);
- }
-
- storeInVectorDb(chunks);
-
- LoadedDocument loaded = LoadedDocument.builder()
- .documentType(getExtensionOrTxt(filename))
- .chunkCount(chunks.size())
- .filename(filename)
- .contentHash(contentHash)
- .userId(userId)
- .build();
-
- documentRepository.save(loaded);
-
- log.info("Successfully processed file: {} with {} chunks for user: {}",
- filename, chunks.size(), userId);
- }
-
- /**
- * Stores documents in vector store with retry via Spring Retry.
- */
- @Retryable(
- retryFor = RuntimeException.class,
- maxAttemptsExpression = "${app.document.retry.max-attempts:3}",
- backoff = @Backoff(
- delayExpression = "${app.document.retry.delay-ms:1500}",
- multiplier = 2
- )
- )
- public void storeInVectorDb(List chunks) {
- vectorStore.accept(chunks);
- }
-
- private String getFilename(MultipartFile file) {
- String filename = file.getOriginalFilename();
- if (filename == null || filename.isBlank()) {
- log.trace(ApiLogMessage.NAME_OF_CURRENT_METHOD.getValue(), UPLOADED_FILENAME_EMPTY);
- return EMPTY_FILENAME;
- }
- return filename;
- }
-
- private String getExtensionOrTxt(String filename) {
- int idx = filename.lastIndexOf('.');
- if (idx == -1 || idx == filename.length() - 1) {
- return TXT_EXTENSION;
- }
- return filename.substring(idx + 1).toLowerCase();
- }
-
- private String computeSha256Hash(byte[] content) {
- try {
- MessageDigest digest = MessageDigest.getInstance("SHA-256");
- byte[] hash = digest.digest(content);
- return HexFormat.of().formatHex(hash);
- } catch (NoSuchAlgorithmException e) {
- throw new IllegalStateException("SHA-256 algorithm not available", e);
- }
- }
-
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/service/impl/UserServiceImpl.java b/rag-service/src/main/java/com/balex/rag/service/impl/UserServiceImpl.java
deleted file mode 100644
index cba4559..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/impl/UserServiceImpl.java
+++ /dev/null
@@ -1,157 +0,0 @@
-package com.balex.rag.service.impl;
-
-import com.balex.rag.mapper.UserMapper;
-import com.balex.rag.model.LoadedDocument;
-import com.balex.rag.model.constants.ApiErrorMessage;
-import com.balex.rag.model.dto.UserDTO;
-import com.balex.rag.model.dto.UserSearchDTO;
-import com.balex.rag.model.entity.LoadedDocumentInfo;
-import com.balex.rag.model.entity.User;
-import com.balex.rag.model.entity.UserInfo;
-import com.balex.rag.model.exception.NotFoundException;
-import com.balex.rag.model.request.user.NewUserRequest;
-import com.balex.rag.model.request.user.UpdateUserRequest;
-import com.balex.rag.model.response.PaginationResponse;
-import com.balex.rag.model.response.RagResponse;
-import com.balex.rag.repo.DocumentRepository;
-import com.balex.rag.repo.UserRepository;
-import com.balex.rag.repo.VectorStoreRepository;
-import com.balex.rag.security.validation.AccessValidator;
-import com.balex.rag.service.UserService;
-import com.balex.rag.service.model.exception.DataExistException;
-import jakarta.validation.constraints.NotNull;
-import lombok.RequiredArgsConstructor;
-import org.springframework.data.domain.Page;
-import org.springframework.data.domain.Pageable;
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.List;
-
-@Service
-@RequiredArgsConstructor
-public class UserServiceImpl implements UserService {
- private final UserRepository userRepository;
- private final UserMapper userMapper;
- private final PasswordEncoder passwordEncoder;
- private final AccessValidator accessValidator;
- private final DocumentRepository documentRepository;
- private final VectorStoreRepository vectorStoreRepository;
-
- @Override
- @Transactional(readOnly = true)
- public RagResponse getById(@NotNull Integer userId) {
- User user = userRepository.findByIdAndDeletedFalse(userId)
- .orElseThrow(() -> new NotFoundException(ApiErrorMessage.USER_NOT_FOUND_BY_ID.getMessage(userId)));
-
- return RagResponse.createSuccessful(userMapper.toDto(user));
- }
-
- @Override
- @Transactional
- public RagResponse createUser(@NotNull NewUserRequest request) {
- if (userRepository.existsByEmail(request.getEmail())) {
- throw new DataExistException(ApiErrorMessage.EMAIL_ALREADY_EXISTS.getMessage(request.getEmail()));
- }
-
- if (userRepository.existsByUsername(request.getUsername())) {
- throw new DataExistException(ApiErrorMessage.USERNAME_ALREADY_EXISTS.getMessage(request.getUsername()));
- }
-
- User user = userMapper.createUser(request);
- user.setPassword(passwordEncoder.encode(request.getPassword()));
- User savedUser = userRepository.save(user);
-
- return RagResponse.createSuccessful(userMapper.toDto(savedUser));
- }
-
- @Override
- @Transactional
- public RagResponse updateUser(@NotNull Integer userId, UpdateUserRequest request) {
- User user = userRepository.findByIdAndDeletedFalse(userId)
- .orElseThrow(() -> new NotFoundException(ApiErrorMessage.USER_NOT_FOUND_BY_ID.getMessage(userId)));
-
- if (!user.getUsername().equals(request.getUsername()) && userRepository.existsByUsername(request.getUsername())) {
- throw new DataExistException(ApiErrorMessage.USERNAME_ALREADY_EXISTS.getMessage(request.getUsername()));
- }
-
- if (!user.getEmail().equals(request.getEmail()) && userRepository.existsByEmail(request.getEmail())) {
- throw new DataExistException(ApiErrorMessage.EMAIL_ALREADY_EXISTS.getMessage(request.getEmail()));
- }
-
- userMapper.updateUser(user, request);
- user = userRepository.save(user);
-
- return RagResponse.createSuccessful(userMapper.toDto(user));
- }
-
- @Override
- @Transactional
- public void softDeleteUser(Integer userId, Integer currentUserId) {
- User user = userRepository.findByIdAndDeletedFalse(userId)
- .orElseThrow(() -> new NotFoundException(ApiErrorMessage.USER_NOT_FOUND_BY_ID.getMessage(userId)));
-
- accessValidator.validateOwnerAccess(userId, currentUserId);
-
- user.setDeleted(true);
- userRepository.save(user);
- }
-
- @Override
- @Transactional(readOnly = true)
- public RagResponse> findAllUsers(Pageable pageable) {
- Page users = userRepository.findAll(pageable)
- .map(userMapper::toUserSearchDto);
-
- PaginationResponse paginationResponse = new PaginationResponse<>(
- users.getContent(),
- new PaginationResponse.Pagination(
- users.getTotalElements(),
- pageable.getPageSize(),
- users.getNumber() + 1,
- users.getTotalPages()
- )
- );
-
- return RagResponse.createSuccessful(paginationResponse);
- }
-
- @Override
- @Transactional(readOnly = true)
- public RagResponse getUserInfo(Integer userId) {
- User user = userRepository.findByIdAndDeletedFalse(userId)
- .orElseThrow(() -> new NotFoundException(ApiErrorMessage.USER_NOT_FOUND_BY_ID.getMessage(userId)));
-
- List loadedFiles = documentRepository
- .findByUserId(user.getId())
- .stream()
- .map(doc -> new LoadedDocumentInfo(doc.getId(), doc.getFilename()))
- .toList();
-
- UserInfo userInfo = new UserInfo(user.getId(),
- user.getUsername(),
- user.getEmail(),
- loadedFiles);
-
- return RagResponse.createSuccessful(userInfo);
- }
-
- @Override
- @Transactional
- public RagResponse deleteUserDocuments(Integer userId) {
- User user = userRepository.findByIdAndDeletedFalse(userId)
- .orElseThrow(() -> new NotFoundException(ApiErrorMessage.USER_NOT_FOUND_BY_ID.getMessage(userId)));
-
- List documents = documentRepository.findByUserId(user.getId());
-
- if (documents.isEmpty()) {
- return RagResponse.createSuccessful(0);
- }
-
- vectorStoreRepository.deleteByUserId(user.getId().longValue());
- documentRepository.deleteAll(documents);
-
- return RagResponse.createSuccessful(documents.size());
- }
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/service/model/AuthenticationConstants.java b/rag-service/src/main/java/com/balex/rag/service/model/AuthenticationConstants.java
deleted file mode 100644
index 2460543..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/model/AuthenticationConstants.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.balex.rag.service.model;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class AuthenticationConstants {
-
- public static final String USER_ID = "userId";
- public static final String USERNAME = "username";
- public static final String USER_EMAIL = "email";
- public static final String USER_REGISTRATION_STATUS = "userRegistrationStatus";
- public static final String LAST_UPDATE = "lastUpdate";
- public static final String SESSION_ID = "sessionId";
- public static final String ACCESS_KEY_HEADER_NAME = "key";
-
-}
diff --git a/rag-service/src/main/java/com/balex/rag/service/model/exception/DataExistException.java b/rag-service/src/main/java/com/balex/rag/service/model/exception/DataExistException.java
deleted file mode 100644
index c3fd09c..0000000
--- a/rag-service/src/main/java/com/balex/rag/service/model/exception/DataExistException.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.balex.rag.service.model.exception;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public class DataExistException extends RuntimeException {
-
- public DataExistException(String message) {
- super(message);
- }
-}
-
-
diff --git a/rag-service/src/main/java/com/balex/rag/utils/ApiUtils.java b/rag-service/src/main/java/com/balex/rag/utils/ApiUtils.java
deleted file mode 100644
index a87affb..0000000
--- a/rag-service/src/main/java/com/balex/rag/utils/ApiUtils.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.balex.rag.utils;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class ApiUtils {
-
- public static String getMethodName() {
- try {
- return new Throwable().getStackTrace()[1].getMethodName();
- } catch (Exception cause) {
- return "undefined";
- }
- }
-}
\ No newline at end of file
diff --git a/rag-service/src/main/java/com/balex/rag/utils/PasswordUtils.java b/rag-service/src/main/java/com/balex/rag/utils/PasswordUtils.java
deleted file mode 100644
index 4c9602c..0000000
--- a/rag-service/src/main/java/com/balex/rag/utils/PasswordUtils.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package com.balex.rag.utils;
-
-import com.balex.rag.model.constants.ApiConstants;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.apache.commons.lang3.RandomStringUtils;
-
-import java.security.SecureRandom;
-import java.util.ArrayList;
-import java.util.Random;
-
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class PasswordUtils {
- private static final Random RND = new Random();
-
- public static boolean isNotValidPassword(String password) {
- if (password == null || password.isEmpty() || password.trim().isEmpty()) {
- return true;
- }
- String trim = password.trim();
- if (trim.length() < ApiConstants.REQUIRED_MIN_PASSWORD_LENGTH) {
- return true;
- }
- int charactersNumber = ApiConstants.REQUIRED_MIN_CHARACTERS_NUMBER_IN_PASSWORD;
- int lettersUCaseNumber = ApiConstants.REQUIRED_MIN_LETTERS_NUMBER_EVERY_CASE_IN_PASSWORD;
- int lettersLCaseNumber = ApiConstants.REQUIRED_MIN_LETTERS_NUMBER_EVERY_CASE_IN_PASSWORD;
- int digitsNumber = ApiConstants.REQUIRED_MIN_DIGITS_NUMBER_IN_PASSWORD;
- for (int i = 0; i < trim.length(); i++) {
- String currentLetter = String.valueOf(trim.charAt(i));
- if (!ApiConstants.PASSWORD_ALL_CHARACTERS.contains(currentLetter)) {
- return true;
- }
- charactersNumber -= ApiConstants.PASSWORD_CHARACTERS.contains(currentLetter) ? 1 : 0;
- lettersUCaseNumber -= ApiConstants.PASSWORD_LETTERS_UPPER_CASE.contains(currentLetter) ? 1 : 0;
- lettersLCaseNumber -= ApiConstants.PASSWORD_LETTERS_LOWER_CASE.contains(currentLetter) ? 1 : 0;
- digitsNumber -= ApiConstants.PASSWORD_DIGITS.contains(currentLetter) ? 1 : 0;
- }
- return ((charactersNumber > 0) || (lettersUCaseNumber > 0) || (lettersLCaseNumber > 0) || (digitsNumber > 0));
- }
-
- private static String randomFromChars(int count, String chars) {
- final SecureRandom RANDOM = new SecureRandom();
- StringBuilder sb = new StringBuilder(count);
- for (int i = 0; i < count; i++) {
- int idx = RANDOM.nextInt(chars.length());
- sb.append(chars.charAt(idx));
- }
- return sb.toString();
- }
-
- public static String generatePassword() {
- int charactersNumber = ApiConstants.REQUIRED_MIN_CHARACTERS_NUMBER_IN_PASSWORD;
- int digitsNumber = ApiConstants.REQUIRED_MIN_DIGITS_NUMBER_IN_PASSWORD;
- int lettersUCaseNumber = ApiConstants.REQUIRED_MIN_LETTERS_NUMBER_EVERY_CASE_IN_PASSWORD;
- int lettersLCaseNumber = ApiConstants.REQUIRED_MIN_PASSWORD_LENGTH
- - charactersNumber - digitsNumber - lettersUCaseNumber;
- String characters = randomFromChars(charactersNumber, ApiConstants.PASSWORD_CHARACTERS);
- String digits = randomFromChars(digitsNumber, ApiConstants.PASSWORD_DIGITS);
- String lettersUCase = randomFromChars(lettersUCaseNumber, ApiConstants.PASSWORD_LETTERS_UPPER_CASE);
- String lettersLCase = randomFromChars(lettersLCaseNumber, ApiConstants.PASSWORD_LETTERS_LOWER_CASE);
-
-
- ArrayList randomPasswordCharacters = new ArrayList<>();
- for (char character : (characters + digits + lettersUCase + lettersLCase).toCharArray()) {
- randomPasswordCharacters.add(character);
- }
-
- StringBuilder password = new StringBuilder();
- int length = randomPasswordCharacters.size();
- for (int i = 0; i < length; i++) {
- int randomPosition = RND.nextInt((randomPasswordCharacters.size()));
- password.append(randomPasswordCharacters.get(randomPosition));
- randomPasswordCharacters.remove(randomPosition);
- }
-
- return password.toString();
- }
-
-}
-
diff --git a/rag-service/src/main/java/com/balex/rag/utils/UserContext.java b/rag-service/src/main/java/com/balex/rag/utils/UserContext.java
deleted file mode 100644
index a6f8392..0000000
--- a/rag-service/src/main/java/com/balex/rag/utils/UserContext.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.balex.rag.utils;
-
-import jakarta.servlet.http.HttpServletRequest;
-
-public final class UserContext {
-
- private UserContext() {}
-
- public static Integer getUserId(HttpServletRequest request) {
- String userId = (String) request.getAttribute("userId");
- return userId != null ? Integer.parseInt(userId) : null;
- }
-
- public static String getUserEmail(HttpServletRequest request) {
- return (String) request.getAttribute("userEmail");
- }
-
- public static String getUserName(HttpServletRequest request) {
- return (String) request.getAttribute("userName");
- }
-
- public static String getUserRole(HttpServletRequest request) {
- return (String) request.getAttribute("userRole");
- }
-}
\ No newline at end of file
diff --git a/rag-service/src/main/resources/application.properties b/rag-service/src/main/resources/application.properties
deleted file mode 100644
index 9095258..0000000
--- a/rag-service/src/main/resources/application.properties
+++ /dev/null
@@ -1,62 +0,0 @@
-spring.application.name=rag-service
-
-# --- LLM Provider: Groq (OpenAI-compatible API) ---
-spring.ai.openai.base-url=${SPRING_AI_OPENAI_BASE_URL:https://api.groq.com/openai}
-spring.ai.openai.api-key=${SPRING_AI_OPENAI_API_KEY:}
-spring.ai.openai.chat.model=${SPRING_AI_OPENAI_CHAT_MODEL:llama-3.3-70b-versatile}
-spring.jpa.hibernate.ddl-auto=update
-
-# Embedding via separate OpenAI API bean (see EmbeddingConfig.java)
-embedding.openai.api-key=${OPENAI_API_KEY:}
-embedding.openai.model=text-embedding-3-small
-spring.ai.vectorstore.pgvector.initialize-schema=true
-
-# --- Consul service discovery ---
-spring.cloud.consul.host=${SPRING_CLOUD_CONSUL_HOST:localhost}
-spring.cloud.consul.port=${SPRING_CLOUD_CONSUL_PORT:8500}
-spring.cloud.consul.discovery.service-name=rag-service
-spring.cloud.consul.discovery.instance-id=${spring.application.name}-${random.value}
-spring.cloud.consul.discovery.prefer-ip-address=true
-spring.cloud.consul.discovery.health-check-interval=15s
-spring.cloud.consul.discovery.deregister-critical-service-after=1m
-
-# --- Actuator ---
-management.endpoints.web.exposure.include=health,info
-management.endpoint.health.show-details=always
-
-spring.servlet.multipart.max-file-size=5MB
-spring.servlet.multipart.max-request-size=10MB
-
-spring.datasource.url=${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/ragdb}
-spring.datasource.username=${SPRING_DATASOURCE_USERNAME:postgres}
-spring.datasource.password=${SPRING_DATASOURCE_PASSWORD:postgres}
-logging.level.org.springframework.ai.chat.client.advisor=DEBUG
-logging.level.org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping=DEBUG
-logging.level.org.springframework.web=DEBUG
-logging.level.org.flywaydb=DEBUG
-logging.level.com.balex.rag.controller=DEBUG
-app.document.chunk-size=200
-server.compression.enabled=false
-server.tomcat.connection-timeout=60000
-spring.mvc.async.request-timeout=60000
-end.points.users=/users
-end.points.id=/{id}
-end.points.all=/all
-end.points.create=/create
-end.points.userinfo=/userinfo
-end.points.refresh.token=/refresh/token
-end.points.auth=/auth
-end.points.login=/login
-end.points.register=/register
-end.points.chat=/chat
-end.points.entry=/entry
-end.points.document=/documents
-rag.rerank-fetch-multiplier=2
-#Swagger
-swagger.servers.first=http://localhost:8080
-springdoc.swagger-ui.path=/swagger-ui.html
-springdoc.api-docs.path=/v3/api-docs
-server.forward-headers-strategy=framework
-#Kafka
-spring.kafka.bootstrap-servers=${KAFKA_BOOTSTRAP_SERVERS:localhost:9092}
-analytics.kafka.topic=user-events
\ No newline at end of file