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 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.customUserDetailsService = customUserDetailsService;
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
this.userMapper = userMapper;
|
this.userMapper = userMapper;
|
||||||
|
this.passwordEncoder = passwordEncoder;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
// 비밀번호 암호화를 위한 BCryptPasswordEncoder 빈 생성
|
// 비밀번호 암호화를 위한 BCryptPasswordEncoder 빈 생성
|
||||||
@Bean
|
@Bean
|
||||||
public PasswordEncoder passwordEncoder() {
|
public PasswordEncoder passwordEncoder() {
|
||||||
@ -52,7 +57,7 @@ public class SecurityConfig {
|
|||||||
log.info(" + UserRestController 등록된 PasswordEncoder instance: {}", encoder);
|
log.info(" + UserRestController 등록된 PasswordEncoder instance: {}", encoder);
|
||||||
|
|
||||||
return encoder;
|
return encoder;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// Spring Security의 보안 필터 체인을 설정하는 핵심 메서드
|
// Spring Security의 보안 필터 체인을 설정하는 핵심 메서드
|
||||||
@Bean
|
@Bean
|
||||||
@ -170,7 +175,7 @@ public class SecurityConfig {
|
|||||||
log.info("로그인 실패 - DB 비번(encoded): [{}]", user.getPassword());
|
log.info("로그인 실패 - DB 비번(encoded): [{}]", user.getPassword());
|
||||||
|
|
||||||
// 비번 매칭 테스트
|
// 비번 매칭 테스트
|
||||||
boolean match = passwordEncoder().matches(rawPassword, user.getPassword());
|
boolean match = passwordEncoder.matches(rawPassword, user.getPassword());
|
||||||
log.info("비밀번호 일치 여부: [{}]", match);
|
log.info("비밀번호 일치 여부: [{}]", match);
|
||||||
} else {
|
} else {
|
||||||
log.warn("로그인 실패 - 아이디에 해당하는 사용자 없음");
|
log.warn("로그인 실패 - 아이디에 해당하는 사용자 없음");
|
||||||
|
|||||||
@ -96,9 +96,6 @@ public class CommuteServiceImpl implements CommuteService {
|
|||||||
userAllVO.forEach(userVO -> log.info("userVO : [{}][{}]", userVO.getBiostarId(), userVO) );
|
userAllVO.forEach(userVO -> log.info("userVO : [{}][{}]", userVO.getBiostarId(), userVO) );
|
||||||
|
|
||||||
commuteList.stream().forEach(t->{
|
commuteList.stream().forEach(t->{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 지각 체크
|
// 지각 체크
|
||||||
t.setFirstActivityTimeMemo(this.getLateChk(t.getFirstActivityTime()));
|
t.setFirstActivityTimeMemo(this.getLateChk(t.getFirstActivityTime()));
|
||||||
// 조기퇴근 체크
|
// 조기퇴근 체크
|
||||||
|
|||||||
@ -47,4 +47,5 @@ public interface UserMapper {
|
|||||||
@Select("SELECT * FROM users WHERE user_name LIKE CONCAT('%', #{userName}, '%')")
|
@Select("SELECT * FROM users WHERE user_name LIKE CONCAT('%', #{userName}, '%')")
|
||||||
List<UserVO> findByUniqUserName(String userName);
|
List<UserVO> findByUniqUserName(String userName);
|
||||||
|
|
||||||
|
void insertUser(UserVO userVO);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,4 +27,6 @@ public interface UserService {
|
|||||||
|
|
||||||
RestResponse findByUniqUserName(String userName);
|
RestResponse findByUniqUserName(String userName);
|
||||||
RestResponse findByUniqApprovalUser(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.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.time.DayOfWeek;
|
import java.time.DayOfWeek;
|
||||||
@ -21,10 +22,7 @@ import java.time.LocalDate;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@ -38,6 +36,8 @@ public class UserServiceImpl implements UserService {
|
|||||||
@Autowired
|
@Autowired
|
||||||
TCodeUtils tCodeUtils;
|
TCodeUtils tCodeUtils;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private PasswordEncoder passwordEncoder;
|
||||||
|
|
||||||
public Map<String, Object> getList(UserVO userVO) {
|
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")
|
@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()) {
|
if (result.hasErrors()) {
|
||||||
return "register";
|
return "register";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,4 +80,13 @@ public class UserRestController {
|
|||||||
return ResponseEntity.ok().body(userService.changepassword(setUserVO));
|
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'
|
AND u.active_yn = 'Y'
|
||||||
|
|
||||||
</select>
|
</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>
|
</mapper>
|
||||||
@ -169,13 +169,14 @@
|
|||||||
<script>
|
<script>
|
||||||
|
|
||||||
const commonExportOptions = {
|
const commonExportOptions = {
|
||||||
columns: ':visible',
|
columns: function (idx, data, node) {
|
||||||
|
return idx !== 12; // 관리 열 제외
|
||||||
|
},
|
||||||
format: {
|
format: {
|
||||||
body: function (data, row, column, node) {
|
body: function (data, row, column, node) {
|
||||||
if ($(node).find('select').length) {
|
if ($(node).find('select').length) {
|
||||||
return $(node).find('select option:selected').text();
|
return $(node).find('select option:selected').text();
|
||||||
}
|
}
|
||||||
// 태그 제거: 보이는 텍스트만 반환
|
|
||||||
return $(node).text();
|
return $(node).text();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,6 +202,7 @@
|
|||||||
{
|
{
|
||||||
extend: 'excel',
|
extend: 'excel',
|
||||||
charset: 'UTF-8',
|
charset: 'UTF-8',
|
||||||
|
bom: true,
|
||||||
exportOptions: commonExportOptions
|
exportOptions: commonExportOptions
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -63,7 +63,16 @@
|
|||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<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>
|
</div>
|
||||||
<!-- /.card-header -->
|
<!-- /.card-header -->
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
@ -127,7 +136,6 @@
|
|||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<!-- /.card-body -->
|
|
||||||
</div>
|
</div>
|
||||||
<!-- /.card -->
|
<!-- /.card -->
|
||||||
</div>
|
</div>
|
||||||
@ -214,6 +222,84 @@
|
|||||||
</div>
|
</div>
|
||||||
</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 fade" id="changePasswordModal" tabindex="-1" role="dialog" aria-labelledby="changePasswordModalLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog" role="document">
|
<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>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user