Merge branch 'main' of http://192.168.0.251:3000/localnet/localhost-back.git into main
This commit is contained in:
commit
f8da4b8b0b
@ -131,3 +131,4 @@ tasks.javadoc {
|
||||
tasks.named('test') {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
|
||||
@ -15,10 +15,14 @@
|
||||
package io.company.localhost.common.config;
|
||||
|
||||
import io.company.localhost.common.resolver.RequestToMapArgumentResolver;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
|
||||
import org.springframework.web.multipart.MultipartResolver;
|
||||
import org.springframework.web.multipart.support.StandardServletMultipartResolver;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
@ -35,6 +39,12 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
public static final String WILD_CARD = "/**";
|
||||
|
||||
@Value("${filePath.boardfile}")
|
||||
private String boardFilePath;
|
||||
|
||||
@Value("${filePath.profile}")
|
||||
private String uploadPath;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// 여기서 인터셉터를 추가할 수 있음
|
||||
@ -47,6 +57,13 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
||||
registry
|
||||
.addResourceHandler("/index.html")
|
||||
.addResourceLocations("classpath:/static/index.html", "/index.html");
|
||||
|
||||
//게시판 에디터 안 이미지 업로드 경로
|
||||
registry.addResourceHandler("/upload/img/board/**")
|
||||
.addResourceLocations("file:" + boardFilePath);
|
||||
//프로필 이미지 업로드 경로
|
||||
registry.addResourceHandler("/upload/img/profile/**")
|
||||
.addResourceLocations("file:" + uploadPath);
|
||||
}
|
||||
|
||||
// Controller의 파라미터를 처리할 Resolver 등록
|
||||
@ -82,4 +99,11 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
return localeResolver;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MultipartResolver multipartResolver() {
|
||||
return new StandardServletMultipartResolver();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -23,13 +23,18 @@ import lombok.RequiredArgsConstructor;
|
||||
@RequiredArgsConstructor
|
||||
public enum CommonErrorCode implements ErrorCode {
|
||||
|
||||
INVALID_PARAMETER(HttpStatus.BAD_REQUEST.value(),HttpStatus.BAD_REQUEST,"잘못된 매개변수가 포함되었습니다."),
|
||||
RESOURCE_NOT_FOUND(HttpStatus.NOT_FOUND.value(),HttpStatus.NOT_FOUND,"리소스가 존재하지 않습니다"),
|
||||
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR.value(),HttpStatus.INTERNAL_SERVER_ERROR,"내부 서버 오류"),
|
||||
INVALID_PARAMETER(HttpStatus.BAD_REQUEST,"잘못된 매개변수가 포함되었습니다."),
|
||||
RESOURCE_NOT_FOUND(HttpStatus.NOT_FOUND,"리소스가 존재하지 않습니다"),
|
||||
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR,"내부 서버 오류"),
|
||||
;
|
||||
|
||||
private final long code;
|
||||
private final HttpStatus httpStatus;
|
||||
private final String message;
|
||||
|
||||
CommonErrorCode(HttpStatus httpStatus, String message) {
|
||||
this.code = httpStatus.value();
|
||||
this.httpStatus = httpStatus;
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,13 +24,23 @@ import lombok.RequiredArgsConstructor;
|
||||
@RequiredArgsConstructor
|
||||
public enum UserErrorCode implements ErrorCode {
|
||||
|
||||
NOT_AUTH_USER(HttpStatus.UNAUTHORIZED.value(),HttpStatus.UNAUTHORIZED ,"로그인이 필요합니다."),
|
||||
INACTIVE_USER(HttpStatus.FORBIDDEN.value(),HttpStatus.FORBIDDEN,"권한이 필요합니다.");
|
||||
NOT_AUTH_USER(HttpStatus.UNAUTHORIZED ,"로그인이 필요합니다."),
|
||||
INACTIVE_USER(HttpStatus.FORBIDDEN,"권한이 필요합니다."),
|
||||
USER_NOT_FOUND(HttpStatus.UNAUTHORIZED,"아이디 혹은 비밀번호가 틀렸습니다."),
|
||||
NOT_AUTHORIZED(HttpStatus.UNAUTHORIZED,"비인가 계정입니다."),
|
||||
EXIT_USER(HttpStatus.UNAUTHORIZED,"탈퇴한 계정입니다."),
|
||||
BAD_CREDENTIAL(HttpStatus.UNAUTHORIZED, "아이디 혹은 비밀번호 문제")
|
||||
;
|
||||
|
||||
private final long code;
|
||||
private final HttpStatus httpStatus;
|
||||
private final String message;
|
||||
|
||||
UserErrorCode(HttpStatus httpStatus, String message) {
|
||||
this.code = httpStatus.value();
|
||||
this.httpStatus = httpStatus;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public ApiResponse<?> getApiResponse() {
|
||||
return ApiResponse.error(this.getHttpStatus() , this.getMessage());
|
||||
|
||||
@ -21,10 +21,12 @@ import io.company.localhost.common.security.handler.MemberAuthSuccessHandler;
|
||||
import io.company.localhost.common.security.handler.RestAccessDeniedHandler;
|
||||
import io.company.localhost.common.security.handler.RestAuthenticationEntryPointHandler;
|
||||
import io.company.localhost.common.security.service.CustomRememberMeServices;
|
||||
import io.company.localhost.common.security.service.TokenService;
|
||||
import io.company.localhost.common.security.service.MemberPrincipalDetailService;
|
||||
import io.company.localhost.common.security.session.AuthenticationSessionControlStrategy;
|
||||
import io.company.localhost.common.security.session.CustomSessionRegistryImpl;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
@ -50,6 +52,7 @@ public class SecurityConfig {
|
||||
// 의존성 주입
|
||||
private final AuthenticationProvider memberAuthenticatorProvider;
|
||||
private final MemberPrincipalDetailService userDetailsService;
|
||||
private final MemberAuthSuccessHandler successHandler;
|
||||
private final MemberAuthFailureHandler failureHandler;
|
||||
private final AuthorizationManager<RequestAuthorizationContext> authorizationManager;
|
||||
|
||||
@ -63,6 +66,9 @@ public class SecurityConfig {
|
||||
final String SECURITY_BASE_URL = "/api/user";
|
||||
final String LOGIN_URL = SECURITY_BASE_URL + "/login";
|
||||
|
||||
final String LOGIN_KEY = "loginSecretKey";
|
||||
|
||||
|
||||
// 보안 필터 체인 설정
|
||||
@Bean
|
||||
public SecurityFilterChain restSecurityFilterChain(HttpSecurity http, WebCorsFilter webCorsFilter) throws Exception {
|
||||
@ -71,12 +77,11 @@ public class SecurityConfig {
|
||||
.authenticationProvider(memberAuthenticatorProvider)
|
||||
.build();
|
||||
|
||||
MemberAuthSuccessHandler successHandler = new MemberAuthSuccessHandler(rememberMeServices());
|
||||
|
||||
http
|
||||
.securityMatcher("/api/**") // '/api/**' 경로에 대해서만 보안 적용
|
||||
.authorizeHttpRequests(auth ->
|
||||
auth.requestMatchers("/api/board/general").permitAll() // 특정 엔드포인트 허용
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/api/board/**").hasRole("MEMBER")
|
||||
.requestMatchers("/api/**").permitAll() // 특정 엔드포인트 허용
|
||||
.anyRequest().authenticated() // 나머지 요청은 인증 필요
|
||||
//auth.anyRequest().access(authorizationManager) // 모든 요청에 대해 권한 관리
|
||||
)
|
||||
@ -116,9 +121,15 @@ public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
public RememberMeServices rememberMeServices(){
|
||||
return new CustomRememberMeServices(REMEMBER_KEY , userDetailsService);
|
||||
return new CustomRememberMeServices(tokenService(), userDetailsService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TokenService tokenService() {
|
||||
return new TokenService(REMEMBER_KEY, LOGIN_KEY);
|
||||
}
|
||||
|
||||
|
||||
// 세션 관리
|
||||
protected ConcurrentSessionControlAuthenticationStrategy sessionControlStrategy() {
|
||||
AuthenticationSessionControlStrategy sessionControlStrategy = new AuthenticationSessionControlStrategy(sessionRegistry());
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
package io.company.localhost.common.security.handler;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.company.localhost.common.dto.ApiResponse;
|
||||
import io.company.localhost.common.exception.code.UserErrorCode;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.http.MediaType;
|
||||
@ -35,10 +37,17 @@ public class MemberAuthFailureHandler implements AuthenticationFailureHandler {
|
||||
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
|
||||
if (exception instanceof BadCredentialsException) {
|
||||
mapper.writeValue(response.getWriter(),"아이디 혹은 비밀번호 문제");
|
||||
ApiResponse<?> res = UserErrorCode.BAD_CREDENTIAL.getApiResponse();
|
||||
String message = exception.getMessage();
|
||||
|
||||
if (exception instanceof BadCredentialsException || message.startsWith("NOT_FOUND")) {
|
||||
res = UserErrorCode.USER_NOT_FOUND.getApiResponse();
|
||||
} else if (message.startsWith("NOT_AUTHORIZED")) {
|
||||
res = UserErrorCode.NOT_AUTHORIZED.getApiResponse();
|
||||
} else if (message.startsWith("EXIT")) {
|
||||
res = UserErrorCode.EXIT_USER.getApiResponse();
|
||||
}
|
||||
|
||||
mapper.writeValue(response.getWriter(), "인증 실패");
|
||||
response.getWriter().write(mapper.writeValueAsString(res));
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,54 +15,75 @@
|
||||
package io.company.localhost.common.security.handler;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.company.localhost.common.dto.ApiResponse;
|
||||
import io.company.localhost.common.dto.MapDto;
|
||||
import io.company.localhost.common.security.service.TokenService;
|
||||
import io.company.localhost.service.NetmemberService;
|
||||
import io.company.localhost.vo.MemberVo;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.web.WebAttributes;
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Slf4j
|
||||
@Component("successHandler")
|
||||
public class MemberAuthSuccessHandler implements AuthenticationSuccessHandler{
|
||||
public class MemberAuthSuccessHandler implements AuthenticationSuccessHandler {
|
||||
|
||||
private final RememberMeServices rememberMeServices;
|
||||
private final TokenService tokenService;
|
||||
private final NetmemberService netmemberService;
|
||||
|
||||
public MemberAuthSuccessHandler(RememberMeServices rememberMeServices) {
|
||||
this.rememberMeServices = rememberMeServices;
|
||||
}
|
||||
public MemberAuthSuccessHandler(@Lazy TokenService tokenService, NetmemberService netmemberService) {
|
||||
this.tokenService = tokenService;
|
||||
this.netmemberService = netmemberService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
@Override
|
||||
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
|
||||
Authentication authentication) throws IOException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
Boolean rememberMe = (Boolean) request.getAttribute("remember");
|
||||
if (rememberMe != null && rememberMe) {
|
||||
rememberMeServices.loginSuccess(request, response, authentication);
|
||||
}
|
||||
|
||||
MemberVo member = (MemberVo) authentication.getPrincipal();
|
||||
response.setStatus(HttpStatus.OK.value());
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
|
||||
mapper.writeValue(response.getWriter(), member);
|
||||
|
||||
clearAuthenticationAttributes(request);
|
||||
}
|
||||
|
||||
protected final void clearAuthenticationAttributes(HttpServletRequest request) {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session == null) {
|
||||
// 로그인 성공한 사용자 가져오기
|
||||
Object principal = authentication.getPrincipal();
|
||||
if (!(principal instanceof MemberVo member)) {
|
||||
response.setStatus(HttpStatus.UNAUTHORIZED.value());
|
||||
return;
|
||||
}
|
||||
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
|
||||
}
|
||||
|
||||
// 로그인 토큰 생성
|
||||
String username = member.getLoginId();
|
||||
String loginToken = tokenService.generateToken(username, "login");
|
||||
|
||||
// DB에 저장
|
||||
MapDto map = new MapDto();
|
||||
map.put("id", username);
|
||||
map.put("token", loginToken);
|
||||
netmemberService.updateMemberToken(map);
|
||||
|
||||
response.setStatus(HttpStatus.OK.value());
|
||||
response.setContentType(MediaType.APPLICATION_JSON_VALUE);
|
||||
|
||||
response.getWriter().write(mapper.writeValueAsString(ApiResponse.ok("Success")));
|
||||
|
||||
clearAuthenticationAttributes(request);
|
||||
}
|
||||
|
||||
protected final void clearAuthenticationAttributes(HttpServletRequest request) {
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,11 +10,12 @@
|
||||
* DATE AUTHOR NOTE
|
||||
* -----------------------------------------------------------
|
||||
* 24.12.06 조인제 최초 생성
|
||||
*
|
||||
* 24.02.03 박지윤 토큰 로직 변경
|
||||
*************************************************************/
|
||||
package io.company.localhost.common.security.service;
|
||||
|
||||
import io.company.localhost.common.security.details.MemberPrincipalDetails;
|
||||
import io.company.localhost.service.NetmemberService;
|
||||
import io.company.localhost.vo.MemberVo;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
@ -27,8 +28,6 @@ import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
@ -39,11 +38,12 @@ public class CustomRememberMeServices implements RememberMeServices {
|
||||
private static final long TOKEN_VALIDITY_SECONDS = 60 * 60 * 24 * 365; // 1 year
|
||||
private static final String DELIMITER = ":";
|
||||
|
||||
private final String secretKey;
|
||||
|
||||
private final TokenService tokenService;
|
||||
private final UserDetailsService userDetailsService;
|
||||
|
||||
public CustomRememberMeServices(String secretKey, UserDetailsService userDetailsService) {
|
||||
this.secretKey = secretKey;
|
||||
public CustomRememberMeServices(TokenService tokenService, UserDetailsService userDetailsService) {
|
||||
this.tokenService = tokenService;
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
|
||||
@ -55,33 +55,22 @@ public class CustomRememberMeServices implements RememberMeServices {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] tokenParts = decodeAndSplitCookie(rememberMeCookie.getValue());
|
||||
if (tokenParts == null || tokenParts.length != 3) {
|
||||
return null;
|
||||
}
|
||||
String token = rememberMeCookie.getValue();
|
||||
|
||||
String username = tokenParts[0];
|
||||
long expiryTime;
|
||||
try {
|
||||
expiryTime = Long.parseLong(tokenParts[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
return null;
|
||||
}
|
||||
if (!tokenService.validateToken(token, "rememberme")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String signature = tokenParts[2];
|
||||
if (!isTokenValid(username, expiryTime, signature)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (System.currentTimeMillis() > expiryTime) {
|
||||
return null;
|
||||
}
|
||||
String[] tokenParts = decodeAndSplitCookie(token);
|
||||
String username = tokenParts[0];
|
||||
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||
if (userDetails != null) {
|
||||
MemberPrincipalDetails memberDetails = (MemberPrincipalDetails) userDetails;
|
||||
MemberVo memberVo = memberDetails.member();
|
||||
RememberMeAuthenticationToken auth = new RememberMeAuthenticationToken(secretKey, memberVo, userDetails.getAuthorities());
|
||||
|
||||
String rememberMeSecretKey = tokenService.getRememberMeSecretKey();
|
||||
RememberMeAuthenticationToken auth = new RememberMeAuthenticationToken(rememberMeSecretKey, memberVo, userDetails.getAuthorities());
|
||||
auth.setAuthenticated(true);
|
||||
SecurityContextHolder.getContext().setAuthentication(auth);
|
||||
return auth;
|
||||
@ -92,16 +81,19 @@ public class CustomRememberMeServices implements RememberMeServices {
|
||||
|
||||
@Override
|
||||
public void loginSuccess(HttpServletRequest request, HttpServletResponse response, Authentication successfulAuthentication) {
|
||||
Boolean rememberMe = (Boolean) request.getAttribute("remember");
|
||||
|
||||
if(!rememberMe){
|
||||
return;
|
||||
}
|
||||
|
||||
Object principal = successfulAuthentication.getPrincipal();
|
||||
if (!(principal instanceof MemberVo member)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String username = member.getLoginId();
|
||||
long expiryTime = System.currentTimeMillis() + (TOKEN_VALIDITY_SECONDS * 1000);
|
||||
String signature = generateSignature(username, expiryTime);
|
||||
String tokenValue = encodeToken(username, expiryTime, signature);
|
||||
|
||||
String tokenValue = tokenService.generateToken(username, "rememberme");
|
||||
|
||||
SecurityContextHolder.getContext().setAuthentication(successfulAuthentication);
|
||||
|
||||
@ -143,24 +135,4 @@ public class CustomRememberMeServices implements RememberMeServices {
|
||||
}
|
||||
}
|
||||
|
||||
private String encodeToken(String username, long expiryTime, String signature) {
|
||||
String tokenValue = username + DELIMITER + expiryTime + DELIMITER + signature;
|
||||
return Base64.getEncoder().encodeToString(tokenValue.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
private boolean isTokenValid(String username, long expiryTime, String signature) {
|
||||
String expectedSignature = generateSignature(username, expiryTime);
|
||||
return expectedSignature.equals(signature);
|
||||
}
|
||||
|
||||
private String generateSignature(String username, long expiryTime) {
|
||||
try {
|
||||
String data = username + DELIMITER + expiryTime;
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
|
||||
return Base64.getEncoder().encodeToString(mac.doFinal(data.getBytes(StandardCharsets.UTF_8)));
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Failed to generate signature", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,28 +21,28 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import io.company.localhost.common.security.details.MemberPrincipalDetails;
|
||||
import io.company.localhost.vo.MemberVo;
|
||||
import io.company.localhost.mapper.MemberMapper;
|
||||
import io.company.localhost.mapper.NetmemberMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class MemberPrincipalDetailService implements UserDetailsService {
|
||||
|
||||
private final MemberMapper memberMapper;
|
||||
private final NetmemberMapper memberMapper;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String id) throws UsernameNotFoundException {
|
||||
MemberVo member = memberMapper.findByLoginId(id);
|
||||
|
||||
// 없을경우 에러 발생
|
||||
//FailHandler 에서 처리
|
||||
if(member == null)
|
||||
throw new UsernameNotFoundException(id + "을 찾을 수 없습니다.");
|
||||
throw new UsernameNotFoundException("NOT_FOUND");
|
||||
|
||||
if(!"Y".equals(member.getIsUsed()))
|
||||
throw new UsernameNotFoundException("사용할 수 없는 계정입니다.");
|
||||
throw new UsernameNotFoundException("NOT_AUTHORIZED");
|
||||
|
||||
if(!"N".equals(member.getIsDel()))
|
||||
throw new UsernameNotFoundException("삭제된 계정입니다.");
|
||||
throw new UsernameNotFoundException("EXIT");
|
||||
|
||||
// MemberPrincipalDetails 에 Member 객체를 넘겨줌
|
||||
return new MemberPrincipalDetails(member);
|
||||
|
||||
@ -0,0 +1,121 @@
|
||||
/************************************************************
|
||||
*
|
||||
* @packageName : io.company.localhost.common.security.service
|
||||
* @fileName : TokenService.java
|
||||
* @author : 박지윤
|
||||
* @date : 24.01.24
|
||||
* @description :
|
||||
*
|
||||
* ===========================================================
|
||||
* DATE AUTHOR NOTE
|
||||
* -----------------------------------------------------------
|
||||
* 24.01.24 박지윤 최초 생성
|
||||
*************************************************************/
|
||||
package io.company.localhost.common.security.service;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class TokenService {
|
||||
private static final long REMBER_TOKEN_VALIDITY_SECONDS = 60 * 60 * 24 * 365; // 1년
|
||||
private static final long LOGIN_TOKEN_VALIDITY_SECONDS = 60 * 60 * 24 * 365; // 하루
|
||||
private static final String DELIMITER = ":";
|
||||
private final String rememberMeSecretKey;
|
||||
private final String loginSecretKey;
|
||||
|
||||
public TokenService(String rememberMeSecretKey, String loginSecretKey) {
|
||||
this.rememberMeSecretKey = rememberMeSecretKey;
|
||||
this.loginSecretKey = loginSecretKey;
|
||||
}
|
||||
|
||||
public String generateToken(String username, String tokenType) {
|
||||
long expiryTime;
|
||||
|
||||
// 토큰타입에 따라 만료기간 다르게 설정
|
||||
if ("rememberme".equals(tokenType)) {
|
||||
expiryTime = System.currentTimeMillis() + (REMBER_TOKEN_VALIDITY_SECONDS * 1000);
|
||||
} else if ("login".equals(tokenType)) {
|
||||
expiryTime = System.currentTimeMillis() + (LOGIN_TOKEN_VALIDITY_SECONDS * 1000);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid token type");
|
||||
}
|
||||
|
||||
String signature = generateSignature(username, expiryTime, tokenType);
|
||||
return encodeToken(username, expiryTime, signature);
|
||||
}
|
||||
|
||||
public boolean validateToken(String token, String tokenType) {
|
||||
try {
|
||||
String[] tokenParts = decodeAndSplitToken(token);
|
||||
if (tokenParts == null || tokenParts.length != 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String username = tokenParts[0];
|
||||
long expiryTime;
|
||||
try {
|
||||
expiryTime = Long.parseLong(tokenParts[1]);
|
||||
} catch (NumberFormatException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String signature = tokenParts[2];
|
||||
if (!isTokenValid(username, expiryTime, signature, tokenType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return System.currentTimeMillis() <= expiryTime;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String generateSignature(String username, long expiryTime, String tokenType) {
|
||||
try {
|
||||
// tokenType에 따라 login 또는 remember secretKey 사용
|
||||
String secretKeyToUse = "rememberme".equals(tokenType) ? rememberMeSecretKey : loginSecretKey;
|
||||
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(new SecretKeySpec(secretKeyToUse.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
|
||||
String data = username + DELIMITER + expiryTime;
|
||||
return Base64.getEncoder().encodeToString(mac.doFinal(data.getBytes(StandardCharsets.UTF_8)));
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Failed to generate signature", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String encodeToken(String username, long expiryTime, String signature) {
|
||||
String tokenValue = username + DELIMITER + expiryTime + DELIMITER + signature;
|
||||
return Base64.getEncoder().encodeToString(tokenValue.getBytes(StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
private String[] decodeAndSplitToken(String token) {
|
||||
try {
|
||||
String decodedValue = new String(Base64.getDecoder().decode(token), StandardCharsets.UTF_8);
|
||||
return decodedValue.split(DELIMITER);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isTokenValid(String username, long expiryTime, String signature, String tokenType) {
|
||||
String expectedSignature = generateSignature(username, expiryTime, tokenType);
|
||||
return expectedSignature.equals(signature);
|
||||
}
|
||||
|
||||
public String getRememberMeSecretKey() {
|
||||
return rememberMeSecretKey;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,25 +1,35 @@
|
||||
/************************************************************
|
||||
*
|
||||
* @packageName : io.company.localhost.controller.api
|
||||
* @fileName : BoardController.java
|
||||
* @author : 서지희
|
||||
* @date : 25.01.07
|
||||
* @description : 게시판
|
||||
*
|
||||
* ===========================================================
|
||||
* DATE AUTHOR NOTE
|
||||
* -----------------------------------------------------------
|
||||
* 24.01.02 서지희 최초 생성
|
||||
*
|
||||
*************************************************************/
|
||||
|
||||
package io.company.localhost.controller.api;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Blob;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import io.company.localhost.common.annotation.Member;
|
||||
import io.company.localhost.common.annotation.ParameterCheck;
|
||||
import io.company.localhost.common.annotation.ReqMap;
|
||||
import io.company.localhost.common.dto.ApiResponse;
|
||||
import io.company.localhost.common.dto.MapDto;
|
||||
import io.company.localhost.service.LocalBordService;
|
||||
import io.company.localhost.service.commoncodService;
|
||||
import io.company.localhost.service.localbordService;
|
||||
import io.company.localhost.utils.AuthUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@ -28,108 +38,209 @@ import lombok.extern.slf4j.Slf4j;
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
public class BoardController {
|
||||
private final LocalBordService boardService;
|
||||
|
||||
//공지사항
|
||||
private final localbordService boardService;
|
||||
private final commoncodService commoncodService;
|
||||
|
||||
/**
|
||||
* 공지사항 목록 조회
|
||||
* @ReqMap map 요청 파라미터 (searchKeyword)
|
||||
* @return 전체 공지사항 목록
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@GetMapping("/notices")
|
||||
public ApiResponse<List<Map<String, Object>>> getNotices() {
|
||||
return ApiResponse.ok(boardService.getNotices());
|
||||
public ApiResponse<List<MapDto>> getNotices(@ReqMap MapDto map) {
|
||||
return ApiResponse.ok(boardService.getNotices(map));
|
||||
}
|
||||
//비밀,자유게시판
|
||||
|
||||
/**
|
||||
* 자유/익명 게시판 목록 조회
|
||||
* @ReqMap map 요청 파라미터 (page, searchKeyword, orderBy, size)
|
||||
* @return 페이징된 자유/익명 게시판 목록
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@GetMapping("/general")
|
||||
public ApiResponse<List<Map<String, Object>>> getGeneralPosts() {
|
||||
List<Map<String, Object>> posts = boardService.getGeneralPosts();
|
||||
for (Map<String, Object> post : posts) {
|
||||
Object content = post.get("content");
|
||||
if (content instanceof Blob) {
|
||||
Blob blob = (Blob) content;
|
||||
try {
|
||||
post.put("content", new String(blob.getBytes(1, (int) blob.length()), StandardCharsets.UTF_8));
|
||||
} catch (Exception e) {
|
||||
post.put("content", ""); // 변환 실패 시 기본 값 설정
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println(posts);
|
||||
return ApiResponse.ok(posts);
|
||||
public ApiResponse<PageInfo<MapDto>> getGeneralPosts(@ReqMap MapDto map) {
|
||||
return ApiResponse.ok(boardService.getGeneralPosts(map));
|
||||
}
|
||||
//게시물 작성
|
||||
|
||||
/**
|
||||
* 게시물 작성
|
||||
* @ReqMap map 요청 파라미터 (LOCBRDTTL, LOCBRDCON, MEMBERSEQ, LOCBRDTYP,
|
||||
* LOCBRDPWD(익명일 때만), LOCBRDCAT(지식커뮤니티만))
|
||||
* @return 작성된 게시물의 ID
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@PostMapping
|
||||
public ApiResponse<String> createBoard(@ReqMap MapDto map) {
|
||||
boardService.createBoard(map);
|
||||
return ApiResponse.ok("게시물이 작성되었습니다.");
|
||||
public ApiResponse<BigInteger> createBoard(@ReqMap MapDto map) {
|
||||
Long userId = AuthUtil.getUser().getId();
|
||||
map.put("MEMBERSEQ", userId);
|
||||
return ApiResponse.ok(boardService.createBoard(map));
|
||||
}
|
||||
// 첨부파일 추가
|
||||
@PostMapping("/{boardId}/attachments")
|
||||
public ApiResponse<String> uploadAttachment(@PathVariable Long boardId, @ReqMap MapDto map) {
|
||||
map.put("LOCBRDSEQ", boardId);
|
||||
log.info("Uploading attachment for board ID: {}", boardId);
|
||||
boardService.addAttachment(map);
|
||||
return ApiResponse.ok("첨부파일이 저장되었습니다.");
|
||||
|
||||
/**
|
||||
* 게시물 상세보기
|
||||
* @param boardId 게시물 ID
|
||||
* @return 게시물 상세정보
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@GetMapping("/{boardId}")
|
||||
public ApiResponse<MapDto> getBoardDetail(@PathVariable("boardId") Long boardId) {
|
||||
return ApiResponse.ok(boardService.getBoardDetail(boardId));
|
||||
}
|
||||
// 게시물 삭제
|
||||
|
||||
/**
|
||||
* 게시물 삭제
|
||||
* @param boardId 게시물 ID
|
||||
* @return 삭제 결과 메시지
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@DeleteMapping("/{boardId}")
|
||||
public ApiResponse<String> deleteBoard(@PathVariable Long boardId, @ReqMap MapDto map) {
|
||||
public ApiResponse<String> deleteBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) {
|
||||
map.put("LOCBRDSEQ", boardId);
|
||||
log.info("Deleting board with ID: {}", boardId);
|
||||
boardService.deleteBoard(map);
|
||||
return ApiResponse.ok("게시물이 삭제되었습니다.");
|
||||
}
|
||||
//게시물 수정
|
||||
@PutMapping
|
||||
public ApiResponse<String> updateBoard(@ReqMap MapDto map) {
|
||||
|
||||
/**
|
||||
* 게시물 수정
|
||||
* @param boardId 게시물 ID
|
||||
* @ReqMap map 수정 데이터 (LOCBRDTTL, LOCBRDCON)
|
||||
* @return 수정 결과 메시지
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@PutMapping("/{boardId}")
|
||||
public ApiResponse<String> updateBoard(@PathVariable("boardId") Long boardId, @ReqMap MapDto map) {
|
||||
map.put("LOCBRDSEQ", boardId);
|
||||
boardService.updateBoard(map);
|
||||
return ApiResponse.ok("게시물이 수정되었습니다.");
|
||||
}
|
||||
//게시물과 댓글에 좋아요/싫어요 추가
|
||||
@PostMapping("/{boardId}/reaction")
|
||||
public ApiResponse<String> reactToBoard(@PathVariable Long boardId, @ReqMap MapDto map) {
|
||||
map.put("LOCBRDSEQ", boardId);
|
||||
boardService.reactToBoard(map);
|
||||
return ApiResponse.ok("반응이 추가되었습니다.");
|
||||
|
||||
/**
|
||||
* 첨부파일 추가
|
||||
* @ReqMap map 요청 파라미터 (CMNFLEREG, CMNFLESIZ, CMNFLEEXT, CMNFLEORG, CMNFLENAM, CMNFLEPAT, CMNBRDSEQ)
|
||||
* @return 첨부파일 저장 결과 메시지
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@PostMapping("/{CMNBRDSEQ}/attachments")
|
||||
public ApiResponse<String> uploadAttachment(@ReqMap MapDto map) {
|
||||
Long userId = AuthUtil.getUser().getId();
|
||||
map.put("CMNFLEREG", userId);
|
||||
boardService.addAttachment(map);
|
||||
return ApiResponse.ok("첨부파일이 저장되었습니다.");
|
||||
}
|
||||
//댓글/대댓글 조회
|
||||
|
||||
/**
|
||||
* 게시물, 댓글 좋아요/싫어요 추가
|
||||
* @ReqMap map 데이터 (LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD, LOCBRDSEQ)
|
||||
* @return 반응 추가 결과 메시지
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@PostMapping("/{LOCBRDSEQ}/{LOCCMTSEQ}/reaction")
|
||||
public ApiResponse<String> reactToBoard(@ReqMap MapDto map) {
|
||||
Long userId = AuthUtil.getUser().getId();
|
||||
map.put("MEMBERSEQ", userId);
|
||||
boardService.reactToBoard(map);
|
||||
return ApiResponse.ok("반응이 성공적으로 처리되었습니다.");
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글/대댓글 조회
|
||||
* @param boardId 게시물 ID
|
||||
* @return 댓글과 대댓글의 계층 구조 데이터
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@GetMapping("/{boardId}/comments")
|
||||
public ApiResponse<List<Map<String, Object>>> getComments(@PathVariable int boardId) {
|
||||
public ApiResponse<List<MapDto>> getComments(@PathVariable("boardId") int boardId) {
|
||||
return ApiResponse.ok(boardService.getComments(boardId));
|
||||
}
|
||||
//댓글/대댓글 작성
|
||||
@PostMapping("/{boardId}/comment")
|
||||
public ApiResponse<String> addCommentOrReply(@PathVariable int boardId, @ReqMap MapDto map) {
|
||||
map.put("LOCBRDSEQ", boardId);
|
||||
|
||||
/**
|
||||
* 댓글/대댓글 작성
|
||||
* @param boardId 게시물 ID
|
||||
* @ReqMap map 댓글 데이터 (LOCBRDSEQ, LOCCMTRPY, LOCCMTPNT, LOCCMTPWD, MEMBERSEQ 등)
|
||||
* @return 작성 결과 메시지
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@PostMapping("/{LOCBRDSEQ}/comment")
|
||||
public ApiResponse<String> addCommentOrReply(@ReqMap MapDto map) {
|
||||
Long userId = AuthUtil.getUser().getId();
|
||||
map.put("MEMBERSEQ", userId);
|
||||
boardService.addCommentOrReply(map);
|
||||
return ApiResponse.ok("댓글 또는 대댓글이 작성되었습니다.");
|
||||
}
|
||||
//댓글/대댓글 수정
|
||||
|
||||
/**
|
||||
* 댓글/대댓글 수정
|
||||
* @param commentId 댓글 ID
|
||||
* @ReqMap map 수정 데이터 (LOCCMTSEQ, LOCCMTRPY)
|
||||
* @return 수정 결과 메시지
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@PutMapping("/comment/{commentId}")
|
||||
public ApiResponse<String> updateComment(@PathVariable int commentId, @ReqMap MapDto map) {
|
||||
map.put("LOCCMTSEQ", commentId);
|
||||
public ApiResponse<String> updateComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) {
|
||||
boardService.updateComment(map);
|
||||
return ApiResponse.ok("댓글이 수정되었습니다.");
|
||||
}
|
||||
//댓글/대댓글 삭제
|
||||
|
||||
/**
|
||||
* 댓글/대댓글 삭제
|
||||
* @param commentId 댓글 ID
|
||||
* @ReqMap map 삭제 데이터
|
||||
* @return 삭제 결과 메시지
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@DeleteMapping("/comment/{commentId}")
|
||||
public ApiResponse<String> deleteComment(@PathVariable int commentId, @ReqMap MapDto map) {
|
||||
map.put("LOCCMTSEQ", commentId);
|
||||
public ApiResponse<String> deleteComment(@PathVariable("commentId") int commentId, @ReqMap MapDto map) {
|
||||
boardService.deleteComment(map);
|
||||
return ApiResponse.ok("댓글이 삭제되었습니다.");
|
||||
}
|
||||
//비밀번호 확인 (게시물)
|
||||
|
||||
/**
|
||||
* 댓글 비밀번호 확인
|
||||
* @param commentId 댓글 ID
|
||||
* @ReqMap map 비밀번호 데이터
|
||||
* @return 비밀번호 확인 결과
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@PostMapping("/comment/{commentId}/password")
|
||||
public ApiResponse<Boolean> checkCommentPassword(@PathVariable int commentId, @ReqMap MapDto map) {
|
||||
map.put("LOCCMTSEQ", commentId);
|
||||
return ApiResponse.ok(boardService.checkCommentPassword(map));
|
||||
public ApiResponse<Boolean> checkCommentPassword(@PathVariable("commentId") int commentId, @ReqMap MapDto map) {
|
||||
return ApiResponse.ok(boardService.getCommentPassword(commentId).equals(map.getString("LOCCMTPWD")));
|
||||
}
|
||||
//비밀번호 확인 (댓글)
|
||||
|
||||
/**
|
||||
* 게시물 비밀번호 확인
|
||||
* @param boardId 게시물 ID
|
||||
* @ReqMap map 비밀번호 데이터
|
||||
* @return 비밀번호 확인 결과
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@PostMapping("/{boardId}/password")
|
||||
public ApiResponse<Boolean> checkBoardPassword(@PathVariable int boardId, @ReqMap MapDto map) {
|
||||
map.put("LOCBRDSEQ", boardId);
|
||||
return ApiResponse.ok(boardService.checkBoardPassword(map));
|
||||
public ApiResponse<Boolean> checkBoardPassword(@PathVariable("boardId") int boardId, @ReqMap MapDto map) {
|
||||
return ApiResponse.ok(boardService.getBoardPassword(boardId).equals(map.getString("LOCBRDPWD")));
|
||||
}
|
||||
// 비밀게시판 여부 확인
|
||||
@GetMapping("/{boardId}/isSecret")
|
||||
public ApiResponse<Boolean> isSecretBoard(@PathVariable Long boardId) {
|
||||
log.info("Checking if board ID {} is secret", boardId);
|
||||
return ApiResponse.ok(boardService.isSecretBoard(boardId));
|
||||
|
||||
/**
|
||||
* 카테고리 목록 조회
|
||||
* @return 카테고리 리스트
|
||||
*/
|
||||
@GetMapping("/categories")
|
||||
public ApiResponse<List<MapDto>> getCategories() {
|
||||
List<MapDto> categories = commoncodService.getCategoryList();
|
||||
return ApiResponse.ok(categories);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
package io.company.localhost.controller.api;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import io.company.localhost.common.annotation.ReqMap;
|
||||
import io.company.localhost.common.dto.ApiResponse;
|
||||
import io.company.localhost.common.dto.MapDto;
|
||||
import io.company.localhost.service.localvacaService; // 서비스 클래스 경로 수정
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/api/vacation")
|
||||
public class VacationController {
|
||||
|
||||
private final localvacaService localVacaService;
|
||||
|
||||
@PostMapping
|
||||
public ApiResponse<String> saveVacations(@RequestBody List<MapDto> map) {
|
||||
|
||||
for (MapDto request : map) {
|
||||
// 각 요청 데이터의 필수 값 검증
|
||||
Integer employeeId = (Integer) request.get("employeeId");
|
||||
String date = request.getString("date");
|
||||
String type = request.getString("type");
|
||||
|
||||
if (employeeId == null || date == null || type == null) {
|
||||
throw new IllegalArgumentException("요청 데이터에 누락된 값이 있습니다: " + request);
|
||||
}
|
||||
|
||||
// 데이터 저장
|
||||
localVacaService.insertVacation(request);
|
||||
}
|
||||
|
||||
// 성공적으로 저장된 경우 응답 반환
|
||||
return ApiResponse.ok("모든 휴가가 성공적으로 저장되었습니다.");
|
||||
}
|
||||
|
||||
/**
|
||||
* 휴가 정보를 조회하여 프론트엔드로 전달
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public ApiResponse<List<MapDto>> getVacationList(@ReqMap MapDto map) {
|
||||
|
||||
// 서비스 호출을 통해 데이터 조회
|
||||
List<MapDto> vacationList = localVacaService.getVacationList(map);
|
||||
|
||||
return ApiResponse.ok(vacationList);
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
/************************************************************
|
||||
*
|
||||
* @packageName : io.company.localhost.controller.common
|
||||
* @packageName : io.company.localhost.controller.api
|
||||
* @fileName : worddictController.java
|
||||
* @author : 공현지
|
||||
* @date : 25.01.07
|
||||
@ -12,7 +12,7 @@
|
||||
* 24.12.06 공현지 최초 생성
|
||||
*
|
||||
*************************************************************/
|
||||
package io.company.localhost.controller.common;
|
||||
package io.company.localhost.controller.api;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -23,8 +23,6 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import io.company.localhost.common.annotation.Member;
|
||||
import io.company.localhost.common.annotation.ParameterCheck;
|
||||
import io.company.localhost.common.annotation.ReqMap;
|
||||
@ -54,10 +52,18 @@ public class worddictController {
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@GetMapping("getWordList")
|
||||
public ApiResponse<PageInfo<MapDto>> getWordList(@ReqMap MapDto map) {
|
||||
PageInfo<MapDto> WordList = worddictyservice.getWordList(map);
|
||||
return ApiResponse.ok(WordList);
|
||||
}
|
||||
public ApiResponse<MapDto> getWordList(@ReqMap MapDto map) {
|
||||
|
||||
int total = worddictyservice.getTotal(map);
|
||||
List<MapDto> wordList = worddictyservice.getWordList(map);
|
||||
|
||||
MapDto OutData = new MapDto();
|
||||
OutData.put("total", total);
|
||||
OutData.put("data", wordList);
|
||||
|
||||
return ApiResponse.ok(OutData);
|
||||
}
|
||||
|
||||
/**
|
||||
* 용어집 카테고리 목록
|
||||
* @param
|
||||
@ -70,6 +76,17 @@ public class worddictController {
|
||||
List<MapDto> WordCategoryList = commoncodservice.getWordCategory();
|
||||
return ApiResponse.ok(WordCategoryList);
|
||||
}
|
||||
/**
|
||||
* 용어집 상세 조회
|
||||
* @param WRDDICSEQ 용어 번호
|
||||
* @return
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@GetMapping("getWordDetail")
|
||||
public ApiResponse<MapDto> getWordDetail(@ReqMap MapDto map) {
|
||||
return ApiResponse.ok( worddictyservice.getWordDetail(map));
|
||||
}
|
||||
/**
|
||||
* 용어집 카테고리 등록
|
||||
* @param CMNCODNAM 용어집 등록 카테고리 이름
|
||||
@ -84,11 +101,10 @@ public class worddictController {
|
||||
}
|
||||
/**
|
||||
* 용어 등록
|
||||
* @param WRDDICCAT 카테고리,WRDDICTTL 용어,WRDDICCON 내용 ,WRDDICRIK 링크
|
||||
* @param WRDDICCAT 카테고리 코드값 ,WRDDICTTL 용어,WRDDICCON 내용 ,WRDDICRIK 링크
|
||||
* @return
|
||||
*/
|
||||
@Member
|
||||
@ParameterCheck
|
||||
@PostMapping("insertWord")
|
||||
public ApiResponse<Long> insertWord(@AuthenticationPrincipal MemberVo memberVo,@ReqMap MapDto map) {
|
||||
|
||||
@ -116,6 +132,4 @@ public class worddictController {
|
||||
|
||||
return ApiResponse.ok(result);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
/************************************************************
|
||||
*
|
||||
* @packageName : io.company.localhost.controller.common
|
||||
* @fileName : ImageUploadController.java
|
||||
* @author : 공현지
|
||||
* @date : 25.01.16
|
||||
* @description :
|
||||
*
|
||||
* ===========================================================
|
||||
* DATE AUTHOR NOTE
|
||||
* -----------------------------------------------------------
|
||||
* 25.01.16 공현지 최초 생성
|
||||
*
|
||||
*************************************************************/
|
||||
package io.company.localhost.controller.common;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.company.localhost.common.annotation.ParameterCheck;
|
||||
import io.company.localhost.common.annotation.ReqMap;
|
||||
import io.company.localhost.common.dto.ApiResponse;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/quilleditor")
|
||||
@RequiredArgsConstructor
|
||||
public class ImageUploadController {
|
||||
|
||||
@Value("${filePath.boardfile}")
|
||||
private String boardFilePath;
|
||||
|
||||
/**
|
||||
* quilleditor 안에서 삽입된 이미지를 서버에 저장하는 메소드
|
||||
* @form-data 서버에 저장된 이미지 경로와 이름
|
||||
* @return
|
||||
*/
|
||||
@ParameterCheck
|
||||
@PostMapping("/upload")
|
||||
public ApiResponse<String> uploadImage(@ReqMap MultipartFile file) throws IOException {
|
||||
|
||||
if (file.isEmpty()) {
|
||||
return ApiResponse.error(HttpStatus.BAD_REQUEST, "File is empty");
|
||||
}
|
||||
String originalFileName = file.getOriginalFilename();
|
||||
String fileExtension = originalFileName.substring(originalFileName.lastIndexOf("."));
|
||||
String fileName = UUID.randomUUID().toString() + fileExtension;
|
||||
Path filePath = Paths.get(boardFilePath, fileName);
|
||||
|
||||
Files.createDirectories(filePath.getParent());
|
||||
Files.write(filePath, file.getBytes());
|
||||
|
||||
String fileUrl = "upload/img/board/" + fileName;
|
||||
|
||||
return ApiResponse.ok(fileUrl);
|
||||
}
|
||||
|
||||
}
|
||||
@ -10,6 +10,7 @@
|
||||
* DATE AUTHOR NOTE
|
||||
* -----------------------------------------------------------
|
||||
* 24.12.06 조인제 최초 생성
|
||||
* 24.01.17 박지윤 Register 합침
|
||||
*
|
||||
*************************************************************/
|
||||
package io.company.localhost.controller.common;
|
||||
@ -17,7 +18,12 @@ package io.company.localhost.controller.common;
|
||||
import io.company.localhost.common.annotation.Admin;
|
||||
import io.company.localhost.common.annotation.Guest;
|
||||
import io.company.localhost.common.annotation.Member;
|
||||
import io.company.localhost.common.annotation.ParameterCheck;
|
||||
import io.company.localhost.common.annotation.ReqMap;
|
||||
import io.company.localhost.common.dto.ApiResponse;
|
||||
import io.company.localhost.common.dto.MapDto;
|
||||
import io.company.localhost.service.NetmemberService;
|
||||
import io.company.localhost.service.commoncodService;
|
||||
import io.company.localhost.utils.AuthUtil;
|
||||
import io.company.localhost.utils.SessionListener;
|
||||
import io.company.localhost.vo.MemberVo;
|
||||
@ -35,10 +41,15 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PatchMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY;
|
||||
@ -49,8 +60,113 @@ import static org.springframework.security.web.authentication.rememberme.Abstrac
|
||||
@RequiredArgsConstructor
|
||||
public class UserController {
|
||||
|
||||
private final commoncodService commoncodservice;
|
||||
private final NetmemberService netmemberservice;
|
||||
|
||||
//security 인증 체크
|
||||
/**
|
||||
* 사용 가능 색상 조회
|
||||
*
|
||||
* @return ApiResponse<List<MapDto>>
|
||||
*
|
||||
*/
|
||||
@ParameterCheck
|
||||
@GetMapping("/color")
|
||||
public ApiResponse<List<MapDto>> getColorList() {
|
||||
List<MapDto> ColorList = commoncodservice.getColorList();
|
||||
return ApiResponse.ok(ColorList);
|
||||
}
|
||||
|
||||
/**
|
||||
* MBTI 목록 조회
|
||||
*
|
||||
* @return ApiResponse<List<MapDto>>
|
||||
*
|
||||
*/
|
||||
@ParameterCheck
|
||||
@GetMapping("/mbti")
|
||||
public ApiResponse<List<MapDto>> getMbtiList() {
|
||||
List<MapDto> MbtiList = commoncodservice.getMbtiList();
|
||||
return ApiResponse.ok(MbtiList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 비밀번호 힌트 목록 조회
|
||||
*
|
||||
* @return ApiResponse<List<MapDto>>
|
||||
*
|
||||
*/
|
||||
@ParameterCheck
|
||||
@GetMapping("/pwhint")
|
||||
public ApiResponse<List<MapDto>> getPwhintList() {
|
||||
List<MapDto> PwhintList = commoncodservice.getPwhintList();
|
||||
return ApiResponse.ok(PwhintList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 회원가입
|
||||
*
|
||||
* @param profile
|
||||
* @param map
|
||||
* @return ApiResponse<Integer>
|
||||
* @throws RuntimeException 파일 업로드 실패 시
|
||||
*/
|
||||
@PostMapping("/join")
|
||||
public ApiResponse<Integer> register(@RequestParam("memberPrf") MultipartFile memberPrf, @ReqMap MapDto map) {
|
||||
int member = netmemberservice.register(memberPrf, map);
|
||||
return ApiResponse.ok(member);
|
||||
}
|
||||
|
||||
/**
|
||||
* 아이디 중복 체크
|
||||
*
|
||||
* @param memberIds
|
||||
* @return ApiResponse<Boolean>
|
||||
*
|
||||
*/
|
||||
@GetMapping("/checkId")
|
||||
public ApiResponse<Boolean> selectCheckId(@RequestParam String memberIds) {
|
||||
boolean isDuplicate = netmemberservice.selectCheckId(memberIds);
|
||||
return ApiResponse.ok(!isDuplicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그인 여부 체크
|
||||
*
|
||||
* @return ApiResponse<Boolean>
|
||||
*/
|
||||
@GetMapping("/isLogin")
|
||||
public ApiResponse<Boolean> checkLogin() {
|
||||
boolean isLoggedIn = AuthUtil.isLoggedIn();
|
||||
return ApiResponse.ok(isLoggedIn);
|
||||
}
|
||||
|
||||
/**
|
||||
* 비밀번호 재설정 member 체크
|
||||
*
|
||||
* @param map
|
||||
* @return ApiResponse<Boolean>
|
||||
*
|
||||
*/
|
||||
@PostMapping("/pwReset")
|
||||
public ApiResponse<Boolean> selectPwReset(@ReqMap MapDto map) {
|
||||
boolean isPwReset = netmemberservice.selectPwReset(map);
|
||||
return ApiResponse.ok(isPwReset);
|
||||
}
|
||||
|
||||
/**
|
||||
* 비밀번호 재설정
|
||||
*
|
||||
* @param map
|
||||
* @return ApiResponse<Boolean>
|
||||
*
|
||||
*/
|
||||
@PatchMapping("/pwNew")
|
||||
public ApiResponse<Boolean> updatePassword(@ReqMap MapDto map) {
|
||||
boolean isPwNew = netmemberservice.updatePassword(map);
|
||||
return ApiResponse.ok(isPwNew);
|
||||
}
|
||||
|
||||
// security 인증 체크
|
||||
@GetMapping("userInfo")
|
||||
public ApiResponse<MemberVo> getUserInfo(@AuthenticationPrincipal MemberVo memberVo) {
|
||||
SecurityContextHolderStrategy contextHolderStrategy = SecurityContextHolder.getContextHolderStrategy();
|
||||
@ -67,9 +183,9 @@ public class UserController {
|
||||
return ApiResponse.ok(memberVo);
|
||||
}
|
||||
|
||||
//유저 세션 체크
|
||||
// 유저 세션 체크
|
||||
@GetMapping(value = "check")
|
||||
public ApiResponse<?> check(){
|
||||
public ApiResponse<?> check() {
|
||||
Map<String, HttpSession> sessions = SessionListener.getSessions();
|
||||
Map<String, Object> sessionData = new HashMap<>();
|
||||
|
||||
@ -106,10 +222,7 @@ public class UserController {
|
||||
return ApiResponse.ok(remember);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//로그아웃
|
||||
// 로그아웃
|
||||
@Guest
|
||||
@GetMapping("/logout")
|
||||
public ApiResponse<String> logout(HttpServletRequest request, HttpServletResponse response) {
|
||||
@ -133,6 +246,23 @@ public class UserController {
|
||||
return ApiResponse.ok(returnMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 사원 목록 전체 조회
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
@ParameterCheck
|
||||
@GetMapping("/allUserList")
|
||||
public ApiResponse<MapDto> getallUserList() {
|
||||
List<MapDto> allUserList = netmemberservice.getallUserList();
|
||||
MemberVo user = AuthUtil.getUser();
|
||||
|
||||
MapDto outData = new MapDto();
|
||||
outData.put("allUserList", allUserList);
|
||||
outData.put("user", user);
|
||||
return ApiResponse.ok(outData);
|
||||
}
|
||||
|
||||
@Guest
|
||||
@GetMapping("get1")
|
||||
|
||||
@ -1,55 +0,0 @@
|
||||
package io.company.localhost.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import io.company.localhost.common.dto.MapDto;
|
||||
|
||||
@Mapper
|
||||
public interface LocalBordMapper {
|
||||
// 공지사항 조회
|
||||
List<Map<String, Object>> getNotices();
|
||||
|
||||
// 자유/비밀 게시판 조회
|
||||
List<Map<String, Object>> getGeneralPosts();
|
||||
|
||||
// 게시물 작성
|
||||
void createBoard(MapDto map);
|
||||
|
||||
// 첨부파일 저장
|
||||
void addAttachment(MapDto map);
|
||||
|
||||
// 게시물 삭제
|
||||
void deleteBoard(MapDto map);
|
||||
|
||||
// 게시물 수정
|
||||
void updateBoard(MapDto map);
|
||||
|
||||
// 게시물 좋아요/싫어요 추가
|
||||
void reactToBoard(MapDto map);
|
||||
|
||||
// 댓글 조회
|
||||
List<Map<String, Object>> getComments(int boardSeq);
|
||||
|
||||
// 댓글/대댓글 작성
|
||||
void addCommentOrReply(MapDto map);
|
||||
|
||||
// 댓글/대댓글 수정
|
||||
void updateComment(MapDto map);
|
||||
|
||||
// 댓글/대댓글 삭제
|
||||
void deleteComment(MapDto map);
|
||||
|
||||
// 게시물 비밀번호 확인
|
||||
boolean checkBoardPassword(MapDto map);
|
||||
|
||||
// 댓글 비밀번호 확인
|
||||
boolean checkCommentPassword(MapDto map);
|
||||
|
||||
// 비밀 게시판 여부 확인
|
||||
boolean isSecretBoard(Long boardId);
|
||||
}
|
||||
|
||||
@ -14,12 +14,30 @@
|
||||
*************************************************************/
|
||||
package io.company.localhost.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import io.company.localhost.common.dto.MapDto;
|
||||
import io.company.localhost.vo.MemberVo;
|
||||
|
||||
@Mapper
|
||||
public interface MemberMapper {
|
||||
public interface NetmemberMapper {
|
||||
|
||||
MemberVo findByLoginId(String id);
|
||||
|
||||
int updateMemberToken(MapDto map);
|
||||
|
||||
int insertMember(MapDto map);
|
||||
|
||||
int selectCheckId(String memberIds);
|
||||
|
||||
int selectPwReset(MapDto map);
|
||||
|
||||
String selectPassword(String id);
|
||||
|
||||
int updatePassword(MapDto map);
|
||||
|
||||
List<MapDto> getallUserList();
|
||||
|
||||
}
|
||||
@ -27,4 +27,13 @@ public interface commoncodMapper {
|
||||
|
||||
Long insertCategory(MapDto map);
|
||||
|
||||
List<MapDto> getColorList();
|
||||
|
||||
List<MapDto> getMbtiList();
|
||||
|
||||
List<MapDto> getPwhintList();
|
||||
|
||||
int updateColorYon(String color);
|
||||
|
||||
List<MapDto> getCategories();
|
||||
}
|
||||
|
||||
@ -0,0 +1,98 @@
|
||||
package io.company.localhost.mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import io.company.localhost.common.dto.MapDto;
|
||||
|
||||
@Mapper
|
||||
public interface localbordMapper {
|
||||
// 공지사항 조회
|
||||
List<MapDto> getNotices(MapDto map);
|
||||
|
||||
// 자유/비밀 게시판 조회
|
||||
List<MapDto> getGeneralPosts(MapDto map);
|
||||
|
||||
// 조회수 증가
|
||||
void incrementViewCount(Long boardId);
|
||||
|
||||
// 게시물 작성
|
||||
void createBoard(MapDto map);
|
||||
|
||||
// 첨부파일 저장
|
||||
void addAttachment(MapDto map);
|
||||
|
||||
// 게시물 삭제
|
||||
void deleteBoard(MapDto map);
|
||||
|
||||
// 게시물 삭제시 댓글/대댓글 삭제
|
||||
void deleteCommentsByBoardId(MapDto map);
|
||||
|
||||
// 게시물 수정
|
||||
void updateBoard(MapDto map);
|
||||
|
||||
// 기존 반응 조회
|
||||
MapDto findReaction(MapDto map);
|
||||
|
||||
// 새 반응 삽입
|
||||
void insertReaction(MapDto map);
|
||||
|
||||
// 기존 반응 업데이트
|
||||
void updateReaction(MapDto map);
|
||||
|
||||
// 댓글 조회
|
||||
List<MapDto> getComments(int boardSeq);
|
||||
|
||||
// 댓글/대댓글 작성
|
||||
void addCommentOrReply(MapDto map);
|
||||
|
||||
// 댓글/대댓글 수정
|
||||
void updateComment(MapDto map);
|
||||
|
||||
// 대댓글인지 확인
|
||||
boolean isReply(MapDto map);
|
||||
|
||||
// 댓글에 대댓글이 있는지 확인
|
||||
boolean hasReplies(MapDto map);
|
||||
|
||||
// 댓글 내용만 삭제 처리 (대댓글 유지)
|
||||
void softDeleteComment(MapDto map);
|
||||
|
||||
// 댓글 삭제 (대댓글 없음)
|
||||
void deleteComment(MapDto map);
|
||||
|
||||
// 대댓글 삭제
|
||||
void deleteReply(MapDto map);
|
||||
|
||||
// 게시물 비밀번호 조회
|
||||
String selectCommentPassword(int commentId);
|
||||
|
||||
// 댓글 비밀번호 조회
|
||||
String selectBoardPassword(int boardId);
|
||||
|
||||
// 게시물 상세보기
|
||||
MapDto selectBoardDetail(Long boardId);
|
||||
|
||||
// 댓글 갯수
|
||||
int countComments(Long boardId);
|
||||
|
||||
// 첨부파일 유무
|
||||
int countAttachments(Long boardId);
|
||||
|
||||
// 게시물 좋아요/싫어요 개수
|
||||
MapDto getBoardReactions(Long boardId);
|
||||
|
||||
// 댓글 좋아요/싫어요 개수
|
||||
List<MapDto> getCommentReactions(Long boardId);
|
||||
|
||||
// 첨부파일 가져오기
|
||||
List<MapDto> selectAttachments(Long boardId);
|
||||
|
||||
//댓글id 확인
|
||||
MapDto getCommentById(int commentId);
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,19 @@
|
||||
package io.company.localhost.mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import io.company.localhost.common.dto.MapDto;
|
||||
|
||||
|
||||
@Mapper
|
||||
public interface localvacaMapper {
|
||||
void insertVacation(MapDto map);
|
||||
|
||||
List<MapDto> findVacations(MapDto map);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -29,6 +29,10 @@ public interface worddictyMapper {
|
||||
|
||||
Long updateWord(MapDto map);
|
||||
|
||||
MapDto getWordDetail(MapDto map);
|
||||
|
||||
int getTotal(MapDto map);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
68
src/main/java/io/company/localhost/service/FileService.java
Normal file
68
src/main/java/io/company/localhost/service/FileService.java
Normal file
@ -0,0 +1,68 @@
|
||||
/************************************************************
|
||||
*
|
||||
* @packageName : io.company.localhost.FileService
|
||||
* @fileName : FileService.java
|
||||
* @author : 박지윤
|
||||
* @date : 25.01.17
|
||||
* @description :
|
||||
*
|
||||
* ===========================================================
|
||||
* DATE AUTHOR NOTE
|
||||
* -----------------------------------------------------------
|
||||
* 24.01.17 박지윤 최초 생성
|
||||
*
|
||||
*************************************************************/
|
||||
package io.company.localhost.service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.UUID;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class FileService {
|
||||
|
||||
|
||||
@Value("${filePath.profile}")
|
||||
private String uploadPath;
|
||||
|
||||
/**
|
||||
* 파일 업로드
|
||||
*
|
||||
* @param file
|
||||
* @return
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public String uploadFile(MultipartFile file) {
|
||||
try {
|
||||
// 원본 파일명
|
||||
String originalFilename = file.getOriginalFilename();
|
||||
// 파일 확장자
|
||||
String extension = FilenameUtils.getExtension(originalFilename);
|
||||
// UUID를 사용하여 고유한 파일명 생성
|
||||
String newFilename = UUID.randomUUID().toString() + "." + extension;
|
||||
|
||||
// 최종 저장 경로 생성 (기본경로 + 파일명)
|
||||
Path targetPath = Paths.get(uploadPath, newFilename);
|
||||
// 저장될 디렉토리가 없는 경우 생성
|
||||
Files.createDirectories(targetPath.getParent());
|
||||
|
||||
// 동일 파일명이 있을 경우 덮어쓰기
|
||||
Files.copy(file.getInputStream(), targetPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
// 저장된 파일의 상대 경로 반환
|
||||
return newFilename;
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("파일 업로드 실패: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
package io.company.localhost.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import io.company.localhost.common.dto.MapDto;
|
||||
import io.company.localhost.mapper.LocalBordMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class LocalBordService {
|
||||
private final LocalBordMapper boardMapper;
|
||||
|
||||
public List<Map<String, Object>> getNotices() {
|
||||
return boardMapper.getNotices();
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getGeneralPosts() {
|
||||
return boardMapper.getGeneralPosts();
|
||||
}
|
||||
|
||||
public void createBoard(MapDto map) {
|
||||
boardMapper.createBoard(map);
|
||||
}
|
||||
|
||||
public void addAttachment(MapDto map) {
|
||||
boardMapper.addAttachment(map);
|
||||
}
|
||||
|
||||
public void deleteBoard(MapDto map) {
|
||||
boardMapper.deleteBoard(map);
|
||||
}
|
||||
|
||||
public void updateBoard(MapDto map) {
|
||||
boardMapper.updateBoard(map);
|
||||
}
|
||||
|
||||
public void reactToBoard(MapDto map) {
|
||||
boardMapper.reactToBoard(map);
|
||||
}
|
||||
|
||||
public List<Map<String, Object>> getComments(int boardSeq) {
|
||||
return boardMapper.getComments(boardSeq);
|
||||
}
|
||||
|
||||
public void addCommentOrReply(MapDto map) {
|
||||
boardMapper.addCommentOrReply(map);
|
||||
}
|
||||
|
||||
public void updateComment(MapDto map) {
|
||||
boardMapper.updateComment(map);
|
||||
}
|
||||
|
||||
public void deleteComment(MapDto map) {
|
||||
boardMapper.deleteComment(map);
|
||||
}
|
||||
|
||||
public boolean checkBoardPassword(MapDto map) {
|
||||
return boardMapper.checkBoardPassword(map);
|
||||
}
|
||||
|
||||
public boolean checkCommentPassword(MapDto map) {
|
||||
return boardMapper.checkCommentPassword(map);
|
||||
}
|
||||
|
||||
|
||||
public boolean isSecretBoard(Long boardId) {
|
||||
return boardMapper.isSecretBoard(boardId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
140
src/main/java/io/company/localhost/service/NetmemberService.java
Normal file
140
src/main/java/io/company/localhost/service/NetmemberService.java
Normal file
@ -0,0 +1,140 @@
|
||||
/************************************************************
|
||||
*
|
||||
* @packageName : io.company.localhost.RegisterService
|
||||
* @fileName : RegisterService.java
|
||||
* @author : 박지윤
|
||||
* @date : 25.01.17
|
||||
* @description :
|
||||
*
|
||||
* ===========================================================
|
||||
* DATE AUTHOR NOTE
|
||||
* -----------------------------------------------------------
|
||||
* 24.01.17 박지윤 최초 생성
|
||||
*
|
||||
*************************************************************/
|
||||
package io.company.localhost.service;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import io.company.localhost.common.dto.MapDto;
|
||||
import io.company.localhost.mapper.NetmemberMapper;
|
||||
import io.company.localhost.mapper.commoncodMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class NetmemberService {
|
||||
private final NetmemberMapper memberMapper;
|
||||
private final commoncodMapper commoncodMapper;
|
||||
private final DelegatingPasswordEncoder passwordEncoder;
|
||||
private final FileService fileService;
|
||||
|
||||
/**
|
||||
* 회원 가입
|
||||
*
|
||||
* @param profile
|
||||
* @param map
|
||||
* @return
|
||||
*/
|
||||
public int register(MultipartFile memberPrf, MapDto map) {
|
||||
// 프로필 이미지 저장, 저장된 경로 가져옴
|
||||
String profilePath = fileService.uploadFile(memberPrf);
|
||||
map.put("memberPrf", profilePath);
|
||||
|
||||
// 비밀번호 암호화 및 저장
|
||||
String encodedPassword = passwordEncoder.encode(map.getString("memberPwd"));
|
||||
map.put("memberPwd", encodedPassword);
|
||||
|
||||
// 회원 기본 정보 설정
|
||||
map.put("memberRol", "ROLE_MEMBER");
|
||||
map.put("memberPos", 500107);
|
||||
map.put("memberTkn", "Null");
|
||||
map.put("memberPrm", "Y");
|
||||
map.put("memberDel", "N");
|
||||
map.put("memberLea", "N");
|
||||
map.put("memberRdt", LocalDateTime.now());
|
||||
map.put("memberCdt", LocalDateTime.now());
|
||||
|
||||
// 회원 정보 저장
|
||||
int result = memberMapper.insertMember(map);
|
||||
|
||||
// 선택한 색상 코드 사용 처리
|
||||
String color = map.getString("memberCol");
|
||||
commoncodMapper.updateColorYon(color);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 아이디 중복 체크
|
||||
*
|
||||
* @param memberIds
|
||||
* @return
|
||||
*/
|
||||
public boolean selectCheckId(String memberIds) {
|
||||
return memberMapper.selectCheckId(memberIds) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 사원 목록 전체 조회
|
||||
*
|
||||
* @param
|
||||
* @return
|
||||
*/
|
||||
public List<MapDto> getallUserList() {
|
||||
return memberMapper.getallUserList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 로그인 토큰
|
||||
*
|
||||
* @param id, token
|
||||
* @return
|
||||
*/
|
||||
public void updateMemberToken(MapDto map) {
|
||||
memberMapper.updateMemberToken(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* 비밀번호 재설정 member 체크
|
||||
*
|
||||
* @param map
|
||||
* @return
|
||||
*/
|
||||
public boolean selectPwReset(MapDto map) {
|
||||
return memberMapper.selectPwReset(map) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 기존 비밀번호 체크
|
||||
*
|
||||
* @param map
|
||||
* @return
|
||||
*/
|
||||
public boolean selectPassword(MapDto map) {
|
||||
String currentPassword = memberMapper.selectPassword(map.getString("id"));
|
||||
String newPassword = map.getString("password");
|
||||
|
||||
// 기존 비밀번호, 새 비밀번호 같은지 확인
|
||||
return !passwordEncoder.matches(newPassword, currentPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* 비밀번호 재설정
|
||||
*
|
||||
* @param map
|
||||
* @return
|
||||
*/
|
||||
public boolean updatePassword(MapDto map) {
|
||||
String encodedPassword = passwordEncoder.encode(map.getString("password"));
|
||||
map.put("password", encodedPassword);
|
||||
System.out.println("암호화된 비밀번호: " + encodedPassword);
|
||||
return memberMapper.updatePassword(map) > 0;
|
||||
}
|
||||
|
||||
}
|
||||
@ -36,4 +36,18 @@ public class commoncodService {
|
||||
return commoncodmapper.insertCategory(map);
|
||||
}
|
||||
|
||||
public List<MapDto> getColorList() {
|
||||
return commoncodmapper.getColorList();
|
||||
}
|
||||
|
||||
public List<MapDto> getMbtiList() {
|
||||
return commoncodmapper.getMbtiList();
|
||||
}
|
||||
|
||||
public List<MapDto> getPwhintList() {
|
||||
return commoncodmapper.getPwhintList();
|
||||
}
|
||||
public List<MapDto> getCategoryList() {
|
||||
return commoncodmapper.getCategories();
|
||||
}
|
||||
}
|
||||
|
||||
304
src/main/java/io/company/localhost/service/localbordService.java
Normal file
304
src/main/java/io/company/localhost/service/localbordService.java
Normal file
@ -0,0 +1,304 @@
|
||||
package io.company.localhost.service;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
|
||||
import io.company.localhost.common.dto.MapDto;
|
||||
import io.company.localhost.mapper.localbordMapper;
|
||||
import io.company.localhost.utils.PageUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class localbordService {
|
||||
private final localbordMapper boardMapper;
|
||||
private static final long MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
|
||||
|
||||
public List<MapDto> getNotices(MapDto map) {
|
||||
List<MapDto> posts = boardMapper.getNotices(map);
|
||||
enrichPostsWithAdditionalData(posts);
|
||||
return posts;
|
||||
}
|
||||
|
||||
public PageInfo<MapDto> getGeneralPosts(MapDto map) {
|
||||
System.out.println(map);
|
||||
int page = map.getString("page") != null ? Integer.parseInt(map.getString("page")) : 1;
|
||||
int size = map.getString("size") != null ? Integer.parseInt(map.getString("size")) : 10;
|
||||
|
||||
String orderBy = map.getString("orderBy");
|
||||
if (orderBy == null || (!orderBy.equals("date") && !orderBy.equals("views"))) {
|
||||
map.put("orderBy", "date");
|
||||
}
|
||||
|
||||
PageHelper.startPage(page, size);
|
||||
|
||||
List<MapDto> result = boardMapper.getGeneralPosts(map);
|
||||
enrichPostsWithAdditionalData(result);
|
||||
|
||||
return PageUtil.redefineNavigation(new PageInfo<>(result, size));
|
||||
}
|
||||
|
||||
public void incrementViewCount(Long boardId) {
|
||||
boardMapper.incrementViewCount(boardId);
|
||||
}
|
||||
|
||||
public BigInteger createBoard(MapDto map) {
|
||||
boardMapper.createBoard(map);
|
||||
return (BigInteger) map.get("LOCBRDSEQ");
|
||||
}
|
||||
|
||||
public void addAttachment(MapDto map) {
|
||||
String boardSeqStr = (String) map.get("CMNBRDSEQ");
|
||||
Long boardSeq = Long.parseLong(boardSeqStr);
|
||||
map.put("CMNBRDSEQ", boardSeq);
|
||||
|
||||
String newFilename = UUID.randomUUID().toString();
|
||||
map.put("CMNFLENAM", newFilename);
|
||||
|
||||
boardMapper.addAttachment(map);
|
||||
}
|
||||
|
||||
public void validateAttachmentsSize(List<MapDto> attachments) {
|
||||
long totalSize = attachments.stream()
|
||||
.mapToLong(attachment -> (Long) attachment.get("size"))
|
||||
.sum();
|
||||
|
||||
if (totalSize > MAX_FILE_SIZE) {
|
||||
throw new IllegalArgumentException("첨부파일의 총 용량이 5MB를 초과합니다.");
|
||||
}
|
||||
}
|
||||
|
||||
public MapDto getBoardDetail(Long boardId) {
|
||||
incrementViewCount(boardId);
|
||||
MapDto boardDetail = boardMapper.selectBoardDetail(boardId);
|
||||
if (boardDetail != null) {
|
||||
enrichBoardDetail(boardDetail);
|
||||
}
|
||||
return boardDetail;
|
||||
}
|
||||
|
||||
public List<MapDto> getAttachments(Long boardId) {
|
||||
return boardMapper.selectAttachments(boardId);
|
||||
}
|
||||
|
||||
public void deleteBoard(MapDto map) {
|
||||
boardMapper.deleteCommentsByBoardId(map);
|
||||
boardMapper.deleteBoard(map);
|
||||
}
|
||||
|
||||
public void updateBoard(MapDto map) {
|
||||
boardMapper.updateBoard(map);
|
||||
}
|
||||
|
||||
public void reactToBoard(MapDto map) {
|
||||
MapDto existingReaction = boardMapper.findReaction(map);
|
||||
|
||||
if (existingReaction != null) {
|
||||
boardMapper.updateReaction(map);
|
||||
} else {
|
||||
boardMapper.insertReaction(map);
|
||||
}
|
||||
}
|
||||
|
||||
public List<MapDto> getComments(int boardSeq) {
|
||||
return boardMapper.getComments(boardSeq);
|
||||
}
|
||||
|
||||
public void addCommentOrReply(MapDto map) {
|
||||
if (map.get("LOCCMTPNT") == null) {
|
||||
map.put("LOCCMTPNT", null);
|
||||
}
|
||||
boardMapper.addCommentOrReply(map);
|
||||
}
|
||||
|
||||
public void updateComment(MapDto map) {
|
||||
boardMapper.updateComment(map);
|
||||
}
|
||||
|
||||
public void deleteComment(MapDto map) {
|
||||
boolean isReply = boardMapper.isReply(map);
|
||||
|
||||
if (isReply) {
|
||||
boardMapper.deleteReply(map);
|
||||
} else {
|
||||
boolean hasReplies = boardMapper.hasReplies(map);
|
||||
|
||||
if (hasReplies) {
|
||||
boardMapper.softDeleteComment(map);
|
||||
} else {
|
||||
boardMapper.deleteComment(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getCommentPassword(int commentId) {
|
||||
return boardMapper.selectCommentPassword(commentId);
|
||||
}
|
||||
|
||||
public String getBoardPassword(int boardId) {
|
||||
return boardMapper.selectBoardPassword(boardId);
|
||||
}
|
||||
|
||||
public MapDto getCommentById(int commentId) {
|
||||
return boardMapper.getCommentById(commentId);
|
||||
}
|
||||
|
||||
public int getCommentCount(Long boardId) {
|
||||
return boardMapper.countComments(boardId);
|
||||
}
|
||||
|
||||
public boolean hasAttachments(Long boardId) {
|
||||
int count = boardMapper.countAttachments(boardId);
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
public MapDto getBoardReactions(Long boardId) {
|
||||
return boardMapper.getBoardReactions(boardId);
|
||||
}
|
||||
|
||||
public List<MapDto> getCommentReactions(Long boardId) {
|
||||
return boardMapper.getCommentReactions(boardId);
|
||||
}
|
||||
|
||||
private void enrichBoardDetail(MapDto boardDetail) {
|
||||
long boardId = ((Number) boardDetail.get("id")).longValue();
|
||||
boardDetail.put("hasAttachment", hasAttachments(boardId));
|
||||
boardDetail.put("commentCount", getCommentCount(boardId));
|
||||
MapDto reactions = getBoardReactions(boardId);
|
||||
boardDetail.put("likeCount", reactions.getOrDefault("likeCount", 0));
|
||||
boardDetail.put("dislikeCount", reactions.getOrDefault("dislikeCount", 0));
|
||||
|
||||
// Blob 데이터를 문자열로 변환
|
||||
Object content = boardDetail.get("content");
|
||||
if (content != null) {
|
||||
String contentString = convertBlobToString(content); // Blob을 문자열로 변환
|
||||
boardDetail.put("content", contentString); // JSON 변환 가능
|
||||
}
|
||||
}
|
||||
|
||||
private String convertBlobToString(Object blob) {
|
||||
try {
|
||||
if (blob instanceof String) {
|
||||
return (String) blob; // 이미 문자열인 경우 반환
|
||||
} else if (blob instanceof java.sql.Blob) {
|
||||
java.sql.Blob sqlBlob = (java.sql.Blob) blob;
|
||||
long blobLength = sqlBlob.length();
|
||||
byte[] blobBytes = sqlBlob.getBytes(1, (int) blobLength);
|
||||
return new String(blobBytes, StandardCharsets.UTF_8);
|
||||
} else if (blob instanceof ByteArrayInputStream) {
|
||||
ByteArrayInputStream inputStream = (ByteArrayInputStream) blob;
|
||||
byte[] bytes = inputStream.readAllBytes();
|
||||
return new String(bytes, StandardCharsets.UTF_8);
|
||||
} else {
|
||||
System.err.println("Unsupported blob type: " + blob.getClass());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Failed to convert Blob to String: " + e.getMessage(), e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String extractFirstImageUrl(String jsonContent) {
|
||||
try {
|
||||
// JSON 유효성 검사
|
||||
if (!isValidJson(jsonContent)) {
|
||||
throw new IllegalArgumentException("Invalid JSON content: " + jsonContent);
|
||||
}
|
||||
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
JsonNode rootNode = objectMapper.readTree(jsonContent);
|
||||
|
||||
// JSON 배열 순회
|
||||
for (JsonNode node : rootNode) {
|
||||
JsonNode insertNode = node.get("insert");
|
||||
if (insertNode != null && insertNode.has("image")) {
|
||||
return insertNode.get("image").asText(); // 첫 번째 이미지 URL 반환
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Failed to extract first image URL: " + e.getMessage(), e);
|
||||
}
|
||||
return null; // 이미지가 없는 경우
|
||||
}
|
||||
|
||||
private boolean isValidJson(String json) {
|
||||
try {
|
||||
final ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.readTree(json); // JSON 파싱 시도
|
||||
return true; // JSON이 유효하면 true 반환
|
||||
} catch (Exception e) {
|
||||
return false; // 유효하지 않은 경우 false 반환
|
||||
}
|
||||
}
|
||||
|
||||
private String extractPlainTextFromJson(String jsonContent) {
|
||||
StringBuilder plainTextBuilder = new StringBuilder();
|
||||
try {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
JsonNode rootNode = objectMapper.readTree(jsonContent);
|
||||
|
||||
// JSON 배열인지 확인
|
||||
if (!rootNode.isArray()) {
|
||||
System.err.println("JSON content is not an array");
|
||||
return "";
|
||||
}
|
||||
|
||||
// JSON 노드 순회
|
||||
for (JsonNode node : rootNode) {
|
||||
JsonNode insertNode = node.get("insert");
|
||||
|
||||
// insert 노드가 텍스트인지 확인
|
||||
if (insertNode != null && insertNode.isTextual()) {
|
||||
String text = insertNode.asText();
|
||||
|
||||
// '\n' 제거하고 순수 텍스트만 추가
|
||||
if (!text.trim().isEmpty() && !text.trim().equals("\n")) {
|
||||
plainTextBuilder.append(text.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("Failed to extract plain text: " + e.getMessage(), e);
|
||||
}
|
||||
return plainTextBuilder.toString();
|
||||
}
|
||||
|
||||
private void enrichPostsWithAdditionalData(List<MapDto> posts) {
|
||||
for (MapDto post : posts) {
|
||||
Object idObject = post.get("id");
|
||||
if (idObject instanceof Number) {
|
||||
long postId = ((Number) idObject).longValue();
|
||||
post.put("commentCount", getCommentCount(postId));
|
||||
post.put("hasAttachment", hasAttachments(postId));
|
||||
MapDto reactions = getBoardReactions(postId);
|
||||
post.put("likeCount", reactions.getOrDefault("likeCount", 0));
|
||||
post.put("dislikeCount", reactions.getOrDefault("dislikeCount", 0));
|
||||
|
||||
Object content = post.get("content");
|
||||
String contentString = convertBlobToString(content);
|
||||
post.put("content", contentString);
|
||||
|
||||
String firstImageUrl = extractFirstImageUrl(contentString);
|
||||
post.put("firstImageUrl", firstImageUrl);
|
||||
|
||||
String plainContent = extractPlainTextFromJson(contentString);
|
||||
post.put("plainContent", plainContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package io.company.localhost.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import io.company.localhost.common.dto.MapDto;
|
||||
import io.company.localhost.mapper.localvacaMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class localvacaService {
|
||||
private final localvacaMapper localvacaMapper;
|
||||
|
||||
|
||||
public void insertVacation(MapDto map) {
|
||||
localvacaMapper.insertVacation(map);
|
||||
}
|
||||
|
||||
public List<MapDto> getVacationList(MapDto map) {
|
||||
return localvacaMapper.findVacations(map);
|
||||
}
|
||||
|
||||
}
|
||||
@ -15,14 +15,13 @@
|
||||
package io.company.localhost.service;
|
||||
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import com.github.pagehelper.PageInfo;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import io.company.localhost.common.dto.MapDto;
|
||||
import io.company.localhost.mapper.worddictyMapper;
|
||||
import io.company.localhost.utils.PageUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@Service
|
||||
@ -31,12 +30,36 @@ public class worddictyService {
|
||||
|
||||
private final worddictyMapper worddictymapper;
|
||||
|
||||
public PageInfo<MapDto> getWordList(MapDto map) {
|
||||
int page = map.getString("page") != null ? Integer.parseInt(map.getString("page")) : 1;
|
||||
PageHelper.startPage(page, 10);
|
||||
return PageUtil.redefineNavigation(new PageInfo<>(worddictymapper.getWordList(map),10));
|
||||
public List<MapDto> getWordList(MapDto map) {
|
||||
List<MapDto> wordList = worddictymapper.getWordList(map);
|
||||
List<MapDto> processedList = new ArrayList<>();
|
||||
|
||||
// 데이터 가공
|
||||
for (MapDto dto : wordList) {
|
||||
MapDto author = new MapDto();
|
||||
author.put("profileImage", dto.remove("REGPRF"));
|
||||
author.put("name", dto.remove("REGNAME"));
|
||||
author.put("color", dto.remove("REGCOLOR"));
|
||||
author.put("createdAt", dto.remove("REGRDT"));
|
||||
|
||||
MapDto lastEditor = new MapDto();
|
||||
lastEditor.put("profileImage", dto.remove("UPDPRF"));
|
||||
lastEditor.put("name", dto.remove("UPDNAME"));
|
||||
lastEditor.put("color", dto.remove("UPDCOLOR"));
|
||||
lastEditor.put("updatedAt", dto.remove("UPDUDT"));
|
||||
|
||||
dto.put("author", author);
|
||||
dto.put("lastEditor", lastEditor);
|
||||
|
||||
MapDto processedDto = new MapDto();
|
||||
processedDto.putAll(dto);
|
||||
processedList.add(processedDto);
|
||||
}
|
||||
return processedList;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Long insertWord(MapDto map) {
|
||||
return worddictymapper.insertWord(map);
|
||||
}
|
||||
@ -45,6 +68,14 @@ public class worddictyService {
|
||||
return worddictymapper.updateWord(map);
|
||||
}
|
||||
|
||||
public MapDto getWordDetail(MapDto map) {
|
||||
return worddictymapper.getWordDetail(map);
|
||||
}
|
||||
|
||||
public int getTotal(MapDto map) {
|
||||
return worddictymapper.getTotal(map);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -58,6 +58,18 @@ public class PageUtil {
|
||||
list.setNavigateLastPage(nav2[nav2.length -1]);
|
||||
}
|
||||
|
||||
// 페이지 그룹 크기 (예: 10개씩)
|
||||
int groupSize = list.getNavigatePages();
|
||||
int totalPages = list.getPages();
|
||||
|
||||
// 현재 페이지 그룹 계산
|
||||
int currentGroup = (int) Math.ceil((double) currentPage / groupSize);
|
||||
int totalGroups = (int) Math.ceil((double) totalPages / groupSize);
|
||||
|
||||
// 이전/다음 그룹 존재 여부 설정
|
||||
list.setHasPreviousPage(currentGroup > 1); // 이전 그룹 존재
|
||||
list.setHasNextPage(currentGroup < totalGroups); // 다음 그룹 존재
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
@ -25,16 +25,28 @@ import java.util.Date;
|
||||
@AllArgsConstructor
|
||||
@ToString
|
||||
public class MemberVo {
|
||||
|
||||
private Long id;
|
||||
private String loginId;
|
||||
private String role;
|
||||
private String name;
|
||||
private String password;
|
||||
private String email;
|
||||
private String isUsed;
|
||||
private String isDel;
|
||||
private Date isrtDate;
|
||||
private Date updtDate;
|
||||
private Boolean remember;
|
||||
private String loginId; // 사용자 아이디
|
||||
private String role; // 권한
|
||||
private String token; // 토큰
|
||||
private String profile; // 프로필사진
|
||||
private String name; // 이름
|
||||
private String password; // 비밀번호
|
||||
private String passwordhint; // 비밀번호힌트
|
||||
private String passwordRes; // 비밀번호힌트답변
|
||||
private int position; // 직급
|
||||
private String address; // 주소
|
||||
private String addressDetail; // 상세주소
|
||||
private String zipcode; // 우편번호
|
||||
private Date birth; // 생년월일
|
||||
private String phone; // 전화번호
|
||||
private Date regist; // 가입요청일
|
||||
private Date isCdt; // 입사일
|
||||
private String isUsed; // 허가여부
|
||||
private String isDel; // 퇴사여부
|
||||
private String isLea; // 휴직여부
|
||||
private int color; // 색상
|
||||
private int mbit; // MBTI
|
||||
private Boolean remember; // 로그인 유지
|
||||
}
|
||||
|
||||
|
||||
@ -4,11 +4,6 @@ project:
|
||||
time-zone: Asia/Seoul
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
url: jdbc:mariadb://192.168.0.251:3306/localnet
|
||||
username: root
|
||||
password: host1234
|
||||
driver-class-name: org.mariadb.jdbc.Driver
|
||||
devtools:
|
||||
livereload:
|
||||
enabled: true
|
||||
@ -23,6 +18,10 @@ spring:
|
||||
web:
|
||||
resources:
|
||||
add-mappings: false
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 5MB
|
||||
max-request-size: 5MB
|
||||
|
||||
mybatis:
|
||||
mapper-locations: classpath:mapper/**/*.xml
|
||||
@ -89,3 +88,10 @@ logging:
|
||||
connection: off
|
||||
io.company: DEBUG
|
||||
io.company.localhost.mapper: off
|
||||
|
||||
|
||||
filePath:
|
||||
boardfile: C:\\localhost-back\\upload\\img\\board\\
|
||||
profile: C:\\localhost-back\\upload\\img\\profile\\
|
||||
|
||||
|
||||
|
||||
@ -1,110 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.company.localhost.mapper.LocalBordMapper">
|
||||
|
||||
<!-- 공지사항 조회 -->
|
||||
<select id="getNotices" resultType="java.util.Map">
|
||||
SELECT
|
||||
b.LOCBRDSEQ,
|
||||
b.LOCBRDTTL,
|
||||
b.LOCBRDCON,
|
||||
b.LOCBRDRDT,
|
||||
b.LOCBRDTYP,
|
||||
a.FILE_PATH,
|
||||
a.FILE_NAME,
|
||||
a.FILE_TYPE
|
||||
FROM localbord b
|
||||
LEFT JOIN attachments a ON b.LOCBRDSEQ = a.LOCBRDSEQ
|
||||
WHERE b.LOCBRDTYP = 'N'
|
||||
ORDER BY b.LOCBRDRDT DESC
|
||||
</select>
|
||||
|
||||
<!-- 자유/비밀 게시판 조회 -->
|
||||
<select id="getGeneralPosts" resultType="map">
|
||||
SELECT
|
||||
LOCBRDSEQ AS id,
|
||||
LOCBRDTTL AS title,
|
||||
LOCBRDCON AS content,
|
||||
LOCBRDRDT AS date
|
||||
FROM localbord
|
||||
WHERE LOCBRDTYP IN ('F', 'S')
|
||||
ORDER BY LOCBRDRDT DESC
|
||||
</select>
|
||||
|
||||
<!-- 게시물 작성 -->
|
||||
<insert id="createBoard">
|
||||
INSERT INTO localbord (LOCBRDTTL, LOCBRDCON, LOCBRDCAT, MEMBERSEQ, LOCBRDCNT, LOCBRDRDT, LOCBRDUDT, LOCBRDPWD, LOCBRDTYP)
|
||||
VALUES (#{LOCBRDTTL}, #{LOCBRDCON}, #{LOCBRDCAT}, #{MEMBERSEQ}, 0, NOW(), NOW(), #{LOCBRDPWD}, #{LOCBRDTYP})
|
||||
</insert>
|
||||
|
||||
<!-- 첨부파일 저장 -->
|
||||
<insert id="addAttachment">
|
||||
INSERT INTO commonfil (CMNBRDSEQ, CMNFLEPAT, CMNFLENAM, CMNFLEORG, CMNFLEEXT, CMNFLESIZ, CMNFLEREG, CMNFLERDT)
|
||||
VALUES (#{CMNBRDSEQ}, #{CMNFLEPAT}, #{CMNFLENAM}, #{CMNFLEORG}, #{CMNFLEEXT}, #{CMNFLESIZ}, #{CMNFLEREG}, NOW())
|
||||
</insert>
|
||||
|
||||
<!-- 게시물 삭제 -->
|
||||
<delete id="deleteBoard">
|
||||
DELETE FROM localbord WHERE LOCBRDSEQ = #{LOCBRDSEQ}
|
||||
</delete>
|
||||
|
||||
<!-- 게시물 수정 -->
|
||||
<update id="updateBoard">
|
||||
UPDATE localbord
|
||||
SET LOCBRDTTL = #{LOCBRDTTL}, LOCBRDCON = #{LOCBRDCON}, LOCBRDUDT = NOW()
|
||||
WHERE LOCBRDSEQ = #{LOCBRDSEQ}
|
||||
</update>
|
||||
|
||||
<!-- 게시물 좋아요/싫어요 추가 -->
|
||||
<insert id="reactToBoard">
|
||||
INSERT INTO localgorb (LOCBRDSEQ, LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD )
|
||||
VALUES (#{LOCBRDSEQ}, #{LOCCMTSEQ}, #{MEMBERSEQ}, #{LOCGOBGOD}, #{LOCGOBBAD})
|
||||
ON DUPLICATE KEY UPDATE LOCGOBGOD = #{LOCGOBGOD}, LOCGOBBAD = #{LOCGOBBAD}
|
||||
</insert>
|
||||
|
||||
<!-- 댓글/대댓글 조회 -->
|
||||
<select id="getComments" resultType="java.util.Map">
|
||||
SELECT LOCCMTSEQ, LOCBRDSEQ, LOCCMTRPY, LOCCMTPWD, LOCCMTRDT, LOCCMTPNT
|
||||
FROM loccomt
|
||||
WHERE LOCBRDSEQ = #{LOCBRDSEQ}
|
||||
ORDER BY LOCCMTPNT ASC, LOCCMTRDT ASC
|
||||
</select>
|
||||
|
||||
<!-- 댓글/대댓글 작성 -->
|
||||
<insert id="addCommentOrReply">
|
||||
INSERT INTO loccomt (LOCBRDSEQ, LOCCMTRPY, LOCCMTPWD, LOCCMTRDT, LOCCMTPNT)
|
||||
VALUES (#{LOCBRDSEQ}, #{LOCCMTRPY}, #{LOCCMTPWD}, NOW(), #{LOCCMTPNT})
|
||||
</insert>
|
||||
|
||||
<!-- 댓글/대댓글 수정 -->
|
||||
<update id="updateComment">
|
||||
UPDATE loccomt
|
||||
SET LOCCMTRPY = #{LOCCMTRPY}, LOCCMTUDT = NOW()
|
||||
WHERE LOCCMTSEQ = #{LOCCMTSEQ} AND LOCCMTPWD = #{LOCCMTPWD}
|
||||
</update>
|
||||
|
||||
<!-- 댓글/대댓글 삭제 -->
|
||||
<delete id="deleteComment">
|
||||
DELETE FROM loccomt
|
||||
WHERE LOCCMTSEQ = #{LOCCMTSEQ} AND LOCCMTPWD = #{LOCCMTPWD}
|
||||
</delete>
|
||||
|
||||
<!-- 비밀번호 확인 (게시물) -->
|
||||
<select id="checkBoardPassword" resultType="boolean">
|
||||
SELECT COUNT(*) > 0 FROM localbord WHERE LOCBRDSEQ = #{LOCBRDSEQ} AND LOCBRDPWD = #{LOCBRDPWD}
|
||||
</select>
|
||||
|
||||
<!-- 비밀번호 확인 (댓글) -->
|
||||
<select id="checkCommentPassword" resultType="boolean">
|
||||
SELECT COUNT(*) > 0 FROM loccomt WHERE LOCCMTSEQ = #{LOCCMTSEQ} AND LOCCMTPWD = #{LOCCMTPWD}
|
||||
</select>
|
||||
|
||||
<!-- 비밀 게시판 여부 확인 -->
|
||||
<select id="isSecretBoard" resultType="boolean">
|
||||
SELECT CASE WHEN LOCBRDTYP = 'S' THEN TRUE ELSE FALSE END
|
||||
FROM localbord
|
||||
WHERE LOCBRDSEQ = #{LOCBRDSEQ}
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
@ -29,4 +29,55 @@
|
||||
WHERE
|
||||
CMNCODLV1 = 600;
|
||||
</insert>
|
||||
|
||||
<select id="getColorList" resultType="Map">
|
||||
SELECT
|
||||
CMNCODVAL
|
||||
,CMNCODNAM
|
||||
FROM
|
||||
commoncod
|
||||
WHERE
|
||||
CMNCODLV1 = 100
|
||||
AND
|
||||
CMNCODODR != 0
|
||||
AND
|
||||
CMNCODYON = 0
|
||||
</select>
|
||||
|
||||
<select id="getMbtiList" resultType="Map">
|
||||
SELECT
|
||||
CMNCODVAL
|
||||
,CMNCODNAM
|
||||
FROM
|
||||
commoncod
|
||||
WHERE
|
||||
CMNCODLV1 = 200
|
||||
AND
|
||||
CMNCODODR != 0
|
||||
</select>
|
||||
|
||||
<select id="getPwhintList" resultType="Map">
|
||||
SELECT
|
||||
CMNCODVAL
|
||||
,CMNCODNAM
|
||||
FROM
|
||||
commoncod
|
||||
WHERE
|
||||
CMNCODLV1 = 800
|
||||
AND
|
||||
CMNCODODR != 0
|
||||
</select>
|
||||
|
||||
<update id="updateColorYon" parameterType="String">
|
||||
UPDATE commoncod
|
||||
SET CMNCODYON = 1
|
||||
WHERE CMNCODVAL = #{color};
|
||||
</update>
|
||||
|
||||
<select id="getCategories" resultType="Map">
|
||||
SELECT CMNCODVAL, CMNCODNAM FROM commoncod
|
||||
WHERE CMNCODVAL BETWEEN 300101 AND 300103
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
|
||||
249
src/main/resources/mapper/localbordMapper.xml
Normal file
249
src/main/resources/mapper/localbordMapper.xml
Normal file
@ -0,0 +1,249 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.company.localhost.mapper.localbordMapper">
|
||||
|
||||
<!-- 공지사항 조회 -->
|
||||
<select id="getNotices" resultType="io.company.localhost.common.dto.MapDto">
|
||||
SELECT
|
||||
b.LOCBRDSEQ AS id,
|
||||
b.LOCBRDTTL AS title,
|
||||
b.LOCBRDCON AS content,
|
||||
b.LOCBRDUDT AS date,
|
||||
b.LOCBRDCNT AS cnt,
|
||||
m.MEMBERNAM AS author
|
||||
FROM localbord b
|
||||
LEFT JOIN netmember m ON b.MEMBERSEQ = m.MEMBERSEQ
|
||||
WHERE LOCBRDTYP = '300103'
|
||||
<if test="searchKeyword != null and searchKeyword != ''">
|
||||
AND LOCBRDTTL LIKE CONCAT('%', #{searchKeyword}, '%')
|
||||
</if>
|
||||
ORDER BY LOCBRDUDT DESC
|
||||
</select>
|
||||
|
||||
<!-- 자유/익명 게시판 조회 (작성자 이름 포함) -->
|
||||
<select id="getGeneralPosts" resultType="io.company.localhost.common.dto.MapDto">
|
||||
SELECT
|
||||
b.LOCBRDSEQ AS id,
|
||||
b.LOCBRDTTL AS title,
|
||||
b.LOCBRDCON AS content,
|
||||
b.LOCBRDUDT AS date,
|
||||
b.LOCBRDCNT AS cnt,
|
||||
m.MEMBERNAM AS author
|
||||
FROM localbord b
|
||||
LEFT JOIN netmember m ON b.MEMBERSEQ = m.MEMBERSEQ
|
||||
WHERE b.LOCBRDTYP IN ('300101', '300102')
|
||||
<if test="searchKeyword != null and searchKeyword != ''">
|
||||
AND b.LOCBRDTTL LIKE CONCAT('%', #{searchKeyword}, '%')
|
||||
</if>
|
||||
ORDER BY
|
||||
<choose>
|
||||
<when test="orderBy == 'date'"> b.LOCBRDUDT DESC </when>
|
||||
<when test="orderBy == 'views'"> b.LOCBRDCNT DESC </when>
|
||||
</choose>
|
||||
</select>
|
||||
|
||||
|
||||
<!-- 조회수 증가 -->
|
||||
<update id="incrementViewCount">
|
||||
UPDATE localbord SET LOCBRDCNT = LOCBRDCNT + 1 WHERE LOCBRDSEQ = #{LOCBRDSEQ}
|
||||
</update>
|
||||
|
||||
<!-- 게시물 작성 -->
|
||||
<insert id="createBoard" parameterType="map" useGeneratedKeys="true" keyProperty="LOCBRDSEQ">
|
||||
INSERT INTO localbord (LOCBRDTTL, LOCBRDCON, LOCBRDCAT, MEMBERSEQ, LOCBRDCNT, LOCBRDRDT, LOCBRDUDT, LOCBRDPWD, LOCBRDTYP)
|
||||
VALUES (#{LOCBRDTTL}, #{LOCBRDCON}, #{LOCBRDCAT}, #{MEMBERSEQ}, 0, NOW(), NOW(), #{LOCBRDPWD}, #{LOCBRDTYP})
|
||||
</insert>
|
||||
|
||||
<!-- 첨부파일 저장 -->
|
||||
<insert id="addAttachment" parameterType="map">
|
||||
INSERT INTO commonfil (
|
||||
CMNBRDSEQ,CMNFLENAM,CMNFLEORG,CMNFLEPAT,
|
||||
CMNFLEEXT,CMNFLESIZ,CMNFLEREG,CMNFLERDT
|
||||
) VALUES (
|
||||
#{CMNBRDSEQ},#{CMNFLENAM},#{CMNFLEORG},#{CMNFLEPAT},
|
||||
#{CMNFLEEXT},#{CMNFLESIZ},#{CMNFLEREG},NOW()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 게시물 상세정보 조회 -->
|
||||
<select id="selectBoardDetail" resultType="io.company.localhost.common.dto.MapDto">
|
||||
SELECT LOCBRDSEQ AS id, LOCBRDTTL AS title, LOCBRDCON AS content, LOCBRDUDT AS date, LOCBRDTYP AS type, LOCBRDCNT AS cnt
|
||||
FROM localbord
|
||||
WHERE LOCBRDSEQ = #{boardId}
|
||||
</select>
|
||||
|
||||
<!-- 첨부파일 목록 조회 -->
|
||||
<select id="selectAttachments" resultType="io.company.localhost.common.dto.MapDto">
|
||||
SELECT CMNFLESEQ AS id, CMNFLEORG AS originalName, CMNFLENAM AS fileName, CMNFLEPAT AS path,
|
||||
CMNFLEEXT AS extension, CMNFLESIZ AS size, CMNFLERDT AS uploadDate
|
||||
FROM commonfil
|
||||
WHERE CMNBRDSEQ = #{boardId}
|
||||
ORDER BY CMNFLERDT DESC
|
||||
</select>
|
||||
|
||||
<!-- 게시물 삭제 -->
|
||||
<delete id="deleteBoard">
|
||||
DELETE FROM localbord WHERE LOCBRDSEQ = #{LOCBRDSEQ}
|
||||
</delete>
|
||||
|
||||
<!-- 게시물 삭제 시 댓글/대댓글 삭제 -->
|
||||
<delete id="deleteCommentsByBoardId">
|
||||
DELETE FROM localcomt
|
||||
WHERE LOCBRDSEQ = #{LOCBRDSEQ}
|
||||
</delete>
|
||||
|
||||
<!-- 게시물 수정 -->
|
||||
<update id="updateBoard">
|
||||
UPDATE localbord
|
||||
SET LOCBRDTTL = #{LOCBRDTTL}, LOCBRDCON = #{LOCBRDCON}, LOCBRDUDT = NOW()
|
||||
WHERE LOCBRDSEQ = #{LOCBRDSEQ}
|
||||
</update>
|
||||
|
||||
<!-- 기존 반응 조회 -->
|
||||
<select id="findReaction" resultType="io.company.localhost.common.dto.MapDto">
|
||||
SELECT LOCBRDSEQ, LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD
|
||||
FROM localgorb
|
||||
WHERE (LOCBRDSEQ = #{LOCBRDSEQ} OR (#{LOCBRDSEQ} IS NULL AND LOCBRDSEQ IS NULL))
|
||||
AND (LOCCMTSEQ = #{LOCCMTSEQ} OR (#{LOCCMTSEQ} IS NULL AND LOCCMTSEQ IS NULL))
|
||||
AND MEMBERSEQ = #{MEMBERSEQ}
|
||||
</select>
|
||||
|
||||
<!-- 반응 업데이트 -->
|
||||
<update id="updateReaction">
|
||||
UPDATE localgorb
|
||||
SET LOCGOBGOD = #{LOCGOBGOD}, LOCGOBBAD = #{LOCGOBBAD}
|
||||
WHERE (LOCBRDSEQ = #{LOCBRDSEQ} OR (#{LOCBRDSEQ} IS NULL AND LOCBRDSEQ IS NULL))
|
||||
AND (LOCCMTSEQ = #{LOCCMTSEQ} OR (#{LOCCMTSEQ} IS NULL AND LOCCMTSEQ IS NULL))
|
||||
AND MEMBERSEQ = #{MEMBERSEQ}
|
||||
</update>
|
||||
|
||||
<!-- 새 반응 삽입 -->
|
||||
<insert id="insertReaction">
|
||||
INSERT INTO localgorb (LOCBRDSEQ, LOCCMTSEQ, MEMBERSEQ, LOCGOBGOD, LOCGOBBAD)
|
||||
VALUES (#{LOCBRDSEQ}, #{LOCCMTSEQ}, #{MEMBERSEQ}, #{LOCGOBGOD}, #{LOCGOBBAD})
|
||||
</insert>
|
||||
|
||||
<!-- 댓글/대댓글 조회 -->
|
||||
<select id="getComments" resultType="io.company.localhost.common.dto.MapDto">
|
||||
SELECT
|
||||
LOCCMTSEQ,LOCBRDSEQ,LOCCMTPNT,LOCCMTRPY,
|
||||
LOCCMTUDT,LOCCMTPWD,LOCCMTRDT,LOCCMTPNT
|
||||
FROM localcomt
|
||||
WHERE LOCBRDSEQ = #{boardId}
|
||||
ORDER BY LOCCMTPNT ASC, LOCCMTUDT ASC
|
||||
</select>
|
||||
|
||||
<!-- 댓글/대댓글 작성 -->
|
||||
<insert id="addCommentOrReply">
|
||||
INSERT INTO localcomt (LOCBRDSEQ, LOCCMTRPY, LOCCMTPWD, LOCCMTRDT, LOCCMTUDT, LOCCMTPNT, MEMBERSEQ)
|
||||
VALUES (#{LOCBRDSEQ}, #{LOCCMTRPY}, #{LOCCMTPWD}, NOW(), NOW() , #{LOCCMTPNT}, #{MEMBERSEQ})
|
||||
</insert>
|
||||
|
||||
<!-- 댓글/대댓글 수정 -->
|
||||
<update id="updateComment">
|
||||
UPDATE localcomt
|
||||
SET LOCCMTRPY = #{LOCCMTRPY}, LOCCMTUDT = NOW()
|
||||
WHERE LOCCMTSEQ = #{LOCCMTSEQ}
|
||||
</update>
|
||||
|
||||
<!-- 댓글 삭제 -->
|
||||
<update id="softDeleteComment">
|
||||
UPDATE localcomt
|
||||
SET LOCCMTRPY = '삭제된 댓글입니다'
|
||||
WHERE LOCCMTSEQ = #{LOCCMTSEQ}
|
||||
AND EXISTS (
|
||||
SELECT 1 FROM localcomt WHERE LOCCMTPNT = #{LOCCMTSEQ}
|
||||
)
|
||||
</update>
|
||||
|
||||
<!-- 댓글 삭제 (대댓글 없을 경우) -->
|
||||
<delete id="deleteComment">
|
||||
DELETE FROM localcomt
|
||||
WHERE LOCCMTSEQ = #{LOCCMTSEQ}
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM localcomt WHERE LOCCMTPNT = #{LOCCMTSEQ}
|
||||
)
|
||||
</delete>
|
||||
|
||||
<!-- 대댓글 삭제 -->
|
||||
<delete id="deleteReply">
|
||||
DELETE FROM localcomt
|
||||
WHERE LOCCMTSEQ = #{LOCCMTSEQ}
|
||||
AND LOCCMTPNT IS NOT NULL
|
||||
</delete>
|
||||
|
||||
<!-- 대댓글인지 확인 -->
|
||||
<select id="isReply" resultType="boolean">
|
||||
SELECT COUNT(1) > 0 FROM localcomt
|
||||
WHERE LOCCMTSEQ = #{LOCCMTSEQ} AND LOCCMTPNT IS NOT NULL
|
||||
</select>
|
||||
|
||||
<!-- 댓글에 대댓글이 있는지 확인 -->
|
||||
<select id="hasReplies" resultType="boolean">
|
||||
SELECT COUNT(1) > 0 FROM localcomt WHERE LOCCMTPNT = #{LOCCMTSEQ}
|
||||
</select>
|
||||
|
||||
<!-- 댓글 비밀번호 조회 -->
|
||||
<select id="selectCommentPassword" resultType="String">
|
||||
SELECT LOCCMTPWD
|
||||
FROM localcomt
|
||||
WHERE LOCCMTSEQ = #{commentId}
|
||||
</select>
|
||||
|
||||
<!-- 게시물 비밀번호 조회 -->
|
||||
<select id="selectBoardPassword" resultType="String">
|
||||
SELECT LOCBRDPWD
|
||||
FROM localbord
|
||||
WHERE LOCBRDSEQ = #{boardId}
|
||||
</select>
|
||||
|
||||
<!-- 비밀 게시판 여부 확인 -->
|
||||
<select id="isSecretBoard" resultType="boolean">
|
||||
SELECT CASE WHEN LOCBRDTYP = 'S' THEN TRUE ELSE FALSE END
|
||||
FROM localbord
|
||||
WHERE LOCBRDSEQ = #{boardId}
|
||||
</select>
|
||||
|
||||
<!-- 댓글 id확인 -->
|
||||
<select id="getCommentById" resultType="io.company.localhost.common.dto.MapDto">
|
||||
SELECT LOCCMTSEQ AS id, LOCCMTPNT AS point
|
||||
FROM localcomt
|
||||
WHERE LOCCMTSEQ = #{commentId}
|
||||
</select>
|
||||
|
||||
<!-- 댓글 개수 조회 -->
|
||||
<select id="countComments" parameterType="long" resultType="int">
|
||||
SELECT COUNT(*)
|
||||
FROM localcomt
|
||||
WHERE LOCBRDSEQ = #{boardId}
|
||||
</select>
|
||||
|
||||
<!-- 첨부파일 유무 -->
|
||||
<select id="countAttachments" resultType="int">
|
||||
SELECT COUNT(*)
|
||||
FROM commonfil
|
||||
WHERE CMNBRDSEQ = #{boardId}
|
||||
</select>
|
||||
|
||||
<!-- 게시물 좋아요/싫어요 개수 조회 -->
|
||||
<select id="getBoardReactions" resultType="io.company.localhost.common.dto.MapDto">
|
||||
SELECT
|
||||
COALESCE(SUM(CASE WHEN LOCGOBGOD = 'T' THEN 1 ELSE 0 END), 0) AS likeCount,
|
||||
COALESCE(SUM(CASE WHEN LOCGOBBAD = 'T' THEN 1 ELSE 0 END), 0) AS dislikeCount
|
||||
FROM localgorb
|
||||
WHERE LOCBRDSEQ = #{boardId};
|
||||
|
||||
</select>
|
||||
|
||||
<!-- 댓글별 좋아요/싫어요 개수 조회 -->
|
||||
<select id="getCommentReactions" resultType="io.company.localhost.common.dto.MapDto">
|
||||
SELECT
|
||||
LOCCMTSEQ,
|
||||
COALESCE(SUM(CASE WHEN LOCGOBGOD = 'T' THEN 1 ELSE 0 END), 0) AS likeCount,
|
||||
COALESCE(SUM(CASE WHEN LOCGOBBAD = 'T' THEN 1 ELSE 0 END), 0) AS dislikeCount
|
||||
FROM localgorb
|
||||
WHERE LOCBRDSEQ = #{boardId}
|
||||
GROUP BY LOCCMTSEQ
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
20
src/main/resources/mapper/localvacaMapper.xml
Normal file
20
src/main/resources/mapper/localvacaMapper.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.company.localhost.mapper.localvacaMapper">
|
||||
|
||||
<!-- 휴가 저장 -->
|
||||
<insert id="insertVacation" parameterType="io.company.localhost.common.dto.MapDto">
|
||||
INSERT INTO localvaca (MEMBERSEQ, LOCVACUDT, LOCVACTYP, LOCVACRDT)
|
||||
VALUES (#{employeeId}, #{date}, #{type}, NOW())
|
||||
</insert>
|
||||
|
||||
<!-- 휴가 정보 조회 -->
|
||||
<select id="findVacations" parameterType="io.company.localhost.common.dto.MapDto">
|
||||
SELECT
|
||||
MEMBERSEQ,
|
||||
LOCVACUDT,
|
||||
LOCVACTYP
|
||||
FROM
|
||||
localvaca
|
||||
</select>
|
||||
</mapper>
|
||||
@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.company.localhost.mapper.MemberMapper">
|
||||
|
||||
<select id="findByLoginId" parameterType="String" resultType="io.company.localhost.vo.MemberVo">
|
||||
SELECT
|
||||
MEMBER_ID AS id
|
||||
, MEMBER_LOGIN_ID AS loginId
|
||||
, MEMBER_ROLE AS role
|
||||
, MEMBER_NAME AS name
|
||||
, MEMBER_PASSWORD AS password
|
||||
, MEMBER_EMAIL AS email
|
||||
, IS_USED AS isUsed
|
||||
, IS_DEL AS isDel
|
||||
, ISRT_DATE AS isrtDate
|
||||
, UPDT_DATE AS updtDate
|
||||
, #{remember} as remember
|
||||
FROM
|
||||
MEMBER_TB
|
||||
WHERE
|
||||
MEMBER_LOGIN_ID = #{id}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
142
src/main/resources/mapper/netmemberMapper.xml
Normal file
142
src/main/resources/mapper/netmemberMapper.xml
Normal file
@ -0,0 +1,142 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.company.localhost.mapper.NetmemberMapper">
|
||||
|
||||
<select id="findByLoginId" parameterType="String" resultType="io.company.localhost.vo.MemberVo">
|
||||
SELECT
|
||||
MEMBERSEQ AS id
|
||||
, MEMBERIDS AS loginId
|
||||
, MEMBERROL AS role
|
||||
, MEMBERTKN AS token
|
||||
, MEMBERPRF AS profile
|
||||
, MEMBERNAM AS name
|
||||
, MEMBERPWD AS password
|
||||
, MEMBERPWH AS passwordhint
|
||||
, MEMBERPWR AS passwordRes
|
||||
, MEMBERPOS AS position
|
||||
, MEMBERARR AS address
|
||||
, MEMBERDTL AS addressDetail
|
||||
, MEMBERZIP AS zipcode
|
||||
, MEMBERBTH AS birth
|
||||
, MEMBERTEL AS phone
|
||||
, MEMBERRDT AS regist
|
||||
, MEMBERCDT AS isCdt
|
||||
, MEMBERPRM AS isUsed
|
||||
, MEMBERDEL AS isDel
|
||||
, MEMBERLEA AS isLea
|
||||
, MEMBERCOL AS color
|
||||
, MEMBERMBT AS mbit
|
||||
FROM
|
||||
netmember
|
||||
WHERE
|
||||
MEMBERIDS = #{id}
|
||||
</select>
|
||||
|
||||
<update id="updateMemberToken">
|
||||
UPDATE netmember
|
||||
SET MEMBERTKN = #{token}
|
||||
WHERE MEMBERIDS = #{id}
|
||||
</update>
|
||||
|
||||
|
||||
<!-- 회원가입 -->
|
||||
<insert id="insertMember" useGeneratedKeys="true" keyProperty="MEMBERSEQ">
|
||||
INSERT INTO netmember (
|
||||
MEMBERIDS,
|
||||
MEMBERROL,
|
||||
MEMBERTKN,
|
||||
MEMBERPRF,
|
||||
MEMBERNAM,
|
||||
MEMBERPWD,
|
||||
MEMBERPWH,
|
||||
MEMBERPWR,
|
||||
MEMBERPOS,
|
||||
MEMBERARR,
|
||||
MEMBERDTL,
|
||||
MEMBERZIP,
|
||||
MEMBERBTH,
|
||||
MEMBERTEL,
|
||||
MEMBERRDT,
|
||||
MEMBERCDT,
|
||||
MEMBERPRM,
|
||||
MEMBERDEL,
|
||||
MEMBERLEA,
|
||||
MEMBERCOL,
|
||||
MEMBERMBT
|
||||
) VALUES (
|
||||
#{memberIds},
|
||||
#{memberRol},
|
||||
#{memberTkn},
|
||||
#{memberPrf},
|
||||
#{memberNam},
|
||||
#{memberPwd},
|
||||
#{memberPwh},
|
||||
#{memberPwr},
|
||||
#{memberPos},
|
||||
#{memberArr},
|
||||
#{memberDtl},
|
||||
#{memberZip},
|
||||
#{memberBth},
|
||||
#{memberTel},
|
||||
#{memberRdt},
|
||||
#{memberCdt},
|
||||
#{memberPrm},
|
||||
#{memberDel},
|
||||
#{memberLea},
|
||||
#{memberCol},
|
||||
#{memberMbt}
|
||||
)
|
||||
</insert>
|
||||
|
||||
<!-- 중복체크 -->
|
||||
<select id="selectCheckId" resultType="int">
|
||||
SELECT COUNT(*)
|
||||
FROM netmember
|
||||
WHERE MEMBERIDS = #{memberIds}
|
||||
</select>
|
||||
|
||||
<!-- 비밀번호 재설정 member 체크 -->
|
||||
<select id="selectPwReset" resultType="int">
|
||||
SELECT COUNT(*)
|
||||
FROM netmember
|
||||
WHERE MEMBERIDS = #{id}
|
||||
AND MEMBERBTH = #{birth}
|
||||
AND MEMBERPWH = #{pwhint}
|
||||
AND MEMBERPWR = #{pwhintRes}
|
||||
</select>
|
||||
|
||||
<!-- 비밀번호 재설정 기존 비밀번호 체크 -->
|
||||
<select id="selectPassword">
|
||||
SELECT MEMBERPWD
|
||||
FROM netmember
|
||||
WHERE MEMBERIDS = #{id}
|
||||
</select>
|
||||
|
||||
<!-- 비밀번호 재설정 -->
|
||||
<update id="updatePassword">
|
||||
UPDATE netmember
|
||||
SET MEMBERPWD = #{password}
|
||||
WHERE MEMBERIDS = #{id}
|
||||
</update>
|
||||
|
||||
<!-- 전체 회원 목록 -->
|
||||
<select id="getallUserList" resultType="Map">
|
||||
SELECT
|
||||
m.*
|
||||
,c.CMNCODNAM usercolor
|
||||
FROM
|
||||
netmember m
|
||||
left join
|
||||
commoncod c
|
||||
on
|
||||
M.MEMBERCOL = C.CMNCODVAL
|
||||
WHERE
|
||||
m.MEMBERDEL = "N"
|
||||
AND
|
||||
m.MEMBERPRM = "Y"
|
||||
AND
|
||||
m.MEMBERLEA ="N"
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
||||
@ -1,34 +1,191 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.company.localhost.mapper.worddictyMapper">
|
||||
<select id="getWordList" parameterType="map" resultType="Map">
|
||||
select
|
||||
w.*
|
||||
,DATE_FORMAT(w.WRDDICRDT,'%y.%m.%d %H:%i') AS formatWRDDICRDT
|
||||
,c.CMNCODNAM category
|
||||
from
|
||||
worddicty w
|
||||
left join
|
||||
commoncod c
|
||||
on
|
||||
w.WRDDICCAT = c.CMNCODVAL
|
||||
where
|
||||
1=1
|
||||
<!-- 검색어 조건 -->
|
||||
<sql id="searchConditions">
|
||||
<!-- 검색어 조건 -->
|
||||
<if test="searchKeyword != null and searchKeyword != ''">
|
||||
and (w.WRDDICTTL like CONCAT('%', #{searchKeyword}, '%')
|
||||
or w.WRDDICCON like CONCAT('%', #{searchKeyword}, '%'))
|
||||
or w.WRDDICCON like CONCAT('%', #{searchKeyword}, '%'))
|
||||
</if>
|
||||
<!-- 색인표 조건 -->
|
||||
<if test="indexKeyword != null and indexKeyword != ''">
|
||||
and w.WRDDICTTL like CONCAT(#{indexKeyword}, '%')
|
||||
</if>
|
||||
<choose>
|
||||
<!-- 한글 ㄱ ~ ㅎ에 대한 검색 -->
|
||||
<when test='indexKeyword == "ㄱ"'>
|
||||
and w.WRDDICTTL BETWEEN '가' AND '깋'
|
||||
</when>
|
||||
<when test='indexKeyword == "ㄴ"'>
|
||||
and w.WRDDICTTL BETWEEN '나' AND '닣'
|
||||
</when>
|
||||
<when test='indexKeyword == "ㄷ"'>
|
||||
and w.WRDDICTTL BETWEEN '다' AND '딷'
|
||||
</when>
|
||||
<when test='indexKeyword == "ㄹ"'>
|
||||
and w.WRDDICTTL BETWEEN '라' AND '릿'
|
||||
</when>
|
||||
<when test='indexKeyword == "ㅁ"'>
|
||||
and w.WRDDICTTL BETWEEN '마' AND '맇'
|
||||
</when>
|
||||
<when test='indexKeyword == "ㅂ"'>
|
||||
and w.WRDDICTTL BETWEEN '바' AND '빟'
|
||||
</when>
|
||||
<when test='indexKeyword == "ㅅ"'>
|
||||
and w.WRDDICTTL BETWEEN '사' AND '싷'
|
||||
</when>
|
||||
<when test='indexKeyword == "ㅇ"'>
|
||||
and w.WRDDICTTL BETWEEN '아' AND '잏'
|
||||
</when>
|
||||
<when test='indexKeyword == "ㅈ"'>
|
||||
and w.WRDDICTTL BETWEEN '자' AND '짛'
|
||||
</when>
|
||||
<when test='indexKeyword == "ㅊ"'>
|
||||
and w.WRDDICTTL BETWEEN '차' AND '칳'
|
||||
</when>
|
||||
<when test='indexKeyword == "ㅋ"'>
|
||||
and w.WRDDICTTL BETWEEN '카' AND '킿'
|
||||
</when>
|
||||
<when test='indexKeyword == "ㅌ"'>
|
||||
and w.WRDDICTTL BETWEEN '타' AND '틷'
|
||||
</when>
|
||||
<when test='indexKeyword == "ㅍ"'>
|
||||
and w.WRDDICTTL BETWEEN '파' AND '핗'
|
||||
</when>
|
||||
<when test='indexKeyword == "ㅎ"'>
|
||||
and w.WRDDICTTL BETWEEN '하' AND '힣'
|
||||
</when>
|
||||
<!-- 알파벳 a ~ z에 대한 검색 -->
|
||||
<when test='indexKeyword == "a"'>
|
||||
and w.WRDDICTTL like "a%"
|
||||
</when>
|
||||
<when test='indexKeyword == "b"'>
|
||||
and w.WRDDICTTL like "b%"
|
||||
</when>
|
||||
<when test='indexKeyword == "c"'>
|
||||
and w.WRDDICTTL like "c%"
|
||||
</when>
|
||||
<when test='indexKeyword == "d"'>
|
||||
and w.WRDDICTTL like "d%"
|
||||
</when>
|
||||
<when test='indexKeyword == "e"'>
|
||||
and w.WRDDICTTL like "e%"
|
||||
</when>
|
||||
<when test='indexKeyword == "f"'>
|
||||
and w.WRDDICTTL like "f%"
|
||||
</when>
|
||||
<when test='indexKeyword == "g"'>
|
||||
and w.WRDDICTTL like "g%"
|
||||
</when>
|
||||
<when test='indexKeyword == "h"'>
|
||||
and w.WRDDICTTL like "h%"
|
||||
</when>
|
||||
<when test='indexKeyword == "i"'>
|
||||
and w.WRDDICTTL like "i%"
|
||||
</when>
|
||||
<when test='indexKeyword == "j"'>
|
||||
and w.WRDDICTTL like "j%"
|
||||
</when>
|
||||
<when test='indexKeyword == "k"'>
|
||||
and w.WRDDICTTL like "k%"
|
||||
</when>
|
||||
<when test='indexKeyword == "l"'>
|
||||
and w.WRDDICTTL like "l%"
|
||||
</when>
|
||||
<when test='indexKeyword == "m"'>
|
||||
and w.WRDDICTTL like "m%"
|
||||
</when>
|
||||
<when test='indexKeyword == "n"'>
|
||||
and w.WRDDICTTL like "n%"
|
||||
</when>
|
||||
<when test='indexKeyword == "o"'>
|
||||
and w.WRDDICTTL like "o%"
|
||||
</when>
|
||||
<when test='indexKeyword == "p"'>
|
||||
and w.WRDDICTTL like "p%"
|
||||
</when>
|
||||
<when test='indexKeyword == "q"'>
|
||||
and w.WRDDICTTL like "q%"
|
||||
</when>
|
||||
<when test='indexKeyword == "r"'>
|
||||
and w.WRDDICTTL like "r%"
|
||||
</when>
|
||||
<when test='indexKeyword == "s"'>
|
||||
and w.WRDDICTTL like "s%"
|
||||
</when>
|
||||
<when test='indexKeyword == "t"'>
|
||||
and w.WRDDICTTL like "t%"
|
||||
</when>
|
||||
<when test='indexKeyword == "u"'>
|
||||
and w.WRDDICTTL like "u%"
|
||||
</when>
|
||||
<when test='indexKeyword == "v"'>
|
||||
and w.WRDDICTTL like "v%"
|
||||
</when>
|
||||
<when test='indexKeyword == "w"'>
|
||||
and w.WRDDICTTL like "w%"
|
||||
</when>
|
||||
<when test='indexKeyword == "x"'>
|
||||
and w.WRDDICTTL like "x%"
|
||||
</when>
|
||||
<when test='indexKeyword == "y"'>
|
||||
and w.WRDDICTTL like "y%"
|
||||
</when>
|
||||
<when test='indexKeyword == "z"'>
|
||||
and w.WRDDICTTL like "z%"
|
||||
</when>
|
||||
</choose>
|
||||
</if>
|
||||
<!-- 카테고리 조건 -->
|
||||
<if test="category != null and category != ''">
|
||||
and w.WRDDICCAT = #{category}
|
||||
</if>
|
||||
</sql>
|
||||
<select id="getWordList" parameterType="map" resultType="io.company.localhost.common.dto.MapDto">
|
||||
select
|
||||
w.WRDDICSEQ,
|
||||
w.WRDDICCAT,
|
||||
w.WRDDICTTL,
|
||||
w.WRDDICCON,
|
||||
c.CMNCODNAM category,
|
||||
m1.MEMBERPRF REGPRF,
|
||||
m1.MEMBERNAM REGNAME,
|
||||
cr.CMNCODNAM REGCOLOR,
|
||||
w.WRDDICRDT REGRDT,
|
||||
m2.MEMBERPRF UPDPRF,
|
||||
m2.MEMBERNAM UPDNAME,
|
||||
cu.CMNCODNAM UPDCOLOR,
|
||||
w.WRDDICUDT UPDUDT
|
||||
from
|
||||
worddicty w
|
||||
left join
|
||||
commoncod c
|
||||
on
|
||||
w.WRDDICCAT = c.CMNCODVAL
|
||||
left join
|
||||
netmember m1
|
||||
on
|
||||
w.WRDDICREG = m1.MEMBERSEQ
|
||||
left join
|
||||
commoncod cr
|
||||
on
|
||||
m1.MEMBERCOL = cr.CMNCODVAL -- 등록자 색상
|
||||
left join
|
||||
netmember m2
|
||||
on
|
||||
w.WRDDICUPD = m2.MEMBERSEQ
|
||||
left join
|
||||
commoncod cu
|
||||
on
|
||||
m2.MEMBERCOL = cu.CMNCODVAL -- 수정자 색상
|
||||
where
|
||||
1=1
|
||||
<include refid="searchConditions"/>
|
||||
order by w.WRDDICRDT desc
|
||||
</select>
|
||||
<select id="getTotal" parameterType="map" >
|
||||
select count(*) from worddicty w
|
||||
where 1=1
|
||||
<include refid="searchConditions"/>
|
||||
</select>
|
||||
<insert id="insertWord" parameterType="map">
|
||||
insert into worddicty
|
||||
(
|
||||
@ -72,4 +229,11 @@
|
||||
where
|
||||
WRDDICSEQ = #{WRDDICSEQ}
|
||||
</update>
|
||||
<select id="getWordDetail" parameterType="map" resultType="io.company.localhost.common.dto.MapDto">
|
||||
select *
|
||||
from
|
||||
worddicty
|
||||
where
|
||||
WRDDICSEQ = #{WRDDICSEQ}
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user