diff --git a/src/main/java/com/delfood/config/DatabaseConfig.java b/src/main/java/com/delfood/config/DatabaseConfig.java index 7270e28..b7fd830 100644 --- a/src/main/java/com/delfood/config/DatabaseConfig.java +++ b/src/main/java/com/delfood/config/DatabaseConfig.java @@ -19,6 +19,8 @@ public class DatabaseConfig { public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); + // TypeAlias로 설정할 클래스들이 있는 패키지를 설정하면 DTO에 @Alias("aliasName")으로 typeAlias를 설정 가능 + sessionFactory.setTypeAliasesPackage("com.delfood.dto."); PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sessionFactory.setMapperLocations(resolver.getResources("classpath:mybatis/mapper/*.xml")); return sessionFactory.getObject(); diff --git a/src/main/java/com/delfood/controller/OwnerController.java b/src/main/java/com/delfood/controller/OwnerController.java index f9e9f72..d7f7597 100644 --- a/src/main/java/com/delfood/controller/OwnerController.java +++ b/src/main/java/com/delfood/controller/OwnerController.java @@ -1,10 +1,289 @@ package com.delfood.controller; +import com.delfood.dto.OwnerDTO; +import com.delfood.dto.OwnerDTO.Status; +import com.delfood.mapper.DMLOperationError; +import com.delfood.service.OwnerService; +import javax.servlet.http.HttpSession; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +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.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/owners/") +@Log4j2 public class OwnerController { + @Autowired + private OwnerService ownerService; + + /** + * 회원 로그인 기능 수행. + * + * @param loginRequest 로그인 요청 ( id, password ) + * @return + */ + @PostMapping("login") + public ResponseEntity login(@RequestBody OwnerLoginRequest loginRequest, + HttpSession session) { + OwnerDTO ownerInfo = ownerService.getOwner(loginRequest.getId(), loginRequest.getPassword()); + OwnerLoginResponse ownerLoginResponse; + ResponseEntity responseEntity; + + if (ownerInfo == null) { // 아이디와 비밀번호가 일치하지 않거나, 회원정보가 없음 + ownerLoginResponse = OwnerLoginResponse.FAIL; + responseEntity = + new ResponseEntity(ownerLoginResponse, HttpStatus.UNAUTHORIZED); + } else { // 회원 정보가 존재 + Status ownerStatus = ownerInfo.getStatus(); + if (ownerStatus == Status.DEFAULT) { + ownerLoginResponse = OwnerLoginResponse.success(ownerInfo); + session.setAttribute("LOGIN_OWNER_ID", ownerInfo.getId()); + responseEntity = new ResponseEntity(ownerLoginResponse, HttpStatus.OK); + } else { + ownerLoginResponse = OwnerLoginResponse.DELETED; + responseEntity = new ResponseEntity(ownerLoginResponse, + HttpStatus.UNAUTHORIZED); + } + } + return responseEntity; + } + + + /** + * 사장님 로그아웃. + * + * @param session 현재 사용자 세션 + * @return + */ + @PostMapping("logout") + public ResponseEntity logout(HttpSession session) { + String id = (String) session.getAttribute("LOGIN_OWNER_ID"); + if (id != null) { + session.invalidate(); + return new ResponseEntity(logoutResponse.SUCCESS, + HttpStatus.OK); + } else { + return new ResponseEntity(logoutResponse.NO_LOGIN, + HttpStatus.UNAUTHORIZED); + } + } + + + /** + * 로그인한 사장의 정보를 조회. + * + * @param session 현재 사용자 세션 + * @return + */ + @GetMapping("myInfo") + public ResponseEntity ownerInfo(HttpSession session) { + ResponseEntity responseEntity = null; + String id = (String) session.getAttribute("LOGIN_OWNER_ID"); + if (id == null) { + responseEntity = new ResponseEntity(HttpStatus.UNAUTHORIZED); + } else { + OwnerDTO ownerInfo = ownerService.getOwner(id); + responseEntity = new ResponseEntity(ownerInfo, HttpStatus.OK); + } + return responseEntity; + } + + /** + * 사장 이메일, 전화번호 변경. + * + * @param updateRequest 이메일, 전화번호를 포함한 update 객체 + * @param session 현재 사용자 세션 + * @return + */ + @PatchMapping + public ResponseEntity updateOwnerInfo( + @RequestBody UpdateOwnerMailAndTelRequest updateRequest, HttpSession session) { + + String mail = updateRequest.getMail(); + String tel = updateRequest.getTel(); + String password = updateRequest.getPassword(); + String id = (String) session.getAttribute("LOGIN_OWNER_ID"); + + if (id == null) { // 로그인 상태가 아닌 경우 + return new ResponseEntity( + UpdateOwnerResponse.NO_LOGIN, HttpStatus.UNAUTHORIZED); + } + + if (ownerService.getOwner(id, password) == null) { + return new ResponseEntity( + UpdateOwnerResponse.PASSWORD_MISMATCH, HttpStatus.UNAUTHORIZED); + } + + if (mail == null && tel == null) { // 변경하려는 정보가 둘 다 null일 경우 + return new ResponseEntity( + UpdateOwnerResponse.EMPTY_CONTENT, HttpStatus.BAD_REQUEST); + } + + DMLOperationError dmlOperationError = ownerService.updateOwnerMailAndTel(id, mail, tel); + if (dmlOperationError == DMLOperationError.SUCCESS) { + return new ResponseEntity( + UpdateOwnerResponse.SUCCESS, HttpStatus.OK); + } else { + log.error("Member mail and tel update ERROR : {}", updateRequest); + throw new RuntimeException("Member mail and tel update ERROR"); + } + } + + /** + * 사장 패스워드 변경. + * + * @param passwordResquest 변경전 패스워드, 변경할 패스워드을 담은 요청 객체 + * @param session 현재 사용자의 세션 + * @return + */ + @PatchMapping("password") + public ResponseEntity updatePassword( + @RequestBody UpdateOwnerPasswordRequest passwordResquest, HttpSession session) { + String id = (String) session.getAttribute("LOGIN_OWNER_ID"); + String password = passwordResquest.getPassword(); + String newPassword = passwordResquest.getNewPassword(); + + ResponseEntity responseEntity; + + + if (id == null) { // 비 로그인 상태 + responseEntity = new ResponseEntity( + UpdateOwnerResponse.NO_LOGIN, HttpStatus.UNAUTHORIZED); + } else if (password == null || newPassword == null) { // 비밀번호나 새 비밀번호를 입력하지 않은 경우 + responseEntity = new ResponseEntity( + UpdateOwnerResponse.EMPTY_PASSOWRD, HttpStatus.BAD_REQUEST); + } else if (ownerService.getOwner(id, password) == null) { // 아이디와 비밀번호 불일치 + responseEntity = new ResponseEntity( + UpdateOwnerResponse.PASSWORD_MISMATCH, HttpStatus.UNAUTHORIZED); + } else if (password.equals(newPassword)) { // 이전 패스워드와 동일한 경우 + responseEntity = new ResponseEntity( + UpdateOwnerResponse.PASSWORD_DUPLICATED, HttpStatus.CONFLICT); + } else { + DMLOperationError dmlOperationError = ownerService.updateOwnerPassword(id, newPassword); + + if (DMLOperationError.SUCCESS.equals(dmlOperationError)) { + responseEntity = new ResponseEntity( + UpdateOwnerResponse.SUCCESS, HttpStatus.OK); + } else { + log.error("Password Update Error {}", passwordResquest); + throw new RuntimeException("Password Update Error"); + } + + } + return responseEntity; + } + + + + // ============= Requset 객체 ================ + + @Setter + @Getter + private static class OwnerLoginRequest { + @NonNull + private String id; + @NonNull + private String password; + } + + @Setter + @Getter + private static class UpdateOwnerMailAndTelRequest { + @NonNull + private String password; + @NonNull + private String mail; + @NonNull + private String tel; + } + + @Setter + @Getter + private static class UpdateOwnerPasswordRequest { + @NonNull + private String password; + @NonNull + private String newPassword; + } + + + // ============ resopnse 객체 ===================== + + @Getter + @AllArgsConstructor + @RequiredArgsConstructor + private static class OwnerLoginResponse { + enum LoginStatus { + SUCCESS, FAIL, DELETED, ERROR + } + + @NonNull + private LoginStatus result; + private OwnerDTO ownerInfo; + + private static final OwnerLoginResponse FAIL = new OwnerLoginResponse(LoginStatus.FAIL); + private static final OwnerLoginResponse DELETED = new OwnerLoginResponse(LoginStatus.DELETED); + + private static OwnerLoginResponse success(OwnerDTO ownerInfo) { + return new OwnerLoginResponse(LoginStatus.SUCCESS, ownerInfo); + } + + } + + @Getter + @RequiredArgsConstructor + private static class UpdateOwnerResponse { + enum UpdateStatus { + SUCCESS, NO_LOGIN, EMPTY_CONTENT, EMPTY_PASSOWRD, PASSWORD_MISMATCH, PASSWORD_DUPLICATED + } + + @NonNull + private UpdateStatus result; + + private static final UpdateOwnerResponse SUCCESS = + new UpdateOwnerResponse(UpdateStatus.SUCCESS); + private static final UpdateOwnerResponse NO_LOGIN = + new UpdateOwnerResponse(UpdateStatus.NO_LOGIN); + private static final UpdateOwnerResponse EMPTY_CONTENT = + new UpdateOwnerResponse(UpdateStatus.EMPTY_CONTENT); + private static final UpdateOwnerResponse EMPTY_PASSOWRD = + new UpdateOwnerResponse(UpdateStatus.EMPTY_PASSOWRD); + private static final UpdateOwnerResponse PASSWORD_MISMATCH = + new UpdateOwnerResponse(UpdateStatus.PASSWORD_MISMATCH); + private static final UpdateOwnerResponse PASSWORD_DUPLICATED = + new UpdateOwnerResponse(UpdateStatus.PASSWORD_DUPLICATED); + } + + + @Getter + @RequiredArgsConstructor + private static class logoutResponse { + enum logoutStatus { + SUCCESS, NO_LOGIN + } + + @NonNull + private logoutStatus result; + + private static final logoutResponse SUCCESS = new logoutResponse(logoutStatus.SUCCESS); + private static final logoutResponse NO_LOGIN = new logoutResponse(logoutStatus.NO_LOGIN); + + } + } + + diff --git a/src/main/java/com/delfood/dto/OwnerDTO.java b/src/main/java/com/delfood/dto/OwnerDTO.java index 329fd9c..109037a 100644 --- a/src/main/java/com/delfood/dto/OwnerDTO.java +++ b/src/main/java/com/delfood/dto/OwnerDTO.java @@ -1,19 +1,23 @@ package com.delfood.dto; import java.time.LocalDateTime; + import lombok.Getter; import lombok.NonNull; import lombok.Setter; import lombok.ToString; -@Getter +import org.apache.ibatis.type.Alias; + +@Getter @Setter @ToString +@Alias("Owner") public class OwnerDTO { public enum Status { DEFAULT, DELETED } - + @NonNull private String id; @NonNull @@ -27,6 +31,6 @@ public enum Status { private LocalDateTime createdAt; private LocalDateTime updatedAt; private Status status; - - -} + + +} \ No newline at end of file diff --git a/src/main/java/com/delfood/mapper/MemberMapper.java b/src/main/java/com/delfood/mapper/MemberMapper.java index c3e7524..95cfb7e 100644 --- a/src/main/java/com/delfood/mapper/MemberMapper.java +++ b/src/main/java/com/delfood/mapper/MemberMapper.java @@ -21,4 +21,5 @@ public interface MemberMapper { int updateMemberAddress(String id, String address, String addressDetail); int idCheck(String id); + } diff --git a/src/main/java/com/delfood/mapper/OwnerMapper.java b/src/main/java/com/delfood/mapper/OwnerMapper.java index 89dfb74..ae44d52 100644 --- a/src/main/java/com/delfood/mapper/OwnerMapper.java +++ b/src/main/java/com/delfood/mapper/OwnerMapper.java @@ -1,8 +1,19 @@ package com.delfood.mapper; +import com.delfood.dto.OwnerDTO; + import org.springframework.stereotype.Repository; @Repository public interface OwnerMapper { + OwnerDTO findByIdAndPassword(String id, String password); + + OwnerDTO findById(String id); + + int updatePassword(String id, String password); + + int updateMailAndTel(String id, String mail, String tel); + + } diff --git a/src/main/java/com/delfood/service/OwnerService.java b/src/main/java/com/delfood/service/OwnerService.java index d7810cf..6af5da3 100644 --- a/src/main/java/com/delfood/service/OwnerService.java +++ b/src/main/java/com/delfood/service/OwnerService.java @@ -1,8 +1,86 @@ package com.delfood.service; +import com.delfood.dto.OwnerDTO; +import com.delfood.mapper.DMLOperationError; +import com.delfood.mapper.OwnerMapper; +import com.delfood.utils.SHA256Util; +import javax.management.RuntimeErrorException; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.interceptor.RollbackRuleAttribute; + @Service public class OwnerService { + @Autowired + private OwnerMapper ownerMapper; + + /** + * 사장 정보 조회. + * + * @param id 아이디 + * @param password 패스워드 + * @return id, name, mail, tel, createAt, updatedAt, status + */ + public OwnerDTO getOwner(String id, String password) { + String cryptoPassword = SHA256Util.encryptSHA256(password); + OwnerDTO ownerInfo = ownerMapper.findByIdAndPassword(id, cryptoPassword); + return ownerInfo; + } + + /** + * 사장 정보 조회. + * + * @param id 아이디 + * @return id, name, mail, tel, createAt, updatedAt, status + */ + public OwnerDTO getOwner(String id) { + return ownerMapper.findById(id); + } + + /** + * 사장 이메일, 전화번호 수정. + * + * @param id 아이디 + * @param mail 변경할 이메일 + * @param tel 변경할 전화번호 + * + * @return + */ + @Transactional(rollbackFor = RuntimeException.class) + public DMLOperationError updateOwnerMailAndTel(String id, String mail, String tel) { + int result = ownerMapper.updateMailAndTel(id, mail, tel); + if (result == 1) { + return DMLOperationError.SUCCESS; // 정상 수행 + } else if (result == 0) { + return DMLOperationError.NONE_CHANGED; // 데이터가 변경되지 않음 + } else { + throw new RuntimeException("password update error : " + DMLOperationError.TOO_MANY_CHANGED); + } + } + + /** + * 사장 비밀번호 수정. + * + * @param id 아이디 + * @param password 변경할 비밀번호 + * @return + */ + @Transactional(rollbackFor = RuntimeException.class) // runtimeException이 발생하면 rollback을 수행한다. + public DMLOperationError updateOwnerPassword(String id, String password) { + String cryptoPassword = SHA256Util.encryptSHA256(password); + int result = ownerMapper.updatePassword(id, cryptoPassword); + if (result == 1) { + return DMLOperationError.SUCCESS; + } else if (result == 0) { + return DMLOperationError.NONE_CHANGED; + } else { + throw new RuntimeException("password update error : " + DMLOperationError.TOO_MANY_CHANGED); + } + + } + + } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8b48434..e9dd540 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,19 +1,8 @@ # Server server.port=80 -# DB -spring.datasource.driver-class-name=org.mariadb.jdbc.Driver -mybatis.configuration.map-underscore-to-camel-case=true - # profile spring.profiles.active=local -# redis -spring.redis.lettuce.pool.max-active=10 -spring.redis.lettuce.pool.max-idle=10 -spring.redis.lettuce.pool.min-idle=2 -spring.redis.port=6379 -spring.redis.host=127.0.0.1 - # session spring.session.store-type=redis \ No newline at end of file diff --git a/src/main/resources/mybatis/mapper/owner.xml b/src/main/resources/mybatis/mapper/owner.xml index ee5747b..ff6389c 100644 --- a/src/main/resources/mybatis/mapper/owner.xml +++ b/src/main/resources/mybatis/mapper/owner.xml @@ -1,5 +1,37 @@ - + + + + + + + UPDATE OWNER + SET password = #{password} + WHERE id = #{id} + + + + UPDATE OWNER + SET + + mail = #{mail}, + + + tel = #{tel}, + + updated_at = NOW() + WHERE id = #{id} + + \ No newline at end of file