diff --git a/src/main/java/com/kamco/cd/kamcoback/auth/JwtAuthenticationFilter.java b/src/main/java/com/kamco/cd/kamcoback/auth/JwtAuthenticationFilter.java index 42d87d9d..6b1b84f1 100644 --- a/src/main/java/com/kamco/cd/kamcoback/auth/JwtAuthenticationFilter.java +++ b/src/main/java/com/kamco/cd/kamcoback/auth/JwtAuthenticationFilter.java @@ -39,6 +39,15 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { filterChain.doFilter(request, response); } + @Override + protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException { + String path = request.getServletPath(); + + // 여기에 JWT 필터를 타지 않게 할 URL 패턴들 작성 + return path.startsWith("/api/auth/signin") || path.startsWith("/api/auth/refresh"); + // 필요하면 "/api/auth/logout" 도 추가 + } + private String resolveToken(HttpServletRequest request) { String bearer = request.getHeader("Authorization"); if (bearer != null && bearer.startsWith("Bearer ")) { diff --git a/src/main/java/com/kamco/cd/kamcoback/config/OpenApiConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/OpenApiConfig.java index 9b0d84d3..3f8623ef 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/OpenApiConfig.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/OpenApiConfig.java @@ -3,6 +3,8 @@ package com.kamco.cd.kamcoback.config; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.servers.Server; import java.util.List; import org.springframework.context.annotation.Bean; @@ -13,6 +15,21 @@ public class OpenApiConfig { @Bean public OpenAPI kamcoOpenAPI() { + // 🔹 1) SecurityScheme 정의 (Bearer JWT) + SecurityScheme bearerAuth = + new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT") + .in(SecurityScheme.In.HEADER) + .name("Authorization"); + + // 🔹 2) SecurityRequirement (기본으로 BearerAuth 사용) + SecurityRequirement securityRequirement = new SecurityRequirement().addList("BearerAuth"); + + // 🔹 3) Components 에 SecurityScheme 등록 + Components components = new Components().addSecuritySchemes("BearerAuth", bearerAuth); + return new OpenAPI() .info( new Info() @@ -32,6 +49,8 @@ public class OpenApiConfig { new Server().url("https://kamco.dev-api.gs.dabeeo.com").description("개발 서버") // , new Server().url("https://api.kamco.com").description("운영 서버") )) - .components(new Components()); + .components(new Components()) + // 🔥 여기 한 줄이 "모든 API 기본적으로 BearerAuth 요구" 의미 + .addSecurityItem(securityRequirement); } } diff --git a/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java index 85b160fe..5d7b6be1 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/SecurityConfig.java @@ -2,6 +2,7 @@ package com.kamco.cd.kamcoback.config; import com.kamco.cd.kamcoback.auth.CustomAuthenticationProvider; import com.kamco.cd.kamcoback.auth.JwtAuthenticationFilter; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -11,6 +12,9 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; @Configuration @EnableWebSecurity @@ -22,29 +26,39 @@ public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { - http.csrf(csrf -> csrf.disable()) // CSRF 보안 기능 비활성화 - .sessionManagement( - sm -> - sm.sessionCreationPolicy( - SessionCreationPolicy.STATELESS)) // 서버 세션 만들지 않음 요청은 JWT 인증 - .formLogin(form -> form.disable()) // react에서 로그인 요청 관리 - .httpBasic(basic -> basic.disable()) // 기본 basic 인증 비활성화 JWT 인증사용 - .logout(logout -> logout.disable()) // 기본 로그아웃 비활성화 JWT는 서버 상태가 없으므로 로그아웃 처리 필요 없음 - .authenticationProvider( - customAuthenticationProvider) // 로그인 패스워드 비교방식 스프링 기본 Provider 사용안함 커스텀 사용 - .authorizeHttpRequests(auth -> auth.anyRequest().permitAll()); - // auth.requestMatchers( - // "/api/auth/signin", - // "/api/auth/refresh", - // "/swagger-ui/**", - // "/v3/api-docs/**") // 로그인 없이 접근가능 url - // .permitAll() - // .anyRequest() - // .authenticated()) - // .addFilterBefore( - // jwtAuthenticationFilter, - // UsernamePasswordAuthenticationFilter - // .class) // 요청 들어오면 먼저 JWT 토큰 검사 후 security context 에 사용자 정보 저장. + // http.csrf(csrf -> csrf.disable()) // CSRF 보안 기능 비활성화 + // .sessionManagement( + // sm -> + // sm.sessionCreationPolicy( + // SessionCreationPolicy.STATELESS)) // 서버 세션 만들지 않음 요청은 JWT 인증 + // .formLogin(form -> form.disable()) // react에서 로그인 요청 관리 + // .httpBasic(basic -> basic.disable()) // 기본 basic 인증 비활성화 JWT 인증사용 + // .logout(logout -> logout.disable()) // 기본 로그아웃 비활성화 JWT는 서버 상태가 없으므로 로그아웃 처리 필요 없음 + // .authenticationProvider( + // customAuthenticationProvider) // 로그인 패스워드 비교방식 스프링 기본 Provider 사용안함 커스텀 사용 + // .authorizeHttpRequests( + // auth -> + // auth.requestMatchers( + // "/api/auth/signin", + // "/api/auth/refresh", + // "/swagger-ui/**", + // "/v3/api-docs/**") + // .permitAll() + // .anyRequest() + // .authenticated()) + // .addFilterBefore( + // jwtAuthenticationFilter, + // UsernamePasswordAuthenticationFilter + // .class) // 요청 들어오면 먼저 JWT 토큰 검사 후 security context 에 사용자 정보 저장. + http.csrf(csrf -> csrf.disable()) + .sessionManagement(sm -> sm.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .formLogin(form -> form.disable()) + .httpBasic(basic -> basic.disable()) + .logout(logout -> logout.disable()) + .authenticationProvider(customAuthenticationProvider) + .authorizeHttpRequests( + auth -> auth.anyRequest().permitAll() // 🔥 인증 필요 없음 + ); ; return http.build(); @@ -55,4 +69,18 @@ public class SecurityConfig { throws Exception { return configuration.getAuthenticationManager(); } + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration config = new CorsConfiguration(); // CORS 객체 생성 + config.setAllowedOriginPatterns(List.of("*")); // 도메인 허용 + config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); + config.setAllowedHeaders(List.of("*")); // 헤더요청 Authorization, Content-Type, X-Custom-Header + config.setAllowCredentials(true); // 쿠키, Authorization 헤더, Bearer Token 등 자격증명 포함 요청을 허용할지 설정 + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + /** "/**" → 모든 API 경로에 대해 이 CORS 규칙을 적용 /api/** 같이 특정 경로만 지정 가능. */ + source.registerCorsConfiguration("/**", config); // CORS 정책을 등록 + return source; + } } diff --git a/src/main/java/com/kamco/cd/kamcoback/config/SwaggerConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/SwaggerConfig.java new file mode 100644 index 00000000..bfd430f1 --- /dev/null +++ b/src/main/java/com/kamco/cd/kamcoback/config/SwaggerConfig.java @@ -0,0 +1,10 @@ +package com.kamco.cd.kamcoback.config; + +// @Configuration +// @SecurityScheme( +// name = "BearerAuth", +// type = SecuritySchemeType.HTTP, +// scheme = "bearer", +// bearerFormat = "JWT" +// ) +public class SwaggerConfig {} diff --git a/src/main/java/com/kamco/cd/kamcoback/config/WebConfig.java b/src/main/java/com/kamco/cd/kamcoback/config/WebConfig.java index 8ee5e50b..0af7fa2b 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/WebConfig.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/WebConfig.java @@ -10,22 +10,11 @@ import org.locationtech.jts.geom.Polygon; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; -import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { - @Override - public void addCorsMappings(CorsRegistry registry) { - registry - .addMapping("/**") // 모든 URL 허용 - .allowedOriginPatterns("*") - .allowedMethods("*") - .allowedHeaders("*") - .allowCredentials(true); - } - @Bean public ObjectMapper objectMapper() { SimpleModule module = new SimpleModule(); diff --git a/src/main/java/com/kamco/cd/kamcoback/config/api/ApiLogFunction.java b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiLogFunction.java index 2c4e8cba..93c3bddf 100644 --- a/src/main/java/com/kamco/cd/kamcoback/config/api/ApiLogFunction.java +++ b/src/main/java/com/kamco/cd/kamcoback/config/api/ApiLogFunction.java @@ -9,6 +9,7 @@ import java.util.stream.Collectors; import org.springframework.web.util.ContentCachingRequestWrapper; public class ApiLogFunction { + // 클라이언트 IP 추출 public static String getClientIp(HttpServletRequest request) { String[] headers = { @@ -34,6 +35,7 @@ public class ApiLogFunction { // 사용자 ID 추출 예시 (Spring Security 기준) public static String getUserId(HttpServletRequest request) { try { + Object userId = request.getUserPrincipal(); return request.getUserPrincipal() != null ? request.getUserPrincipal().getName() : null; } catch (Exception e) { return null; @@ -45,8 +47,12 @@ public class ApiLogFunction { String uri = request.getRequestURI().toLowerCase(); // URL 기반 DOWNLOAD/PRINT 분류 - if (uri.contains("/download") || uri.contains("/export")) return EventType.DOWNLOAD; - if (uri.contains("/print")) return EventType.PRINT; + if (uri.contains("/download") || uri.contains("/export")) { + return EventType.DOWNLOAD; + } + if (uri.contains("/print")) { + return EventType.PRINT; + } // 일반 CRUD return switch (method) { @@ -97,7 +103,9 @@ public class ApiLogFunction { // JSON Body 읽기 public static String getBodyData(ContentCachingRequestWrapper request) { byte[] buf = request.getContentAsByteArray(); - if (buf.length == 0) return null; + if (buf.length == 0) { + return null; + } try { return new String(buf, request.getCharacterEncoding()); } catch (UnsupportedEncodingException e) { diff --git a/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java b/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java index ad0c3e5e..69b43f85 100644 --- a/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java +++ b/src/main/java/com/kamco/cd/kamcoback/mapsheet/MapSheetMngApiController.java @@ -49,7 +49,6 @@ public class MapSheetMngApiController { return ApiResponseDto.createOK(mapSheetMngService.getFolderAll(srchDto)); } - @Operation(summary = "지정폴더내 파일목록 조회", description = "지정폴더내 파일목록 조회") @ApiResponses( value = { diff --git a/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/FileDto.java b/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/FileDto.java index bc663d42..276a2bbe 100644 --- a/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/FileDto.java +++ b/src/main/java/com/kamco/cd/kamcoback/mapsheet/dto/FileDto.java @@ -1,6 +1,5 @@ package com.kamco.cd.kamcoback.mapsheet.dto; -import com.fasterxml.jackson.annotation.JsonView; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import java.util.List; @@ -43,7 +42,6 @@ public class FileDto { @Schema(description = "파일종료위치", example = "100") @NotNull private Integer endPos; - } @Getter diff --git a/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java b/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java index 2d90a674..068c0c60 100644 --- a/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java +++ b/src/main/java/com/kamco/cd/kamcoback/mapsheet/service/MapSheetMngService.java @@ -182,7 +182,6 @@ public class MapSheetMngService { } } - return new FilesDto(dirPath, fileTotCnt, fileTotSize, files); } @@ -194,7 +193,7 @@ public class MapSheetMngService { String extension = srchDto.getExtension(); String sortType = srchDto.getSortType(); - int startPos = srchDto.getStartPos(); + int startPos = srchDto.getStartPos(); int endPos = srchDto.getEndPos(); int limit = endPos - startPos + 1; @@ -206,7 +205,6 @@ public class MapSheetMngService { int fileTotCnt = 0; long fileTotSize = 0; - try (Stream stream = Files.walk(startPath, maxDepth)) { fileDtoList = @@ -243,8 +241,6 @@ public class MapSheetMngService { fileTotCnt = fileDtoList.size(); fileTotSize = fileDtoList.stream().mapToLong(FileDto.Basic::getFileSize).sum(); - - } catch (IOException e) { System.err.println("파일 I/O 오류 발생: " + e.getMessage()); } diff --git a/src/main/java/com/kamco/cd/kamcoback/members/service/AdminService.java b/src/main/java/com/kamco/cd/kamcoback/members/service/AdminService.java index 6e5458cb..46b5a0da 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/service/AdminService.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/service/AdminService.java @@ -1,6 +1,6 @@ package com.kamco.cd.kamcoback.members.service; -import com.kamco.cd.kamcoback.config.BCryptSaltGenerator; +import com.kamco.cd.kamcoback.auth.BCryptSaltGenerator; import com.kamco.cd.kamcoback.members.dto.MembersDto; import com.kamco.cd.kamcoback.postgres.core.MembersCoreService; import lombok.RequiredArgsConstructor; diff --git a/src/main/java/com/kamco/cd/kamcoback/members/service/MemberDetailsService.java b/src/main/java/com/kamco/cd/kamcoback/members/service/MemberDetailsService.java index b0bc258d..ff548d2d 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/service/MemberDetailsService.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/service/MemberDetailsService.java @@ -3,6 +3,7 @@ package com.kamco.cd.kamcoback.members.service; import com.kamco.cd.kamcoback.auth.CustomUserDetails; import com.kamco.cd.kamcoback.postgres.entity.MemberEntity; import com.kamco.cd.kamcoback.postgres.repository.members.MembersRepository; +import java.util.UUID; import lombok.RequiredArgsConstructor; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; @@ -17,9 +18,10 @@ public class MemberDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + UUID uuid = UUID.fromString(username); MemberEntity member = membersRepository - .findByEmployeeNo(username) + .findByUUID(uuid) .orElseThrow(() -> new UsernameNotFoundException("USER NOT FOUND")); return new CustomUserDetails(member); diff --git a/src/main/java/com/kamco/cd/kamcoback/members/service/MembersService.java b/src/main/java/com/kamco/cd/kamcoback/members/service/MembersService.java index 943f331a..383097bd 100644 --- a/src/main/java/com/kamco/cd/kamcoback/members/service/MembersService.java +++ b/src/main/java/com/kamco/cd/kamcoback/members/service/MembersService.java @@ -1,7 +1,7 @@ package com.kamco.cd.kamcoback.members.service; +import com.kamco.cd.kamcoback.auth.BCryptSaltGenerator; import com.kamco.cd.kamcoback.common.exception.CustomApiException; -import com.kamco.cd.kamcoback.config.BCryptSaltGenerator; import com.kamco.cd.kamcoback.members.dto.MembersDto; import com.kamco.cd.kamcoback.members.dto.MembersDto.Basic; import com.kamco.cd.kamcoback.postgres.core.MembersCoreService; diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MembersCoreService.java b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MembersCoreService.java index 64226b53..9287f3fb 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/core/MembersCoreService.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/core/MembersCoreService.java @@ -41,12 +41,12 @@ public class MembersCoreService { public Long saveMembers(MembersDto.AddReq addReq) { if (membersRepository.existsByEmployeeNo(addReq.getEmployeeNo())) { throw new MemberException.DuplicateMemberException( - MemberException.DuplicateMemberException.Field.EMPLOYEE_NO, addReq.getEmployeeNo()); + MemberException.DuplicateMemberException.Field.EMPLOYEE_NO, addReq.getEmployeeNo()); } if (membersRepository.existsByEmail(addReq.getEmail())) { throw new MemberException.DuplicateMemberException( - MemberException.DuplicateMemberException.Field.EMAIL, addReq.getEmail()); + MemberException.DuplicateMemberException.Field.EMAIL, addReq.getEmail()); } MemberEntity memberEntity = new MemberEntity(); @@ -66,7 +66,7 @@ public class MembersCoreService { */ public void updateMembers(UUID uuid, MembersDto.UpdateReq updateReq) { MemberEntity memberEntity = - membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException()); + membersRepository.findByUUID(uuid).orElseThrow(() -> new MemberNotFoundException()); if (StringUtils.isNotBlank(memberEntity.getEmployeeNo())) { memberEntity.setEmployeeNo(updateReq.getEmployeeNo()); @@ -93,13 +93,13 @@ public class MembersCoreService { public void saveRoles(MembersDto.RolesDto rolesDto) { MemberEntity memberEntity = - membersRepository - .findByUUID(rolesDto.getUuid()) - .orElseThrow(() -> new MemberNotFoundException()); + membersRepository + .findByUUID(rolesDto.getUuid()) + .orElseThrow(() -> new MemberNotFoundException()); if (memberRoleRepository.findByUuidAndRoleName(rolesDto)) { throw new MemberException.DuplicateMemberException( - MemberException.DuplicateMemberException.Field.DEFAULT, "중복된 역할이 있습니다."); + MemberException.DuplicateMemberException.Field.DEFAULT, "중복된 역할이 있습니다."); } MemberRoleEntityId memberRoleEntityId = new MemberRoleEntityId(); @@ -120,9 +120,9 @@ public class MembersCoreService { */ public void deleteRoles(MembersDto.RolesDto rolesDto) { MemberEntity memberEntity = - membersRepository - .findByUUID(rolesDto.getUuid()) - .orElseThrow(() -> new MemberNotFoundException()); + membersRepository + .findByUUID(rolesDto.getUuid()) + .orElseThrow(() -> new MemberNotFoundException()); MemberRoleEntityId memberRoleEntityId = new MemberRoleEntityId(); memberRoleEntityId.setMemberUuid(rolesDto.getUuid()); @@ -142,9 +142,9 @@ public class MembersCoreService { */ public void updateStatus(MembersDto.StatusDto statusDto) { MemberEntity memberEntity = - membersRepository - .findByUUID(statusDto.getUuid()) - .orElseThrow(() -> new MemberNotFoundException()); + membersRepository + .findByUUID(statusDto.getUuid()) + .orElseThrow(() -> new MemberNotFoundException()); memberEntity.setStatus(statusDto.getStatus()); memberEntity.setUpdatedDttm(ZonedDateTime.now()); @@ -158,9 +158,9 @@ public class MembersCoreService { */ public void deleteAccount(MembersDto.StatusDto statusDto) { MemberEntity memberEntity = - membersRepository - .findByUUID(statusDto.getUuid()) - .orElseThrow(() -> new MemberNotFoundException()); + membersRepository + .findByUUID(statusDto.getUuid()) + .orElseThrow(() -> new MemberNotFoundException()); MemberArchivedEntityId memberArchivedEntityId = new MemberArchivedEntityId(); memberArchivedEntityId.setUserId(memberEntity.getId()); @@ -193,10 +193,10 @@ public class MembersCoreService { */ public void resetPassword(Long id) { MemberEntity memberEntity = - membersRepository.findById(id).orElseThrow(() -> new MemberNotFoundException()); + membersRepository.findById(id).orElseThrow(() -> new MemberNotFoundException()); String salt = - BCryptSaltGenerator.generateSaltWithEmployeeNo(memberEntity.getEmployeeNo().trim()); + BCryptSaltGenerator.generateSaltWithEmployeeNo(memberEntity.getEmployeeNo().trim()); // 패스워드 암호화, 초기 패스워드 고정 String hashedPassword = BCrypt.hashpw(password, salt); diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberArchivedEntity.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberArchivedEntity.java index 2d6ae8c0..8a1281aa 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberArchivedEntity.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberArchivedEntity.java @@ -17,8 +17,7 @@ import org.hibernate.annotations.ColumnDefault; @Table(name = "tb_member_archived") public class MemberArchivedEntity { - @EmbeddedId - private MemberArchivedEntityId id; + @EmbeddedId private MemberArchivedEntityId id; @Size(max = 50) @Column(name = "employee_no", length = 50) @@ -51,5 +50,4 @@ public class MemberArchivedEntity { @ColumnDefault("now()") @Column(name = "archived_dttm", nullable = false) private ZonedDateTime archivedDttm; - } diff --git a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberArchivedEntityId.java b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberArchivedEntityId.java index 13453f2c..6e525254 100644 --- a/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberArchivedEntityId.java +++ b/src/main/java/com/kamco/cd/kamcoback/postgres/entity/MemberArchivedEntityId.java @@ -16,6 +16,7 @@ import org.hibernate.Hibernate; public class MemberArchivedEntityId implements Serializable { private static final long serialVersionUID = -7102800377481389036L; + @NotNull @Column(name = "user_id", nullable = false) private Long userId; @@ -33,13 +34,11 @@ public class MemberArchivedEntityId implements Serializable { return false; } MemberArchivedEntityId entity = (MemberArchivedEntityId) o; - return Objects.equals(this.userId, entity.userId) && - Objects.equals(this.uuid, entity.uuid); + return Objects.equals(this.userId, entity.userId) && Objects.equals(this.uuid, entity.uuid); } @Override public int hashCode() { return Objects.hash(userId, uuid); } - }