Skip to content

[FEAT] 2차 과제 구현 #11

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web:3.4.4'
implementation 'org.springframework.boot:spring-boot-starter-jdbc:3.4.4'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf:3.4.4'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'

implementation 'dev.akkinoc.spring.boot:logback-access-spring-boot-starter:4.5.1'

Expand All @@ -33,6 +34,7 @@ dependencies {

testImplementation 'org.springframework.boot:spring-boot-starter-test:3.4.4'
testImplementation 'io.rest-assured:rest-assured:5.5.1'

}

tasks.named('test') {
Expand Down
1 change: 1 addition & 0 deletions java-sprout 복사본
Submodule java-sprout 복사본 added at bfab66
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ public class RoomescapeApplication {
public static void main(String[] args) {
SpringApplication.run(RoomescapeApplication.class, args);
}
}
}
23 changes: 23 additions & 0 deletions src/main/java/com/yourssu/roomescape/WebConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.yourssu.roomescape;

import com.yourssu.roomescape.member.LoginMemberArgumentResolver;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class WebConfig implements WebMvcConfigurer {

private final LoginMemberArgumentResolver loginMemberArgumentResolver;

public WebConfig(LoginMemberArgumentResolver loginMemberArgumentResolver) {
this.loginMemberArgumentResolver = loginMemberArgumentResolver;
}

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(loginMemberArgumentResolver);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.yourssu.roomescape.member;

public class LoginCheckResponse {

private String name;

public LoginCheckResponse(String memberName) {
this.name = memberName;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}
8 changes: 8 additions & 0 deletions src/main/java/com/yourssu/roomescape/member/LoginMember.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.yourssu.roomescape.member;

import java.lang.annotation.*;

@Target(ElementType.PARAMETER) // 파라미터에 붙일 수 있음
@Retention(RetentionPolicy.RUNTIME) // 런타임에도 유지되어야 함
public @interface LoginMember {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.yourssu.roomescape.member;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

@Slf4j
@Component
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
private final TokenService tokenService;
private final MemberService memberService;

public LoginMemberArgumentResolver(TokenService tokenService, MemberService memberService) {
this.tokenService = tokenService;
this.memberService = memberService;
}

@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(LoginMember.class)
&& parameter.getParameterType().equals(LoginMemberInfo.class);
}


@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory){
log.info("✅ LoginMemberArgumentResolver is called!");
HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
Long memberId = tokenService.getMemberIdFromRequest(request);
Member member = memberService.findByMemberId(memberId);
return new LoginMemberInfo(member.getId(), member.getName(), member.getEmail(), member.getRole());
}
}
33 changes: 33 additions & 0 deletions src/main/java/com/yourssu/roomescape/member/LoginMemberInfo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.yourssu.roomescape.member;

public class LoginMemberInfo {

private Long id;
private String name;
private String email;
private String role;

public LoginMemberInfo(Long id, String name, String email, String role) {
this.id = id;
this.name = name;
this.email = email;
this.role = role;
}

// Getter만 필요하면 이 정도면 충분해
public Long getId() {
return id;
}

public String getName() {
return name;
}

public String getEmail() {
return email;
}

public String getRole() {
return role;
}
}
68 changes: 65 additions & 3 deletions src/main/java/com/yourssu/roomescape/member/MemberController.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
package com.yourssu.roomescape.member;

import com.yourssu.roomescape.reservation.Reservation;
import com.yourssu.roomescape.reservation.ReservationRequest;
import com.yourssu.roomescape.reservation.ReservationResponse;
import com.yourssu.roomescape.reservation.ReservationService;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
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;
Expand All @@ -12,9 +20,13 @@
@RestController
public class MemberController {
private MemberService memberService;
private HttpServletResponse response;
private TokenService tokenService;
private ReservationService reservationService;

public MemberController(MemberService memberService) {
public MemberController(MemberService memberService, TokenService tokenService) {
this.memberService = memberService;
this.tokenService = tokenService;
}

@PostMapping("/members")
Expand All @@ -23,13 +35,63 @@ public ResponseEntity createMember(@RequestBody MemberRequest memberRequest) {
return ResponseEntity.created(URI.create("/members/" + member.getId())).body(member);
}

// 토큰 생성 후 쿠키 생성해서 반환하는 부분
@PostMapping("/login")
public ResponseEntity<String> login(@RequestBody MemberRequest memberRequest, HttpServletResponse response) {
String email = memberRequest.getEmail();
String password = memberRequest.getPassword();
MemberResponse member = new MemberResponse(memberService.findByEmailAndPassword(email, password));
// 토큰 생성부분
String secretKey = "Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E=";
String accessToken = Jwts.builder().setSubject(member.getId().toString()).claim("email", member.getEmail()).claim("password", member.getPassword()).signWith(Keys.hmacShaKeyFor(secretKey.getBytes())).compact();

// 쿠키 생성부분
Cookie cookie = new Cookie("token", accessToken);
cookie.setHttpOnly(true);
cookie.setPath("/");
response.addCookie(cookie);
return ResponseEntity.ok().build();
}

@PostMapping("/logout")
public ResponseEntity logout(HttpServletResponse response) {
Cookie cookie = new Cookie("token", "");
cookie.setHttpOnly(true);
cookie.setPath("/");
cookie.setMaxAge(0);
response.addCookie(cookie);
return ResponseEntity.ok().build();

return ResponseEntity.ok("로그인 성공");
}

@GetMapping("/login/check")
public ResponseEntity<MemberResponse> checkLogin(HttpServletRequest request){
try {
Long memberId = tokenService.getMemberIdFromRequest(request);
Member member = memberService.findByMemberId(memberId);

MemberResponse memberResponse = new MemberResponse(
member.getId(),
member.getName(),
member.getEmail(),
member.getRole()
);
return ResponseEntity.ok(memberResponse);
} catch (Exception e) {
return ResponseEntity.status(401).build();
}
}
}

// @PostMapping("/reservations")
// public ResponseEntity<?> create(@RequestBody ReservationRequest request, @LoginMember LoginMemberInfo loginMember){
// Member member;
// if(request.getName() != null && !request.getName().isBlank()){
// member = memberService.findByName(request.getName());
// } else {
// member = memberService.findByMemberId(loginMember.getId());
// }
//
// ReservationResponse reservation = reservationService.save(request);
// return ResponseEntity.created(URI.create("/reservations/" + reservation.getId()))
// .body(reservation);
// }
85 changes: 85 additions & 0 deletions src/main/java/com/yourssu/roomescape/member/MemberDao.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,89 @@ public Member findByName(String name) {
name
);
}

public Member findByMemberId(Long memberId){
return jdbcTemplate.queryForObject(
"SELECT id, name, email, role FROM member WHERE id = ?",
(rs, rowNum) -> new Member(
rs.getLong("id"),
rs.getString("name"),
rs.getString("email"),
rs.getString("role")
),
memberId
);
}
}



moru
package com.yourssu.roomescape.member;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.stereotype.Repository;

@Repository
public class MemberDao {
private JdbcTemplate jdbcTemplate;

public MemberDao(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}

public Member save(Member member) {
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(connection -> {
var ps = connection.prepareStatement("INSERT INTO member(name, email, password, role) VALUES (?, ?, ?, ?)", new String[]{"id"});
ps.setString(1, member.getName());
ps.setString(2, member.getEmail());
ps.setString(3, member.getPassword());
ps.setString(4, member.getRole());
return ps;
}, keyHolder);

return new Member(keyHolder.getKey().longValue(), member.getName(), member.getEmail(), "USER");
}

public Member findByEmailAndPassword(String email, String password) {
return jdbcTemplate.queryForObject(
"SELECT id, name, email, role FROM member WHERE email = ? AND password = ?",
(rs, rowNum) -> new Member(
rs.getLong("id"),
rs.getString("name"),
rs.getString("email"),
rs.getString("role")
),
email, password
);
}

public Member findByName(String name) {
return jdbcTemplate.queryForObject(
"SELECT id, name, email, role FROM member WHERE name = ?",
(rs, rowNum) -> new Member(
rs.getLong("id"),
rs.getString("name"),
rs.getString("email"),
rs.getString("role")
),
name
);
}

public Member findByEmail(String email) {
return jdbcTemplate.queryForObject(
"SELECT id, name, email, role FROM member WHERE email = ?",
(rs, rowNum) -> new Member(
rs.getLong("id"),
rs.getString("name"),
rs.getString("email"),
rs.getString("role")
),
email
);
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/yourssu/roomescape/member/MemberRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.yourssu.roomescape.member;

import org.springframework.data.jpa.repository.JpaRepository;

public interface MemberRepository extends JpaRepository<Member, Long> {
Member findByEmailAndPassword(String email, String password);

Member findByName(String name);

Member findByEmail(String email);
}
Loading