diff --git a/build.gradle b/build.gradle index 57267157c..07f0d14cb 100644 --- a/build.gradle +++ b/build.gradle @@ -14,8 +14,19 @@ repositories { dependencies { implementation 'org.springframework.boot:spring-boot-starter' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'io.rest-assured:rest-assured:5.3.1' + // DB + implementation 'org.springframework.boot:spring-boot-starter-jdbc' + runtimeOnly 'com.h2database:h2' + + //jwt + implementation 'io.jsonwebtoken:jjwt:0.9.1' + implementation 'javax.xml.bind:jaxb-api:2.3.1' + } test { diff --git a/src/main/java/Hello/Hello.java b/src/main/java/Hello/Hello.java new file mode 100644 index 000000000..90590d808 --- /dev/null +++ b/src/main/java/Hello/Hello.java @@ -0,0 +1,30 @@ +package Hello; + +public class Hello { + String name; + Printer printer; + + public Hello() { + } + + public Hello(String name, Printer printer) { + this.name = name; + this.printer = printer; + } + + public void setName(String name) { + this.name = name; + } + + public void setPrinter(Printer printer) { + this.printer = printer; + } + + public String sayHello() { + return "Hello " + this.name; + } + + public void print() { + this.printer.print(sayHello()); + } +} diff --git a/src/main/java/Hello/Printer.java b/src/main/java/Hello/Printer.java new file mode 100644 index 000000000..19f7cbc82 --- /dev/null +++ b/src/main/java/Hello/Printer.java @@ -0,0 +1,8 @@ +package Hello; + +public class Printer { + + public void print(String data) { + System.out.println(data); + } +} diff --git a/src/main/java/Hello/StringPrinter.java b/src/main/java/Hello/StringPrinter.java new file mode 100644 index 000000000..fe2267f20 --- /dev/null +++ b/src/main/java/Hello/StringPrinter.java @@ -0,0 +1,5 @@ +package Hello; + +public class StringPrinter extends Printer{ + +} diff --git a/src/main/java/jdbctest/Customer.java b/src/main/java/jdbctest/Customer.java new file mode 100644 index 000000000..ae2eb9bad --- /dev/null +++ b/src/main/java/jdbctest/Customer.java @@ -0,0 +1,25 @@ +package jdbctest; + +public class Customer { + private long id; + private String firstName; + private String lastName; + + public Customer(long id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + public long getId() { + return id; + } + + public String getFirstName() { + return firstName; + } + + public String getLastName() { + return lastName; + } +} diff --git a/src/main/java/jdbctest/CustomerController.java b/src/main/java/jdbctest/CustomerController.java new file mode 100644 index 000000000..7e981b263 --- /dev/null +++ b/src/main/java/jdbctest/CustomerController.java @@ -0,0 +1,41 @@ +package jdbctest; + +import org.springframework.http.ResponseEntity; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +public class CustomerController { + private JdbcTemplate jdbcTemplate; + + public CustomerController(JdbcTemplate jdbcTemplate) { + this.jdbcTemplate = jdbcTemplate; + } + + @PostMapping("/customers") + public ResponseEntity save(@RequestBody Customer customer) { + String sql = "INSERT INTO customers(first_name, last_name) VALUES (?,?)"; + jdbcTemplate.update(sql, customer.getFirstName(), customer.getLastName()); + return ResponseEntity.ok().build(); + } + + @GetMapping("/customers") + public ResponseEntity> list() { + String sql = "select id, first_name, last_name from customers"; + List customers = jdbcTemplate.query( + sql, (resultSet, rowNum) -> { + Customer customer = new Customer( + resultSet.getLong("id"), + resultSet.getString("first_name"), + resultSet.getString("last_name") + ); + return customer; + }); + return ResponseEntity.ok().body(customers); + } +} diff --git a/src/main/java/jdbctest/DemoApplication.java b/src/main/java/jdbctest/DemoApplication.java new file mode 100644 index 000000000..2aa213315 --- /dev/null +++ b/src/main/java/jdbctest/DemoApplication.java @@ -0,0 +1,35 @@ +package jdbctest; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.jdbc.core.JdbcTemplate; + +@SpringBootApplication +public class DemoApplication implements CommandLineRunner { + + public static void main(String args[]) { + SpringApplication.run(DemoApplication.class, args); + } + + @Autowired + JdbcTemplate jdbcTemplate; + + @Override + public void run(String... strings) throws Exception { + + jdbcTemplate.execute("DROP TABLE customers IF EXISTS"); + jdbcTemplate.execute("CREATE TABLE customers(id SERIAL, first_name VARCHAR(255), last_name VARCHAR(255))"); + + List splitUpNames = Arrays.asList("John Woo", "Jeff Dean", "Josh Bloch", "Josh Long").stream() + .map(name -> name.split(" ")) + .collect(Collectors.toList()); + + jdbcTemplate.batchUpdate("INSERT INTO customers(first_name, last_name) VALUES (?,?)", splitUpNames); + + } +} diff --git a/src/main/java/roomescape/Domains/Auth/LoginController.java b/src/main/java/roomescape/Domains/Auth/LoginController.java new file mode 100644 index 000000000..41019f622 --- /dev/null +++ b/src/main/java/roomescape/Domains/Auth/LoginController.java @@ -0,0 +1,65 @@ +package roomescape.Domains.Auth; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import java.util.Date; +import java.util.Map; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class LoginController { + + final private String secretKey = "Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E="; + private final UserRepository userRepository; + + public LoginController(final UserRepository userRepository) { + this.userRepository = userRepository; + } + + @PostMapping("/login") + public final ResponseEntity login(@RequestBody Map credentials) { + String password = credentials.get("password"); + String email = credentials.get("email"); + String name = "어드민"; + + this.userRepository.save(new User(name, email, password)); + + Claims claims = Jwts.claims().setSubject(name); + + Date now = new Date(); + Date expiryDate = new Date(now.getTime() + 1000L * 60 * 60); // 토큰 만료 시간: 1시간 후 + + String accessToken = Jwts.builder().setClaims(claims).setIssuedAt(now).setExpiration(expiryDate) + .signWith(SignatureAlgorithm.HS256, secretKey).compact(); + + return ResponseEntity.ok().header("Set-Cookie", "token=" + accessToken + ";").build(); + } + + @GetMapping("/login/check") + public final ResponseEntity> loginCheck(HttpServletRequest request) { + Cookie[] cookies = request.getCookies(); + String token = getToken(cookies); + String memberName = String.valueOf(Jwts.parser() + .setSigningKey(secretKey) + .parseClaimsJws(token) + .getBody().getSubject()); + return ResponseEntity.ok().body(Map.of("name", memberName)); + } + + private static String getToken(final Cookie[] cookies) { + for (Cookie cookie : cookies) { + if (cookie.getName().equals("token")) { + return cookie.getValue(); + } + } + return ""; + } + +} diff --git a/src/main/java/roomescape/Domains/Auth/User.java b/src/main/java/roomescape/Domains/Auth/User.java new file mode 100644 index 000000000..6ee64a63a --- /dev/null +++ b/src/main/java/roomescape/Domains/Auth/User.java @@ -0,0 +1,49 @@ +package roomescape.Domains.Auth; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import roomescape.Domains.Time.Time; + +@Entity +@Table(name = "customer") +public class User { + + protected User() { + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + private String email; + private String password; + + public User(final String name,final String email, final String password) { + this.name = name; + this.email = email; + this.password = password; + } + + public Long getId() { + return id; + } + + public String getName() { + return name; + } + + public String getEmail() { + return email; + } + + public String getPassword() { + return password; + } + +} diff --git a/src/main/java/roomescape/Domains/Auth/UserRepository.java b/src/main/java/roomescape/Domains/Auth/UserRepository.java new file mode 100644 index 000000000..562c8cc58 --- /dev/null +++ b/src/main/java/roomescape/Domains/Auth/UserRepository.java @@ -0,0 +1,7 @@ +package roomescape.Domains.Auth; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UserRepository extends JpaRepository { + +} diff --git a/src/main/java/roomescape/Domains/Reservation/Reservation.java b/src/main/java/roomescape/Domains/Reservation/Reservation.java new file mode 100644 index 000000000..6922c5fd7 --- /dev/null +++ b/src/main/java/roomescape/Domains/Reservation/Reservation.java @@ -0,0 +1,55 @@ +package roomescape.Domains.Reservation; + +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.OneToOne; +import roomescape.Domains.Time.Time; + +@Entity +public class Reservation { + + protected Reservation() { + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + private String date; + @ManyToOne + @JoinColumn(name = "time_id") + private Time time; + + public Reservation(final String name, final String date, final Time time) { + this.name = name; + this.date = date; + this.time = time; + } + + public Long getId() { + return id; + } + + public Time getTime() { + return time; + } + + + public String getName() { + return name; + } + + public String getDate() { + return date; + } + + public void setId(final Long id) { + this.id = id; + } +} diff --git a/src/main/java/roomescape/Domains/Reservation/ReservationApiController.java b/src/main/java/roomescape/Domains/Reservation/ReservationApiController.java new file mode 100644 index 000000000..c6a60d515 --- /dev/null +++ b/src/main/java/roomescape/Domains/Reservation/ReservationApiController.java @@ -0,0 +1,52 @@ +package roomescape.Domains.Reservation; + +import java.net.URI; +import java.util.List; +import java.util.Objects; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import roomescape.exceptions.BadRequestException; + +@RestController +public class ReservationApiController { + + private final ReservationService reservationService; + + public ReservationApiController(final ReservationService reservationService) { + this.reservationService = reservationService; + } + + + @GetMapping("/reservations") + public ResponseEntity> getReservations() { + List reservations = reservationService.list(); + + return ResponseEntity.ok().body(reservations); + } + + @PostMapping("/reservations") + public ResponseEntity create(@RequestBody ReservationStoreRequestDto requestDto) { + if (Objects.isNull(requestDto.date()) || requestDto.date().isEmpty() || + Objects.isNull(requestDto.time()) || requestDto.time().isEmpty() || + Objects.isNull(requestDto.name()) || requestDto.name().isEmpty()) { + throw new BadRequestException("올바르지 않은 입력입니다."); + } + Reservation reservation = reservationService.create(requestDto); + + return ResponseEntity.created(URI.create("/reservations/" + reservation.getId())) + .body(reservation); + } + + @DeleteMapping("/reservations/{id}") + public ResponseEntity delete(@PathVariable Long id) { + reservationService.deleteByIdOrElseThrowException(id); + + return ResponseEntity.noContent().build(); + } +} diff --git a/src/main/java/roomescape/Domains/Reservation/ReservationController.java b/src/main/java/roomescape/Domains/Reservation/ReservationController.java new file mode 100644 index 000000000..8bbbd03cb --- /dev/null +++ b/src/main/java/roomescape/Domains/Reservation/ReservationController.java @@ -0,0 +1,13 @@ +package roomescape.Domains.Reservation; + +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; + +@Controller +public class ReservationController { + + @GetMapping("/reservation") + public String index() { + return "new-reservation"; + } +} diff --git a/src/main/java/roomescape/Domains/Reservation/ReservationRepository.java b/src/main/java/roomescape/Domains/Reservation/ReservationRepository.java new file mode 100644 index 000000000..f29689e4f --- /dev/null +++ b/src/main/java/roomescape/Domains/Reservation/ReservationRepository.java @@ -0,0 +1,7 @@ +package roomescape.Domains.Reservation; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReservationRepository extends JpaRepository { + Reservation findByName(String name); +} diff --git a/src/main/java/roomescape/Domains/Reservation/ReservationService.java b/src/main/java/roomescape/Domains/Reservation/ReservationService.java new file mode 100644 index 000000000..7a61e5ff0 --- /dev/null +++ b/src/main/java/roomescape/Domains/Reservation/ReservationService.java @@ -0,0 +1,39 @@ +package roomescape.Domains.Reservation; + +import java.util.List; +import org.springframework.stereotype.Service; +import roomescape.Domains.Time.Time; +import roomescape.Domains.Time.TimeRepository; +import roomescape.exceptions.BadRequestException; + +@Service +public class ReservationService { + + private final TimeRepository timeRepository; + private final ReservationRepository reservationRepository; + + public ReservationService( + final TimeRepository timeRepository, + final ReservationRepository reservationRepository) { + this.timeRepository = timeRepository; + this.reservationRepository = reservationRepository; + } + + public Reservation create(ReservationStoreRequestDto requestDto) { + Time time = timeRepository.findFirstByTime(requestDto.time()) + .orElseThrow(() -> new BadRequestException("존재하지 않는 시간입니다.")); + + return reservationRepository.save( + new Reservation(requestDto.name(), requestDto.date(), time)); + } + + public List list() { + return this.reservationRepository.findAll(); + } + + public void deleteByIdOrElseThrowException(Long id) { + Reservation reservation = this.reservationRepository.findById(id) + .orElseThrow(() -> new BadRequestException("존재하지 않는 예약입니다.")); + this.reservationRepository.delete(reservation); + } +} diff --git a/src/main/java/roomescape/Domains/Reservation/ReservationStoreRequestDto.java b/src/main/java/roomescape/Domains/Reservation/ReservationStoreRequestDto.java new file mode 100644 index 000000000..c516af515 --- /dev/null +++ b/src/main/java/roomescape/Domains/Reservation/ReservationStoreRequestDto.java @@ -0,0 +1,10 @@ +package roomescape.Domains.Reservation; + +import org.springframework.lang.NonNull; + +public record ReservationStoreRequestDto( + String date, + String time, + String name +) { +} diff --git a/src/main/java/roomescape/Domains/Time/Time.java b/src/main/java/roomescape/Domains/Time/Time.java new file mode 100644 index 000000000..dc1d581d5 --- /dev/null +++ b/src/main/java/roomescape/Domains/Time/Time.java @@ -0,0 +1,23 @@ +package roomescape.Domains.Time; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity +public class Time { + + public Time() { + } + + public Time(String time) { + this.time = time; + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String time; +} diff --git a/src/main/java/roomescape/Domains/Time/TimeApiController.java b/src/main/java/roomescape/Domains/Time/TimeApiController.java new file mode 100644 index 000000000..6164d912f --- /dev/null +++ b/src/main/java/roomescape/Domains/Time/TimeApiController.java @@ -0,0 +1,42 @@ +package roomescape.Domains.Time; + +import java.net.URI; +import java.util.List; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TimeApiController { + + private final TimeService timeService; + + public TimeApiController(TimeService timeService) { + this.timeService = timeService; + } + + @GetMapping("/times") + public ResponseEntity> index() { + List