feat: 공지사항 조회수 count 반영

dev
minuk926 3 years ago
parent bcec7df978
commit c5109e7dff

@ -98,8 +98,8 @@ public class AuthMinService implements IAuthMinService {
MinUserinfo user = userRepository.findByUserid(loginRequestDto.getUserid()).orElseThrow(() -> new UsernameNotFoundException(loginRequestDto.getUserid() + " -> 사용자를 찾을 수 없습니다."));
Map<String, Object> infoMap = new HashMap<>();
infoMap.put("userName", user.getName());
infoMap.put("userEmail", user.getEmail());
infoMap.put(XitConstants.JwtToken.TOKEN_USER_NAME.getCode(), user.getName());
infoMap.put(XitConstants.JwtToken.TOKEN_USER_MAIL.getCode(), user.getEmail());
RefreshToken savedRefreshToken = refreshTokenRepository.findByKey(authentication.getName())
.orElse(null);
@ -252,8 +252,8 @@ public class AuthMinService implements IAuthMinService {
MinUserinfo user = userRepository.findByUserid(authentication.getName()).orElse(null);
if(Checks.isNull(user)) throw new TokenAuthException(ErrorCode.INVALID_ROLE_TOKEN);
Map<String, Object> infoMap = new HashMap<>();
infoMap.put("userName", user.getName());
infoMap.put("userEmail", user.getEmail());
infoMap.put(XitConstants.JwtToken.TOKEN_USER_NAME.getCode(), user.getName());
infoMap.put(XitConstants.JwtToken.TOKEN_USER_MAIL.getCode(), user.getEmail());
// TODO : refresh토큰 발급 기준인 정의 필요
// refresh 토큰 기간이 3일 이하로 남은 경우, refresh 토큰 갱신

@ -6,6 +6,8 @@ import com.xit.biz.ctgy.entity.MinInfoBoard680;
import com.xit.biz.ctgy.service.ICtgyFileService;
import com.xit.core.api.IRestResponse;
import com.xit.core.api.RestResponse;
import com.xit.core.constant.ErrorCode;
import com.xit.core.exception.CustomBaseException;
import com.xit.core.util.AssertUtils;
import com.xit.core.util.Checks;
import io.swagger.v3.oas.annotations.Operation;
@ -14,9 +16,9 @@ import lombok.RequiredArgsConstructor;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.core.io.InputStreamResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.lang.NonNull;
import org.springframework.web.bind.annotation.*;
@ -26,6 +28,9 @@ import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
@ -48,15 +53,15 @@ public class CtgyFileMgtController {
private final ICtgyFileService service;
@Operation(summary = "파일 조회" , description = "등록된 파일 조회")
@Operation(summary = "파일 조회", description = "등록된 파일 조회")
@GetMapping("/{id}")
public ResponseEntity<? extends IRestResponse> findFiles(@PathVariable("inCode") @NonNull final Long inCode) {
AssertUtils.isTrue(!Checks.isEmpty(inCode), "대상 게시글[inCode]을 선택해 주세요.");
return RestResponse.of(service.findFiles(inCode));
}
@Operation(summary = "공지사항 저장" , description = "공지사항 저장")
@PostMapping(value="/pboard", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@Operation(summary = "공지사항 저장", description = "공지사항 저장")
@PostMapping(value = "/pboard", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<? extends IRestResponse> savePublicBoardFiles(@Nonnull MinInfoBoard680Dto dto) {
AssertUtils.isTrue(!Checks.isEmpty(dto), "파일 정보가 존재하지 않습니다.");
@ -70,8 +75,8 @@ public class CtgyFileMgtController {
return RestResponse.of(service.saveFiles(minInfoBoard680, dto.getFiles()));
}
@Operation(summary = "공지사항 삭제" , description = "공지사항 삭제")
@PostMapping(value="/pboard/{inCode}")
@Operation(summary = "공지사항 삭제", description = "공지사항 삭제")
@PostMapping(value = "/pboard/{inCode}")
public ResponseEntity<? extends IRestResponse> removePublicBoardFile(@PathVariable @Nonnull final Long inCode) {
AssertUtils.isTrue(!Checks.isEmpty(inCode), "공지 사항이 선택되지 않았습니다.");
service.removePublicBoardFile(inCode);
@ -80,29 +85,90 @@ public class CtgyFileMgtController {
}
@GetMapping("/download/{inCode}")
public void download(@PathVariable Long inCode, HttpServletResponse response) throws IOException {
public void download2(@PathVariable Long inCode, HttpServletResponse response) {
MinInfoBoard680 entity = service.findFiles(inCode);
String absFile = "";
if(Arrays.asList(env.getActiveProfiles()).contains("prod"))
if (Arrays.asList(env.getActiveProfiles()).contains("prod"))
absFile = entity.getInFileurl() + File.separator + entity.getInFilename();
else
absFile = rootPath + entity.getInFileurl().split(serviceUrl)[1] + File.separator + entity.getInFilename();
Path path = Paths.get(absFile);
String contentType = null;
try {
contentType = Files.probeContentType(path);
} catch (IOException e) {
throw new CustomBaseException(ErrorCode.FILE_NOT_FOUND);
}
File file = new File(absFile);
byte[] fileByte = new byte[0];
try {
fileByte = FileUtils.readFileToByteArray(file);
} catch (IOException e) {
throw new CustomBaseException(ErrorCode.FILE_NOT_FOUND);
}
response.setContentType(contentType);
response.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + URLEncoder.encode(entity.getInFilename(), StandardCharsets.UTF_8) + "\";");
//response.setHeader(HttpHeaders.CONTENT_ENCODING, "binary");
response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(entity.getInFilesize()));
try {
response.getOutputStream().write(fileByte);
response.getOutputStream().flush();
response.getOutputStream().close();
} catch (IOException e) {
throw new CustomBaseException(ErrorCode.FILE_NOT_FOUND);
}
}
@GetMapping("/download2/{inCode}")
public ResponseEntity<Resource> download(@PathVariable Long inCode, HttpServletResponse response) {
byte[] fileByte = FileUtils.readFileToByteArray(new File(absFile));
MinInfoBoard680 entity = service.findFiles(inCode);
String absFile = "";
response.setContentType("application/octet-stream");
//response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(entity.getInFilename(), StandardCharsets.UTF_8)+"\";");
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Length", String.valueOf(entity.getInFilesize()));
if (Arrays.asList(env.getActiveProfiles()).contains("prod"))
absFile = entity.getInFileurl() + File.separator + entity.getInFilename();
else
absFile = rootPath + entity.getInFileurl().split(serviceUrl)[1] + File.separator + entity.getInFilename();
response.getOutputStream().write(fileByte);
response.getOutputStream().flush();
response.getOutputStream().close();
Path path = Paths.get(absFile);
String contentType = null;
try {
contentType = Files.probeContentType(path);
} catch (IOException e) {
throw new CustomBaseException(ErrorCode.FILE_NOT_FOUND);
}
// File file = new File(absFile);
// try {
// byte[] fileByte = FileUtils.readFileToByteArray(file);
// } catch (IOException e) {
// throw new CustomBaseException(ErrorCode.FILE_NOT_FOUND);
// }
HttpHeaders headers = new HttpHeaders();
headers.add(HttpHeaders.CONTENT_TYPE, contentType);
headers.setContentDisposition(ContentDisposition.builder("attachment")
.filename(entity.getInFilename(), StandardCharsets.UTF_8)
//.filename(URLEncoder.encode(entity.getInFilename(), StandardCharsets.UTF_8))
.build());
headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(entity.getInFilesize()));
Resource resource = null;
try {
resource = new InputStreamResource(Files.newInputStream(path));
} catch (IOException e) {
throw new CustomBaseException(ErrorCode.FILE_NOT_FOUND);
}
return new ResponseEntity<>(resource, headers, HttpStatus.OK);
}
}

@ -57,25 +57,16 @@ public class OAuth2MinController {
* @return ResponseEntity
*/
@Operation(summary = "login" , description = "login")
// @Parameters({
// @Parameter(in = ParameterIn.QUERY, name = "providerType", description = "ProviderType", required = true, example = "GOOGLE"),
// @Parameter(in = ParameterIn.QUERY, name = "userId", description = "사용자ID", required = true, example = "minuk926926"),
// @Parameter(in = ParameterIn.QUERY, name = "password", description = "비밀번호", required = true, example = "minuk926926")
// })
@PostMapping("/login")
@Transactional
public ResponseEntity<? extends IRestResponse> login(
//@Validated
@Valid
@RequestBody
final LoginMinRequestDto loginRequestDto,
HttpServletRequest request,
HttpServletResponse response,
HttpSession session
//Errors errors
) {
return RestResponse.of(
authMinService.login(
loginRequestDto,

@ -16,10 +16,7 @@ import org.springframework.data.domain.Pageable;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
@Tag(name = "PublicBoardController", description = "공지사항 관리")
@RestController
@ -33,7 +30,7 @@ public class PublicBoardController {
private final MinInfoBoard680Mapstruct mapstruct = Mappers.getMapper(MinInfoBoard680Mapstruct.class);
// TODO :: 파라메터 정의 필요
@Operation(summary = "게시글 목록 조회" , description = "게시글 목록 조회")
@Operation(summary = "공지사항 목록 조회" , description = "공지사항 목록 조회")
@Parameters({
@Parameter(in = ParameterIn.QUERY, name = "inTitle", description = "제목", required = false, example = " "),
@Parameter(in = ParameterIn.QUERY, name = "inName", description = "이름", required = false, example = " "),
@ -49,12 +46,21 @@ public class PublicBoardController {
return RestResponse.of(service.findAll(mapstruct.toEntity(dto), pageable));
}
@Operation(summary = "게시글상세" , description = "게시글상세")
@Operation(summary = "공지사항상세" , description = "공지사항상세")
@Parameters({
@Parameter(in = ParameterIn.PATH, name = "inCode", description = "게시글번호", required = true, example = "18"),
@Parameter(in = ParameterIn.PATH, name = "inCode", description = "공지사항번호", required = true, example = "18"),
})
@GetMapping(value = "/{inCode}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<? extends IRestResponse> findByInCode(@PathVariable final Long inCode) {
return RestResponse.of(service.findByInCode(inCode));
}
@Operation(summary = "공지사항 조회수 증가" , description = "공지사항 조회수 증가")
@Parameters({
@Parameter(in = ParameterIn.PATH, name = "inCode", description = "공지사항번호", required = true, example = "18"),
})
@PutMapping(value = "/hit/{inCode}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<? extends IRestResponse> modifyByInCode(@PathVariable final Long inCode) {
return RestResponse.of(service.modifyByInCode(inCode));
}
}

@ -83,16 +83,16 @@ public class MinInfoBoard680 implements Serializable {
LocalDateTime localDateTime = LocalDateTime.now();
this.inNalja = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
this.inTime = localDateTime.format(DateTimeFormatter.ofPattern("HH:mm"));
this.inName = HeaderUtil.getUserId();
this.inName = HeaderUtil.getUserName();
this.inHit = 0L;
}
@PreUpdate
public void onPreUpdate(){
LocalDateTime localDateTime = LocalDateTime.now();
this.inNalja = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
this.inTime = localDateTime.format(DateTimeFormatter.ofPattern("HH:mm"));
this.inName = HeaderUtil.getUserId();
// LocalDateTime localDateTime = LocalDateTime.now();
// this.inNalja = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
// this.inTime = localDateTime.format(DateTimeFormatter.ofPattern("HH:mm"));
// this.inName = HeaderUtil.getUserName();
// this.inHit = this.inHit + 1;
}
}

@ -5,6 +5,7 @@ import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
public interface IPublicBoardRepository extends JpaRepository<MinInfoBoard680, Long> {
@ -14,5 +15,7 @@ public interface IPublicBoardRepository extends JpaRepository<MinInfoBoard680, L
MinInfoBoard680 findByInCode(final Long inCode);
Page<MinInfoBoard680> findAllByOrderByInCodeDesc(Example<MinInfoBoard680> example, Pageable pageable);
@Modifying(clearAutomatically = true)
@Query("UPDATE MinInfoBoard680 m SET m.inHit = m.inHit + 1 WHERE m.inCode = :inCode")
int updateInHitForMinInfoBoard680(Long inCode);
}

@ -8,4 +8,6 @@ public interface IPublicBoardService {
Page<MinInfoBoard680> findAll(final MinInfoBoard680 entity, Pageable pageable);
MinInfoBoard680 findByInCode(final Long inCode);
int modifyByInCode(Long inCode);
}

@ -127,6 +127,7 @@ public class CtgyFileService implements ICtgyFileService {
}
@Override
@Transactional
public void removePublicBoardFile(Long inCode) {
MinInfoBoard680 savedEntity = repository.findById(inCode).orElseThrow(() -> new CustomBaseException(ErrorCode.NOT_FOUND));

@ -37,4 +37,10 @@ public class PublicBoardService implements IPublicBoardService {
public MinInfoBoard680 findByInCode(final Long inCode) {
return repository.findByInCode(inCode);
}
@Override
@Transactional
public int modifyByInCode(Long inCode) {
return repository.updateInHitForMinInfoBoard680(inCode);
}
}

@ -38,6 +38,7 @@ public enum ErrorCode {
BAD_REQUEST(HttpStatus.BAD_REQUEST, "요청 매개변수 오류 입니다."),
NOT_FOUND(HttpStatus.NOT_FOUND, "잘못된 요청 입니다"),
FILE_NOT_FOUND(HttpStatus.NOT_FOUND, "파일이 존재하지 않습니다"),
/* 400 BAD_REQUEST : 잘못된 요청 */
CANNOT_FOLLOW_MYSELF(HttpStatus.BAD_REQUEST, "자기 자신은 팔로우 할 수 없습니다"),

@ -66,8 +66,10 @@ public class XitConstants {
GRANT_TYPE("Bearer"),
ACCESS_TOKEN_NAME("accessToken"),
REFRESH_TOKEN_NAME("refreshToken"),
AUTHORITIES_KEY("role")
;
AUTHORITIES_KEY("role"),
TOKEN_USER_NAME("userName"),
TOKEN_USER_MAIL("userEmail"),
TOKEN_USER_ID("userId");
private final String code;

@ -97,8 +97,8 @@ public class AuthService implements IAuthService {
CmmUser cmmUser = cmmUserRepository.findByUserId(loginRequestDto.getUserId()).orElseThrow(() -> new UsernameNotFoundException(loginRequestDto.getUserId() + " -> 사용자를 찾을 수 없습니다."));
Map<String, Object> infoMap = new HashMap<>();
infoMap.put("userName", cmmUser.getUserName());
infoMap.put("userEmail", cmmUser.getEmail());
infoMap.put(XitConstants.JwtToken.TOKEN_USER_NAME.getCode(), cmmUser.getUserName());
infoMap.put(XitConstants.JwtToken.TOKEN_USER_MAIL.getCode(), cmmUser.getEmail());
RefreshToken savedRefreshToken = refreshTokenRepository.findByKey(authentication.getName())
.orElse(null);
@ -250,8 +250,8 @@ public class AuthService implements IAuthService {
CmmUser cmmUser = cmmUserRepository.findByUserId(authentication.getName()).orElse(null);
if(Checks.isNull(cmmUser)) throw new TokenAuthException(ErrorCode.INVALID_ROLE_TOKEN);
Map<String, Object> infoMap = new HashMap<>();
infoMap.put("userName", cmmUser.getUserName());
infoMap.put("userEmail", cmmUser.getEmail());
infoMap.put(XitConstants.JwtToken.TOKEN_USER_NAME.getCode(), cmmUser.getUserName());
infoMap.put(XitConstants.JwtToken.TOKEN_USER_MAIL.getCode(), cmmUser.getEmail());
// TODO : refresh토큰 발급 기준인 정의 필요
// refresh 토큰 기간이 3일 이하로 남은 경우, refresh 토큰 갱신

@ -264,9 +264,9 @@ public class JwtTokenProvider {
if (authorities != null) {
//map.put("header", claims)
map.put("audience", claims.getAudience());
map.put("userId", claims.getSubject());
map.put("userName", claims.get("userName"));
map.put("userEmail", claims.get("userEmail"));
map.put(XitConstants.JwtToken.TOKEN_USER_ID.getCode(), claims.getSubject());
map.put(XitConstants.JwtToken.TOKEN_USER_NAME.getCode(), claims.get(XitConstants.JwtToken.TOKEN_USER_NAME.getCode()));
map.put(XitConstants.JwtToken.TOKEN_USER_MAIL.getCode(), claims.get(XitConstants.JwtToken.TOKEN_USER_MAIL.getCode()));
map.put(XitConstants.JwtToken.AUTHORITIES_KEY.getCode(), authorities);
map.put("Issuer", claims.getIssuer());
map.put("IssuedAt", DateUtil.getFormatedDT(claims.getIssuedAt(), "yyyy-MM-dd HH:mm:ss"));
@ -305,8 +305,8 @@ public class JwtTokenProvider {
.setAudience(auth.getAudience())
.setSubject(userId) // payload "sub": "name" - ID
.claim(XitConstants.JwtToken.AUTHORITIES_KEY.getCode(), authorities) // payload "auth": "ROLE_USER"
.claim("userName", info.get("userName"))
.claim("userEmail", info.get("userEmail"))
.claim(XitConstants.JwtToken.TOKEN_USER_NAME.getCode(), info.get(XitConstants.JwtToken.TOKEN_USER_NAME.getCode()))
.claim(XitConstants.JwtToken.TOKEN_USER_MAIL.getCode(), info.get(XitConstants.JwtToken.TOKEN_USER_MAIL.getCode()))
.setIssuedAt(new Date())
.signWith(key, Objects.equals("HS512", auth.getAlg())? SignatureAlgorithm.HS512 : SignatureAlgorithm.HS256) // header "alg": "HS512"
.setExpiration(accessTokenExpiresIn) // payload "exp": 1516239022 (예시)

@ -52,6 +52,10 @@ public class HeaderUtil {
return getUserIdFromToken(getAccessToken(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()));
}
public static String getUserName(){
return getUserNameFromToken(getAccessToken(((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()));
}
private static String getUserIdFromToken(String accessToken){
if(Checks.isEmpty(accessToken)) throw new TokenAuthException(ErrorCode.AUTH_HEADER_NOT_EXISTS);
@ -67,4 +71,20 @@ public class HeaderUtil {
};
throw new TokenAuthException(ErrorCode.INVALID_TOKEN);
}
private static String getUserNameFromToken(String accessToken){
if(Checks.isEmpty(accessToken)) throw new TokenAuthException(ErrorCode.AUTH_HEADER_NOT_EXISTS);
// JwtToken authToken = SpringUtils.getAuthTokenProvider().convertJwtToken(accessToken);
// if (!authToken.validate()) {
// return ApiResponse.invalidAccessToken();
// }
JwtTokenProvider jwtTokenProvider = SpringUtils.getJwtTokenProvider();
if(jwtTokenProvider.validateTokenExcludeExpired(accessToken, false, false)){
return (String) jwtTokenProvider.parseClaims(accessToken).get(XitConstants.JwtToken.TOKEN_USER_NAME.getCode());
};
throw new TokenAuthException(ErrorCode.INVALID_TOKEN);
}
}

Loading…
Cancel
Save