-
Notifications
You must be signed in to change notification settings - Fork 13
Feat/week/4 #31
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
base: 김명성
Are you sure you want to change the base?
Feat/week/4 #31
Changes from all commits
071b8ff
4208540
9108967
e9ef3a4
812551b
58dec04
1f89a47
115e38d
ca4b499
063bc25
d085569
f82ab5c
2bd85da
b0a3c0f
878e021
3a15789
a7392c7
a6ad9dc
a84fe64
65901fe
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,3 +35,5 @@ out/ | |
|
|
||
| ### VS Code ### | ||
| .vscode/ | ||
|
|
||
| .env | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,12 @@ | |
| @Getter | ||
| @NoArgsConstructor | ||
| @AllArgsConstructor | ||
| @Table( | ||
| name = "heart", | ||
| indexes = { | ||
| @Index(name ="idx_heart_post_liked", columnList = "post_id , like_status") | ||
| } | ||
| ) | ||
|
Comment on lines
+14
to
+19
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 부분 생각을 좀 더 해봤는데, Heart 엔티티의 liked속성이 false라면 튜플이 존재하지 않는 상태랑 차이가 없을 것 같아요 그리고 index의 경우 속성이 중복되지 않을수록 이점이 큰데 현재는 like속성도 사실상 boolean이라 상태가 2가지밖에 없네요 그래서 제 생각에는 index를 아예 없애버리고 heart 객체가 존재 -> 좋아요, heart 객체가 없음 -> 좋아요 x 이렇게 구성하면 토글 로직도 간단하게 떨어질 것 같아요 |
||
| public class Heart { | ||
|
|
||
| @Id | ||
|
|
@@ -29,21 +35,15 @@ public class Heart { | |
| // 리포지터리에 메소드로 계산하면 되겠지? | ||
|
|
||
| @Column(name ="like_status", nullable = false) | ||
| @Enumerated(EnumType.STRING) | ||
| private LikeStatus like; | ||
| private boolean liked; | ||
|
|
||
| public Heart(Post post, Member member, LikeStatus heart) { | ||
| public Heart(Post post, Member member, boolean like) { | ||
| this.post = post; | ||
| this.member = member; | ||
| this.like = heart; | ||
| this.liked = like; | ||
| } | ||
|
|
||
| public void toggleLike() { | ||
|
|
||
| if (like == LikeStatus.LIKE) { | ||
| like = LikeStatus.NONE; | ||
| }else if(like == LikeStatus.NONE){ | ||
| like = LikeStatus.LIKE; | ||
| } | ||
| this.liked = !this.liked; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| package com.example.devSns.Jwt; | ||
|
|
||
| import io.jsonwebtoken.Jwts; | ||
| import io.jsonwebtoken.SignatureAlgorithm; | ||
| import org.springframework.beans.factory.annotation.Value; | ||
| import org.springframework.stereotype.Component; | ||
|
|
||
| import java.util.Date; | ||
|
|
||
| @Component | ||
| public class JwtUtil { | ||
|
|
||
|
|
||
| private final String secret;// 실제 프로젝트에서는 환경변수로 관리 | ||
| private final long EXPIRATION = 1000L * 60 * 60; // 1시간 | ||
|
|
||
| public JwtUtil(@Value("${jwt.secret}") String secret) { | ||
| this.secret = secret; | ||
| } | ||
|
Comment on lines
+14
to
+19
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 잘 구성해주셨네요! 다만 현재 구조에서는 1시간마다 재인증 해야 하는 구조라 리프레시 토큰도 추후에 도입해보면 좋을 것 같습니다! |
||
| public String createToken(Long memberId) { | ||
| Date now = new Date(); | ||
| Date expireTime = new Date(now.getTime() + EXPIRATION); | ||
|
|
||
| return Jwts.builder() | ||
| .setSubject(String.valueOf(memberId)) | ||
| .setIssuedAt(now) | ||
| .setExpiration(expireTime) | ||
| .signWith(SignatureAlgorithm.HS256, secret) | ||
| .compact(); | ||
| } | ||
|
|
||
| public boolean validateToken(String token) { | ||
| try { | ||
| Jwts.parser() | ||
| .setSigningKey(secret) | ||
| .parseClaimsJws(token); | ||
| return true; | ||
| } catch (Exception e) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| public Long extractMemberId(String token) { | ||
| return Long.valueOf( | ||
| Jwts.parser() | ||
| .setSigningKey(secret) | ||
| .parseClaimsJws(token) | ||
| .getBody() | ||
| .getSubject() | ||
| ); | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.example.devSns.Login; | ||
|
|
||
| import lombok.Data; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.web.bind.annotation.PostMapping; | ||
| import org.springframework.web.bind.annotation.RequestBody; | ||
| import org.springframework.web.bind.annotation.RequestMapping; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
|
|
||
| @RestController | ||
| @RequiredArgsConstructor | ||
| @RequestMapping("/auth") | ||
| public class LoginController { | ||
|
|
||
| private final LoginService loginService; | ||
|
|
||
| @PostMapping("/login") | ||
| public String login(@RequestBody LoginRequest request) { | ||
| return loginService.login(request.getEmail(), request.getPassword()); | ||
| } | ||
|
|
||
| @Data | ||
| static class LoginRequest { | ||
| private String email; | ||
| private String password; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| package com.example.devSns.Login; | ||
|
|
||
| import com.example.devSns.Jwt.JwtUtil; | ||
| import com.example.devSns.Member.Member; | ||
| import com.example.devSns.Member.MemberRepository; | ||
| import lombok.RequiredArgsConstructor; | ||
| import org.springframework.security.crypto.password.PasswordEncoder; | ||
| import org.springframework.stereotype.Service; | ||
| import org.springframework.transaction.annotation.Transactional; | ||
|
|
||
| @Service | ||
| @Transactional | ||
| @RequiredArgsConstructor | ||
| public class LoginService { | ||
|
|
||
| private final MemberRepository memberRepository; | ||
| private final PasswordEncoder passwordEncoder; | ||
| private final JwtUtil jwtUtil; | ||
|
|
||
| public String login(String email, String rawPassword) { | ||
|
|
||
| Member member = memberRepository.findByEmail(email) | ||
| .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 이메일입니다.")); | ||
|
|
||
| if (!passwordEncoder.matches(rawPassword, member.getPassword())) { | ||
| throw new IllegalArgumentException("비밀번호가 일치하지 않습니다."); | ||
| } | ||
|
|
||
| // JWT 발급 | ||
| return jwtUtil.createToken(member.getId()); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,28 +2,29 @@ | |
|
|
||
| import com.example.devSns.Member.Gender; | ||
| import com.example.devSns.Member.Member; | ||
| import jakarta.validation.constraints.Email; | ||
| import jakarta.validation.constraints.NotBlank; | ||
| import jakarta.validation.constraints.NotNull; | ||
| import jakarta.validation.constraints.Size; | ||
| import jakarta.validation.constraints.*; | ||
|
|
||
| public record SignMemberRequestDto( | ||
|
|
||
| @NotBlank(message = "공백 또는 null 값은 허용하지 않습니다") | ||
| @NotBlank(message = "이름은 공백 또는 null 값은 허용하지 않습니다") | ||
| String nickname, | ||
|
|
||
| @NotBlank(message = "공백 또는 null 값은 허용하지 않습니다") | ||
| @NotBlank(message = "이메일은 공백 또는 null 값은 허용하지 않습니다") | ||
| @Email(message ="올바른 이메일 양식이 아닙니다") | ||
| String email, | ||
|
|
||
| @NotBlank(message = "공백 또는 null 값은 허용하지 않습니다") | ||
| @NotBlank(message = "비밀번호는 공백 또는 null 값은 허용하지 않습니다") | ||
|
Comment on lines
+12
to
+16
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 좋습니다! message 옵션 상세히 적어둬야 나중에 프론트분들과 협업할 때 좋은 것 같더라고요 |
||
| @Size(min = 8, max =16, message = "비밀번호는 8자 이상 16자 이하로 설정해주세요") | ||
| @Pattern( | ||
| regexp = "^(?=.*[A-Za-z])(?=.*\\d)(?=.*[@$!%*#?&])[A-Za-z\\d@$!%*#?&]+$", | ||
| message = "영어, 숫자, 특수문자를 각각 최소 1개 이상 포함해야 합니다" | ||
| ) | ||
| String password, | ||
|
|
||
| @NotNull(message = "공백 또는 null 값은 허용하지 않습니다") | ||
| @NotNull(message = "성별은 공백 또는 null 값은 허용하지 않습니다") | ||
| Gender gender, | ||
|
|
||
| @NotNull(message = "공백 또는 null 값은 허용하지 않습니다") | ||
| @NotNull(message = "나이는 공백 또는 null 값은 허용하지 않습니다") | ||
| Integer age | ||
|
|
||
| ) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
피드백 반영 좋습니다!