Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
imenuuu committed Nov 22, 2023
2 parents 8724b54 + 4f6cb0d commit df071f5
Show file tree
Hide file tree
Showing 24 changed files with 412 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ private void getExceptionStackTrace(Exception e, User user, HttpServletRequest r
pw.append("ERROR_MESSAGE : ").append(errors.toString()).append("\n");
}
else {
pw.append("ERROR_MESSAGE : ").append(e.getMessage()).append("\n");
pw.append("ERROR_MESSAGE : ").append(e.toString()).append("\n");
pw.append("ERROR_MESSAGE : ").append(e.getLocalizedMessage()).append("\n");
}
pw.append("=====================================================================");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.example.matchapi.common.security.*;
import com.example.matchdomain.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
Expand All @@ -14,11 +15,7 @@
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.CorsUtils;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
Expand All @@ -29,6 +26,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
private final UserDetailsService userDetailsService;
@Value("${spring.config.activate.on-profile}")
private String profile;

@Bean
public PasswordEncoder passwordEncoder() {
Expand All @@ -51,85 +50,94 @@ public void configure(WebSecurity web) throws Exception {
;

}

protected void configure(HttpSecurity httpSecurity) throws Exception {
configureCsrfAndHeaders(httpSecurity);
configureSessionManagement(httpSecurity);
configureExceptionHandling(httpSecurity);
configureAuthorizationRequests(httpSecurity);
disableFormLogin(httpSecurity);
configureEnvironmentSpecificAccess(httpSecurity);
}

private void configureCsrfAndHeaders(HttpSecurity httpSecurity) throws Exception {
httpSecurity
// token을 사용하는 방식이기 때문에 csrf를 disable합니다.
.csrf().disable()
// enable h2-console
.headers()
.frameOptions()
.sameOrigin()
.sameOrigin();
}

// 세션을 사용하지 않기 때문에 STATELESS로 설정
.and()
private void configureSessionManagement(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}

.and()
private void configureExceptionHandling(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.exceptionHandling()
.authenticationEntryPoint(jwtAuthenticationEntryPoint)
.accessDeniedHandler(jwtAccessDeniedHandler)

.accessDeniedHandler(jwtAccessDeniedHandler);
}

.and()
private void configureAuthorizationRequests(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.antMatchers("/swagger-resources/**").permitAll()
.antMatchers("/swagger-ui/**").permitAll()
.antMatchers("/api-docs/**").permitAll()
.antMatchers("/webjars/**").permitAll()
.antMatchers("/v3/api-docs").permitAll()
.antMatchers("/image/**").permitAll()
.antMatchers("/users/refresh").permitAll()
.antMatchers("/profile").permitAll()
.antMatchers("/login/**").permitAll()
.antMatchers("/test/**").permitAll()
.antMatchers("/login/**").permitAll()
.antMatchers("/auth/**").permitAll()
.antMatchers("/health").permitAll()
.antMatchers("/order").permitAll()
.antMatchers("/order/serverAuth").permitAll()
.antMatchers("/projects").permitAll()
.antMatchers(HttpMethod.GET, "/projects/{projectId}").permitAll()
.antMatchers("/projects/list").authenticated()
.antMatchers("/").permitAll()
.antMatchers("/serverAuth").permitAll()
.antMatchers(HttpMethod.GET,"/donation-temporaries").permitAll()
.antMatchers("/projects/list").authenticated()
.antMatchers("/users/refresh").permitAll()
.antMatchers(HttpMethod.GET,"/donation-temporaries").permitAll()
.antMatchers("/terms/**").permitAll()
.antMatchers("/admin/projects/**").hasAnyRole("ADMIN")
.antMatchers("/admin/users/**").hasAnyRole("ADMIN")
.antMatchers("/admin/users/**").hasAnyRole("ADMIN")
.antMatchers("/admin/donation-users/**").hasAnyRole("ADMIN")
.antMatchers("/admin/donation-temporaries/**").hasAnyRole("ADMIN")
.antMatchers("/admin/order/**").hasAnyRole("ADMIN")
.antMatchers("/admin/auth/logIn").permitAll()
.antMatchers("/test/fcm/user").authenticated()
.antMatchers("/terms/**").permitAll()
.anyRequest().authenticated()

.and()
.apply(new JwtSecurityConfig(jwtService));
}

private void disableFormLogin(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.httpBasic()
.and()
.formLogin()
.disable();
}

@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedOrigin("*"); // 모든 도메인으로부터의 요청을 허용
configuration.addAllowedMethod("*"); // 모든 HTTP 메서드를 허용
configuration.addAllowedHeader("DEVICE_ID"); // 특정 헤더를 허용
private void configureEnvironmentSpecificAccess(HttpSecurity httpSecurity) throws Exception {
if (!profile.equals("prod")) {
allowSwaggerForNonProd(httpSecurity);
} else {
restrictSwaggerForProd(httpSecurity);
}
}

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
private void allowSwaggerForNonProd(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers("/swagger-ui/**").permitAll()
.antMatchers("/api-docs/**").permitAll()
.antMatchers("/swagger-resources/**").permitAll()
.anyRequest().authenticated();
}

return source;
private void restrictSwaggerForProd(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers("/swagger-ui/**").authenticated()
.antMatchers("/api-docs/**").authenticated()
.antMatchers("/swagger-resources/**").authenticated()
.anyRequest().authenticated();
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package com.example.matchapi.donation.controller;

import com.example.matchapi.donation.dto.DonationReq;
import com.example.matchapi.donation.dto.DonationRes;
import com.example.matchapi.donation.service.DonationService;
import com.example.matchapi.project.service.ProjectService;
import com.example.matchapi.user.dto.UserRes;
import com.example.matchcommon.annotation.ApiErrorCodeExample;
import com.example.matchcommon.annotation.RedissonLock;
import com.example.matchcommon.exception.errorcode.RequestErrorCode;
import com.example.matchcommon.reponse.CommonResponse;
import com.example.matchcommon.reponse.PageResponse;
import com.example.matchdomain.donation.exception.*;
import com.example.matchdomain.project.entity.Project;
import com.example.matchdomain.user.entity.User;
import com.example.matchdomain.user.exception.UserAuthErrorCode;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
Expand All @@ -25,6 +31,7 @@
@Tag(name = "05-Donation💸",description = "기부금 관련 API 입니다.")
public class DonationController {
private final DonationService donationService;
private final ProjectService projectService;

@PatchMapping("/{donationId}")
@ApiErrorCodeExample({UserAuthErrorCode.class, DonationRefundErrorCode.class})
Expand Down Expand Up @@ -183,4 +190,24 @@ public CommonResponse<PageResponse<List<DonationRes.BurningFlameDto>>> getBurnin
return CommonResponse.onSuccess(donationService.getBurningFlameList(user, page, size));
}


@Operation(summary = "05-13 튜토리얼 기부 리스트", description = "튜토리얼 기부 리스트")
@GetMapping("/tutorial")
@ApiErrorCodeExample(UserAuthErrorCode.class)
public CommonResponse<List<DonationRes.Tutorial>> getTutorialDonation(
@AuthenticationPrincipal User user
){
return CommonResponse.onSuccess(projectService.getTutorialDonation());
}

@Operation(summary = "05-14 튜토리얼 기부 ", description = "튜토리얼 1원 기부 POST API 입니다.")
@PostMapping("/tutorial")
@ApiErrorCodeExample({UserAuthErrorCode.class, RequestErrorCode.class})
@RedissonLock(LockName = "유저 튜토리얼 기부", key = "#user.id")
public CommonResponse<DonationRes.CompleteDonation> postTutorialDonation(
@AuthenticationPrincipal User user,
@RequestBody DonationReq.Tutorial tutorial){
Project project = projectService.findByProjectId(tutorial.getProjectId());
return CommonResponse.onSuccess(donationService.postTutorialDonation(user, tutorial, project));
}
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
package com.example.matchapi.donation.converter;

import com.example.matchapi.common.util.TimeHelper;
import com.example.matchapi.donation.dto.DonationReq;
import com.example.matchapi.donation.dto.DonationRes;
import com.example.matchapi.donation.helper.DonationHelper;
import com.example.matchapi.order.dto.OrderRes;
import com.example.matchapi.project.dto.ProjectRes;
import com.example.matchcommon.annotation.Converter;
import com.example.matchdomain.donation.entity.*;
import com.example.matchdomain.donation.entity.enums.DonationStatus;
import com.example.matchdomain.donation.entity.enums.HistoryStatus;
import com.example.matchdomain.donation.entity.enums.PayMethod;
import com.example.matchdomain.donation.entity.enums.RegularStatus;
import com.example.matchdomain.donation.entity.flameEnum.FlameImage;
import com.example.matchdomain.donation.entity.flameEnum.FlameType;
import com.example.matchdomain.donation.repository.DonationUserRepository;
import com.example.matchdomain.donation.repository.HistoryImageRepository;
import com.example.matchdomain.project.entity.Project;
import com.example.matchdomain.user.entity.User;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;

Expand Down Expand Up @@ -306,4 +314,28 @@ public List<DonationRes.PayList> convertToPayList(List<DonationUser> donationUse
}


public DonationUser convertToTutorialDonation(User user, DonationReq.Tutorial tutorial, OrderRes.CreateInherenceDto createInherenceDto) {
return DonationUser.builder()
.userId(user.getId())
.projectId(tutorial.getProjectId())
.price(1L)
.donationStatus(DonationStatus.EXECUTION_BEFORE)
.payMethod(PayMethod.TUTORIAL)
.inherenceName(createInherenceDto.getInherenceName())
.inherenceNumber(createInherenceDto.getInherenceNumber())
.regularStatus(RegularStatus.ONE_TIME)
.flameImage(FlameImage.NORMAL_IMG.getImg())
.flameType(FlameType.NORMAL_FLAME)
.build();
}

public DonationRes.CompleteDonation convertToCompleteDonation(DonationUser donationUser, Project project) {
return DonationRes.CompleteDonation
.builder()
.projectId(donationUser.getProjectId())
.image(donationUser.getFlameImage())
.inherenceName(donationUser.getInherenceName())
.randomMessage(donationHelper.createRandomMessageTutorial(project.getProjectKind()))
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,14 @@ public static class SomeExecution{

private Long amount;
}

@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public static class Tutorial {
private Long projectId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.example.matchdomain.donation.entity.enums.DonationStatus;
import com.example.matchdomain.donation.entity.enums.HistoryStatus;
import com.example.matchdomain.donation.entity.enums.RegularPayStatus;
import com.example.matchdomain.project.entity.enums.ProjectKind;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
Expand Down Expand Up @@ -333,4 +334,34 @@ public static class ProjectDonationStatus {
@Schema(description = "지출 완료 금액")
private int completeAmount;
}


@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class Tutorial {
private Long projectId;

private ProjectKind projectKind;
}

@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class CompleteDonation {
private Long projectId;

@Schema(description = "고유 불꽃이 이름")
private String inherenceName;

@Schema(description = "불꽃이 이미지")
private String image;

@Schema(description = "랜덤 불꽃이 메세지")
private String randomMessage;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.example.matchdomain.common.model.RandomMessage;
import com.example.matchdomain.donation.entity.DonationUser;
import com.example.matchdomain.donation.entity.enums.DonationStatus;
import com.example.matchdomain.project.entity.enums.ProjectKind;
import lombok.RequiredArgsConstructor;

import java.text.DecimalFormat;
Expand All @@ -15,6 +16,7 @@
import java.util.Random;
import java.util.stream.Collectors;

import static com.example.matchcommon.constants.RandomMessageStatic.*;
import static com.example.matchdomain.common.model.MessageType.*;
import static com.example.matchdomain.donation.entity.enums.RegularStatus.ONE_TIME;

Expand Down Expand Up @@ -71,4 +73,31 @@ public String getRandomMessageType(MessageType messageType) {
public boolean isOneDayPassed(LocalDateTime dateTime) {
return Duration.between(dateTime, LocalDateTime.now()).toDays() >= 1;
}

public String createRandomMessageTutorial(ProjectKind projectKind) {
switch (projectKind){
case CHILDREN:
return CHILDREN_MESSAGE;
case YOUTH:
return YOUTH_MESSAGE;
case WOMEN:
return WOMEN_MESSAGE;
case ELDER:
return ELDER_MESSAGE;
case DISABLED:
return DISABLED_MESSAGE;
case SOCIAL:
return SOCIAL_MESSAGE;
case NEIGHBOR:
return NEIGHBOR_MESSAGE;
case EARTH:
return EARTH_MESSAGE;
case ANIMAL:
return ANIMAL_MESSAGE;
case ENVIRONMENT:
return ENVIRONMENT_MESSAGE;
default:
return RANDOM_MESSAGE;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ public void saveDonationHistory(DonationHistory donationHistory){
}

public void oneTimeDonationHistory(Long donationId){
saveDonationHistory(donationConverter.convertToDonationHistory(donationId, CREATE));
donationHistoryAdaptor.saveDonationHistory(donationConverter.convertToDonationHistory(donationId, CREATE));
}
}
Loading

0 comments on commit df071f5

Please sign in to comment.