Feat/180 domain user minsu#26
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis PR establishes the foundational API infrastructure for a mobile data management backend. It introduces OpenAPI/Swagger documentation support, 14 REST controllers spanning apps, data, family, lines, notifications, permissions, policies, and questions domains, corresponding request/response DTOs with OpenAPI annotations, Spring Security configuration, application properties, database schema initialization with migration scripts, and domain entities. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 10
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🟡 Minor comments (11)
src/main/resources/db/migration/V2602231343__convert_timestamp_to_datetime6.sql-1-1 (1)
1-1:⚠️ Potential issue | 🟡 MinorRemove the UTF-8 BOM from the first line of this file.
The file starts with a UTF-8 BOM (byte sequence
efbbbf), which can cause Flyway and some SQL parsers to misinterpret the opening comment. Save the file as UTF-8 without BOM.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/resources/db/migration/V2602231343__convert_timestamp_to_datetime6.sql` at line 1, The first line of the migration file begins with a UTF-8 BOM (byte sequence efbbbf) which can break Flyway/SQL parsing; open the file containing the comment "-- Convert TIMESTAMP columns created in V1__init.sql to DATETIME(6)." and re-save it as UTF-8 without BOM (remove the BOM bytes from the start of the file) so the opening comment is plain ASCII/UTF-8 and no BOM remains.src/main/java/com/pooli/data/domain/dto/response/MonthlyDataUsageResDto.java-27-38 (1)
27-38:⚠️ Potential issue | 🟡 MinorAdd missing Lombok annotations to nested DTO.
MonthlyUsageDtohas@Builderbut is missing@AllArgsConstructorand@NoArgsConstructorannotations. Without these, JSON deserialization with Jackson may fail. The outer class and similar nested DTOs (e.g.,AppUsageDtoinAppDataUsageResDto) include these annotations.🛠️ Proposed fix
`@Builder` `@Getter` + `@AllArgsConstructor`(access = AccessLevel.PRIVATE) + `@NoArgsConstructor`(access = AccessLevel.PRIVATE) `@Schema`(description = "월별 사용량 DTO") public static class MonthlyUsageDto {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/data/domain/dto/response/MonthlyDataUsageResDto.java` around lines 27 - 38, The nested DTO MonthlyUsageDto currently only has `@Builder` and `@Getter` which can break Jackson deserialization; add Lombok annotations `@AllArgsConstructor` and `@NoArgsConstructor` to the MonthlyUsageDto declaration (alongside the existing `@Builder` and `@Getter`) so Jackson can instantiate it, matching the pattern used for other nested DTOs like AppUsageDto in AppDataUsageResDto.build.gradle-31-31 (1)
31-31:⚠️ Potential issue | 🟡 MinorUpdate springdoc-openapi to the latest stable version.
The dependency is compatible with Spring Boot 3.5.10, but version 2.8.5 is outdated. Update to
2.8.15(the latest stable in the 2.8.x line for Spring Boot 3.x, released Jan 1, 2026) unless there's a specific compatibility reason to pin to 2.8.5 (e.g., Spring AI integration).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@build.gradle` at line 31, Update the springdoc-openapi dependency version from 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.5' to 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.15' in the build.gradle dependency block; ensure no other code relies on the older version (e.g., Spring AI integrations) before changing and run a quick build/test to confirm compatibility.src/main/java/com/pooli/line/domain/dto/response/IndividualThresholdResDto.java-12-12 (1)
12-12:⚠️ Potential issue | 🟡 MinorTypo in schema description: "bite" should be "byte".
The unit description has a spelling error that will appear in the API documentation.
📝 Suggested fix
- `@Schema`(description = "개인 데이터 임계치(bite)", example = "3000") + `@Schema`(description = "개인 데이터 임계치(byte)", example = "3000")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/line/domain/dto/response/IndividualThresholdResDto.java` at line 12, The Schema description for the individual data threshold contains a typo ("bite"); update the `@Schema` description in IndividualThresholdResDto (the annotation on the field/property annotated with `@Schema`(description = "개인 데이터 임계치(bite)", example = "3000")) to use the correct unit string "byte" so the API docs read "개인 데이터 임계치(byte)".src/main/java/com/pooli/family/domain/dto/response/FamilySharedPoolResDto.java-12-23 (1)
12-23:⚠️ Potential issue | 🟡 MinorResolve TODO comments about units and type choices before release.
Line 12 and Line 23 read like unresolved questions. Please decide the unit (MB/KB/byte) and numeric type, then update the
@Schemadescriptions and remove the TODOs.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/family/domain/dto/response/FamilySharedPoolResDto.java` around lines 12 - 23, Decide on units and numeric types: use MB as the canonical unit and keep all three fields as Long (poolTotalData, poolRemainingData, pool_base_data); update each `@Schema` description to mention "(MB)" and change the example values to MB-appropriate numbers (e.g., 20, 8.5) or integer MB values as needed, then remove the TODO comments; ensure the field types remain Long in the DTO so no downstream type changes are required.src/main/java/com/pooli/question/domain/dto/response/QuestionResDto.java-3-38 (1)
3-38:⚠️ Potential issue | 🟡 MinorChange
createdAtfromLocalDatetoLocalDateTime.The field is declared as
LocalDatebut the schema example includes a time component (2026-02-23T14:30:00). Additionally, all othercreatedAtfields across the codebase (User, UserRole, PermissionResDto, NotiSendResDto, AppResDto, etc.) useLocalDateTime. Align this field with the codebase pattern and the example format.Suggested fix
-import java.time.LocalDate; +import java.time.LocalDateTime; @@ - `@Schema`(description = "문의사항 생성 시점", example = "2026-02-23T14:30:00") - private LocalDate createdAt; + `@Schema`(description = "문의사항 생성 시점", example = "2026-02-23T14:30:00") + private LocalDateTime createdAt;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/question/domain/dto/response/QuestionResDto.java` around lines 3 - 38, The createdAt field in QuestionResDto is typed as LocalDate but its schema example includes a time and other DTOs use LocalDateTime; update the field type in QuestionResDto from java.time.LocalDate to java.time.LocalDateTime and adjust the import accordingly (replace LocalDate import with LocalDateTime) so the field signature (private LocalDateTime createdAt) and schema example align with the rest of the codebase (class QuestionResDto, field createdAt).src/main/java/com/pooli/policy/domain/dto/request/AppPolicyUpdateReqDto.java-11-15 (1)
11-15:⚠️ Potential issue | 🟡 MinorAlign AppPolicyUpdateReqDto fields with update DTO pattern or explicitly document partial update support.
Lines 11 and 14 lack
requiredMode, while similar update DTOs (BlockPolicyUpdateReqDto,LimitPolicyUpdateReqDto) mark their fields asrequiredMode = Schema.RequiredMode.REQUIRED. The controller's null-checking logic (applyingBoolean.FALSEand0defaults) suggests this DTO intentionally supports partial updates, but this should be either:
- Explicitly documented in the class or field descriptions, OR
- Aligned with other update DTOs by adding
requiredMode = Schema.RequiredMode.REQUIREDif full updates are expected✏️ Option 1: Align with other update DTOs
- `@Schema`(description = "앱 정책 활성화 여부", example = "true") + `@Schema`(description = "앱 정책 활성화 여부", example = "true", requiredMode = Schema.RequiredMode.REQUIRED) private Boolean enabled; - `@Schema`(description = "일일 제한량(MB)", example = "500") + `@Schema`(description = "일일 제한량(MB)", example = "500", requiredMode = Schema.RequiredMode.REQUIRED) private Integer dailyLimitMb;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/policy/domain/dto/request/AppPolicyUpdateReqDto.java` around lines 11 - 15, AppPolicyUpdateReqDto currently leaves the fields enabled and dailyLimitMb without Schema.requiredMode while similar update DTOs (BlockPolicyUpdateReqDto, LimitPolicyUpdateReqDto) mark fields as required; update this DTO to either (a) mark both fields with `@Schema`(requiredMode = Schema.RequiredMode.REQUIRED) to match the other update DTOs if full updates are expected, or (b) explicitly document partial-update semantics on the class or these field Schemas (e.g., note that null means “no change”) to match the controller’s null-checking logic that applies defaults; locate AppPolicyUpdateReqDto and edit the annotations or Javadoc for enabled and dailyLimitMb accordingly.src/main/java/com/pooli/data/domain/dto/response/AppDataUsageResDto.java-15-15 (1)
15-15:⚠️ Potential issue | 🟡 MinorTypo: "bite" should be "byte".
The schema description says "bite" but should be "byte". This typo also appears in related DTOs (
DataBalancesResDto,MonthlyDataUsageResDto).🔧 Fix typo
- `@Schema`(description = "총 사용 데이터량(bite)", example = "5200") + `@Schema`(description = "총 사용 데이터량(byte)", example = "5200")🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/data/domain/dto/response/AppDataUsageResDto.java` at line 15, Fix the typo in the `@Schema` description texts: change "총 사용 데이터량(bite)" to "총 사용 데이터량(byte)" in AppDataUsageResDto (class name) and make the same correction in the related DTOs DataBalancesResDto and MonthlyDataUsageResDto so their `@Schema` descriptions/examples use "byte" instead of "bite".src/main/java/com/pooli/notification/domain/dto/request/AlarmSettingReqDto.java-12-28 (1)
12-28:⚠️ Potential issue | 🟡 MinorMake DTO fields private for encapsulation.
Line 12-28 declare package-private fields. Standard DTO practice is
privatefields with Lombok accessors to avoid unintended access across packages.🔒 Proposed fix
- Boolean familyAlarm; + private Boolean familyAlarm; ... - Boolean questionAlarm; + private Boolean questionAlarm;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/notification/domain/dto/request/AlarmSettingReqDto.java` around lines 12 - 28, The DTO AlarmSettingReqDto exposes package-private Boolean fields (familyAlarm, userAlarm, policyChangeAlarm, policyLimitAlarm, permissionAlarm, questionAlarm); change each field to private and rely on existing Lombok accessors (or add `@Getter/`@Setter) so fields are encapsulated, update any direct field accesses to use getters/setters if present elsewhere, and ensure serialization frameworks still see the fields (e.g., keep Lombok annotations or add `@JsonProperty` if needed).src/main/java/com/pooli/data/domain/dto/response/DataBalancesResDto.java-16-20 (1)
16-20:⚠️ Potential issue | 🟡 MinorFix unit typo in schema description (“bite” → “byte”).
This is user-facing Swagger text.
✏️ Proposed fix
- `@Schema`(description = "가족 공유 데이터 잔량(bite)", example = "5000") + `@Schema`(description = "가족 공유 데이터 잔량(byte)", example = "5000") private Long sharedDataRemaining; - `@Schema`(description = "개인 데이터 잔량(bite)", example = "2000") + `@Schema`(description = "개인 데이터 잔량(byte)", example = "2000") private Long personalDataRemaining;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/data/domain/dto/response/DataBalancesResDto.java` around lines 16 - 20, The `@Schema` descriptions on DataBalancesResDto currently use the typo "bite"; update the user-facing Swagger text for the fields sharedDataRemaining and personalDataRemaining to use "byte" instead of "bite" so the descriptions read e.g. "가족 공유 데이터 잔량(byte)" and "개인 데이터 잔량(byte)". Ensure both `@Schema` annotations on the sharedDataRemaining and personalDataRemaining fields are corrected.src/main/java/com/pooli/data/controller/DataController.java-49-80 (1)
49-80:⚠️ Potential issue | 🟡 MinorUse the
monthparam (or validate it) to avoid misleading responses.The handler always returns 3 months regardless of the request, which conflicts with the API description.
💡 One way to apply the parameter
- List<MonthlyDataUsageResDto.MonthlyUsageDto> usages = List.of( + List<MonthlyDataUsageResDto.MonthlyUsageDto> allUsages = List.of( MonthlyDataUsageResDto.MonthlyUsageDto.builder() .yearMonth("2026-01") .usedAmount(1000L) .build(), MonthlyDataUsageResDto.MonthlyUsageDto.builder() .yearMonth("2026-02") .usedAmount(1500L) .build(), MonthlyDataUsageResDto.MonthlyUsageDto.builder() .yearMonth("2026-03") .usedAmount(1100L) .build() ); - Long average = usages.stream() - .mapToLong(MonthlyDataUsageResDto.MonthlyUsageDto::getUsedAmount) - .sum() / usages.size(); + int count = Math.min(Math.max(month, 0), allUsages.size()); + List<MonthlyDataUsageResDto.MonthlyUsageDto> usages = allUsages.subList(0, count); + + Long average = usages.isEmpty() ? 0L : usages.stream() + .mapToLong(MonthlyDataUsageResDto.MonthlyUsageDto::getUsedAmount) + .sum() / usages.size();🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/data/controller/DataController.java` around lines 49 - 80, getMonthlyDataUsage currently ignores the request param month and always returns three hard-coded MonthlyUsageDto entries; update the method to use/validate the month param (e.g., ensure month > 0 and within a sensible max) and generate the usages list dynamically for the requested number of months (or return 400 if invalid). Locate getMonthlyDataUsage in DataController and replace the hard-coded List.of(...) construction with logic that builds MonthlyDataUsageResDto.MonthlyUsageDto items based on the month parameter (using YearMonth or similar to compute yearMonth strings) and recompute averageAmount from that generated list.
🧹 Nitpick comments (29)
src/main/resources/application.yaml (2)
17-17: Ensurebaseline-on-migrateis disabled in production.Setting
baseline-on-migrate: trueon an existing database will create a baseline and may skip pending migrations. Ensure this is set tofalsein production environments to avoid accidental data migration issues.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/resources/application.yaml` at line 17, The Flyway setting baseline-on-migrate is currently controlled by ${FLYWAY_BASELINE_ON_MIGRATE} in application.yaml; ensure this is disabled in production by setting the FLYWAY_BASELINE_ON_MIGRATE environment variable to "false" (or hardcode baseline-on-migrate: false in the production profile), and verify that any deployment/config map or prod Spring profile does not override it to true so migrations will not be baselined accidentally.
11-13: Consider adding HikariCP pool settings for production readiness.The HikariCP configuration only includes
initialization-fail-timeout. For production environments, consider configuring additional pool settings such asmaximum-pool-size,minimum-idle,connection-timeout, andidle-timeoutto prevent resource exhaustion under load.Example HikariCP settings
hikari: # Do not fail app startup immediately when DB is unavailable initialization-fail-timeout: ${DB_INIT_FAIL_TIMEOUT} + maximum-pool-size: ${DB_POOL_MAX_SIZE:10} + minimum-idle: ${DB_POOL_MIN_IDLE:5} + connection-timeout: ${DB_CONNECTION_TIMEOUT:30000} + idle-timeout: ${DB_IDLE_TIMEOUT:600000}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/resources/application.yaml` around lines 11 - 13, Add production-ready HikariCP properties alongside the existing hikari.initialization-fail-timeout: configure hikari.maximum-pool-size, hikari.minimum-idle, hikari.connection-timeout, and hikari.idle-timeout with sensible defaults or environment variables; update application.yaml to read these values (e.g., ${DB_MAX_POOL_SIZE}, ${DB_MIN_IDLE}, ${DB_CONN_TIMEOUT}, ${DB_IDLE_TIMEOUT}) so the pool sizing and timeouts are controllable in different environments and prevent resource exhaustion under load.src/main/resources/db/migration/V2602231343__convert_timestamp_to_datetime6.sql (1)
4-74: Plan for DDL locking/rebuild impact.
A long sequence ofALTER TABLE ... MODIFY COLUMNcan lock or rebuild large tables in MySQL. If this is a production migration, consider an online schema change strategy or a maintenance window.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/resources/db/migration/V2602231343__convert_timestamp_to_datetime6.sql` around lines 4 - 74, This migration runs many blocking ALTER TABLE ... MODIFY COLUMN statements (e.g., ALTER TABLE `DAILY_APP_TOTAL_DATA` MODIFY COLUMN `created_at`..., ALTER TABLE `USERS` MODIFY COLUMN `updated_at`..., ALTER TABLE `ANSWER` MODIFY COLUMN `deleted_at`...), which can lock/rebuild large tables; resolve by converting this single-file migration into a safe deployment plan: either run the changes during a maintenance window, or perform non-blocking online schema changes using tools like pt-online-schema-change or gh-ost per table (or implement a staged deploy that adds new DATETIME(6) columns, backfills, swaps names, drops old columns), and update the migration file / runbook to reflect the chosen approach and include the tool/command or maintenance-window schedule for each of the listed tables.src/main/java/com/pooli/policy/domain/dto/request/PolicyActivationReqDto.java (1)
11-16: Consider adding@NotNullvalidation for runtime enforcement.The
@Schema(requiredMode = REQUIRED)annotation only documents the field as required in OpenAPI specs but doesn't enforce it at runtime. Consider adding Bean Validation annotations to ensure the constraint is enforced when the request is processed.💡 Proposed fix to add validation
package com.pooli.policy.domain.dto.request; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.Setter; `@Getter` `@Setter` `@Schema`(description = "정책 활성화 요청 바디") public class PolicyActivationReqDto { + `@NotNull`(message = "policyId는 필수입니다") `@Schema`( description = "활성화할 정책 식별자", example = "1003", requiredMode = Schema.RequiredMode.REQUIRED ) private Long policyId; }Note: Ensure the controller method parameter is annotated with
@Validto trigger validation.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/policy/domain/dto/request/PolicyActivationReqDto.java` around lines 11 - 16, The PolicyActivationReqDto class has policyId annotated with `@Schema`(requiredMode = REQUIRED) which only documents the requirement; add javax.validation.constraints.NotNull (or jakarta.validation.constraints.NotNull) to the policyId field in PolicyActivationReqDto to enforce runtime validation, and ensure any controller method receiving PolicyActivationReqDto is annotated with `@Valid` on the parameter so bean validation is triggered at request binding.src/main/java/com/pooli/policy/domain/dto/request/LimitPolicyUpdateReqDto.java (1)
11-12: Consider adding@NotNullvalidation for runtime enforcement.Similar to
PolicyActivationReqDto, the@Schema(requiredMode = REQUIRED)only affects API documentation. Add@NotNullto enforce the requirement at runtime.💡 Proposed fix
+import jakarta.validation.constraints.NotNull; + `@Getter` `@Setter` `@Schema`(description = "제한 정책 단건 수정 요청") public class LimitPolicyUpdateReqDto { + `@NotNull`(message = "policyValue는 필수입니다") `@Schema`(description = "수정할 정책 값", example = "1024", requiredMode = Schema.RequiredMode.REQUIRED) private Integer policyValue; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/policy/domain/dto/request/LimitPolicyUpdateReqDto.java` around lines 11 - 12, Add javax.validation.constraints.NotNull to enforce runtime validation on the policyValue field in LimitPolicyUpdateReqDto: annotate the field policyValue with `@NotNull` (in addition to the existing `@Schema`) so the validation framework will reject nulls at runtime; ensure the import for NotNull is added and that this DTO is validated where used (e.g., controller methods annotated with `@Valid`).src/main/java/com/pooli/family/domain/dto/request/CreateSharedPoolContributionReqDto.java (2)
12-16: Inconsistent ID types across DTOs.The identifier types differ between DTOs: this DTO uses
IntegerforfamilyIdandlineId, whileFamilyMembersSimpleResDtousesLongforlineIdanduserId. Consider standardizing onLongfor all entity identifiers to avoid potential mapping issues and to accommodate future growth.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/family/domain/dto/request/CreateSharedPoolContributionReqDto.java` around lines 12 - 16, The DTO CreateSharedPoolContributionReqDto currently declares familyId and lineId as Integer; change both fields to Long to match FamilyMembersSimpleResDto (which uses Long for lineId and userId), update any corresponding getters/setters or Lombok annotations, and adjust `@Schema` example values (e.g., "1" -> "1") and any validation or mapping code that assumes Integer so the identifier types are consistent across DTOs and mappings.
12-19: Add validation annotations for request fields.This request DTO lacks validation annotations. For a contribution request, consider:
familyIdandlineIdshould be non-nullamountshould be non-null and positive (users shouldn't contribute zero or negative data)💡 Proposed fix to add validation
package com.pooli.family.domain.dto.request; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; import lombok.Getter; import lombok.Setter; `@Getter` `@Setter` `@Schema`(description = "공유풀 데이터 담기 요청 DTO") public class CreateSharedPoolContributionReqDto { + `@NotNull` `@Schema`(description = "가족 식별자", example = "1") private Integer familyId; + `@NotNull` `@Schema`(description = "회선 식별자", example = "10") private Integer lineId; + `@NotNull` + `@Positive` `@Schema`(description = "공유풀에 담을 데이터량(MB)", example = "500") private Long amount; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/family/domain/dto/request/CreateSharedPoolContributionReqDto.java` around lines 12 - 19, Add bean validation annotations to the CreateSharedPoolContributionReqDto: mark familyId and lineId with `@NotNull`, and mark amount with `@NotNull` plus a positivity constraint (e.g., `@Positive` or `@Min`(1)) so contributions cannot be zero/negative; update imports to use the proper validation package (javax.validation.constraints.* or jakarta.validation.constraints.*) and ensure the DTO class is validated where requests are bound (e.g., controller methods expecting CreateSharedPoolContributionReqDto).src/main/java/com/pooli/data/domain/dto/response/MonthlyDataUsageResDto.java (1)
23-25: Mutable setter breaks immutability pattern.The
updateAverageAmountmethod introduces mutability, which is inconsistent with other response DTOs in the codebase that use immutable patterns (private constructors + builder). Consider computingaverageAmountduring construction instead, or if post-construction mutation is required, document why this exception is necessary.💡 Alternative: compute average in a static factory
public static MonthlyDataUsageResDto of(List<MonthlyUsageDto> usages) { Long average = usages.isEmpty() ? 0L : usages.stream() .mapToLong(MonthlyUsageDto::getUsedAmount) .average() .orElse(0.0).longValue(); return MonthlyDataUsageResDto.builder() .usages(usages) .averageAmount(average) .build(); }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/data/domain/dto/response/MonthlyDataUsageResDto.java` around lines 23 - 25, The updateAverageAmount method in MonthlyDataUsageResDto introduces post-construction mutability; remove or deprecate this setter and compute averageAmount at creation instead by adding a static factory (e.g., MonthlyDataUsageResDto.of(List<MonthlyUsageDto> usages)) that computes the average (handle empty lists by returning 0L), then build the DTO via the existing builder with usages and averageAmount set; if mutation truly is required, make updateAverageAmount private and add a comment explaining the exceptional need instead of a public setter.src/main/java/com/pooli/permission/domain/dto/request/PermissionReqDto.java (2)
11-12: Consider specifyingrequiredModefor API clarity.Other request DTOs in this PR (e.g.,
BlockPolicyUpdateReqDto) specifyrequiredMode = Schema.RequiredMode.REQUIREDfor mandatory fields. IfpermissionTitleis required for permission creation/update, add this for consistent API documentation.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/permission/domain/dto/request/PermissionReqDto.java` around lines 11 - 12, The `@Schema` on permissionTitle in PermissionReqDto should mark the field as required for consistent API docs; update the annotation to include requiredMode = Schema.RequiredMode.REQUIRED (e.g., `@Schema`(description = "권한 이름", example = "데이터 차단", requiredMode = Schema.RequiredMode.REQUIRED)) so the field appears required like other DTOs such as BlockPolicyUpdateReqDto and ensure any necessary import for Schema.RequiredMode is present.
4-4: Prefer explicit imports over wildcard.The wildcard import
lombok.*is used but only@Getterand@Setterare needed. Related DTOs in this codebase use explicit imports for consistency.♻️ Suggested fix
-import lombok.*; +import lombok.Getter; +import lombok.Setter;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/permission/domain/dto/request/PermissionReqDto.java` at line 4, Replace the wildcard Lombok import with explicit imports: remove "import lombok.*;" and add only the annotations used in PermissionReqDto (e.g., "import lombok.Getter;" and "import lombok.Setter;") so the class uses explicit imports consistent with the codebase; update the import statement near the PermissionReqDto class accordingly.src/main/java/com/pooli/policy/domain/dto/response/PolicyActivationResDto.java (1)
18-19: Consider using a typed date/time representation.Using
StringforactivatedAtworks but loses compile-time type safety and relies on consistent formatting. ConsiderLocalDateTimeorOffsetDateTimewith a@JsonFormatannotation for stricter typing, though the current approach is consistent withPolicyDeactivationResDto.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/policy/domain/dto/response/PolicyActivationResDto.java` around lines 18 - 19, Change the activatedAt field in PolicyActivationResDto from String to a typed temporal type (e.g., java.time.OffsetDateTime or java.time.LocalDateTime) to gain compile-time safety; update the field declaration activatedAt accordingly, add the appropriate `@JsonFormat`(pattern = "...", timezone = "...") (and/or `@JsonSerialize/`@JsonDeserialize if needed) and adjust the `@Schema` example to match the chosen format, and ensure imports are added; mirror the same approach used in PolicyDeactivationResDto (or update that DTO for consistency) so serialization/deserialization behavior is consistent across both DTOs.src/main/java/com/pooli/policy/domain/dto/response/AdminPolicyResDto.java (1)
24-25: Consider usingLocalDateTimefor the timestamp field.The
updatedAtfield is typed asString, while other response DTOs in this codebase (e.g.,SimpleMessageResDto,PermissionResDto,MemberPermissionResDto) useLocalDateTimefor timestamp fields. Using a consistent type improves type safety and ensures uniform serialization behavior across the API.♻️ Suggested change
+import java.time.LocalDateTime; + `@Schema`(description = "최종 수정 시각", example = "2026-02-20T10:10:00") - private String updatedAt; + private LocalDateTime updatedAt;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/policy/domain/dto/response/AdminPolicyResDto.java` around lines 24 - 25, The updatedAt field in AdminPolicyResDto is a String but should be LocalDateTime to match other DTOs and ensure consistent serialization; change the type of the updatedAt field in class AdminPolicyResDto from String to java.time.LocalDateTime, add the necessary import, and update the `@Schema` example/format if needed (e.g., ensure example uses an ISO-8601 datetime) so Jackson/DateTime serializers for LocalDateTime are applied consistently across SimpleMessageResDto, PermissionResDto, and MemberPermissionResDto.src/main/java/com/pooli/notification/domain/dto/request/NotiSendReqDto.java (1)
17-18: Field name should be plural to match theListtype.The field is declared as
List<Long>but nameduserId(singular). This can be confusing for API consumers. Additionally, the@Schemaexample shows"1"which doesn't represent a list value.♻️ Suggested fix
- `@Schema`(description = "알림 보낼 사용자 ID", example = "1") - private List<Long> userId; // 여러명한테 보낼걸 대비해 List 형태 + `@Schema`(description = "알림 보낼 사용자 ID 목록", example = "[1, 2, 3]") + private List<Long> userIds;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/notification/domain/dto/request/NotiSendReqDto.java` around lines 17 - 18, Rename the field userId in NotiSendReqDto to a plural form (e.g., userIds) and update its `@Schema` to reflect a list type (change description to "알림 보낼 사용자 ID 목록" and example to a JSON array like "[1]" or "[1,2]"); also update all references (getters/setters, constructors, builders, DTO mappings, and any code that accesses NotiSendReqDto.userId) to use the new field name to avoid compile errors and keep the API contract consistent.src/main/java/com/pooli/permission/controller/RoleController.java (1)
29-39: Stub implementation lacks validation and business logic.The endpoint currently echoes input parameters without performing actual role transfer. While this appears to be intentional scaffolding for API documentation, consider adding:
- Validation to ensure
currentUserIdandchangeUserIdare different- Service layer injection when implementing actual business logic
♻️ Example validation
public ResponseEntity<RepresentativeRoleTransferResDto> transferRepresentativeRole( `@Parameter`(description = "현재 대표 사용자 ID", example = "101") `@RequestParam` Long currentUserId, `@Parameter`(description = "변경 대상 사용자 ID", example = "202") `@RequestParam` Long changeUserId) { + if (currentUserId.equals(changeUserId)) { + throw new IllegalArgumentException("현재 대표와 변경 대상이 동일할 수 없습니다."); + } + // TODO: Inject and call service layer for actual role transfer RepresentativeRoleTransferResDto representativeRoleTransferResDto = RepresentativeRoleTransferResDto.builder()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/permission/controller/RoleController.java` around lines 29 - 39, The transferRepresentativeRole controller method currently just echoes inputs and lacks validation and service call; update transferRepresentativeRole to validate that currentUserId and changeUserId are not null and are different (return 400/throw a validation exception if invalid), inject and call a RoleService (e.g., roleService.transferRepresentative(currentUserId, changeUserId)) to perform business logic, and build RepresentativeRoleTransferResDto from the service result instead of blindly returning the request values; ensure the method signature and DTO usage remain, and add appropriate exception handling to translate service errors into HTTP responses.src/main/java/com/pooli/family/domain/dto/response/FamilySharedPoolResDto.java (1)
20-21: Renamepool_base_datatopoolBaseDatafor consistency with Java conventions and other fields in this DTO.All other fields in
FamilySharedPoolResDtouse camelCase (poolTotalData,poolRemainingData,monthlyUsageAmount,monthlyContributionAmount), and all DTOs across the codebase follow the same convention. The snake_case field stands out as an inconsistency.Suggested rename
- `@Schema`(description = "공유풀 기본 제공량(bite)", example = "8500") - private Long pool_base_data; + `@Schema`(description = "공유풀 기본 제공량(bite)", example = "8500") + private Long poolBaseData;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/family/domain/dto/response/FamilySharedPoolResDto.java` around lines 20 - 21, Rename the snake_case field pool_base_data in FamilySharedPoolResDto to camelCase poolBaseData to match the DTO convention; update the field declaration and any corresponding getter/setter and usages (e.g., getPool_base_data / setPool_base_data) to getPoolBaseData / setPoolBaseData, and adjust any JSON annotations if present (e.g., `@JsonProperty`) or mapping code that references "pool_base_data" so serialization/deserialization and all references compile and remain consistent with the other fields like poolTotalData and poolRemainingData.src/main/java/com/pooli/question/domain/dto/QuestionAttachmentDto.java (1)
20-21: AlignfileSizewith codebase pattern by usingLonginstead of primitiveint.All other numeric fields in DTOs throughout the codebase use boxed types (
Long,Integer). UsingLongforfileSizemaintains consistency, supports potential null values in DTOs, and avoids the ~2GB cap of primitiveint.♻️ Suggested change
- private int fileSize; + private Long fileSize;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/question/domain/dto/QuestionAttachmentDto.java` around lines 20 - 21, Change the QuestionAttachmentDto.field fileSize from primitive int to boxed Long to match DTO numeric patterns and allow nulls; update the field type in class QuestionAttachmentDto (and any corresponding getter/setter or builder/constructor references) and ensure the `@Schema` annotation remains, adjusting example if needed to a long literal (e.g., "204800")—also update any serialization/deserialization usages or tests that assume an int to accept Long.src/main/java/com/pooli/family/domain/dto/request/UpdateSharedDataThresholdReqDto.java (1)
10-12: Consider adding validation for the threshold value.The
newFamilyThresholdfield lacks validation. Negative or null values could cause issues. Also, the example value of "1500" bytes (~1.5KB) seems unusually small for a data usage threshold—consider if this should be in MB or if the example should be larger (e.g.,"1073741824"for 1GB).💡 Proposed validation
+import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Positive; + `@Getter` `@Setter` `@Schema`(description = "가족 공유 데이터 사용량 임계치 수정 요청 DTO") public class UpdateSharedDataThresholdReqDto { + `@NotNull` + `@Positive` - `@Schema`(description = "새로운 임계치 값(단위: Byte)", example = "1500") + `@Schema`(description = "새로운 임계치 값(단위: Byte)", example = "1073741824") private Long newFamilyThreshold; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/family/domain/dto/request/UpdateSharedDataThresholdReqDto.java` around lines 10 - 12, The UpdateSharedDataThresholdReqDto.newFamilyThreshold field lacks validation and has a misleading small example; add javax/hibernate validation annotations (e.g., `@NotNull` and `@Positive` or `@Min`(1)) to newFamilyThreshold in class UpdateSharedDataThresholdReqDto and update the `@Schema` example to a realistic value (e.g., "1073741824" for 1GB) and a clear unit description, and ensure callers (controllers) validate incoming DTOs with `@Valid` so the annotations are enforced.src/main/java/com/pooli/data/domain/dto/response/AppDataUsageResDto.java (1)
21-31: NestedAppUsageDtois missing@NoArgsConstructor.The nested
AppUsageDtoclass lacks@NoArgsConstructor, which may cause issues with Jackson deserialization or certain frameworks that require a no-args constructor. Other nested DTOs in the codebase (e.g.,MonthlyUsageDto) also follow this pattern, but it's worth ensuring consistency with the outer class annotations.Also, the "bite" typo on line 29 should be "byte".
💡 Proposed fix
`@Getter` `@Builder` + `@NoArgsConstructor`(access = AccessLevel.PRIVATE) + `@AllArgsConstructor`(access = AccessLevel.PRIVATE) `@Schema`(description = "앱별 사용량 DTO") public static class AppUsageDto { `@Schema`(description = "애플리케이션 이름", example = "YouTube") private String appName; - `@Schema`(description = "사용량(bite)", example = "2000") + `@Schema`(description = "사용량(byte)", example = "2000") private Long usedAmount; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/data/domain/dto/response/AppDataUsageResDto.java` around lines 21 - 31, Add a no-args constructor annotation to the nested DTO and fix the typo in the Schema description: annotate the nested class AppUsageDto with Lombok's `@NoArgsConstructor` (in addition to the existing `@Getter/`@Builder) so Jackson/other frameworks can instantiate it, and change the `@Schema` description for usedAmount from "사용량(bite)" to "사용량(byte)". Ensure imports for lombok.NoArgsConstructor are present if missing.src/main/java/com/pooli/application/controller/AppController.java (2)
28-28: Reconsider 404 response for list endpoint.A "list all" endpoint typically returns 200 with an empty list when no items exist, rather than 404. The 404 status is more appropriate for single-resource lookups (e.g.,
/api/apps/{id}). This is consistent with other controllers in the codebase (e.g.,NotiReadController), but worth reconsidering for semantic correctness.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/application/controller/AppController.java` at line 28, The list endpoint in AppController currently declares a 404 ApiResponse which is inappropriate for a collection resource; update the API responses on the list method (e.g., the method in AppController that returns the app list) to remove the 404 response and ensure it documents a 200 response that can return an empty list (match behavior used in NotiReadController); adjust the `@ApiResponse` annotations accordingly so the method only documents successful 200 responses (and any relevant error codes like 500) rather than 404 for "no items".
22-35: Fix inconsistent indentation.The method body has extra leading spaces compared to the class-level indentation. This affects code readability.
🔧 Proposed fix for indentation
- `@Operation`( - summary = "애플리케이션 목록 조회", - description = "애플리케이션 ID 기준 등록된 애플리케이션 목록을 모두 조회한다." - ) - `@ApiResponses`({ - `@ApiResponse`(responseCode = "200", description = "조회 성공"), - `@ApiResponse`(responseCode = "404", description = "앱 정보가 존재하지 않음"), - `@ApiResponse`(responseCode = "500", description = "서버 오류"), - - }) - `@GetMapping` - public ResponseEntity<List<AppResDto>> getApps(){ - return ResponseEntity.ok(List.of()); - } + `@Operation`( + summary = "애플리케이션 목록 조회", + description = "애플리케이션 ID 기준 등록된 애플리케이션 목록을 모두 조회한다." + ) + `@ApiResponses`({ + `@ApiResponse`(responseCode = "200", description = "조회 성공"), + `@ApiResponse`(responseCode = "404", description = "앱 정보가 존재하지 않음"), + `@ApiResponse`(responseCode = "500", description = "서버 오류"), + }) + `@GetMapping` + public ResponseEntity<List<AppResDto>> getApps() { + return ResponseEntity.ok(List.of()); + }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/application/controller/AppController.java` around lines 22 - 35, The getApps method in AppController has inconsistent indentation in its body; align the method signature and body with the class-level indentation by removing the extra leading spaces before the annotations and the method block so that `@Operation`, `@ApiResponses`, `@GetMapping` and the method declaration public ResponseEntity<List<AppResDto>> getApps() and its body use the same indentation level as other class members in AppController; ensure opening and closing braces and the return statement are indented consistently with the surrounding methods.src/main/java/com/pooli/permission/domain/dto/request/MemberPermissionUpsertReqDto.java (1)
12-17: Consider adding validation annotations for required fields.The DTO lacks
@NotNullor other Bean Validation annotations. IfpermissionIdandisEnableare required for the upsert operation, adding validation would prevent invalid requests from reaching the service layer.💡 Optional: Add validation annotations
+import jakarta.validation.constraints.NotNull; + `@Getter` `@Setter` `@Schema`(description = "구성원 권한 부여 변경 요청 DTO") public class MemberPermissionUpsertReqDto { + `@NotNull` `@Schema`(description = "권한 ID", example = "1") private Integer permissionId; + `@NotNull` `@JsonProperty`("is_enable") `@Schema`(description = "권한 활성화 여부", example = "true") private Boolean isEnable; }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/permission/domain/dto/request/MemberPermissionUpsertReqDto.java` around lines 12 - 17, Add Bean Validation to the DTO by annotating MemberPermissionUpsertReqDto's fields that are required: add `@NotNull` to the permissionId and isEnable fields (retain the existing `@JsonProperty`("is_enable") on isEnable), and ensure javax.validation.constraints.NotNull is imported; after this change, make sure any controllers that accept MemberPermissionUpsertReqDto are validating input (e.g., `@Valid` on the controller parameter) so the validation takes effect.src/main/java/com/pooli/common/config/SecurityConfig.java (1)
15-15: CSRF disabled - document the rationale.CSRF protection is disabled, which is common for stateless REST APIs using token-based authentication. However, if the API will use session-based auth or cookies, CSRF protection should be re-enabled. Consider adding a comment explaining why CSRF is disabled.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/common/config/SecurityConfig.java` at line 15, CSRF is being explicitly disabled in SecurityConfig via the .csrf(csrf -> csrf.disable()) call; add a concise comment next to that expression explaining the rationale (e.g., this is a stateless REST API using token-based auth so CSRF is unnecessary) and note the conditions under which it must be re-enabled (e.g., if session/cookie-based auth is introduced). Ensure the comment references SecurityConfig and the .csrf(...) line so future reviewers know why CSRF was turned off and when to revert the change.src/main/java/com/pooli/family/domain/dto/response/FamilyMembersSimpleResDto.java (1)
15-19: Type consistency with existing family DTOs.Line 15-19 use
LongforlineId/userId, butFamilyMembersResDto(src/main/java/com/pooli/family/domain/dto/response/FamilyMembersResDto.java, lines 28-38) usesInteger. Aligning types across DTOs will prevent client-side parsing inconsistencies.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/family/domain/dto/response/FamilyMembersSimpleResDto.java` around lines 15 - 19, The DTO FamilyMembersSimpleResDto currently declares fields lineId and userId as Long; change both to Integer to match the existing FamilyMembersResDto and ensure type consistency across DTOs (update the field types in FamilyMembersSimpleResDto and adjust any related getters/setters/constructors or usages that reference lineId/userId to use Integer as well, and keep or update the `@Schema` examples to valid Integer examples if needed).src/main/java/com/pooli/notification/controller/NotiSendController.java (1)
35-37: Return created resources (or adjust status).Line 35-37 always return
201with an empty list. Consider returning the created notifications (or aLocationheader), or switch to a status that matches the empty body to avoid ambiguous client behavior.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/notification/controller/NotiSendController.java` around lines 35 - 37, The sendAlarm method in NotiSendController currently responds with 201 Created and an empty body which is misleading; update sendAlarm to return the actual created notifications (map service result to List<NotiSendResDto>) and respond with ResponseEntity.created(URI).body(createdList) or, if you don’t have a single resource URI, include a Location header (or return 200/204 to match an empty body). Locate sendAlarm and the request/response DTOs (NotiSendReqDto, NotiSendResDto) and either call the notification creation service, map results into NotiSendResDto and return a 201 with body and Location, or change the status to 200/204 when intentionally returning no content.src/main/java/com/pooli/data/domain/dto/request/DataTransferReqDto.java (1)
12-19: Validate required/positive transfer fields.Line 12-19 accept null/negative values as-is. Consider enforcing non-null and positive checks at the DTO or controller/service validation layer so invalid transfers are rejected early.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/data/domain/dto/request/DataTransferReqDto.java` around lines 12 - 19, The DTO fields fromLineId, toLineId and amount in DataTransferReqDto allow null/negative values; add validation annotations to enforce non-null and positive values (e.g., `@NotNull` on fromLineId and toLineId and `@NotNull/`@Positive on amount or `@PositiveOrZero` if zero allowed) and ensure the consuming controller method accepts `@Valid` DataTransferReqDto so validation is triggered; update any service-level checks if additional business rules (like fromLineId != toLineId) are required and include descriptive validation messages.src/main/java/com/pooli/policy/domain/dto/response/FamilyPolicyChangeResDto.java (1)
18-22: Use a typed timestamp forprocessedAt.Line 21-22 define
processedAtasStringeven though the example is ISO-8601. For consistency and type-safety, consider switching toLocalDateTime(or apply a fixed format annotation) to avoid format drift.♻️ Proposed refactor
- `@Schema`(description = "처리 시각", example = "2026-02-20T10:10:00") - private String processedAt; + `@Schema`(description = "처리 시각", example = "2026-02-20T10:10:00") + private LocalDateTime processedAt;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/policy/domain/dto/response/FamilyPolicyChangeResDto.java` around lines 18 - 22, Change the processedAt field in FamilyPolicyChangeResDto from String to java.time.LocalDateTime and add a Jackson serialization format so the ISO-8601 example is preserved: update the field type to LocalDateTime (add import), annotate processedAt with `@JsonFormat`(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss") (and keep or adjust the `@Schema` example if desired) so serialization/deserialization is consistent and type-safe; ensure necessary imports (java.time.LocalDateTime and com.fasterxml.jackson.annotation.JsonFormat) are added and update any constructors/getters/setters or mappers referencing processedAt accordingly.src/main/java/com/pooli/family/controller/FamilyController.java (1)
42-47: UseLongfor familyId/lineId to align with BIGINT IDs.Integer can overflow or reject valid values once IDs grow. Consider switching to
Longhere (and mirror the change in/members-simple) for consistency with schema/DTOs.♻️ Proposed change
- public ResponseEntity<FamilyMembersResDto> getFamilyMembers( - `@Parameter`(description = "가족 ID", example = "1") - `@RequestParam` Integer familyId, - - `@Parameter`(description = "회선 ID", example = "10") - `@RequestParam` Integer lineId + public ResponseEntity<FamilyMembersResDto> getFamilyMembers( + `@Parameter`(description = "가족 ID", example = "1") + `@RequestParam` Long familyId, + + `@Parameter`(description = "회선 ID", example = "10") + `@RequestParam` Long lineId ) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/family/controller/FamilyController.java` around lines 42 - 47, The request parameters in FamilyController.getFamilyMembers use Integer for familyId and lineId but your DB and DTOs use BIGINT; change the parameter types from Integer to Long (for both `@RequestParam` familyId and lineId) to avoid overflow and type mismatch, and make the same change for the analogous endpoint (/members-simple) so controller signatures align with your DTOs/entities/DTO classes that expect Long IDs; update any usages within these methods to use long/Long accordingly.src/main/resources/db/migration/V1__init.sql (1)
353-415: Add UNIQUE constraints where “UK” is indicated in comments.Columns like
QUESTION_CATEGORY.question_category_name,LINE.phone, andUSERS.emailare marked as unique but not enforced, which can allow duplicates.➕ Example UNIQUE constraints
+ALTER TABLE `QUESTION_CATEGORY` + ADD CONSTRAINT `UK_QUESTION_CATEGORY_NAME` UNIQUE (`question_category_name`); + +ALTER TABLE `LINE` + ADD CONSTRAINT `UK_LINE_PHONE` UNIQUE (`phone`); + +ALTER TABLE `USERS` + ADD CONSTRAINT `UK_USERS_EMAIL` UNIQUE (`email`);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/resources/db/migration/V1__init.sql` around lines 353 - 415, Add UNIQUE constraints for every column marked "UK" in the migration by adding ALTER TABLE ... ADD CONSTRAINT UK_<TABLE>_<COLUMN> UNIQUE(<column>) statements; specifically ensure QUESTION_CATEGORY.question_category_name, LINE.phone, and USERS.email are made unique (use constraint names like UK_QUESTION_CATEGORY_question_category_name, UK_LINE_phone, UK_USERS_email) and add similar UK constraints for any other columns noted as UK in the file so duplicates cannot be inserted.src/main/java/com/pooli/line/controller/LineController.java (1)
57-61: PreferLongfor lineId to match DTO/schema types.Aligning the request param with BIGINT/Long avoids range issues and keeps types consistent across layers.
♻️ Proposed change
- public ResponseEntity<IndividualThresholdResDto> getIndividualThreshold( - `@Parameter`(description = "회선 ID", example = "1") - `@RequestParam` Integer lineId + public ResponseEntity<IndividualThresholdResDto> getIndividualThreshold( + `@Parameter`(description = "회선 ID", example = "1") + `@RequestParam` Long lineId ) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/com/pooli/line/controller/LineController.java` around lines 57 - 61, The request parameter type for lineId in the controller method getIndividualThreshold should be changed from Integer to Long to match BIGINT/Long types used in DTOs and schema; update the method signature parameter (`@RequestParam` Long lineId) and any internal uses or calls (e.g., service method invocations that accept lineId) to accept Long so types remain consistent with IndividualThresholdResDto and downstream layers. Ensure any parsing/validation still works and adjust unit tests or method overloads that referenced Integer lineId to use Long.
| http | ||
| .csrf(csrf -> csrf.disable()) | ||
| .authorizeHttpRequests(auth -> auth | ||
| .requestMatchers( | ||
| "/swagger-ui.html", | ||
| "/swagger-ui/**", | ||
| "/v3/api-docs/**") | ||
| .permitAll() | ||
| .anyRequest() | ||
| .permitAll()) | ||
| .httpBasic(Customizer.withDefaults()); |
There was a problem hiding this comment.
Security configuration permits all requests without authentication.
The current configuration allows all requests without authentication (.anyRequest().permitAll()). While this may be intentional for early development/API scaffolding, ensure this is locked down before production deployment. The .httpBasic(Customizer.withDefaults()) has no effect since all requests are already permitted.
Consider adding a TODO or documentation to track this:
// TODO: Restrict endpoints before production deployment🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/com/pooli/common/config/SecurityConfig.java` around lines 14 -
24, SecurityConfig currently permits all requests via the
http.authorizeHttpRequests(...) chain (notably anyRequest().permitAll()),
rendering httpBasic(...) ineffective; update the authorizeHttpRequests
configuration to enforce authentication for non-public endpoints (e.g., change
anyRequest().permitAll() to anyRequest().authenticated() or restrict by roles)
and add a clear TODO comment in SecurityConfig near the
http.authorizeHttpRequests block to remind developers to tighten rules before
production (e.g., reference http, authorizeHttpRequests, anyRequest, httpBasic
to locate the change).
| @Schema(description = "가족 식별자", example = "1") | ||
| private Integer familyId; | ||
|
|
||
| @Schema(description = "가족 공유풀 총량", example = "10000000") | ||
| private Long sharedPoolTotalData; | ||
|
|
||
| @Schema(description = "가족 구성원 목록") | ||
| private List<FamilyMemberDto> members; | ||
|
|
||
|
|
||
| @Getter | ||
| @Builder | ||
| @AllArgsConstructor(access = AccessLevel.PRIVATE) | ||
| @NoArgsConstructor(access = AccessLevel.PRIVATE) | ||
| @Schema(description = "가족 구성원 DTO") | ||
| public static class FamilyMemberDto { | ||
|
|
||
| @Schema(description = "회원 식별자", example = "100") | ||
| private Integer userId; | ||
|
|
||
| @Schema(description = "회선 식별자", example = "10") | ||
| private Integer lineId; | ||
|
|
||
| @Schema(description = "요금제 식별자", example = "3") | ||
| private Integer planId; | ||
|
|
||
| @Schema(description = "회원 이름", example = "홍길동") | ||
| private String userName; | ||
|
|
||
| @Schema(description = "전화번호", example = "010-1234-5678") | ||
| private String phone; | ||
|
|
||
| @Schema(description = "요금제명", example = "5G 프리미엄") | ||
| private String planName; | ||
|
|
||
| @Schema(description = "기본 제공 데이터 잔량(bite)", example = "5000") | ||
| private Long remainingData; | ||
|
|
||
| @Schema(description = "기본 제공 데이터량(MB)", example = "10000") | ||
| private Long basicDataAmount; | ||
|
|
||
| @Schema(description = "가족 역할 (OWNER / MEMBER)", example = "OWNER") | ||
| private FamilyRole role; | ||
|
|
||
| @Schema(description = "사용 가능한 공유풀 데이터 총량(bite)", example = "120") | ||
| private Long sharedPoolTotalAmount; | ||
|
|
||
| @Schema(description = "사용 가능한 공유풀 데이터 잔량(bite)", example = "12000") | ||
| private Long sharedPoolRemainingAmount; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for identifier types across family/line/user DTOs and entities
rg -n -C2 '\b(Long|Integer)\s+(familyId|lineId|userId|planId)\b' src/main/java/com/pooli -g '*.java'Repository: pooli-dev/pooli-be
Length of output: 28683
🏁 Script executed:
#!/bin/bash
# Search for Family-related entity definitions to check actual DB types
find src/main/java/com/pooli -name "*.java" -path "*/entity/*" | xargs grep -l "Family\|family" | head -10Repository: pooli-dev/pooli-be
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Also check for specific identifier definitions in entity classes
rg -n '@Id|@Column|private.*family|private.*user|private.*line|private.*plan' src/main/java/com/pooli/family/domain/entity -A1 -B1Repository: pooli-dev/pooli-be
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Find all entity files in the family module
find src/main/java/com/pooli/family -name "*.java" -type fRepository: pooli-dev/pooli-be
Length of output: 993
🏁 Script executed:
#!/bin/bash
# Also search for `@Entity` annotation to find all entity classes
rg -l '@Entity' src/main/java/com/pooli --type javaRepository: pooli-dev/pooli-be
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Check overall directory structure to understand the codebase organization
ls -la src/main/java/com/pooli/Repository: pooli-dev/pooli-be
Length of output: 814
🏁 Script executed:
#!/bin/bash
# Search more broadly for `@Entity` across the entire codebase
find src -name "*.java" -type f | xargs grep -l "@Entity" | head -20Repository: pooli-dev/pooli-be
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Let's check if there's an entity directory or package structure
find src -type d -name entityRepository: pooli-dev/pooli-be
Length of output: 192
🏁 Script executed:
#!/bin/bash
# Search for classes with `@Getter` and `@Entity` patterns that might be entities
rg -n "class.*\{" src/main/java/com/pooli/user/domain -A5 | head -30Repository: pooli-dev/pooli-be
Length of output: 1346
🏁 Script executed:
#!/bin/bash
# Let's check the User entity we saw earlier
cat -n src/main/java/com/pooli/user/domain/entity/User.java | head -40Repository: pooli-dev/pooli-be
Length of output: 692
🏁 Script executed:
#!/bin/bash
# Check the Family entity
cat -n src/main/java/com/pooli/family/domain/entity/Family.java 2>/dev/null || echo "Family.java not found"Repository: pooli-dev/pooli-be
Length of output: 83
🏁 Script executed:
#!/bin/bash
# List all files in family entity directory
ls -la src/main/java/com/pooli/family/domain/entity/Repository: pooli-dev/pooli-be
Length of output: 227
🏁 Script executed:
#!/bin/bash
# Check Line entity
cat -n src/main/java/com/pooli/line/domain/entity/Line.java 2>/dev/null | head -50Repository: pooli-dev/pooli-be
Length of output: 44
🏁 Script executed:
#!/bin/bash
# List all files in line entity directory
ls -la src/main/java/com/pooli/line/domain/entity/Repository: pooli-dev/pooli-be
Length of output: 227
🏁 Script executed:
#!/bin/bash
# Search for any schema or database configuration files
find src -name "*.sql" -o -name "schema.sql" -o -name "*.properties" | head -20Repository: pooli-dev/pooli-be
Length of output: 186
🏁 Script executed:
#!/bin/bash
# Check if there's any JPA annotation or column type definitions in the DTOs themselves
rg -n "@Column|@GeneratedValue" src/main/java/com/pooli/family/domain/dto -A2Repository: pooli-dev/pooli-be
Length of output: 44
🏁 Script executed:
#!/bin/bash
# Check the database schema for ID column definitions
cat src/main/resources/db/migration/V1__init.sql | grep -i -E "family|user|line|plan" | head -50Repository: pooli-dev/pooli-be
Length of output: 1645
🏁 Script executed:
#!/bin/bash
# Look for specific table definitions with their column types
rg -n "CREATE TABLE|INT|BIGINT|family_id|user_id|line_id|plan_id" src/main/resources/db/migration/V1__init.sqlRepository: pooli-dev/pooli-be
Length of output: 10501
Align identifier types to avoid truncation and API inconsistency.
familyId, userId, and lineId are Integer but the database defines them as BIGINT, which risks truncation and client model conflicts. FamilyMembersSimpleResDto correctly uses Long for these fields. Standardize to Long for consistency and to match the actual database schema (note: planId is correctly Integer since the PLAN table uses INT).
🛠️ Proposed alignment
- private Integer familyId;
+ private Long familyId;- private Integer userId;
+ private Long userId;- private Integer lineId;
+ private Long lineId;(Keep planId as Integer as it correctly matches the database INT column)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/com/pooli/family/domain/dto/response/FamilyMembersResDto.java`
around lines 19 - 67, Change the identifier types to match the DB BIGINT
columns: update FamilyMembersResDto.familyId and the nested
FamilyMemberDto.userId and FamilyMemberDto.lineId from Integer to Long (leave
FamilyMemberDto.planId as Integer); ensure getters/builders/annotations remain
valid for the new Long types so the DTO aligns with FamilyMembersSimpleResDto
and avoids truncation/inconsistency.
| @Schema(description = "회선 ID", example = "1") | ||
| private Integer lineId; | ||
|
|
||
| @Schema(description = "개인 데이터 임계치(MB)", example = "3000") | ||
| private Integer individualThreshold; |
There was a problem hiding this comment.
Align threshold type/unit with response DTO.
Line 15-16 use Integer and MB, but IndividualThresholdResDto (src/main/java/com/pooli/line/domain/dto/response/IndividualThresholdResDto.java, lines 5-16) uses Long and “bite” (bytes). This mismatch can lead to incorrect thresholds or client confusion. Please align type + unit on both request/response.
🔧 Example alignment (if MB is the canonical unit)
- `@Schema`(description = "개인 데이터 임계치(MB)", example = "3000")
- private Integer individualThreshold;
+ `@Schema`(description = "개인 데이터 임계치(MB)", example = "3000")
+ private Long individualThreshold;📝 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.
| @Schema(description = "회선 ID", example = "1") | |
| private Integer lineId; | |
| @Schema(description = "개인 데이터 임계치(MB)", example = "3000") | |
| private Integer individualThreshold; | |
| `@Schema`(description = "회선 ID", example = "1") | |
| private Integer lineId; | |
| `@Schema`(description = "개인 데이터 임계치(MB)", example = "3000") | |
| private Long individualThreshold; |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/main/java/com/pooli/line/domain/dto/request/UpdateIndividualThresholdReqDto.java`
around lines 12 - 16, The request DTO currently declares individualThreshold as
Integer with unit MB which mismatches IndividualThresholdResDto that uses Long
and bytes; update UpdateIndividualThresholdReqDto by changing the field type
individualThreshold from Integer to Long and adjust the `@Schema`
description/example to indicate bytes (or the same unit/text used in
IndividualThresholdResDto) so both DTOs share the same type and unit semantics
(reference class names: UpdateIndividualThresholdReqDto and
IndividualThresholdResDto).
| @Schema(description = "개인 데이터 임계치 조회 응답 DTO") | ||
| public class IndividualThresholdResDto { | ||
| @Schema(description = "개인 데이터 임계치(bite)", example = "3000") | ||
| private Long individualThreshold; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, let's see all occurrences of individualThreshold with context
rg -n "individualThreshold" --type java -B 2 -A 2Repository: pooli-dev/pooli-be
Length of output: 1795
🏁 Script executed:
#!/bin/bash
# Find and read the request DTO file
fd "UpdateIndividualThresholdReqDto.java" --type fRepository: pooli-dev/pooli-be
Length of output: 146
🏁 Script executed:
#!/bin/bash
# Find and read the response DTO file
fd "IndividualThresholdResDto.java" --type fRepository: pooli-dev/pooli-be
Length of output: 141
Align type consistency and clarify unit semantics between request and response DTOs.
IndividualThresholdResDto.individualThreshold is typed as Long, but UpdateIndividualThresholdReqDto.individualThreshold is typed as Integer. Additionally, the schema descriptions use different units—the request DTO specifies "MB" while the response DTO specifies "bite"—which compounds the confusion. These inconsistencies suggest either a missing conversion between units or a documentation error. Align both the types and unit semantics to represent the same domain concept consistently.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/main/java/com/pooli/line/domain/dto/response/IndividualThresholdResDto.java`
at line 13, The response DTO field IndividualThresholdResDto.individualThreshold
is Long while the request DTO
UpdateIndividualThresholdReqDto.individualThreshold is Integer and their schema
descriptions use different units ("MB" vs "bite"); make both DTOs use the same
numeric type (choose Integer or Long consistently) and update both `@Schema`
descriptions to the same unit (e.g., "MB" or "bytes"); if the domain stores a
different base unit, perform explicit conversion in your mapping layer (the
mapper/converter that maps UpdateIndividualThresholdReqDto ↔
IndividualThresholdResDto) so the DTOs represent the same semantic value.
| @Operation( | ||
| summary = "가족 데이터 알림 설정 변경", | ||
| description = "가족 데이터 알림 설정의 ON/OFF를 변경한다." | ||
| ) | ||
| @ApiResponses({ | ||
| @ApiResponse(responseCode = "200", description = "조회 성공"), | ||
| @ApiResponse(responseCode = "404", description = "알람 정보가 존재하지 않음"), | ||
| @ApiResponse(responseCode = "500", description = "서버 오류"), | ||
| }) | ||
| @PatchMapping("/family-alarm") | ||
| public ResponseEntity<AlarmSettingReqDto> updateFamilyAlarm(){ | ||
|
|
||
| // @AuthenticationPrincipal LoginUser loginUser | ||
|
|
||
| AlarmSettingReqDto response = AlarmSettingReqDto.builder() | ||
| .familyAlarm(false) | ||
| .build(); | ||
|
|
||
| return ResponseEntity.ok(response); | ||
| } |
There was a problem hiding this comment.
PATCH endpoint cannot update state (hardcoded false).
The handler doesn’t accept any input and always returns familyAlarm(false), so clients can’t actually toggle the setting.
🔧 Suggested fix (example)
-@PatchMapping("/family-alarm")
-public ResponseEntity<AlarmSettingReqDto> updateFamilyAlarm(){
+@PatchMapping("/family-alarm")
+public ResponseEntity<AlarmSettingReqDto> updateFamilyAlarm(
+ `@RequestBody` AlarmSettingReqDto request){
- AlarmSettingReqDto response = AlarmSettingReqDto.builder()
- .familyAlarm(false)
- .build();
+ AlarmSettingReqDto response = AlarmSettingReqDto.builder()
+ .familyAlarm(request.getFamilyAlarm())
+ .build();
return ResponseEntity.ok(response);
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/com/pooli/notification/controller/AlarmSettingController.java`
around lines 20 - 39, The updateFamilyAlarm handler in AlarmSettingController
currently ignores input and always returns
AlarmSettingReqDto.builder().familyAlarm(false), so change updateFamilyAlarm to
accept the desired state and user context (e.g., add parameters like
`@RequestBody` AlarmSettingReqDto request and `@AuthenticationPrincipal` LoginUser
loginUser), call a domain/service method (e.g.,
alarmSettingService.updateFamilyAlarm(loginUser.getId(),
request.isFamilyAlarm())) to persist the change, and return the updated
AlarmSettingReqDto from that service; ensure input validation and appropriate
responses for not-found or error cases instead of the hardcoded false.
| @Operation( | ||
| summary = "전체 알림 상태 읽음으로 변경", | ||
| description = "사용자가 읽지 않은 알림의 상태를 모두 읽음으로 변경한다." | ||
| ) | ||
| @ApiResponses({ | ||
| @ApiResponse(responseCode = "200", description = "조회 성공"), | ||
| @ApiResponse(responseCode = "404", description = "알람 정보가 존재하지 않음"), | ||
| @ApiResponse(responseCode = "500", description = "서버 오류"), | ||
| }) | ||
| @PatchMapping("/read-all") | ||
| public ResponseEntity<UnreadCountsResDto> allRead(){ | ||
| Long lineId = 2L; // 일단 임의로 회선 id 변경함 | ||
| UnreadCountsResDto response = UnreadCountsResDto.builder() | ||
| .lineId(lineId) | ||
| .unreadCount(0L) | ||
| .build(); | ||
|
|
||
| return ResponseEntity.ok(response); | ||
| } |
There was a problem hiding this comment.
Hardcoded lineId breaks per-user correctness.
Using a fixed lineId means this endpoint can return or mutate data for the wrong user. Use the authenticated principal or a validated request parameter instead.
🔧 Suggested fix (example)
-@PatchMapping("/read-all")
-public ResponseEntity<UnreadCountsResDto> allRead(){
- Long lineId = 2L; // 일단 임의로 회선 id 변경함
+@PatchMapping("/read-all")
+public ResponseEntity<UnreadCountsResDto> allRead(
+ `@RequestParam` Long lineId){
UnreadCountsResDto response = UnreadCountsResDto.builder()
.lineId(lineId)
.unreadCount(0L)
.build();📝 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.
| @Operation( | |
| summary = "전체 알림 상태 읽음으로 변경", | |
| description = "사용자가 읽지 않은 알림의 상태를 모두 읽음으로 변경한다." | |
| ) | |
| @ApiResponses({ | |
| @ApiResponse(responseCode = "200", description = "조회 성공"), | |
| @ApiResponse(responseCode = "404", description = "알람 정보가 존재하지 않음"), | |
| @ApiResponse(responseCode = "500", description = "서버 오류"), | |
| }) | |
| @PatchMapping("/read-all") | |
| public ResponseEntity<UnreadCountsResDto> allRead(){ | |
| Long lineId = 2L; // 일단 임의로 회선 id 변경함 | |
| UnreadCountsResDto response = UnreadCountsResDto.builder() | |
| .lineId(lineId) | |
| .unreadCount(0L) | |
| .build(); | |
| return ResponseEntity.ok(response); | |
| } | |
| `@Operation`( | |
| summary = "전체 알림 상태 읽음으로 변경", | |
| description = "사용자가 읽지 않은 알림의 상태를 모두 읽음으로 변경한다." | |
| ) | |
| `@ApiResponses`({ | |
| `@ApiResponse`(responseCode = "200", description = "조회 성공"), | |
| `@ApiResponse`(responseCode = "404", description = "알람 정보가 존재하지 않음"), | |
| `@ApiResponse`(responseCode = "500", description = "서버 오류"), | |
| }) | |
| `@PatchMapping`("/read-all") | |
| public ResponseEntity<UnreadCountsResDto> allRead( | |
| `@RequestParam` Long lineId){ | |
| UnreadCountsResDto response = UnreadCountsResDto.builder() | |
| .lineId(lineId) | |
| .unreadCount(0L) | |
| .build(); | |
| return ResponseEntity.ok(response); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/com/pooli/notification/controller/NotiReadController.java`
around lines 61 - 79, The allRead() method in NotiReadController currently uses
a hardcoded Long lineId = 2L which breaks per-user behavior; replace this by
extracting the authenticated user or a validated request parameter and using
that to determine lineId, call the service (e.g., NotiReadService.markAllRead or
a similar method) to perform the update and retrieve the actual unread count,
then build UnreadCountsResDto with the real lineId and unreadCount instead of
the hardcoded values; remove the hardcoded lineId, validate authorization, and
ensure the method signature accepts either `@AuthenticationPrincipal` / Principal
or a `@RequestParam/`@PathVariable as appropriate.
| @Operation( | ||
| summary = "특정 구성원 정책 정보 수정", | ||
| description = "사용자 권한 필요. 앱 정책 PK 기준으로 1건만 수정하고 PK와 값을 응답합니다." | ||
| ) | ||
| @ApiResponses({ | ||
| @ApiResponse(responseCode = "200", description = "요청 성공"), | ||
| @ApiResponse(responseCode = "404", description = "리소스를 찾을 수 없음"), | ||
| @ApiResponse(responseCode = "500", description = "서버 내부 오류") | ||
| }) | ||
| @PatchMapping("/policies/lines/apps") | ||
| public ResponseEntity<AppPolicyResDto> updateAppPolicy( | ||
| @Parameter(description = "회선 식별자", example = "101") | ||
| @RequestParam Long lineId, | ||
| @Parameter(description = "앱 정책 PK", example = "7301") | ||
| @RequestParam Long appPolicyId, | ||
| @RequestBody AppPolicyUpdateReqDto request | ||
| ) { | ||
| AppPolicyResDto response = AppPolicyResDto.builder() | ||
| .appPolicyId(appPolicyId) | ||
| .appId(resolveAppId(appPolicyId)) | ||
| .appName(resolveAppName(appPolicyId)) | ||
| .enabled(request.getEnabled() != null ? request.getEnabled() : Boolean.FALSE) | ||
| .dailyLimitMb(request.getDailyLimitMb() != null ? request.getDailyLimitMb() : 0) | ||
| .build(); | ||
| return ResponseEntity.ok(response); | ||
| } |
There was a problem hiding this comment.
Unknown appPolicyId is silently mapped to 0/Unknown.
Returning 0/Unknown hides invalid input and can mislead clients. Prefer a 404/400 response when the ID isn’t recognized.
🔧 Suggested fix (example)
+import org.springframework.web.server.ResponseStatusException;
+import org.springframework.http.HttpStatus;
...
private Long resolveAppId(Long appPolicyId) {
if (Long.valueOf(7301L).equals(appPolicyId)) {
return 301L;
}
if (Long.valueOf(7302L).equals(appPolicyId)) {
return 302L;
}
if (Long.valueOf(7303L).equals(appPolicyId)) {
return 401L;
}
- return 0L;
+ throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Unknown appPolicyId");
}
private String resolveAppName(Long appPolicyId) {
if (Long.valueOf(7301L).equals(appPolicyId)) {
return "YouTube";
}
if (Long.valueOf(7302L).equals(appPolicyId)) {
return "Instagram";
}
if (Long.valueOf(7303L).equals(appPolicyId)) {
return "GameX";
}
- return "Unknown";
+ throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Unknown appPolicyId");
}Also applies to: 368-392
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/com/pooli/policy/controller/UserPolicyController.java` around
lines 222 - 247, The updateAppPolicy method currently maps unknown appPolicyId
to 0/"Unknown" via resolveAppId/resolveAppName which hides invalid input; change
updateAppPolicy (and the analogous handler around lines 368-392) to validate the
appPolicyId up front by querying the domain/service (e.g.,
AppPolicyService.findById(appPolicyId)) or checking whether
resolveAppId/resolveAppName return a real value, and if not return a 404
(ResponseEntity.notFound() or throw new
ResponseStatusException(HttpStatus.NOT_FOUND, "...")) or a 400 for bad IDs; only
build and return AppPolicyResDto when the policy exists, and include a clear
error message referencing appPolicyId in the response/exception.
| @Operation( | ||
| summary = "문의사항 생성 요청", | ||
| description = "새로운 문의사항을 생성한다" | ||
| ) | ||
| @ApiResponses({ | ||
| @ApiResponse(responseCode = "201", description = "문의사항 생성 성공"), | ||
| @ApiResponse(responseCode = "400", description = "잘못된 요청"), | ||
| @ApiResponse(responseCode = "500", description = "서버 오류"), | ||
|
|
||
| }) | ||
| @PostMapping | ||
| public ResponseEntity<List<QuestionCreateReqDto>> createQuestion(@RequestBody QuestionCreateReqDto request) { | ||
| return ResponseEntity.status(HttpStatus.CREATED).body(List.of()); | ||
| } |
There was a problem hiding this comment.
Create endpoint returns request DTO list + empty body.
POST /api/questions should return a created resource or no body, not a list of request DTOs.
🔧 Suggested fix (minimal)
-@PostMapping
-public ResponseEntity<List<QuestionCreateReqDto>> createQuestion(`@RequestBody` QuestionCreateReqDto request) {
- return ResponseEntity.status(HttpStatus.CREATED).body(List.of());
-}
+@PostMapping
+public ResponseEntity<Void> createQuestion(`@RequestBody` QuestionCreateReqDto request) {
+ return ResponseEntity.status(HttpStatus.CREATED).build();
+}📝 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.
| @Operation( | |
| summary = "문의사항 생성 요청", | |
| description = "새로운 문의사항을 생성한다" | |
| ) | |
| @ApiResponses({ | |
| @ApiResponse(responseCode = "201", description = "문의사항 생성 성공"), | |
| @ApiResponse(responseCode = "400", description = "잘못된 요청"), | |
| @ApiResponse(responseCode = "500", description = "서버 오류"), | |
| }) | |
| @PostMapping | |
| public ResponseEntity<List<QuestionCreateReqDto>> createQuestion(@RequestBody QuestionCreateReqDto request) { | |
| return ResponseEntity.status(HttpStatus.CREATED).body(List.of()); | |
| } | |
| `@Operation`( | |
| summary = "문의사항 생성 요청", | |
| description = "새로운 문의사항을 생성한다" | |
| ) | |
| `@ApiResponses`({ | |
| `@ApiResponse`(responseCode = "201", description = "문의사항 생성 성공"), | |
| `@ApiResponse`(responseCode = "400", description = "잘못된 요청"), | |
| `@ApiResponse`(responseCode = "500", description = "서버 오류"), | |
| }) | |
| `@PostMapping` | |
| public ResponseEntity<Void> createQuestion(`@RequestBody` QuestionCreateReqDto request) { | |
| return ResponseEntity.status(HttpStatus.CREATED).build(); | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/com/pooli/question/controller/QuestionController.java` around
lines 31 - 44, The createQuestion method currently returns a
List<QuestionCreateReqDto> and an empty list body; change the contract to either
return the created resource (e.g., a QuestionResponse DTO) or no body. Minimal
fix: update the method signature of createQuestion to return
ResponseEntity<Void> (replace List<QuestionCreateReqDto>), and return
ResponseEntity.status(HttpStatus.CREATED).build(); alternatively, if you want to
return the created resource, create a QuestionResponse DTO, return
ResponseEntity.created(location).body(createdDto) using createQuestion and
QuestionCreateReqDto to build the response and set the Location header (via
ServletUriComponentsBuilder or similar).
| private Long userId; | ||
| private String userName; | ||
| private String email; | ||
| private String password; |
There was a problem hiding this comment.
Security concern: Password field handling.
Storing password as a plain String field with a Lombok @Getter exposes it to accidental serialization (e.g., JSON responses, logs). Consider:
- Hash the password before storing (use BCrypt or Argon2 via Spring Security's
PasswordEncoder). - Exclude from serialization by adding
@JsonIgnoreor@ToString.Excludeto prevent accidental exposure. - Alternatively, consider removing
passwordfrom the domain entity and handling credentials in a separate, security-focused class.
🛡️ Suggested annotation to reduce exposure risk
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.ToString;
+
`@Getter`
`@Builder`
+@ToString(exclude = "password")
`@AllArgsConstructor`(access = AccessLevel.PRIVATE)
`@NoArgsConstructor`(access = AccessLevel.PROTECTED)
public class User {
private Long userId;
private String userName;
private String email;
+ `@JsonIgnore`
private String password;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/java/com/pooli/user/domain/entity/User.java` at line 16, The User
entity currently declares a plain String password field (private String
password) which is exposed via Lombok-generated accessors; update the handling
by (1) marking the field to be excluded from accidental
serialization/diagnostics (add annotations such as `@JsonIgnore` and
`@ToString.Exclude` on the password field in User) and (2) ensure passwords are
stored hashed by hashing input before setting the field (use a PasswordEncoder
from Spring Security when creating/updating users, e.g., call
encoder.encode(rawPassword) in the service that sets User::setPassword) or move
credentials into a dedicated credential/DTO class instead of the domain entity.
| DROP TABLE IF EXISTS `ALRAM_HISTORY`; | ||
|
|
||
| CREATE TABLE `ALRAM_HISTORY` ( | ||
| `alarm_history_id` BIGINT NOT NULL, | ||
| `user_id` BIGINT NOT NULL, | ||
| `alarm_code` ENUM('LIMIT','POLICY', 'PERMISSION','QUESTION') NOT NULL COMMENT 'enum', | ||
| `value` TEXT NULL COMMENT 'json', | ||
| `created_at` TIMESTAMP NOT NULL, | ||
| `deleted_at` TIMESTAMP NULL, | ||
| `read_at` TIMESTAMP NULL | ||
| ); |
There was a problem hiding this comment.
Fix typo ALRAM_HISTORY → ALARM_HISTORY to avoid mismatched table names.
The typo propagates to PK/FK names and can break ORM mappings or queries expecting ALARM_HISTORY.
🛠️ Proposed fix
-DROP TABLE IF EXISTS `ALRAM_HISTORY`;
+DROP TABLE IF EXISTS `ALARM_HISTORY`;
-CREATE TABLE `ALRAM_HISTORY` (
+CREATE TABLE `ALARM_HISTORY` (
`alarm_history_id` BIGINT NOT NULL,
`user_id` BIGINT NOT NULL,
`alarm_code` ENUM('LIMIT','POLICY', 'PERMISSION','QUESTION') NOT NULL COMMENT 'enum',
`value` TEXT NULL COMMENT 'json',
`created_at` TIMESTAMP NOT NULL,
`deleted_at` TIMESTAMP NULL,
`read_at` TIMESTAMP NULL
);
-ALTER TABLE `ALRAM_HISTORY` ADD CONSTRAINT `PK_ALRAM_HISTORY` PRIMARY KEY (
+ALTER TABLE `ALARM_HISTORY` ADD CONSTRAINT `PK_ALARM_HISTORY` PRIMARY KEY (
`alarm_history_id`
);
-ALTER TABLE `ALRAM_HISTORY` ADD CONSTRAINT `FK_USERS_TO_ALRAM_HISTORY_1` FOREIGN KEY (
+ALTER TABLE `ALARM_HISTORY` ADD CONSTRAINT `FK_USERS_TO_ALARM_HISTORY_1` FOREIGN KEY (
`user_id`
)
-REFERENCES `USERS` (
+REFERENCES `USERS` (
`user_id`
);Also applies to: 422-608
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/main/resources/db/migration/V1__init.sql` around lines 199 - 209, Rename
the misspelled table and all related identifiers from ALRAM_HISTORY to
ALARM_HISTORY in this migration: update the DROP TABLE and CREATE TABLE
statements to use ALARM_HISTORY, ensure the primary key/constraint and any index
names reference ALARM_HISTORY (and the column alarm_history_id remains
unchanged), and update any FK definitions or references elsewhere in this file
(including the regions noted around lines 422-608) that point to ALRAM_HISTORY
so they point to ALARM_HISTORY instead.
개요
User 엔티티 추가
관련 BackLog
Resolves: 180
PR 유형
PR Checklist
Summary by CodeRabbit
Release Notes
New Features
/swagger-ui.htmlConfiguration
Chores