admin 사용자 등록 기능 추가
This commit is contained in:
parent
a6093f9961
commit
82bda62e3f
@ -0,0 +1,17 @@
|
||||
package com.itn.admin.cmn.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
@Slf4j
|
||||
@Configuration
|
||||
public class PasswordEncoderConfig {
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
}
|
||||
@ -37,14 +37,19 @@ public class SecurityConfig {
|
||||
|
||||
private final UserMapper userMapper;
|
||||
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
// 생성자를 통해 의존성 주입
|
||||
public SecurityConfig(CustomUserDetailsService customUserDetailsService, UserService userService, UserMapper userMapper) {
|
||||
public SecurityConfig(CustomUserDetailsService customUserDetailsService
|
||||
, UserService userService
|
||||
, UserMapper userMapper
|
||||
, PasswordEncoder passwordEncoder) {
|
||||
this.customUserDetailsService = customUserDetailsService;
|
||||
this.userService = userService;
|
||||
this.userMapper = userMapper;
|
||||
this.passwordEncoder = passwordEncoder;
|
||||
}
|
||||
|
||||
/*
|
||||
// 비밀번호 암호화를 위한 BCryptPasswordEncoder 빈 생성
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
@ -52,7 +57,7 @@ public class SecurityConfig {
|
||||
log.info(" + UserRestController 등록된 PasswordEncoder instance: {}", encoder);
|
||||
|
||||
return encoder;
|
||||
}
|
||||
}*/
|
||||
|
||||
// Spring Security의 보안 필터 체인을 설정하는 핵심 메서드
|
||||
@Bean
|
||||
@ -170,7 +175,7 @@ public class SecurityConfig {
|
||||
log.info("로그인 실패 - DB 비번(encoded): [{}]", user.getPassword());
|
||||
|
||||
// 비번 매칭 테스트
|
||||
boolean match = passwordEncoder().matches(rawPassword, user.getPassword());
|
||||
boolean match = passwordEncoder.matches(rawPassword, user.getPassword());
|
||||
log.info("비밀번호 일치 여부: [{}]", match);
|
||||
} else {
|
||||
log.warn("로그인 실패 - 아이디에 해당하는 사용자 없음");
|
||||
|
||||
@ -96,9 +96,6 @@ public class CommuteServiceImpl implements CommuteService {
|
||||
userAllVO.forEach(userVO -> log.info("userVO : [{}][{}]", userVO.getBiostarId(), userVO) );
|
||||
|
||||
commuteList.stream().forEach(t->{
|
||||
|
||||
|
||||
|
||||
// 지각 체크
|
||||
t.setFirstActivityTimeMemo(this.getLateChk(t.getFirstActivityTime()));
|
||||
// 조기퇴근 체크
|
||||
|
||||
@ -47,4 +47,5 @@ public interface UserMapper {
|
||||
@Select("SELECT * FROM users WHERE user_name LIKE CONCAT('%', #{userName}, '%')")
|
||||
List<UserVO> findByUniqUserName(String userName);
|
||||
|
||||
void insertUser(UserVO userVO);
|
||||
}
|
||||
|
||||
@ -27,4 +27,6 @@ public interface UserService {
|
||||
|
||||
RestResponse findByUniqUserName(String userName);
|
||||
RestResponse findByUniqApprovalUser(String userName);
|
||||
|
||||
RestResponse insertUser(UserVO userVO);
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.DayOfWeek;
|
||||
@ -21,10 +22,7 @@ import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@Slf4j
|
||||
@ -38,6 +36,8 @@ public class UserServiceImpl implements UserService {
|
||||
@Autowired
|
||||
TCodeUtils tCodeUtils;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
public Map<String, Object> getList(UserVO userVO) {
|
||||
|
||||
@ -160,4 +160,19 @@ public class UserServiceImpl implements UserService {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public RestResponse insertUser(UserVO userVO) {
|
||||
|
||||
userVO.setUniqId("ITN_"+ UUID.randomUUID().toString().replace("-", "").substring(0, 10));
|
||||
userVO.setPassword(passwordEncoder.encode("itn123")); // 초기 비밀번호
|
||||
userVO.setRole(Role.ROLE_GUEST);
|
||||
log.info("userVO : [{}]", userVO);
|
||||
userMapper.insertUser(userVO);
|
||||
return RestResponse.builder()
|
||||
.status(HttpStatus.OK) // 200 성공
|
||||
.data(userVO.getUserName())
|
||||
.msg("등록되었습니다.")
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -43,7 +43,11 @@ public class LoginController {
|
||||
}
|
||||
|
||||
@PostMapping("/user/register")
|
||||
public String register(@Valid @ModelAttribute("user") UserDTO userDTO, BindingResult result, Model model, RedirectAttributes redirectAttributes) {
|
||||
public String register(@Valid @ModelAttribute("user") UserDTO userDTO
|
||||
, BindingResult result
|
||||
, Model model
|
||||
, RedirectAttributes redirectAttributes)
|
||||
{
|
||||
if (result.hasErrors()) {
|
||||
return "register";
|
||||
}
|
||||
|
||||
@ -80,4 +80,13 @@ public class UserRestController {
|
||||
return ResponseEntity.ok().body(userService.changepassword(setUserVO));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/api/admin/user")
|
||||
public ResponseEntity<RestResponse> createUser(@RequestBody UserVO userVO, @AuthenticationPrincipal CustomUserDetails loginUser) {
|
||||
userVO.setFrstRegisterId(loginUser.getUser().getUserId());
|
||||
userVO.setLastUpdusrId(loginUser.getUser().getUserId());
|
||||
return ResponseEntity.ok().body(userService.insertUser(userVO));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -102,4 +102,46 @@
|
||||
AND u.active_yn = 'Y'
|
||||
|
||||
</select>
|
||||
|
||||
<insert id="insertUser" parameterType="userVO">
|
||||
INSERT INTO users (
|
||||
uniq_id,
|
||||
user_id,
|
||||
user_pw,
|
||||
user_name,
|
||||
mobile_phone,
|
||||
rank_cd,
|
||||
dept_cd,
|
||||
role,
|
||||
gw_id,
|
||||
biostar_id,
|
||||
active_yn,
|
||||
hire_date,
|
||||
resign_date,
|
||||
FRST_REGISTER_ID,
|
||||
FRST_REGIST_PNTTM,
|
||||
LAST_UPDUSR_ID,
|
||||
LAST_UPDT_PNTTM
|
||||
)
|
||||
VALUES (
|
||||
#{uniqId},
|
||||
#{userId},
|
||||
#{password},
|
||||
#{userName},
|
||||
#{mobilePhone},
|
||||
#{rankCd},
|
||||
#{deptCd},
|
||||
#{role},
|
||||
#{gwId},
|
||||
#{biostarId},
|
||||
#{activeYn},
|
||||
#{hireDate},
|
||||
#{resignDate},
|
||||
#{frstRegisterId},
|
||||
NOW(),
|
||||
#{lastUpdusrId},
|
||||
NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
</mapper>
|
||||
@ -169,13 +169,14 @@
|
||||
<script>
|
||||
|
||||
const commonExportOptions = {
|
||||
columns: ':visible',
|
||||
columns: function (idx, data, node) {
|
||||
return idx !== 12; // 관리 열 제외
|
||||
},
|
||||
format: {
|
||||
body: function (data, row, column, node) {
|
||||
if ($(node).find('select').length) {
|
||||
return $(node).find('select option:selected').text();
|
||||
}
|
||||
// 태그 제거: 보이는 텍스트만 반환
|
||||
return $(node).text();
|
||||
}
|
||||
}
|
||||
@ -201,6 +202,7 @@
|
||||
{
|
||||
extend: 'excel',
|
||||
charset: 'UTF-8',
|
||||
bom: true,
|
||||
exportOptions: commonExportOptions
|
||||
},
|
||||
{
|
||||
|
||||
@ -63,7 +63,16 @@
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">목록</h3>
|
||||
<div class="row w-100">
|
||||
<div class="col-sm-6 align-self-center">
|
||||
<h3 class="card-title">목록</h3>
|
||||
</div>
|
||||
<div class="col-sm-6 text-right">
|
||||
<button class="btn btn-primary btn-sm" onclick="openUserRegisterModal()">
|
||||
<i class="fas fa-user-plus"></i> 사용자 등록
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.card-header -->
|
||||
<div class="card-body">
|
||||
@ -127,7 +136,6 @@
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<!-- /.card-body -->
|
||||
</div>
|
||||
<!-- /.card -->
|
||||
</div>
|
||||
@ -214,6 +222,84 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- 공통 코드 그룹 등록 모달 -->
|
||||
<div class="modal fade" id="regUserInfoModal" tabindex="-1" role="dialog" aria-labelledby="regUserInfoModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="regUserInfoModalLabel">사용자 정보 등록</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form id="regUserInfoForm">
|
||||
<div class="form-group">
|
||||
<label for="uniqId">고유 ID</label>
|
||||
<input type="text" class="form-control" id="regUniqId" name="uniqId" placeholder="등록하면 자동 생성됩니다." readonly>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="userId">ID</label>
|
||||
<input type="text" class="form-control" id="regUserId" name="userId" placeholder="그룹웨어와 같은 ID로 등록해 주세요.">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="biostarId">출퇴근 ID</label>
|
||||
<input type="text" class="form-control" id="biostarId" name="biostarId" placeholder="출퇴근 관리 목록 이름에 '&@~'로 시작하고 '=='로 끝나는 문자 넣어 주세요">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="mobilePhone">핸드폰번호</label>
|
||||
<input type="text" class="form-control" id="regMobilePhone" name="mobilePhone">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="userName">이름</label>
|
||||
<input type="text" class="form-control" id="regUserName" name="userName">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="rankCd">직급</label>
|
||||
<select class="form-control" id="regRankCd" name="rankCd">
|
||||
<option value="" th:selected>-- 선택 --</option>
|
||||
<option th:each="code : ${@TCodeUtils.getCodeList('RANK')}"
|
||||
th:value="${code.codeId}"
|
||||
th:text="${code.codeName}">
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="deptCd">부서명</label>
|
||||
<select class="form-control" id="regDeptCd" name="deptCd">
|
||||
<option value="" th:selected>-- 선택 --</option>
|
||||
<option th:each="code : ${@TCodeUtils.getCodeList('DEPT')}"
|
||||
th:value="${code.codeId}"
|
||||
th:text="${code.codeName}">
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="activeYn">재직여부</label>
|
||||
<select class="form-control" id="regActiveYn" name="activeYn">
|
||||
<option value="Y">재직</option>
|
||||
<option value="N">퇴사</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="hireDate">입사일</label>
|
||||
<input type="date" id="regHireDate" name="hireDate" class="form-control" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="resignDate">퇴사일</label>
|
||||
<input type="date" id="regResignDate" name="resignDate" class="form-control" required>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">닫기</button>
|
||||
<button type="button" class="btn btn-primary" onclick="createUser()">등록</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 비밀번호 변경 모달 -->
|
||||
<div class="modal fade" id="changePasswordModal" tabindex="-1" role="dialog" aria-labelledby="changePasswordModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog" role="document">
|
||||
@ -461,6 +547,42 @@
|
||||
});
|
||||
}
|
||||
|
||||
window.openUserRegisterModal = function() {
|
||||
$('#regUserInfoForm')[0].reset();
|
||||
$('#regUserInfoModal').modal('show');
|
||||
};
|
||||
|
||||
window.createUser = function() {
|
||||
const formId = "#regUserInfoForm";
|
||||
|
||||
// 필수값 검증 (예시로 이름만)
|
||||
if (!$(formId + ' #regUserName').val()) {
|
||||
alert("이름을 입력하세요.");
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = {};
|
||||
$(formId).serializeArray().forEach(field => {
|
||||
formData[field.name] = field.value;
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
url: '/api/admin/user', // POST로 등록
|
||||
type: 'POST',
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
data: JSON.stringify(formData),
|
||||
success: function(response) {
|
||||
$('#regUserInfoModal').modal('hide');
|
||||
fn_successAlert("등록 완료", response.data + "님 등록됨");
|
||||
location.reload();
|
||||
},
|
||||
error: function() {
|
||||
alert("등록 실패");
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user