108 lines
4.1 KiB
Java
108 lines
4.1 KiB
Java
package com.zioinfo.hrm.admin;
|
|
|
|
import com.zioinfo.hrm.auth.HrmUser;
|
|
import com.zioinfo.hrm.common.ApiResponse;
|
|
import com.zioinfo.hrm.common.AuthSupport;
|
|
import lombok.RequiredArgsConstructor;
|
|
import org.springframework.security.core.Authentication;
|
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
@RestController
|
|
@RequestMapping("/api/hrm/admin")
|
|
@RequiredArgsConstructor
|
|
public class AdminController {
|
|
|
|
private final AdminMapper adminMapper;
|
|
private final PasswordEncoder passwordEncoder;
|
|
|
|
@GetMapping("/users")
|
|
public ApiResponse<List<HrmUser>> users() {
|
|
List<HrmUser> users = adminMapper.findAllUsers();
|
|
users.forEach(u -> u.setPasswordHash(null)); // 비밀번호 해시 미노출
|
|
return ApiResponse.ok(users);
|
|
}
|
|
|
|
@PostMapping("/users")
|
|
public ApiResponse<Void> createUser(@RequestBody HrmUser user) {
|
|
user.setPasswordHash(passwordEncoder.encode(user.getPasswordHash()));
|
|
user.setActive(true);
|
|
adminMapper.insertUser(user);
|
|
return ApiResponse.ok(null);
|
|
}
|
|
|
|
@PutMapping("/users/{id}")
|
|
public ApiResponse<Void> updateUser(@PathVariable Long id, @RequestBody HrmUser user) {
|
|
user.setId(id);
|
|
if (user.getPasswordHash() != null && !user.getPasswordHash().isEmpty()) {
|
|
user.setPasswordHash(passwordEncoder.encode(user.getPasswordHash()));
|
|
}
|
|
adminMapper.updateUser(user);
|
|
return ApiResponse.ok(null);
|
|
}
|
|
|
|
@PatchMapping("/users/{id}/active")
|
|
public ApiResponse<Void> toggleActive(@PathVariable Long id, @RequestParam boolean active) {
|
|
adminMapper.updateUserActive(id, active);
|
|
return ApiResponse.ok(null);
|
|
}
|
|
|
|
/**
|
|
* 관리자 OTP 초기화(SUPERADMIN). 대상 사용자의 OTP 시크릿을 폐기하고 등록을 해제한다.
|
|
* 사용자는 다음 로그인 시 OTP_SETUP(QR 재등록) 플로우를 탄다. 시크릿은 응답/로그에 노출하지 않는다.
|
|
*/
|
|
@PostMapping("/users/{id}/otp-reset")
|
|
public ApiResponse<HrmUser> resetOtp(@PathVariable Long id, Authentication auth) {
|
|
HrmUser user = adminMapper.findUserById(id);
|
|
if (user == null) {
|
|
throw new RuntimeException("ERR-HRM-404: 대상 사용자를 찾을 수 없습니다");
|
|
}
|
|
adminMapper.clearOtp(id);
|
|
|
|
Map<String, Object> log = new HashMap<>();
|
|
log.put("actor", AuthSupport.actor(auth));
|
|
log.put("action", "USER_OTP_RESET");
|
|
log.put("targetType", "auth.otp");
|
|
log.put("targetId", user.getUsername());
|
|
log.put("detail", "OTP 초기화(다음 로그인 재등록)");
|
|
log.put("ipAddr", null);
|
|
adminMapper.insertAuditLog(log);
|
|
|
|
user.setPasswordHash(null); // 비밀번호 해시 미노출
|
|
return ApiResponse.ok(user);
|
|
}
|
|
|
|
@GetMapping("/audit")
|
|
public ApiResponse<Map<String, Object>> audit(
|
|
@RequestParam(required = false) String actor,
|
|
@RequestParam(required = false) String action,
|
|
@RequestParam(defaultValue = "1") int page,
|
|
@RequestParam(defaultValue = "50") int size) {
|
|
int offset = (page - 1) * size;
|
|
List<Map<String, Object>> rows = adminMapper.findAuditLogs(actor, action, offset, size);
|
|
long total = adminMapper.countAuditLogs(actor, action);
|
|
Map<String, Object> r = new HashMap<>();
|
|
r.put("items", rows);
|
|
r.put("total", total);
|
|
return ApiResponse.ok(r);
|
|
}
|
|
|
|
@GetMapping("/settings")
|
|
public ApiResponse<List<Map<String, Object>>> settings() {
|
|
return ApiResponse.ok(adminMapper.findSettings());
|
|
}
|
|
|
|
@PutMapping("/settings/{key}")
|
|
public ApiResponse<Void> upsertSetting(@PathVariable String key,
|
|
@RequestBody Map<String, Object> body, Authentication auth) {
|
|
body.put("key", key);
|
|
body.put("updatedBy", AuthSupport.actor(auth));
|
|
adminMapper.upsertSetting(body);
|
|
return ApiResponse.ok(null);
|
|
}
|
|
}
|