Skip to content
Merged
37 changes: 24 additions & 13 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,32 +28,47 @@ repositories {
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-webflux'

// OAuth2 Client
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

// Test Dependencies
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testImplementation 'io.projectreactor:reactor-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

// Lombok
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'org.postgresql:postgresql'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'


// PostgreSQL Driver
runtimeOnly 'org.postgresql:postgresql'

// JWT
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'

// OkHttp MockWebServer
testImplementation 'com.squareup.okhttp3:mockwebserver:4.12.0'
implementation 'org.springframework.boot:spring-boot-starter-actuator'

// Mockito + AssertJ
testImplementation "org.mockito:mockito-junit-jupiter:5.12.0"
testImplementation "org.assertj:assertj-core:3.26.3"

// GreenMail: SMTP 가짜 서버
testImplementation "com.icegreen:greenmail:1.6.14"
// mail
testImplementation "com.icegreen:greenmail:1.6.14" // GreenMail: SMTP 가짜 서버
implementation 'org.springframework.boot:spring-boot-starter-mail'

// Spring Boot Admin Server & Client
implementation 'de.codecentric:spring-boot-admin-starter-server:3.5.7'
implementation 'de.codecentric:spring-boot-admin-starter-client:3.5.7'

// Actuator
implementation 'org.springframework.boot:spring-boot-starter-actuator'

// spring-retry
implementation 'org.springframework.retry:spring-retry'
Expand All @@ -64,16 +79,12 @@ dependencies {
// swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.3'

implementation 'org.springframework.boot:spring-boot-starter-validation'

// backtesting library
implementation 'org.ta4j:ta4j-core:0.15'

// mail
implementation 'org.springframework.boot:spring-boot-starter-mail'

//validation
implementation 'commons-validator:commons-validator:1.10.0'
implementation 'org.springframework.boot:spring-boot-starter-validation'

// Redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.sejongisc.backend;

import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
Expand All @@ -9,6 +10,7 @@
@EnableScheduling
@EnableJpaAuditing
@EnableRetry
@EnableAdminServer
@SpringBootApplication
public class BackendApplication {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.sejongisc.backend.admin.controller;

public class AdminAttendanceController {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.sejongisc.backend.admin.controller;

public class AdminBoardController {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.sejongisc.backend.admin.controller;

public class AdminDashboardController {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.sejongisc.backend.admin.controller;

public class AdminPointController {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package org.sejongisc.backend.admin.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.sejongisc.backend.admin.dto.AdminUserRequest;
import org.sejongisc.backend.user.dto.UserInfoResponse; // 기존 DTO 활용
import org.sejongisc.backend.user.entity.Role;
import org.sejongisc.backend.user.entity.UserStatus;
import org.sejongisc.backend.user.service.UserService;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;
import java.util.UUID;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/admin/users")
@Tag(name = "관리자 API", description = "운영진 및 개발자용 회원 관리 API")
public class AdminUserController {

private final UserService userService;

// --- [회장/운영진용] 회원 관리 API ---

@Operation(summary = "엑셀 명단 업로드 및 동기화", description = "엑셀 파일을 업로드하여 신규 회원을 등록하고, 기존 회원의 기수/직위를 갱신합니다.")
@PostMapping(value = "/upload-excel", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@PreAuthorize("hasAnyRole('PRESIDENT', 'SYSTEM_ADMIN')") // 회장, 개발자만 가능
public ResponseEntity<?> uploadMemberExcel(@RequestPart("file") MultipartFile file) {
// 엑셀 파싱 및 DB 동기화 결과 반환
//ExcelSyncResultDto result = adminUserService.syncMembersFromExcel(file);
//return ResponseEntity.ok(result);
return null;
}

@Operation(summary = "전체 회원 목록 조회", description = "모든 회원의 정보를 조회합니다. (회장/관리자용)")
@GetMapping("")
@PreAuthorize("hasAnyRole('SYSTEM_ADMIN', 'MANAGER')")
public ResponseEntity<List<UserInfoResponse>> getAllUsers(@RequestBody AdminUserRequest request) {
//return ResponseEntity.ok(userService.findAllUsers()); // TODO : 전체 조회, 기수별 조회, 이름 검색 등 기능 추가 (페이징은 추후 고려)
return null;
}

@Operation(summary = "회원 활동 상태 변경", description = "ACTIVE, INACTIVE, GRADUATED 등으로 상태를 변경합니다.")
@PatchMapping("/{userId}/status")
@PreAuthorize("hasAnyRole('SYSTEM_ADMIN', 'MANAGER')")
public ResponseEntity<?> updateUserStatus(
@PathVariable UUID userId,
@RequestParam UserStatus status) {
//userService.updateUserStatus(userId, status);
return ResponseEntity.ok(Map.of("message", "사용자 상태가 " + status + "(으)로 변경되었습니다."));
}

// --- [시스템 관리자용 or 회장용] 권한 및 계정 제어 API ---
// TODO : 회장 권한 논의 필요
@Operation(summary = "회원 권한 변경", description = "특정 유저의 Role(PRESIDENT, VICE_PRESIDENT, TEAM_LEADER)을 변경합니다.)")
@PatchMapping("/{userId}/role")
@PreAuthorize("hasRole('SYSTEM_ADMIN')")
public ResponseEntity<?> updateUserRole(
@PathVariable UUID userId,
@RequestParam Role role) {
//userService.updateUserRole(userId, role);
return ResponseEntity.ok(Map.of("message", "사용자 권한이 " + role + "(으)로 변경되었습니다."));
}

@Operation(summary = "회원 강제 탈퇴", description = "시스템에서 유저를 완전히 삭제합니다. (시스템 관리자용)")
@DeleteMapping("/{userId}")
@PreAuthorize("hasRole('SYSTEM_ADMIN')")
public ResponseEntity<?> forceDeleteUser(@PathVariable UUID userId) {
//userService.deleteUserWithOauth(userId);
return ResponseEntity.ok(Map.of("message", "해당 사용자가 시스템에서 완전히 삭제되었습니다."));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.sejongisc.backend.admin.dto;

public class AdminUserRequest {

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import org.sejongisc.backend.attendance.dto.AttendanceRoundQrTokenRequest;
import org.sejongisc.backend.attendance.dto.AttendanceStatusUpdateRequest;
import org.sejongisc.backend.attendance.service.AttendanceService;
import org.sejongisc.backend.common.auth.springsecurity.CustomUserDetails;
import org.sejongisc.backend.common.auth.dto.CustomUserDetails;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import org.sejongisc.backend.attendance.dto.AttendanceRoundRequest;
import org.sejongisc.backend.attendance.dto.AttendanceRoundResponse;
import org.sejongisc.backend.attendance.service.AttendanceRoundService;
import org.sejongisc.backend.common.auth.springsecurity.CustomUserDetails;
import org.sejongisc.backend.common.auth.dto.CustomUserDetails;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import org.sejongisc.backend.attendance.dto.AttendanceSessionRequest;
import org.sejongisc.backend.attendance.dto.AttendanceSessionResponse;
import org.sejongisc.backend.attendance.service.AttendanceSessionService;
import org.sejongisc.backend.common.auth.springsecurity.CustomUserDetails;
import org.sejongisc.backend.common.auth.dto.CustomUserDetails;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import lombok.extern.slf4j.Slf4j;
import org.sejongisc.backend.attendance.dto.SessionUserResponse;
import org.sejongisc.backend.attendance.service.SessionUserService;
import org.sejongisc.backend.common.auth.springsecurity.CustomUserDetails;
import org.sejongisc.backend.common.auth.dto.CustomUserDetails;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import org.sejongisc.backend.attendance.repository.AttendanceRoundRepository;
import org.sejongisc.backend.common.exception.CustomException;
import org.sejongisc.backend.common.exception.ErrorCode;
import org.sejongisc.backend.user.dao.UserRepository;
import org.sejongisc.backend.user.repository.UserRepository;
import org.sejongisc.backend.user.entity.User;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Service;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import org.sejongisc.backend.attendance.repository.SessionUserRepository;
import org.sejongisc.backend.common.exception.CustomException;
import org.sejongisc.backend.common.exception.ErrorCode;
import org.sejongisc.backend.user.dao.UserRepository;
import org.sejongisc.backend.user.repository.UserRepository;
import org.sejongisc.backend.user.entity.User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import org.sejongisc.backend.attendance.repository.SessionUserRepository;
import org.sejongisc.backend.common.exception.CustomException;
import org.sejongisc.backend.common.exception.ErrorCode;
import org.sejongisc.backend.user.dao.UserRepository;
import org.sejongisc.backend.user.repository.UserRepository;
import org.sejongisc.backend.user.entity.User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package org.sejongisc.backend.attendance.util;

import java.util.UUID;
import org.sejongisc.backend.common.auth.springsecurity.CustomUserDetails;

import org.sejongisc.backend.common.auth.dto.CustomUserDetails;

public class AuthUserUtil {
private AuthUserUtil() {}
Expand Down
Loading