Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package dev.gyeoul.esginsightboard.config;

import dev.gyeoul.esginsightboard.entity.Company;
import dev.gyeoul.esginsightboard.entity.User;
import dev.gyeoul.esginsightboard.repository.UserRepository;
import dev.gyeoul.esginsightboard.repository.CompanyRepository;
import dev.gyeoul.esginsightboard.util.JwtTokenUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -16,6 +18,7 @@
public class UserDataInitializer {

private final UserRepository userRepository;
private final CompanyRepository companyRepository;
private final JwtTokenUtil jwtTokenUtil;
private final PasswordEncoder passwordEncoder;

Expand All @@ -24,14 +27,19 @@ public CommandLineRunner initUsers() {
return args -> {
// 테스트 계정이 없을 경우에만 생성
if (!userRepository.existsByEmail("admin@example.com")) {
Company company = Company.builder()
.name("ESG 인사이트")
.companyCode("ESG")
.companyPhoneNumber("010-1234-5678")
.build();

company = companyRepository.save(company);

User admin = User.builder()
.email("admin@example.com")
.password(passwordEncoder.encode("admin123"))
.name("관리자")
.department("경영지원팀")
.position("ESG 담당자")
.companyName("ESG 인사이트")
.phoneNumber("010-1234-5678")
.company(company)
.accountNonExpired(true)
.accountNonLocked(true)
.credentialsNonExpired(true)
Expand All @@ -44,10 +52,7 @@ public CommandLineRunner initUsers() {
.email("user@example.com")
.password(passwordEncoder.encode("user123"))
.name("사용자")
.department("ESG팀")
.position("팀원")
.companyName("ESG 인사이트")
.phoneNumber("010-8765-4321")
.company(company)
.accountNonExpired(true)
.accountNonLocked(true)
.credentialsNonExpired(true)
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
Expand Down Expand Up @@ -56,7 +57,7 @@ public class UserController {
})
public ResponseEntity<UserDto> signup(@Valid @RequestBody SignupRequest request) {
UserDto userDto = userService.signup(request);
return ResponseEntity.status(HttpStatus.CREATED).body(userDto);
return ResponseEntity.status(HttpStatus.CREATED).body(userDto); // HTTP 201 Created 상태코드로 생성된 사용자 정보 반환
}

/**
Expand All @@ -76,8 +77,8 @@ public ResponseEntity<UserDto> signup(@Valid @RequestBody SignupRequest request)
@ApiResponse(responseCode = "401", description = "이메일 또는 비밀번호가 일치하지 않음")
})
public ResponseEntity<LoginResponse> login(@RequestBody LoginRequest request) {
LoginResponse response = userService.login(request);
return ResponseEntity.ok(response);
LoginResponse response = userService.login(request); // 서비스 계층에 로그인 요청을 위임하여 처리
return ResponseEntity.ok(response); // 로그인 성공 시 200 OK + JWT 포함된 응답 반환
}

/**
Expand All @@ -98,14 +99,17 @@ public ResponseEntity<LoginResponse> login(@RequestBody LoginRequest request) {
@ApiResponse(responseCode = "401", description = "인증 실패 또는 토큰 없음")
})
public ResponseEntity<UserDto> getMyInfo(HttpServletRequest request) {
// JWT 인증 필터에서 사용자 정보를 request attribute로 설정했다고 가정
UserDto user = (UserDto) request.getAttribute("user");

// 사용자 정보가 존재하면 200 ok, 없으면 401 Unauthorized 반환
if (user != null) {
return ResponseEntity.ok(user);
} else {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}

/**
* API 테스트를 위한 테스트 토큰 발급 API
*
Expand All @@ -124,14 +128,14 @@ public ResponseEntity<UserDto> getMyInfo(HttpServletRequest request) {
public ResponseEntity<Map<String, Object>> generateTestToken(
@Parameter(description = "테스트 토큰에 사용할 이메일", example = "test@example.com")
@RequestParam(defaultValue = "test@example.com") String email) {

String token = jwtTokenUtil.generateTestToken(email); // 1. 테스트용 JWT 토큰 생성
Date expiryDate = jwtTokenUtil.getExpirationDateFromToken(token); // 2. 만료일 추출

Map<String, Object> response = createTestTokenResponse(token, email, expiryDate); // 3. 응답 데이터 구성
log.info("테스트 토큰 발급: {}, 만료일: {}", email, expiryDate); // 4. 로그 기록

String token = jwtTokenUtil.generateTestToken(email);
Date expiryDate = jwtTokenUtil.getExpirationDateFromToken(token);

Map<String, Object> response = createTestTokenResponse(token, email, expiryDate);
log.info("테스트 토큰 발급: {}, 만료일: {}", email, expiryDate);

return ResponseEntity.ok(response);
return ResponseEntity.ok(response); // 5. 응답 반환
}

/**
Expand All @@ -140,17 +144,20 @@ public ResponseEntity<Map<String, Object>> generateTestToken(
private Map<String, Object> createTestTokenResponse(String token, String email, Date expiryDate) {
Map<String, Object> response = new HashMap<>();
Map<String, Object> tokenInfo = new HashMap<>();

tokenInfo.put("token", token);
tokenInfo.put("type", "Bearer");
tokenInfo.put("expiryDate", expiryDate);

response.put("success", true);

// JWT 토큰 정보 구성
tokenInfo.put("token", token); // JWT 문자열
tokenInfo.put("type", "Bearer"); // 토큰 타입 명시 (OAuth2 등에서 사용)
tokenInfo.put("expiryDate", expiryDate); // 만료일 정보

// 최종 응답 객체 구성
response.put("success", true); // 처리 성공 여부
response.put("message", "테스트 토큰이 발급되었습니다");
response.put("tokenInfo", tokenInfo);
response.put("tokenInfo", tokenInfo); // 위에서 구성한 토큰 정보 Map

// Swagger UI 사용법
response.put("swaggerUsage", "Swagger UI 우측 상단의 'Authorize' 버튼을 클릭하고, 발급된 토큰을 입력하세요. (Bearer 접두사 없이)");
// cURL 명령 예시 포함
response.put("curlExample", "curl -X GET 'http://localhost:8080/api/users/me' -H 'Authorization: Bearer " + token + "'");

return response;
Expand Down Expand Up @@ -179,13 +186,67 @@ public ResponseEntity<Map<String, Object>> tokenTest(HttpServletRequest request)
UserDto user = (UserDto) request.getAttribute("user");
response.put("authenticated", user != null);

// 사용자 정보가 존재하면 세부 정보 반환
if (user != null) {
response.put("userInfo", extractUserInfo(user));
}

// 응답 반환
return ResponseEntity.ok(response);
}


/**
* 마이페이지 회원정보 저장 API
*
* @param request 사용자가 보낸 회원정보 수정 요청 (이름, 이메일, 비밀번호, 전화번호)
* @param req HTTP 요청 객체 (JWT 토큰 검증 결과 포함)
* @return 수정 성공 시 요청 내용을 그대로 반환 (HTTP 200), 인증 실패 시 401 반환
*/
@PutMapping("/update")
@Operation(
summary = "사용자 정보 수정",
description = "마이페이지에서 사용자 정보를 수정합니다."
)
@SecurityRequirement(name = "bearerAuth")
public ResponseEntity<UserUpdateRequest> updateUser(
@RequestBody @Valid UserUpdateRequest request, HttpServletRequest req) {
// JWT 필터를 통해 주입된 현재 사용자 정보 꺼내기
UserDto currentUser = (UserDto) req.getAttribute("user");

// 인증되지 않은 경우 401 반환
if (currentUser == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}

// 서비스 계층에 사용자 ID와 수정 요청을 넘겨 DB 반영 수행
userService.updateUser(currentUser.getId(), request);

// 성공적으로 수정된 경우, 원래 요청 객체를 그대로 반환
return ResponseEntity.ok(request);
}

// 회사 정보 수정
@PutMapping("/update-company")
@Operation(
summary = "회사 정보 수정",
description = "마이페이지에서 회사 정보 수정"
)
@SecurityRequirement(name = "bearerAuth")
public ResponseEntity<CompanyUpdateRequest> updateCompany(
@RequestBody CompanyUpdateRequest request,
HttpServletRequest req
) {
UserDto currentUser = (UserDto) req.getAttribute("user");

if(currentUser == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}

userService.updateCompany(currentUser.getCompanyId(), request);
return ResponseEntity.ok(request);
}


/**
* 사용자 정보에서 필요한 정보만 추출하는 메서드
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package dev.gyeoul.esginsightboard.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CompanyUpdateRequest {
private String companyName;
private String ceoName;
private String companyCode;
private String companyPhoneNumber;
}
65 changes: 0 additions & 65 deletions src/main/java/dev/gyeoul/esginsightboard/dto/EsgChartDataDto.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -244,12 +244,6 @@ public static GriDataItemDto fromEntity(GriDataItem entity) {
.createdAt(entity.getCreatedAt())
.updatedAt(entity.getUpdatedAt());

// 회사 정보 설정 (null 체크)
if (entity.getCompany() != null) {
builder.companyId(entity.getCompany().getId())
.companyName(entity.getCompany().getName());
}

return builder.build();
}

Expand Down
32 changes: 16 additions & 16 deletions src/main/java/dev/gyeoul/esginsightboard/dto/UserDto.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.gyeoul.esginsightboard.dto;

import dev.gyeoul.esginsightboard.entity.Company;
import dev.gyeoul.esginsightboard.entity.User;
import lombok.AllArgsConstructor;
import lombok.Builder;
Expand All @@ -26,48 +27,47 @@ public class UserDto {
private Long companyId;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;

/**
* User 엔티티를 UserDto로 변환합니다.
*/
public static UserDto fromEntity(User user) {
if (user == null) {
return null;
}

return UserDto.builder()
.id(user.getId())
.email(user.getEmail())
.name(user.getName())
.department(user.getDepartment())
.position(user.getPosition())
.companyName(user.getCompanyName())
.ceoName(user.getCeoName())
.companyCode(user.getCompanyCode())
.companyPhoneNumber(user.getCompanyPhoneNumber())
.companyName(user.getCompany().getName())
.ceoName(user.getCompany().getCeoName())
.companyCode(user.getCompany().getCompanyCode())
.companyPhoneNumber(user.getCompany().getCompanyPhoneNumber())
.phoneNumber(user.getPhoneNumber())
.companyId(user.getCompany() != null ? user.getCompany().getId() : null)
.createdAt(user.getCreatedAt())
.updatedAt(user.getUpdatedAt())
.build();
}

/**
* UserDto를 User 엔티티로 변환합니다.
* 비밀번호 필드는 포함되지 않으므로 새로운 사용자 생성에는 사용할 수 없습니다.
*/
public User toEntity() {
Company company = Company.builder()
.name(this.companyName)
.ceoName(this.ceoName)
.companyCode(this.companyCode)
.companyPhoneNumber(this.companyPhoneNumber).build();

return User.builder()
.id(this.id)
.email(this.email)
.name(this.name)
.department(this.department)
.position(this.position)
.companyName(this.companyName)
.ceoName(this.ceoName)
.companyCode(this.companyCode)
.companyPhoneNumber(this.companyPhoneNumber)
.phoneNumber(this.phoneNumber)
.company(company)
.build();
}
}
}
Loading