Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
dcd55a7
Feat: SecurityUser implements UserDetails
kkho9654 Apr 21, 2024
5c21b5c
Feat: UserDetailService
kkho9654 Apr 21, 2024
9bbadb0
Feat: jwt token entity, 발급자, security key
kkho9654 Apr 21, 2024
6fe82e4
Feat: jwt token provider
kkho9654 Apr 21, 2024
aa2c801
Feat: UserAuthenticationProvider for login
kkho9654 Apr 21, 2024
86a6902
Feat: refresh token
kkho9654 Apr 21, 2024
c09eff3
Feat: jwt authentication filter
kkho9654 Apr 21, 2024
c2661f7
Feat: security config
kkho9654 Apr 21, 2024
2d5e164
➕Chore: jwt dependency
kkho9654 Apr 21, 2024
35cbcbb
✨Feat: jwt application properties
kkho9654 Apr 21, 2024
e4dfd5a
✨Feat: BCryptPasswordEncoder bean
kkho9654 Apr 23, 2024
a559ab7
:recycle:Refactor : User addresses column 삭제
kkho9654 Apr 24, 2024
c1e65aa
:heavy_plus_sign: Chore: jwt & security dependency
kkho9654 Apr 26, 2024
620d806
:sparkles: Feat: JwtToken Provider
kkho9654 Apr 26, 2024
126e60b
:sparkles: Feat: RefreshToken entity
kkho9654 Apr 26, 2024
1f7b847
:sparkles: Feat: JWT AuthenticationFilter
kkho9654 Apr 26, 2024
269aa51
:sparkles: Feat: User Authentication
kkho9654 Apr 26, 2024
3a9cb02
:sparkles: Feat: User Details Service
kkho9654 Apr 26, 2024
e5fea96
:sparkles: Feat: Security Configuration
kkho9654 Apr 26, 2024
c8240fc
:poop:
kkho9654 Apr 26, 2024
89340d0
✨Feat: Authentication Controller
kkho9654 Apr 28, 2024
348b2ea
✨Feat: Authentication Service
kkho9654 Apr 28, 2024
9be0672
:art: Rename: Authentication package structure
kkho9654 Apr 28, 2024
7d8c6c0
:goal_net: Feat: InvalidTokenException
kkho9654 Apr 28, 2024
603126b
:recycle: Style: remove print, unused dependency
kkho9654 Apr 28, 2024
7677e0f
:recycle: Style: remove print, unused dependency
kkho9654 Apr 28, 2024
e795e40
:coffin: Refactor: move login logic User to Auth
kkho9654 Apr 28, 2024
19c93fa
:recycle: Refactor: User table name
kkho9654 Apr 28, 2024
919cfd9
:sparkles: Feat: Auth token DTO
kkho9654 Apr 28, 2024
21f0e67
:wrench: Feat: security configuration
kkho9654 Apr 28, 2024
accca65
remove: .gitkeep
kkho9654 Apr 28, 2024
a5c3e68
:art: Refactor: refresh token 을 http only cookie에 넣는다.
kkho9654 Apr 29, 2024
17a93ed
:white_check_mark: Test: UserService Unit Test
kkho9654 May 2, 2024
e2cb3f9
:bug: Fix: Auth login request
kkho9654 May 2, 2024
3d9c295
:sparkles: Feat: swagger authentication
kkho9654 May 2, 2024
a25d7e7
:recycle: Refactor: user, address entity
kkho9654 May 2, 2024
94b4382
:recycle: Feat: user createdAt
kkho9654 May 2, 2024
85f5408
:art: Feat: user authority via user type
kkho9654 May 3, 2024
1491c1c
:recycle: Refactor: user update controller, service method include id
kkho9654 May 3, 2024
85fd6e4
:mute: Delete: println
kkho9654 May 3, 2024
4d9a261
:bug: Fix: 권한이 없을 때 default buyer 권한
kkho9654 May 3, 2024
c723ed1
:bug: Fix: User mapper 를 위한 setter
kkho9654 May 3, 2024
16a4681
:art: Fix: 유저 삭제시 관련 refresh토큰 삭제
kkho9654 May 3, 2024
5e4a39a
:art: Fix: 유저 email update 불가능
kkho9654 May 3, 2024
cc737ee
:art: Refactor: user id Long to UUID
kkho9654 May 7, 2024
856e362
:bug: Fix: password encode when updating
kkho9654 May 7, 2024
4074a16
:white_check_mark: Test: update user service test
kkho9654 May 7, 2024
7ba3477
:fire: Refactor: unused success handler
kkho9654 May 8, 2024
4639c4e
:recycle: Refactor: UsernamePasswordAuthenticationFilter
kkho9654 May 8, 2024
09f3b80
:art: Feat: 생성자
kkho9654 May 8, 2024
88a149c
:memo: Docs: 인증 관련 java docs
kkho9654 May 8, 2024
d40bdca
:bug: Fix: invalid access token return 403 -> 401
kkho9654 May 8, 2024
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
8 changes: 7 additions & 1 deletion spring-boot-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@ repositories {

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
// implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
// security
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'io.jsonwebtoken:jjwt:0.9.1'
// https://mvnrepository.com/artifact/javax.xml.bind/jaxb-api
implementation group: 'javax.xml.bind', name: 'jaxb-api', version: '2.1'


// for swagger
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.4'
runtimeOnly 'com.mysql:mysql-connector-j'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.UUID;

@RestController
@RequestMapping("/api/v1/users")
@RequiredArgsConstructor
Expand All @@ -29,21 +31,21 @@ public ResponseEntity<UserSignUpResponse> signUp(@RequestBody UserSignUpRequest
@GetMapping("/{id}")
@ToException
@Operation(summary = "회원 정보", description = "유저정보 얻을 때 사용하는 API")
public ResponseEntity<UserInfoResponse> getInfo(@PathVariable Long id){
public ResponseEntity<UserInfoResponse> getInfo(@PathVariable UUID id){
return ResponseEntity.status(HttpStatus.ACCEPTED).body(userService.getUserInfo(id));
}

@PatchMapping
@PatchMapping("/{id}")
@ToException
@Operation(summary = "회원 정보 수정", description = "회원 정보 수정 할 때 사용하는 API")
public ResponseEntity<UserUpdateResponse> update(@RequestBody UserUpdateRequest userUpdateRequest){
return ResponseEntity.status(HttpStatus.OK).body(userService.updateUserInfo(userUpdateRequest));
public ResponseEntity<UserUpdateResponse> update(@PathVariable(name = "id", required = true) UUID id, @RequestBody UserUpdateRequest userUpdateRequest){
return ResponseEntity.status(HttpStatus.OK).body(userService.updateUserInfo(id, userUpdateRequest));
}

@DeleteMapping("/{id}")
@ToException
@Operation(summary = "회원 탈퇴", description = "회원 탈퇴 할 때 사용하는 API")
public ResponseEntity<Boolean> remove(@PathVariable Long id){
public ResponseEntity<Boolean> remove(@PathVariable UUID id){
userService.removeUser(id);
return ResponseEntity.status(HttpStatus.OK).build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@
import com.ssafy.springbootapi.domain.user.dto.*;
import com.ssafy.springbootapi.domain.user.exception.UserDuplicatedException;
import com.ssafy.springbootapi.domain.user.exception.UserNotFoundException;
import com.ssafy.springbootapi.global.auth.jwt.refreshToken.RefreshTokenRepository;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.UUID;

/*
* TODO:: 사용자 정의 exception
* - user not found exception
Expand All @@ -18,44 +22,62 @@
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository;
private final RefreshTokenRepository refreshTokenRepository;
private final UserMapper userMapper;
private final PasswordEncoder passwordEncoder;

public UserSignUpResponse signUp(UserSignUpRequest requestDTO){
if(userRepository.findByEmail(requestDTO.getEmail()).isPresent()){
throw new UserDuplicatedException(requestDTO.getEmail()+"이미 존재하는 사용자");
}
User user = userRepository.save(requestDTO.toEntity());
User user = userRepository.save(
User.builder()
.email(requestDTO.getEmail())
.password(passwordEncoder.encode(requestDTO.getPassword())) // password 암호화
.name(requestDTO.getName())
.addresses(null)
.build());

return UserSignUpResponse.builder()
.email(user.getEmail())
.name(user.getName())
.build();
}


public UserInfoResponse getUserInfo(Long id) {
public UserInfoResponse getUserInfo(UUID id) {
User user = userRepository.findById(id)
.orElseThrow(()->new UserNotFoundException(id+" 사용자 없음"));
return UserInfoResponse.builder()
.email(user.getEmail())
.name(user.getName())
.createdAt(user.getCreatedAt())
.addresses(user.getAddresses())
.build();
}

@Transactional
public UserUpdateResponse updateUserInfo(UserUpdateRequest requestDTO) {
User user = userRepository.findById(requestDTO.getId())
.orElseThrow(()->new UserNotFoundException(requestDTO.getEmail()+" 사용자 없음"));
public UserUpdateResponse updateUserInfo(UUID id, UserUpdateRequest requestDTO) {
User user = userRepository.findById(id)
.orElseThrow(()->new UserNotFoundException(id+" 사용자 없음"));

requestDTO.setPassword(passwordEncoder.encode(requestDTO.getPassword()));
userMapper.updateUserFromDto(requestDTO,user);

user = userRepository.save(user);

return UserUpdateResponse.builder().email(user.getEmail()).name(user.getName()).build();
return UserUpdateResponse.builder().email(user.getEmail()).name(user.getName()).createdAt(user.getCreatedAt()).build();
}

public void removeUser(Long id) {
@Transactional
public void removeUser(UUID id) {
User user = userRepository.findById(id)
.orElseThrow(()->new UserNotFoundException(id+" 사용자 없음"));

// refresh 토큰 삭제
refreshTokenRepository.findByUserId(id)
.ifPresent(refreshTokenRepository::delete);

userRepository.delete(user);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
import org.springframework.stereotype.Repository;

import java.util.Optional;
import java.util.UUID;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
public interface UserRepository extends JpaRepository<User, UUID> {
Optional<User> findByEmail(String email);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.ssafy.springbootapi.domain.user.domain;

import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
Expand All @@ -26,8 +27,9 @@ public class Address {
@Enumerated(EnumType.STRING)
private IsDefault isDefault;

@ManyToOne // optional true => nullable
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "id")
@JsonIgnore
private User user;

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
package com.ssafy.springbootapi.domain.user.domain;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.*;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.GenericGenerator;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;


/*
* TODO:: id to uuid
*/
@Entity
@Table(name = "users")
@Table(name = "user")
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
@Builder
@ToString
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
@Column(updatable = false, nullable = false)
private UUID id;
// @Id
// @GeneratedValue(strategy = GenerationType.IDENTITY)
// @Column(name = "id")
// private Long id;

@Column(name = "email", unique = true, nullable = false)
private String email;
Expand All @@ -33,18 +41,15 @@ public class User {
@Column(name = "name", unique = false, nullable = false)
private String name;

@OneToMany(mappedBy = "user")
@Column(name = "addresses" , nullable = true)
@Enumerated(EnumType.STRING)
@Column(name = "type", columnDefinition = "varchar(255) default 'BUYER'")
private UserType type = UserType.BUYER;

@Column(nullable = false, updatable = false)
@CreationTimestamp
private LocalDateTime createdAt;

@OneToMany(mappedBy = "user", fetch = FetchType.LAZY)
private List<Address> addresses;

@Override
public String toString() {
return "User{" +
"id=" + id +
", email='" + email + '\'' +
", password='" + password + '\'' +
", name='" + name + '\'' +
", addresses=" + addresses +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.ssafy.springbootapi.domain.user.domain;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum UserType {
ADMIN("ADMIN"),
BUYER("BUYER"),
SELLER("SELLER");

private String description;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import lombok.Builder;
import lombok.Getter;

import java.time.LocalDateTime;
import java.util.List;

@AllArgsConstructor
Expand All @@ -13,5 +14,7 @@
public class UserInfoResponse {
private String email;
private String name;
private LocalDateTime createdAt;
private List<Address> addresses;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.ssafy.springbootapi.domain.user.dto;

import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@NoArgsConstructor
@AllArgsConstructor
@Getter
@Setter
public class UserLoginRequest {

@NotBlank(message = "email is blank!")
public String email;

@NotBlank(message = "password is blank!")
public String password;

@Override
public String toString() {
return "UserSignUpRequestDTO{" +
"email='" + email + '\'' +
", password='" + password + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.ssafy.springbootapi.domain.user.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;

@AllArgsConstructor
@Getter
public class UserLoginResponse {
String accessToken;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;

@AllArgsConstructor
@Getter
public class UserSignUpRequest {

@NotBlank(message = "email is blank!")
public String email;

Expand All @@ -17,15 +20,6 @@ public class UserSignUpRequest {
@NotBlank(message = "name is blank!")
public String name;

public User toEntity(){
return User.builder()
.email(email)
.password(password)
.name(name)
.addresses(null)
.build();
}

@Override
public String toString() {
return "UserSignUpRequestDTO{" +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,12 @@
import jakarta.validation.constraints.NotBlank;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

@AllArgsConstructor
@Getter
@Setter
public class UserUpdateRequest {
@NotBlank(message = "id is blank!")
public Long id;
public String email;
public String password;
public String name;

@Override
public String toString() {
return "UserSignUpRequestDTO{" +
"email='" + email + '\'' +
", password='" + password + '\'' +
", name='" + name + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
import lombok.Builder;
import lombok.Getter;

import java.time.LocalDateTime;

@AllArgsConstructor
@Getter
@Builder
public class UserUpdateResponse {
private String email;
private String name;
private LocalDateTime createdAt;
}
Empty file.
Loading