first commit

This commit is contained in:
2026-04-17 19:06:49 +09:00
commit 2b6378afa3
265 changed files with 28723 additions and 0 deletions

View 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);
}
}

View 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();
}
}

View 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";
}
}

View 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";
}
}

View 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;
}
}

View 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에서 처리)
}

View 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);
}
}

View 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("/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);
}
}

View 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;
}

View 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 등)
}

View 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;
}

View 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;
}

View 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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View 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);
}

View 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;
}

View 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);
}
}

View 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;
}
}

View 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;
}
}

View 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);
}
}