Skip to content
Merged

Dev #14

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,5 @@ public ResponseEntity<Void> likeComment(@AuthenticationPrincipal Member member,
likeService.like(member, Subject.COMMENT, commentId);
return ResponseEntity.status(HttpStatus.OK).build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@

import lombok.RequiredArgsConstructor;
import org.poolc.api.kubernetes.dto.GetKubernetesResponseDto;
import org.poolc.api.kubernetes.dto.GetMyKubernetesKeyResponseDto;
import org.poolc.api.kubernetes.service.KubernetesService;
import org.poolc.api.member.domain.Member;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.Map;
Expand Down Expand Up @@ -31,4 +35,19 @@ public ResponseEntity<Void> refreshMamberKeys(@RequestHeader("X-API-KEY") String
return ResponseEntity.ok().build();
}

@GetMapping(value="/me")
public ResponseEntity<GetMyKubernetesKeyResponseDto> getMyKey(@AuthenticationPrincipal Member loginMember){
if (loginMember == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
try {
GetMyKubernetesKeyResponseDto response = new GetMyKubernetesKeyResponseDto(
kubernetesService.getKubernetesKeyByUUID(loginMember.getUUID())
);
return ResponseEntity.ok().body(response);
} catch (IllegalArgumentException e){
return ResponseEntity.notFound().build();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.poolc.api.kubernetes.dto;

public interface ActiveMemberDto {
String getMember_uuid();
String getLogin_id();
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@

@Getter
public class GetKubernetesResponseDto {
private final List<String> activeMembers;
private final List<ActiveMemberDto> activeMembers;

@JsonCreator
public GetKubernetesResponseDto(List<String> activeMembers) {
public GetKubernetesResponseDto(List<ActiveMemberDto> activeMembers) {
this.activeMembers = activeMembers;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.poolc.api.kubernetes.dto;

import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Getter;

@Getter
public class GetMyKubernetesKeyResponseDto {

private final String key;

@JsonCreator
public GetMyKubernetesKeyResponseDto(String key){
this.key = key;
}
Comment on lines +3 to +14
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard Jackson constructor binding with @JsonProperty.

With @JsonCreator on a single-arg constructor, Jackson switches to delegating mode unless the argument is explicitly named. Without @JsonProperty("key"), ObjectMapper.readValue("{\"key\":\"value\"}", GetMyKubernetesKeyResponseDto.class) will throw InvalidDefinitionException (unless we happen to register ParameterNamesModule everywhere). Please annotate the parameter (and add the import) to keep deserialization safe.

-import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonProperty;
@@
-    @JsonCreator
-    public GetMyKubernetesKeyResponseDto(String key){
+    @JsonCreator
+    public GetMyKubernetesKeyResponseDto(@JsonProperty("key") String key){
         this.key = key;
     }
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Getter;
@Getter
public class GetMyKubernetesKeyResponseDto {
private final String key;
@JsonCreator
public GetMyKubernetesKeyResponseDto(String key){
this.key = key;
}
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
@Getter
public class GetMyKubernetesKeyResponseDto {
private final String key;
@JsonCreator
public GetMyKubernetesKeyResponseDto(@JsonProperty("key") String key) {
this.key = key;
}
}
πŸ€– Prompt for AI Agents
In src/main/java/org/poolc/api/kubernetes/dto/GetMyKubernetesKeyResponseDto.java
around lines 3 to 14, the @JsonCreator single-arg constructor is not guarded
with @JsonProperty, which causes Jackson to use delegating mode and fail
deserialization unless ParameterNamesModule is registered; add the import for
com.fasterxml.jackson.annotation.JsonProperty and annotate the constructor
parameter with @JsonProperty("key") so Jackson can bind the "key" JSON property
to the constructor parameter during deserialization.

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.poolc.api.kubernetes.repository;

import org.poolc.api.kubernetes.domain.KubernetesMapping;
import org.poolc.api.kubernetes.dto.ActiveMemberDto;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
Expand All @@ -12,25 +13,28 @@
public interface KubernetesRepository extends JpaRepository<KubernetesMapping, Long> {


@Query(value = "SELECT DISTINCT MEMBER_UUID\n" +
"FROM ROLES\n" +
"WHERE MEMBER_UUID IN (\n" +
@Query(value = "SELECT DISTINCT T2.MEMBER_UUID\n" +
" , (SELECT login_id" +
" FROM MEMBER T1" +
" WHERE T1.UUID = T2.MEMBER_UUID)\n" +
"FROM ROLES T2\n" +
"WHERE T2.MEMBER_UUID IN (\n" +
" SELECT MEMBER_UUID\n" +
" FROM ROLES\n" +
" WHERE ROLES = 'MEMBER'\n" +
")\n" +
"AND MEMBER_UUID NOT IN (\n" +
"AND T2.MEMBER_UUID NOT IN (\n" +
" SELECT MEMBER_UUID\n" +
" FROM ROLES\n" +
" WHERE ROLES = 'INACTIVE'\n" +
")", nativeQuery = true)
List<String> findAllActiveMembers();
List<ActiveMemberDto> findAllActiveMembers();
Comment on lines +16 to +31
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | πŸ”΄ Critical

Alias the selected columns for ActiveMemberDto projection

Line 17 currently returns the login ID via a scalar subquery without an alias. In Postgres (and most RDBMSs) that yields a ?column? heading, so Spring can’t map it onto the ActiveMemberDto getters and you’ll hit an IllegalArgumentException at runtime. Please alias both selected columns to match the DTO contract (and consider replacing the subquery with a join for clarity). For example:

-    @Query(value = "SELECT DISTINCT T2.MEMBER_UUID\n" +
-            "   , (SELECT login_id" +
-            "       FROM MEMBER T1" +
-            "       WHERE T1.UUID = T2.MEMBER_UUID)\n" +
+    @Query(value = "SELECT DISTINCT T2.MEMBER_UUID AS memberUuid\n" +
+            "   , (SELECT login_id" +
+            "       FROM MEMBER T1" +
+            "       WHERE T1.UUID = T2.MEMBER_UUID) AS loginId\n" +
             "FROM ROLES T2\n" +
             "WHERE T2.MEMBER_UUID IN (\n" +
             "    SELECT MEMBER_UUID\n" +
             "    FROM ROLES\n" +
             "    WHERE ROLES = 'MEMBER'\n" +
             ")\n" +
             "AND T2.MEMBER_UUID NOT IN (\n" +
             "    SELECT MEMBER_UUID\n" +
             "    FROM ROLES\n" +
             "    WHERE ROLES = 'INACTIVE'\n" +
             ")", nativeQuery = true)
πŸ€– Prompt for AI Agents
In src/main/java/org/poolc/api/kubernetes/repository/KubernetesRepository.java
around lines 16 to 31, the native query selects MEMBER_UUID and a scalar
subquery for login_id without aliases which prevents Spring from mapping the
result to ActiveMemberDto; modify the SELECT to alias both columns to the DTO
property names (e.g., memberUuid or member_uuid and loginId or login_id matching
ActiveMemberDto getters/constructor) so the projection maps correctly, and
optionally replace the scalar subquery with an equivalent JOIN to MEMBER for
clarity and performance.


@Modifying
@Transactional
@Query(value = "TRUNCATE TABLE KUBERNETES_MAPPINGS", nativeQuery = true)
void truncateKubernetesMappingTable();

@Query(value = "SELECT kubernetesKey FROM kubernetes_mappings WHERE UUID IN (SELECT UUID FROM Member WHERE loginID = :userId)")
Optional<String> findKubernetesKeyByUserId(String userId);
@Query(value = "SELECT kubernetesKey FROM kubernetes_mappings WHERE UUID = :UUID")
Optional<String> findKubernetesKeyByUUID(String UUID);
Comment on lines +38 to +39
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | πŸ”΄ Critical

Restore nativeQuery = true (and bind the UUID properly)

Line 38 is still raw SQL against kubernetes_mappings, but the @Query annotation no longer sets nativeQuery = true, so Spring will parse it as JPQL and blow up at runtime. Please reinstate the native flag and bind the parameter explicitly:

-    @Query(value = "SELECT kubernetesKey FROM kubernetes_mappings WHERE UUID = :UUID")
-    Optional<String> findKubernetesKeyByUUID(String UUID);
+    @Query(value = "SELECT kubernetesKey FROM kubernetes_mappings WHERE UUID = :uuid", nativeQuery = true)
+    Optional<String> findKubernetesKeyByUUID(@Param("uuid") String uuid);
πŸ“ Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Query(value = "SELECT kubernetesKey FROM kubernetes_mappings WHERE UUID = :UUID")
Optional<String> findKubernetesKeyByUUID(String UUID);
@Query(value = "SELECT kubernetesKey FROM kubernetes_mappings WHERE UUID = :uuid", nativeQuery = true)
Optional<String> findKubernetesKeyByUUID(@Param("uuid") String uuid);
πŸ€– Prompt for AI Agents
In src/main/java/org/poolc/api/kubernetes/repository/KubernetesRepository.java
around lines 38-39, the @Query is raw SQL but missing nativeQuery = true and the
UUID parameter isn't explicitly bound; restore nativeQuery = true on the @Query
and bind the parameter by annotating the method parameter with @Param("UUID")
(or change the placeholder and param name consistently) so the native SQL runs
correctly.

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import lombok.RequiredArgsConstructor;
import org.poolc.api.kubernetes.domain.KubernetesMapping;
import org.poolc.api.kubernetes.dto.ActiveMemberDto;
import org.poolc.api.kubernetes.repository.KubernetesRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
Expand All @@ -19,7 +20,7 @@ public class KubernetesService {
@Value("${kubernetes.api.key}")
private String API_KEY;

public List<String> getAllActiveMembers(String apiKey) {
public List<ActiveMemberDto> getAllActiveMembers(String apiKey) {
if(!isValidApiKey(apiKey)) {
throw new IllegalArgumentException("Invalid API key");
}
Expand All @@ -43,9 +44,9 @@ public void refreshMemberKey(Map<String,String> requestBody, String apiKey) {
kubernetesRepository.saveAll(mappings);
}

public String getKubernetesKeyByUserId(String userId) {
return kubernetesRepository.findKubernetesKeyByUserId(userId)
.orElseThrow(() -> new IllegalArgumentException("No Kubernetes key found for user: " + userId));
public String getKubernetesKeyByUUID(String UUID) {
return kubernetesRepository.findKubernetesKeyByUUID(UUID)
.orElseThrow(() -> new IllegalArgumentException("No Kubernetes key found for the authenticated user"));
}

private boolean isValidApiKey(String apiKey) {
Expand Down