first commit
This commit is contained in:
14
src/main/java/com/owrawww/OwrawwwApplication.java
Normal file
14
src/main/java/com/owrawww/OwrawwwApplication.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.owrawww;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
@MapperScan("com.owrawww.domain.mapper")
|
||||
public class OwrawwwApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(OwrawwwApplication.class, args);
|
||||
}
|
||||
}
|
||||
31
src/main/java/com/owrawww/config/SecurityConfig.java
Normal file
31
src/main/java/com/owrawww/config/SecurityConfig.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package com.owrawww.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.anyRequest().permitAll()
|
||||
)
|
||||
.formLogin(form -> form.disable())
|
||||
.logout(logout -> logout.disable());
|
||||
|
||||
return http.build();
|
||||
}
|
||||
}
|
||||
15
src/main/java/com/owrawww/controller/AuthController.java
Normal file
15
src/main/java/com/owrawww/controller/AuthController.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package com.owrawww.controller;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/auth")
|
||||
public class AuthController {
|
||||
|
||||
@GetMapping("/login")
|
||||
public String loginPage() {
|
||||
return "auth/login";
|
||||
}
|
||||
}
|
||||
104
src/main/java/com/owrawww/controller/BbsController.java
Normal file
104
src/main/java/com/owrawww/controller/BbsController.java
Normal file
@@ -0,0 +1,104 @@
|
||||
package com.owrawww.controller;
|
||||
|
||||
import com.owrawww.service.BbsService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
public class BbsController {
|
||||
|
||||
private final BbsService bbsService;
|
||||
|
||||
@RequestMapping(value = "/bbs/owrainfo", method = {RequestMethod.GET, RequestMethod.POST})
|
||||
public String bbsList(
|
||||
@RequestParam(defaultValue = "1") int page,
|
||||
@RequestParam(defaultValue = "all") String searchType,
|
||||
@RequestParam(defaultValue = "") String keyword,
|
||||
Model model) {
|
||||
int topCode = 1;
|
||||
int leftCode = 1;
|
||||
int subGubun = 1;
|
||||
bbsService.getList(page, searchType, keyword, topCode, leftCode, subGubun)
|
||||
.forEach(model::addAttribute);
|
||||
return "sub04_01";
|
||||
}
|
||||
|
||||
@GetMapping("/bbs/owrainfo/view")
|
||||
public String bbsView(
|
||||
@RequestParam Long id,
|
||||
@RequestParam(defaultValue = "1") int page,
|
||||
@RequestParam(defaultValue = "all") String searchType,
|
||||
@RequestParam(defaultValue = "") String keyword,
|
||||
Model model) {
|
||||
int topCode = 1;
|
||||
int leftCode = 1;
|
||||
int subGubun = 1;
|
||||
bbsService.getDetail(id, topCode, leftCode, subGubun, page, searchType, keyword)
|
||||
.forEach(model::addAttribute);
|
||||
return "sub04_01_view";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/business/progress", method = {RequestMethod.GET, RequestMethod.POST})
|
||||
public String progressList(
|
||||
@RequestParam(defaultValue = "1") int page,
|
||||
@RequestParam(defaultValue = "all") String searchType,
|
||||
@RequestParam(defaultValue = "") String keyword,
|
||||
Model model) {
|
||||
int topCode = 1;
|
||||
int leftCode = 2;
|
||||
int subGubun = 1;
|
||||
bbsService.getList(page, searchType, keyword, topCode, leftCode, subGubun)
|
||||
.forEach(model::addAttribute);
|
||||
return "sub02_08";
|
||||
}
|
||||
|
||||
@GetMapping("/business/progress/view")
|
||||
public String progressView(
|
||||
@RequestParam Long id,
|
||||
@RequestParam(defaultValue = "1") int page,
|
||||
@RequestParam(defaultValue = "all") String searchType,
|
||||
@RequestParam(defaultValue = "") String keyword,
|
||||
Model model) {
|
||||
int topCode = 1;
|
||||
int leftCode = 2;
|
||||
int subGubun = 1;
|
||||
bbsService.getDetail(id, topCode, leftCode, subGubun, page, searchType, keyword)
|
||||
.forEach(model::addAttribute);
|
||||
return "sub02_08_view";
|
||||
}
|
||||
|
||||
@RequestMapping(value = "/bbs/press", method = {RequestMethod.GET, RequestMethod.POST})
|
||||
public String pressList(
|
||||
@RequestParam(defaultValue = "1") int page,
|
||||
@RequestParam(defaultValue = "all") String searchType,
|
||||
@RequestParam(defaultValue = "") String keyword,
|
||||
Model model) {
|
||||
int topCode = 1;
|
||||
int leftCode = 4;
|
||||
int subGubun = 1;
|
||||
bbsService.getList(page, searchType, keyword, topCode, leftCode, subGubun)
|
||||
.forEach(model::addAttribute);
|
||||
return "sub04_03";
|
||||
}
|
||||
|
||||
@GetMapping("/bbs/press/view")
|
||||
public String pressView(
|
||||
@RequestParam Long id,
|
||||
@RequestParam(defaultValue = "1") int page,
|
||||
@RequestParam(defaultValue = "all") String searchType,
|
||||
@RequestParam(defaultValue = "") String keyword,
|
||||
Model model) {
|
||||
int topCode = 1;
|
||||
int leftCode = 4;
|
||||
int subGubun = 1;
|
||||
bbsService.getDetail(id, topCode, leftCode, subGubun, page, searchType, keyword)
|
||||
.forEach(model::addAttribute);
|
||||
return "sub04_03_view";
|
||||
}
|
||||
}
|
||||
168
src/main/java/com/owrawww/controller/CareersController.java
Normal file
168
src/main/java/com/owrawww/controller/CareersController.java
Normal file
@@ -0,0 +1,168 @@
|
||||
package com.owrawww.controller;
|
||||
|
||||
import com.owrawww.domain.Careers;
|
||||
import com.owrawww.service.CareersService;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
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.ResponseBody;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/careers/recruitment")
|
||||
@RequiredArgsConstructor
|
||||
public class CareersController {
|
||||
|
||||
private static final long MAX_FILE_SIZE = 10 * 1024 * 1024L;
|
||||
private static final Set<String> ALLOWED_EXT = Set.of(
|
||||
"pdf", "doc", "docx", "hwp", "hwpx", "ppt", "pptx", "txt", "zip"
|
||||
);
|
||||
|
||||
// 파일 매직 바이트 시그니처
|
||||
private static final byte[] MAGIC_PDF = {0x25, 0x50, 0x44, 0x46}; // %PDF
|
||||
private static final byte[] MAGIC_OLE2 = {(byte)0xD0, (byte)0xCF, 0x11, (byte)0xE0, (byte)0xA1, (byte)0xB1, 0x1A, (byte)0xE1}; // DOC/XLS/PPT/HWP(5)
|
||||
private static final byte[] MAGIC_ZIP = {0x50, 0x4B, 0x03, 0x04}; // DOCX/XLSX/PPTX/HWPX (ZIP 기반)
|
||||
private static final byte[] MAGIC_HWP5 = {0x48, 0x57, 0x50, 0x20, 0x44, 0x6F, 0x63, 0x75}; // "HWP Docu" (HWP 5.x)
|
||||
|
||||
private final CareersService careersService;
|
||||
|
||||
@GetMapping
|
||||
public String careersForm(@ModelAttribute Careers careers) {
|
||||
return "sub03_04";
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@ResponseBody
|
||||
public ResponseEntity<Map<String, Object>> careersSubmit(
|
||||
@Valid @ModelAttribute Careers careers,
|
||||
BindingResult bindingResult,
|
||||
@RequestParam(value = "file", required = false) MultipartFile file) {
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
if (bindingResult.hasErrors()) {
|
||||
result.put("success", false);
|
||||
result.put("message", "입력값을 확인해주세요.");
|
||||
return ResponseEntity.badRequest().body(result);
|
||||
}
|
||||
|
||||
if (file != null && !file.isEmpty()) {
|
||||
// 용량 검증
|
||||
if (file.getSize() > MAX_FILE_SIZE) {
|
||||
result.put("success", false);
|
||||
result.put("message", "파일 용량은 10MB 이하만 가능합니다.");
|
||||
return ResponseEntity.badRequest().body(result);
|
||||
}
|
||||
|
||||
// 확장자 검증
|
||||
String originalName = file.getOriginalFilename() != null ? file.getOriginalFilename() : "";
|
||||
String ext = originalName.contains(".")
|
||||
? originalName.substring(originalName.lastIndexOf('.') + 1).toLowerCase()
|
||||
: "";
|
||||
if (!ALLOWED_EXT.contains(ext)) {
|
||||
result.put("success", false);
|
||||
result.put("message", "허용된 파일 형식이 아닙니다. (PDF, Word, 한글, PPT, 텍스트)");
|
||||
return ResponseEntity.badRequest().body(result);
|
||||
}
|
||||
|
||||
// 파일 내용(매직 바이트) 검증
|
||||
try {
|
||||
String contentError = validateFileContent(file, ext);
|
||||
if (contentError != null) {
|
||||
result.put("success", false);
|
||||
result.put("message", contentError);
|
||||
return ResponseEntity.badRequest().body(result);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
result.put("success", false);
|
||||
result.put("message", "파일을 읽는 중 오류가 발생했습니다.");
|
||||
return ResponseEntity.badRequest().body(result);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
boolean success = careersService.submit(careers, file);
|
||||
result.put("success", success);
|
||||
if (!success) {
|
||||
result.put("message", "처리 중 오류가 발생했습니다. 다시 시도해주세요.");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
result.put("success", false);
|
||||
result.put("message", "파일 저장 중 오류가 발생했습니다.");
|
||||
return ResponseEntity.internalServerError().body(result);
|
||||
}
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 파일 매직 바이트로 실제 형식 검증
|
||||
* - PDF : %PDF 시그니처
|
||||
* - DOC/XLS/PPT/HWP(5) : OLE2 복합 문서 시그니처
|
||||
* - DOCX/XLSX/PPTX/HWPX : ZIP(PK) 시그니처
|
||||
* - TXT : 바이너리 제어문자 미포함 여부
|
||||
*/
|
||||
private String validateFileContent(MultipartFile file, String ext) throws IOException {
|
||||
byte[] header = new byte[8];
|
||||
try (InputStream is = file.getInputStream()) {
|
||||
int read = is.read(header);
|
||||
if (read < 4) {
|
||||
return "파일이 손상되었거나 내용이 없습니다.";
|
||||
}
|
||||
}
|
||||
|
||||
return switch (ext) {
|
||||
case "pdf" -> startsWith(header, MAGIC_PDF)
|
||||
? null : "PDF 파일 형식이 올바르지 않습니다.";
|
||||
|
||||
case "doc", "xls", "ppt" -> startsWith(header, MAGIC_OLE2) || startsWith(header, MAGIC_HWP5)
|
||||
? null : "파일 내용이 선택한 형식(" + ext.toUpperCase() + ")과 일치하지 않습니다.";
|
||||
|
||||
case "hwp" -> startsWith(header, MAGIC_OLE2) || startsWith(header, MAGIC_HWP5) || startsWith(header, MAGIC_ZIP)
|
||||
? null : "HWP 파일 형식이 올바르지 않습니다.";
|
||||
|
||||
case "docx", "xlsx", "pptx", "hwpx" -> startsWith(header, MAGIC_ZIP)
|
||||
? null : "파일 내용이 선택한 형식(" + ext.toUpperCase() + ")과 일치하지 않습니다.";
|
||||
|
||||
case "zip" -> startsWith(header, MAGIC_ZIP)
|
||||
? null : "ZIP 파일 형식이 올바르지 않습니다.";
|
||||
|
||||
case "txt" -> isPlainText(header)
|
||||
? null : "TXT 파일에 허용되지 않는 바이너리 내용이 포함되어 있습니다.";
|
||||
|
||||
default -> "허용된 파일 형식이 아닙니다.";
|
||||
};
|
||||
}
|
||||
|
||||
private boolean startsWith(byte[] data, byte[] magic) {
|
||||
if (data.length < magic.length) return false;
|
||||
for (int i = 0; i < magic.length; i++) {
|
||||
if (data[i] != magic[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** TXT: 제어문자(탭·개행 제외)가 없으면 텍스트로 판단 */
|
||||
private boolean isPlainText(byte[] header) {
|
||||
for (byte b : header) {
|
||||
int c = b & 0xFF;
|
||||
if (c < 0x09) return false; // 0x00~0x08 제어문자
|
||||
if (c == 0x0B || c == 0x0C) return false; // VT, FF
|
||||
if (c >= 0x0E && c <= 0x1F) return false; // 기타 제어문자
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
96
src/main/java/com/owrawww/controller/HomeController.java
Normal file
96
src/main/java/com/owrawww/controller/HomeController.java
Normal file
@@ -0,0 +1,96 @@
|
||||
package com.owrawww.controller;
|
||||
|
||||
import com.owrawww.service.BbsService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@Controller
|
||||
@RequiredArgsConstructor
|
||||
public class HomeController {
|
||||
|
||||
private final BbsService bbsService;
|
||||
|
||||
@GetMapping("/")
|
||||
public String index(Model model) {
|
||||
model.addAttribute("progressList", bbsService.getPreview(1, 2, 1, 5));
|
||||
model.addAttribute("pressList", bbsService.getPreview(1, 4, 1, 8));
|
||||
return "index";
|
||||
}
|
||||
|
||||
@GetMapping("/include/header")
|
||||
public String header() { return "include/header"; }
|
||||
|
||||
@GetMapping("/include/footer")
|
||||
public String footer() { return "include/footer"; }
|
||||
|
||||
@GetMapping("/sitemap")
|
||||
public String sitemap() { return "sitemap"; }
|
||||
|
||||
@GetMapping("/service")
|
||||
public String service() { return "service"; }
|
||||
|
||||
@GetMapping("/etc")
|
||||
public String etc() { return "etc"; }
|
||||
|
||||
@GetMapping("/pub_list")
|
||||
public String pubList() { return "pub_list"; }
|
||||
|
||||
@GetMapping("/board_view")
|
||||
public String boardView() { return "board_view"; }
|
||||
|
||||
// 회사소개
|
||||
@GetMapping("/company/intro")
|
||||
public String sub0101() { return "sub01_01"; }
|
||||
|
||||
@GetMapping("/company/business")
|
||||
public String sub0102() { return "sub01_02"; }
|
||||
|
||||
@GetMapping("/company/history")
|
||||
public String sub0103() { return "sub01_03"; }
|
||||
|
||||
@GetMapping("/company/chart")
|
||||
public String sub0104() { return "sub01_04"; }
|
||||
|
||||
@GetMapping("/company/map")
|
||||
public String sub0105() { return "sub01_05"; }
|
||||
|
||||
// 사업소개
|
||||
@GetMapping("/business/intro")
|
||||
public String sub0201() { return "sub02_01"; }
|
||||
|
||||
@GetMapping("/business/pg")
|
||||
public String sub0202() { return "sub02_02"; }
|
||||
|
||||
@GetMapping("/business/prepayment")
|
||||
public String sub0203() { return "sub02_03"; }
|
||||
|
||||
@GetMapping("/business/payment")
|
||||
public String sub0204() { return "sub02_04"; }
|
||||
|
||||
@GetMapping("/business/sales")
|
||||
public String sub0205() { return "sub02_05"; }
|
||||
|
||||
@GetMapping("/business/b2b")
|
||||
public String sub0206() { return "sub02_06"; }
|
||||
|
||||
@GetMapping("/business/delivery")
|
||||
public String sub0207() { return "sub02_07"; }
|
||||
|
||||
// /business/progress 는 BbsController에서 처리
|
||||
|
||||
// 인재채용
|
||||
@GetMapping("/careers/talent")
|
||||
public String sub0301() { return "sub03_01"; }
|
||||
|
||||
@GetMapping("/careers/benefit")
|
||||
public String sub0302() { return "sub03_02"; }
|
||||
|
||||
@GetMapping("/careers/careers")
|
||||
public String sub0303() { return "sub03_03"; }
|
||||
|
||||
// /careers/recruitment 는 CareersController에서 처리
|
||||
// 게시판 (/bbs/owrainfo 는 BbsController에서, /bbs/partnership 은 PartnershipController에서, /bbs/press 는 BbsController에서 처리)
|
||||
}
|
||||
|
||||
48
src/main/java/com/owrawww/controller/InquiryController.java
Normal file
48
src/main/java/com/owrawww/controller/InquiryController.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package com.owrawww.controller;
|
||||
|
||||
import com.owrawww.domain.Inquiry;
|
||||
import com.owrawww.service.InquiryService;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/sub04_02")
|
||||
@RequiredArgsConstructor
|
||||
public class InquiryController {
|
||||
|
||||
private final InquiryService inquiryService;
|
||||
|
||||
@GetMapping
|
||||
public String inquiryForm(@ModelAttribute Inquiry inquiry) {
|
||||
return "sub04_02";
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@ResponseBody
|
||||
public ResponseEntity<Map<String, Object>> inquirySubmit(@Valid @ModelAttribute Inquiry inquiry,
|
||||
BindingResult bindingResult) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
if (bindingResult.hasErrors()) {
|
||||
result.put("success", false);
|
||||
result.put("message", "입력값을 확인해주세요.");
|
||||
return ResponseEntity.badRequest().body(result);
|
||||
}
|
||||
boolean success = inquiryService.submit(inquiry);
|
||||
result.put("success", success);
|
||||
if (!success) {
|
||||
result.put("message", "처리 중 오류가 발생했습니다. 다시 시도해주세요.");
|
||||
}
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.owrawww.controller;
|
||||
|
||||
import com.owrawww.domain.Inquiry;
|
||||
import com.owrawww.service.InquiryService;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/bbs/partnership")
|
||||
@RequiredArgsConstructor
|
||||
public class PartnershipController {
|
||||
|
||||
private final InquiryService inquiryService;
|
||||
|
||||
@GetMapping
|
||||
public String partnershipForm(@ModelAttribute Inquiry inquiry) {
|
||||
return "sub04_02";
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@ResponseBody
|
||||
public ResponseEntity<Map<String, Object>> partnershipSubmit(@Valid @ModelAttribute Inquiry inquiry,
|
||||
BindingResult bindingResult) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
if (bindingResult.hasErrors()) {
|
||||
result.put("success", false);
|
||||
result.put("message", "입력값을 확인해주세요.");
|
||||
return ResponseEntity.badRequest().body(result);
|
||||
}
|
||||
boolean success = inquiryService.submit(inquiry);
|
||||
result.put("success", success);
|
||||
if (!success) {
|
||||
result.put("message", "처리 중 오류가 발생했습니다. 다시 시도해주세요.");
|
||||
}
|
||||
return ResponseEntity.ok(result);
|
||||
}
|
||||
}
|
||||
19
src/main/java/com/owrawww/domain/Bbs.java
Normal file
19
src/main/java/com/owrawww/domain/Bbs.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package com.owrawww.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class Bbs {
|
||||
|
||||
private Long id;
|
||||
private String title;
|
||||
private String name;
|
||||
private String regDate;
|
||||
private String body;
|
||||
private int viewCnt;
|
||||
private String mainImg;
|
||||
}
|
||||
53
src/main/java/com/owrawww/domain/Careers.java
Normal file
53
src/main/java/com/owrawww/domain/Careers.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package com.owrawww.domain;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class Careers {
|
||||
|
||||
private Long id;
|
||||
|
||||
@NotBlank(message = "성명을 입력해주세요.")
|
||||
private String name;
|
||||
|
||||
@NotBlank(message = "이메일을 입력해주세요.")
|
||||
@Email(message = "올바른 이메일 형식이 아닙니다.")
|
||||
private String email;
|
||||
|
||||
@NotBlank(message = "연락처를 입력해주세요.")
|
||||
@Pattern(regexp = "^[0-9\\-+\\s]{7,20}$", message = "연락처 형식이 올바르지 않습니다.")
|
||||
private String tel;
|
||||
|
||||
@NotBlank(message = "지원분야를 선택해주세요.")
|
||||
private String dept;
|
||||
|
||||
@NotBlank(message = "제목을 입력해주세요.")
|
||||
private String title;
|
||||
|
||||
@NotBlank(message = "내용을 입력해주세요.")
|
||||
private String content;
|
||||
|
||||
private LocalDateTime createdAt;
|
||||
private String code;
|
||||
private String type;
|
||||
private String comment;
|
||||
private Integer topCode;
|
||||
private Integer leftCode;
|
||||
private Integer subGubun;
|
||||
private Integer depth;
|
||||
private String solutionGubun;
|
||||
private String orgFileName; // 원본 파일명 (업로드 시 클라이언트에서 전달받은 이름 확장자제외)
|
||||
private String fileName; // 원본 파일명
|
||||
private String filePath; // 저장 경로 (DB 기록용)
|
||||
private String fileType; // MIME 타입 (예: application/pdf, image/jpeg 등)
|
||||
|
||||
}
|
||||
49
src/main/java/com/owrawww/domain/Inquiry.java
Normal file
49
src/main/java/com/owrawww/domain/Inquiry.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package com.owrawww.domain;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class Inquiry {
|
||||
|
||||
private Long id;
|
||||
|
||||
@NotBlank(message = "성명을 입력해주세요.")
|
||||
private String name;
|
||||
|
||||
@NotBlank(message = "이메일을 입력해주세요.")
|
||||
@Email(message = "올바른 이메일 형식이 아닙니다.")
|
||||
private String email;
|
||||
|
||||
@NotBlank(message = "연락처를 입력해주세요.")
|
||||
@Pattern(regexp = "^[0-9\\-+\\s]{7,20}$", message = "연락처 형식이 올바르지 않습니다.")
|
||||
private String tel;
|
||||
|
||||
@NotBlank(message = "지원분야를 선택해주세요.")
|
||||
private String dept;
|
||||
|
||||
@NotBlank(message = "제목을 입력해주세요.")
|
||||
private String title;
|
||||
|
||||
@NotBlank(message = "내용을 입력해주세요.")
|
||||
private String content;
|
||||
|
||||
private LocalDateTime createdAt;
|
||||
private String code;
|
||||
private String type;
|
||||
private String comment;
|
||||
private Integer topCode;
|
||||
private Integer leftCode;
|
||||
private Integer subGubun;
|
||||
private Integer depth;
|
||||
private String solutionGubun;
|
||||
|
||||
}
|
||||
18
src/main/java/com/owrawww/domain/User.java
Normal file
18
src/main/java/com/owrawww/domain/User.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package com.owrawww.domain;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class User {
|
||||
|
||||
private Long id;
|
||||
private String username;
|
||||
private String password;
|
||||
private String role; // ROLE_USER, ROLE_ADMIN
|
||||
private String email;
|
||||
private boolean enabled;
|
||||
}
|
||||
25
src/main/java/com/owrawww/domain/mapper/BbsMapper.java
Normal file
25
src/main/java/com/owrawww/domain/mapper/BbsMapper.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package com.owrawww.domain.mapper;
|
||||
|
||||
import com.owrawww.domain.Bbs;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Mapper
|
||||
public interface BbsMapper {
|
||||
|
||||
List<Bbs> selectList(Map<String, Object> params);
|
||||
|
||||
int selectCount(Map<String, Object> params);
|
||||
|
||||
Bbs selectById(Map<String, Object> params);
|
||||
|
||||
Bbs selectPrev(Map<String, Object> params);
|
||||
|
||||
Bbs selectNext(Map<String, Object> params);
|
||||
|
||||
int incrementViewCnt(Long id);
|
||||
|
||||
List<Bbs> selectPreview(Map<String, Object> params);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.owrawww.domain.mapper;
|
||||
|
||||
import com.owrawww.domain.Careers;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface CareersMapper {
|
||||
int insert(Careers careers);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.owrawww.domain.mapper;
|
||||
|
||||
import com.owrawww.domain.Inquiry;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface InquiryMapper {
|
||||
int insert(Inquiry inquiry);
|
||||
}
|
||||
21
src/main/java/com/owrawww/domain/mapper/UserMapper.java
Normal file
21
src/main/java/com/owrawww/domain/mapper/UserMapper.java
Normal file
@@ -0,0 +1,21 @@
|
||||
package com.owrawww.domain.mapper;
|
||||
|
||||
import com.owrawww.domain.User;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Mapper
|
||||
public interface UserMapper {
|
||||
|
||||
Optional<User> findByUsername(String username);
|
||||
|
||||
List<User> findAll();
|
||||
|
||||
void insert(User user);
|
||||
|
||||
void update(User user);
|
||||
|
||||
void deleteById(Long id);
|
||||
}
|
||||
24
src/main/java/com/owrawww/dto/UserDto.java
Normal file
24
src/main/java/com/owrawww/dto/UserDto.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.owrawww.dto;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class UserDto {
|
||||
|
||||
@NotBlank(message = "아이디를 입력하세요.")
|
||||
private String username;
|
||||
|
||||
@NotBlank(message = "비밀번호를 입력하세요.")
|
||||
@Size(min = 8, message = "비밀번호는 8자 이상이어야 합니다.")
|
||||
private String password;
|
||||
|
||||
@Email(message = "이메일 형식이 올바르지 않습니다.")
|
||||
private String email;
|
||||
}
|
||||
91
src/main/java/com/owrawww/service/BbsService.java
Normal file
91
src/main/java/com/owrawww/service/BbsService.java
Normal file
@@ -0,0 +1,91 @@
|
||||
package com.owrawww.service;
|
||||
|
||||
import com.owrawww.domain.Bbs;
|
||||
import com.owrawww.domain.mapper.BbsMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class BbsService {
|
||||
|
||||
private static final int PAGE_SIZE = 12;
|
||||
private static final int PAGE_BLOCK = 5;
|
||||
|
||||
private final BbsMapper bbsMapper;
|
||||
|
||||
public Map<String, Object> getList(int page, String searchType, String keyword, int topCode, int leftCode, int subGubun) {
|
||||
if (page < 1) page = 1;
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("size", PAGE_SIZE);
|
||||
params.put("offset", (page - 1) * PAGE_SIZE);
|
||||
params.put("topCode", topCode);
|
||||
params.put("leftCode", leftCode);
|
||||
params.put("subGubun", subGubun);
|
||||
params.put("searchType", searchType);
|
||||
params.put("keyword", keyword);
|
||||
|
||||
List<Bbs> list = bbsMapper.selectList(params);
|
||||
int totalCount = bbsMapper.selectCount(params);
|
||||
int totalPages = Math.max(1, (int) Math.ceil((double) totalCount / PAGE_SIZE));
|
||||
|
||||
if (page > totalPages) page = totalPages;
|
||||
|
||||
int blockStart = ((page - 1) / PAGE_BLOCK) * PAGE_BLOCK + 1;
|
||||
int blockEnd = Math.min(blockStart + PAGE_BLOCK - 1, totalPages);
|
||||
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
model.put("list", list);
|
||||
model.put("totalCount", totalCount);
|
||||
model.put("currentPage", page);
|
||||
model.put("totalPages", totalPages);
|
||||
model.put("blockStart", blockStart);
|
||||
model.put("blockEnd", blockEnd);
|
||||
model.put("searchType", searchType);
|
||||
model.put("keyword", keyword);
|
||||
model.put("topCode", topCode);
|
||||
model.put("leftCode", leftCode);
|
||||
model.put("subGubun", subGubun);
|
||||
return model;
|
||||
}
|
||||
|
||||
public Map<String, Object> getDetail(Long id, int topCode, int leftCode, int subGubun, int page, String searchType, String keyword) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("id", id);
|
||||
params.put("topCode", topCode);
|
||||
params.put("leftCode", leftCode);
|
||||
params.put("subGubun", subGubun);
|
||||
params.put("page", page);
|
||||
params.put("searchType", searchType);
|
||||
params.put("keyword", keyword);
|
||||
|
||||
bbsMapper.incrementViewCnt(id);
|
||||
|
||||
Bbs bbs = bbsMapper.selectById(params);
|
||||
Bbs prev = bbsMapper.selectPrev(params);
|
||||
Bbs next = bbsMapper.selectNext(params);
|
||||
|
||||
Map<String, Object> model = new HashMap<>();
|
||||
model.put("bbs", bbs);
|
||||
model.put("prev", prev);
|
||||
model.put("next", next);
|
||||
model.put("currentPage", page);
|
||||
model.put("searchType", searchType);
|
||||
model.put("keyword", keyword);
|
||||
return model;
|
||||
}
|
||||
|
||||
public List<Bbs> getPreview(int topCode, int leftCode, int subGubun, int limit) {
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("topCode", topCode);
|
||||
params.put("leftCode", leftCode);
|
||||
params.put("subGubun", subGubun);
|
||||
params.put("limit", limit);
|
||||
return bbsMapper.selectPreview(params);
|
||||
}
|
||||
}
|
||||
62
src/main/java/com/owrawww/service/CareersService.java
Normal file
62
src/main/java/com/owrawww/service/CareersService.java
Normal file
@@ -0,0 +1,62 @@
|
||||
package com.owrawww.service;
|
||||
|
||||
import com.owrawww.domain.Careers;
|
||||
import com.owrawww.domain.mapper.CareersMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
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;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class CareersService {
|
||||
|
||||
@Value("${app.upload.path}")
|
||||
private String uploadPath;
|
||||
|
||||
private final CareersMapper careersMapper;
|
||||
|
||||
public boolean submit(Careers careers, MultipartFile file) throws IOException {
|
||||
Careers saved = new Careers();
|
||||
saved.setCode("1");
|
||||
saved.setTitle(careers.getTitle());
|
||||
saved.setComment(careers.getContent());
|
||||
saved.setName(careers.getName());
|
||||
saved.setTel(careers.getTel());
|
||||
saved.setEmail(careers.getEmail());
|
||||
saved.setTopCode(2);
|
||||
saved.setLeftCode(1);
|
||||
saved.setSubGubun(1);
|
||||
saved.setDepth(1);
|
||||
saved.setSolutionGubun(careers.getSolutionGubun());
|
||||
saved.setDept(careers.getDept());
|
||||
|
||||
// 파일 저장
|
||||
if (file != null && !file.isEmpty()) {
|
||||
String originalName = file.getOriginalFilename() != null ? file.getOriginalFilename() : "unknown";
|
||||
String ext = originalName.contains(".")
|
||||
? originalName.substring(originalName.lastIndexOf('.'))
|
||||
: "";
|
||||
String storedName = UUID.randomUUID().toString().replace("-", "") + ext;
|
||||
|
||||
Path dir = Paths.get(uploadPath);
|
||||
Files.createDirectories(dir);
|
||||
Path dest = dir.resolve(storedName);
|
||||
Files.copy(file.getInputStream(), dest, StandardCopyOption.REPLACE_EXISTING);
|
||||
|
||||
saved.setOrgFileName(originalName.replace(ext, "")); // 확장자 제외한 원본 파일명
|
||||
saved.setFileName(originalName); // 원본 파일명
|
||||
saved.setFilePath(uploadPath + "/" + storedName); // 저장 경로
|
||||
saved.setFileType(file.getContentType()); // MIME 타입
|
||||
}
|
||||
|
||||
return careersMapper.insert(saved) > 0;
|
||||
}
|
||||
}
|
||||
30
src/main/java/com/owrawww/service/InquiryService.java
Normal file
30
src/main/java/com/owrawww/service/InquiryService.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.owrawww.service;
|
||||
|
||||
import com.owrawww.domain.Inquiry;
|
||||
import com.owrawww.domain.mapper.InquiryMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class InquiryService {
|
||||
|
||||
private final InquiryMapper inquiryMapper;
|
||||
|
||||
public boolean submit(Inquiry inquiry) {
|
||||
Inquiry savedInquiry = new Inquiry();
|
||||
savedInquiry.setCode("1");
|
||||
savedInquiry.setTitle(inquiry.getTitle());
|
||||
savedInquiry.setComment(inquiry.getContent());
|
||||
savedInquiry.setName(inquiry.getName());
|
||||
savedInquiry.setTel(inquiry.getTel());
|
||||
savedInquiry.setEmail(inquiry.getEmail());
|
||||
savedInquiry.setTopCode(2);
|
||||
savedInquiry.setLeftCode(1);
|
||||
savedInquiry.setSubGubun(1);
|
||||
savedInquiry.setDepth(1);
|
||||
savedInquiry.setSolutionGubun(inquiry.getSolutionGubun());
|
||||
|
||||
return inquiryMapper.insert(savedInquiry) > 0;
|
||||
}
|
||||
}
|
||||
44
src/main/java/com/owrawww/service/UserService.java
Normal file
44
src/main/java/com/owrawww/service/UserService.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package com.owrawww.service;
|
||||
|
||||
import com.owrawww.domain.User;
|
||||
import com.owrawww.domain.mapper.UserMapper;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UserService implements UserDetailsService {
|
||||
|
||||
private final UserMapper userMapper;
|
||||
private final PasswordEncoder passwordEncoder;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
User user = userMapper.findByUsername(username)
|
||||
.orElseThrow(() -> new UsernameNotFoundException("사용자를 찾을 수 없습니다: " + username));
|
||||
|
||||
return org.springframework.security.core.userdetails.User.builder()
|
||||
.username(user.getUsername())
|
||||
.password(user.getPassword())
|
||||
.roles(user.getRole().replace("ROLE_", ""))
|
||||
.disabled(!user.isEnabled())
|
||||
.build();
|
||||
}
|
||||
|
||||
public List<User> findAll() {
|
||||
return userMapper.findAll();
|
||||
}
|
||||
|
||||
public void register(User user) {
|
||||
user.setPassword(passwordEncoder.encode(user.getPassword()));
|
||||
user.setRole("ROLE_USER");
|
||||
user.setEnabled(true);
|
||||
userMapper.insert(user);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user