Skip to content
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
12 changes: 12 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,18 @@ dependencies {

// Testing
testImplementation 'org.springframework.book:spring-boo-starter-test'

// thymeleaf
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6:3.1.1.RELEASE'

// spring security
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'

// oauth2
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'

}

sourceSets {
Expand Down
4 changes: 4 additions & 0 deletions src/main/generated/umc/spring/domain/QMember.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,16 @@ public class QMember extends EntityPathBase<Member> {

public final StringPath name = createString("name");

public final StringPath password = createString("password");

public final StringPath phoneNumber = createString("phoneNumber");

public final NumberPath<Integer> point = createNumber("point", Integer.class);

public final ListPath<Review, QReview> reviewList = this.<Review, QReview>createList("reviewList", Review.class, QReview.class, PathInits.DIRECT2);

public final EnumPath<umc.spring.domain.enums.Role> role = createEnum("role", umc.spring.domain.enums.Role.class);

public final EnumPath<umc.spring.domain.enums.SocialType> socialType = createEnum("socialType", umc.spring.domain.enums.SocialType.class);

public final StringPath specAddress = createString("specAddress");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public class QMemberMission extends EntityPathBase<MemberMission> {

public final umc.spring.domain.QMission mission;

public final EnumPath<MissionStatus> status = createEnum("status", MissionStatus.class);
public final EnumPath<umc.spring.domain.enums.MissionStatus> status = createEnum("status", umc.spring.domain.enums.MissionStatus.class);

//inherited
public final DateTimePath<java.time.LocalDateTime> updatedAt = _super.updatedAt;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package umc.spring.config.security;

import lombok.RequiredArgsConstructor;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.DefaultOAuth2User;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;
import umc.spring.domain.Member;
import umc.spring.domain.enums.Gender;
import umc.spring.domain.enums.Role;
import umc.spring.repository.MemberRepository.MemberRepository;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Service
@RequiredArgsConstructor
public class CustomOAuth2UserService extends DefaultOAuth2UserService {

private final MemberRepository memberRepository;
private final PasswordEncoder passwordEncoder;

@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = super.loadUser(userRequest);

Map<String, Object> attributes = oAuth2User.getAttributes();
Map<String, Object> properties = (Map<String, Object>) attributes.get("properties");

String nickname = (String) properties.get("nickname");
String email = nickname + "@kakao.com"; // 임시 이메일 생성

// 사용자 정보 저장 또는 업데이트
Member member = saveOrUpdateUser(email, nickname);

// 이메일을 Principal로 사용하기 위해 attributes 수정
Map<String, Object> modifiedAttributes = new HashMap<>(attributes);
modifiedAttributes.put("email", email);

return new DefaultOAuth2User(
oAuth2User.getAuthorities(),
modifiedAttributes,
"email" // email Principal로 설정
);
}

private Member saveOrUpdateUser(String email, String nickname) {
Member member = memberRepository.findByEmail(email)
.orElse(Member.builder()
.email(email)
.name(nickname)
.password(passwordEncoder.encode("OAUTH_USER_" + UUID.randomUUID()))
.gender(Gender.NONE) // 기본값 설정
.address("소셜로그인") // 기본값 설정
.specAddress("소셜로그인") // 기본값 설정
.role(Role.USER)
.build());

return memberRepository.save(member);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package umc.spring.config.security;

import lombok.RequiredArgsConstructor;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import umc.spring.domain.Member;
import umc.spring.repository.MemberRepository.MemberRepository;

@Service
@RequiredArgsConstructor
public class CustomUserDetailsService implements UserDetailsService {

private final MemberRepository memberRepository;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Member member = memberRepository.findByEmail(username)
.orElseThrow(() -> new UsernameNotFoundException("해당 이메일을 가진 유저가 없습니다."));

return org.springframework.security.core.userdetails.User
.withUsername(member.getEmail())
.password(member.getPassword())
.roles(member.getRole().name())
.build();

}
}
46 changes: 46 additions & 0 deletions src/main/java/umc/spring/config/security/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package umc.spring.config.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@EnableWebSecurity
@Configuration
public class SecurityConfig {

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((requests) -> requests
.requestMatchers("/", "/home", "/signup", "/members/signup", "/css/**").permitAll()
.requestMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
)
.formLogin((form) -> form
.loginPage("/login")
.defaultSuccessUrl("/home", true)
.permitAll()
)
.logout((logout) -> logout
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.permitAll()
)
.oauth2Login(oauth2 -> oauth2
.loginPage("/login")
.defaultSuccessUrl("/home", true)
.permitAll()
);

return http.build();
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
3 changes: 3 additions & 0 deletions src/main/java/umc/spring/converter/MemberConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,13 @@ public static Member toMember(MemberRequestDTO.JoinDTO request) {

return Member.builder()
.address(request.getAddress())
.email(request.getEmail())
.password(request.getPassword())
.specAddress(request.getSpecAddress())
.gender(gender)
.name(request.getName())
.memberPreferList(new ArrayList<>())
.role(request.getRole())
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import umc.spring.domain.Member;
import umc.spring.domain.Mission;
import umc.spring.domain.mapping.MemberMission;
import umc.spring.domain.mapping.MissionStatus;
import umc.spring.domain.enums.MissionStatus;
import umc.spring.web.dto.MemberMissionDTO.MemberMissionResponseDTO;

import java.time.LocalDateTime;
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/umc/spring/converter/StoreConverter.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public static MissionResponseDTO.MissionPreviewListDTO missionPreviewListDTO(Pag
.totalElements(missionList.getTotalElements())
.listSize(missionPreviewDTOList.size())
.missionList(missionPreviewDTOList)
.build();
}
public static ReviewResponseDTO.ReviewPreviewDTO reviewPreviewDTO(Review review) {
return ReviewResponseDTO.ReviewPreviewDTO.builder()
.ownerNickname(review.getMember().getName())
Expand Down
13 changes: 12 additions & 1 deletion src/main/java/umc/spring/domain/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import umc.spring.domain.common.BaseEntity;
import umc.spring.domain.enums.Gender;
import umc.spring.domain.enums.MemberStatus;
import umc.spring.domain.enums.Role;
import umc.spring.domain.enums.SocialType;
import umc.spring.domain.mapping.MemberAgree;
import umc.spring.domain.mapping.MemberMission;
Expand Down Expand Up @@ -52,7 +53,7 @@ public class Member extends BaseEntity {

private LocalDate inactiveDate;

// @Column(nullable = false, length = 50)
@Column(nullable = false, unique = true, length = 50)
private String email;

@Column(length = 15)
Expand All @@ -61,6 +62,12 @@ public class Member extends BaseEntity {
@ColumnDefault("0")
private Integer point;

@Column(nullable = false)
private String password;

@Enumerated(EnumType.STRING)
private Role role;

@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<MemberAgree> memberAgreeList = new ArrayList<>();

Expand All @@ -73,4 +80,8 @@ public class Member extends BaseEntity {
@OneToMany(mappedBy = "member", cascade = CascadeType.ALL)
private List<MemberMission> memberMissionList = new ArrayList<>();

public void encodePassword(String password) {
this.password = password;
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package umc.spring.domain.mapping;
package umc.spring.domain.enums;

public enum MissionStatus {
CHALLENGING, COMPLETE
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/umc/spring/domain/enums/Role.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package umc.spring.domain.enums;

public enum Role {
ADMIN, USER
}
2 changes: 1 addition & 1 deletion src/main/java/umc/spring/domain/mapping/MemberMission.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import jakarta.persistence.*;
import lombok.*;
import org.hibernate.annotations.Fetch;
import umc.spring.domain.Member;
import umc.spring.domain.Mission;
import umc.spring.domain.common.BaseEntity;
import umc.spring.domain.enums.MissionStatus;

@Entity
@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import org.springframework.data.repository.query.Param;
import umc.spring.domain.Mission;
import umc.spring.domain.mapping.MemberMission;
import umc.spring.domain.mapping.MissionStatus;
import umc.spring.domain.enums.MissionStatus;

import java.util.Optional;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@
import org.springframework.data.jpa.repository.JpaRepository;
import umc.spring.domain.Member;

import java.util.Optional;

public interface MemberRepository extends JpaRepository<Member, Long> , MemberRepositoryCustom {
Optional<Member> findByEmail(String email);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,14 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.validation.Errors;
import umc.spring.apiPayload.code.status.ErrorStatus;
import umc.spring.apiPayload.exception.handler.MemberHandler;
import umc.spring.apiPayload.exception.handler.MissionHandler;
import umc.spring.converter.MemberMissionConverter;
import umc.spring.domain.Member;
import umc.spring.domain.Mission;
import umc.spring.domain.mapping.MemberMission;
import umc.spring.domain.mapping.MissionStatus;
import umc.spring.domain.enums.MissionStatus;
import umc.spring.repository.MemberMissionRepository.MemberMissionRepository;
import umc.spring.repository.MemberRepository.MemberRepository;
import umc.spring.repository.MissionRepository.MissionRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import umc.spring.apiPayload.code.status.ErrorStatus;
import umc.spring.apiPayload.exception.handler.FoodCategoryHandler;
Expand All @@ -28,12 +29,16 @@ public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository;
private final FoodCategoryRepository foodCategoryRepository;
private final ReviewRepository reviewRepository;
private final PasswordEncoder passwordEncoder;

@Override
@Transactional
public Member joinMember(MemberRequestDTO.JoinDTO request) {

Member newMember = MemberConverter.toMember(request);

newMember.encodePassword(passwordEncoder.encode(request.getPassword()));

List<FoodCategory> foodCategoryList = request.getPreferCategory().stream()
.map(category -> {
return foodCategoryRepository.findById(category).orElseThrow(() -> new FoodCategoryHandler(ErrorStatus.FOOD_CATEGORY_NOT_FOUND));
Expand Down
Loading