Skip to content

Commit

Permalink
Merge pull request #67 from Tune-Fun/feature/vote/paper_list
Browse files Browse the repository at this point in the history
Feature/vote/paper list
  • Loading branch information
habinkim authored May 3, 2024
2 parents b3318c6 + 4a4cbc0 commit e34094b
Show file tree
Hide file tree
Showing 55 changed files with 1,739 additions and 370 deletions.
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ plugins {
id 'idea'
id 'java'
id 'jacoco'
id 'org.springframework.boot' version '3.2.4'
id 'org.springframework.boot' version '3.2.5'
id 'io.spring.dependency-management' version '1.1.4'
id 'org.asciidoctor.jvm.convert' version '4.0.2'
id 'com.epages.restdocs-api-spec' version '0.19.2'
Expand Down Expand Up @@ -101,6 +101,7 @@ dependencies {
implementation 'software.amazon.awssdk:kms'
implementation 'com.amazonaws:aws-encryption-sdk-java:3.0.0'
implementation 'software.amazon.cryptography:aws-cryptographic-material-providers:1.2.0'
implementation 'org.springframework.boot:spring-boot-starter-quartz'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.1'
implementation 'com.slack.api:slack-app-backend:1.39.0'
implementation 'io.netty:netty-resolver-dns-native-macos:4.1.108.Final:osx-aarch_64'
Expand Down
24 changes: 22 additions & 2 deletions src/docs/asciidoc/vote-api.adoc
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
[[Vote-API]]
== Vote API
== Vote Paper API

=== 투표 게시물 스크롤 조회 API

==== 성공

operation::get-vote-papers-success[snippets='http-request,http-response,query-parameters,response-fields']

=== 투표 게시물 등록 API

==== 성공

operation::register-vote-paper-success[snippets='http-request,http-response,request-fields']
operation::register-vote-paper-success[snippets='http-request,http-response,request-fields']

=== 투표 게시물 영상 제공일 등록 API

==== 성공

operation::update-delivery-date-success[snippets='http-request,http-response,path-parameters,request-fields,response-fields']

== Vote API

=== 투표 등록 API

==== 성공

operation::register-vote-success[snippets='http-request,http-response,path-parameters,response-fields']
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.tune_fun.v1.account.domain.behavior.SaveJwtToken;
import com.tune_fun.v1.account.domain.value.LoginResult;
import com.tune_fun.v1.account.domain.value.RegisteredAccount;
import com.tune_fun.v1.common.constant.Constants;
import com.tune_fun.v1.common.exception.CommonApplicationException;
import com.tune_fun.v1.common.hexagon.UseCase;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -54,7 +55,7 @@ public LoginResult login(final AccountCommands.Login command) {
if (!passwordEncoder.matches(command.password(), registeredAccount.password()))
throw new CommonApplicationException(ACCOUNT_NOT_FOUND);

String authorities = String.join(",", registeredAccount.roles());
String authorities = String.join(Constants.COMMA, registeredAccount.roles());

SaveJwtToken saveJwtTokenBehavior = getSaveJwtToken(registeredAccount, authorities);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import com.tune_fun.v1.account.domain.behavior.SaveJwtToken;
import com.tune_fun.v1.account.domain.value.CurrentAccount;
import com.tune_fun.v1.account.domain.value.RegisterResult;
import com.tune_fun.v1.common.constant.Constants;
import com.tune_fun.v1.common.exception.CommonApplicationException;
import com.tune_fun.v1.common.hexagon.UseCase;
import com.tune_fun.v1.common.util.StringUtil;
Expand Down Expand Up @@ -51,13 +52,13 @@ private static RegisterResult getRegisterResult(CurrentAccount savedAccount, Str
@Override
@Transactional
public RegisterResult register(final String registerType, final AccountCommands.Register command) {
checkRegisterdAccount(command);
checkRegisteredAccount(command);

String encodedPassword = passwordEncoder.encode(command.password());
SaveAccount saveAccount = getSaveAccount(registerType, command, encodedPassword);
CurrentAccount savedAccount = saveAccountPort.saveAccount(saveAccount);

String authorities = String.join(",", savedAccount.roles());
String authorities = String.join(Constants.COMMA, savedAccount.roles());

SaveJwtToken saveJwtToken = new SaveJwtToken(savedAccount.username(), authorities);

Expand All @@ -68,7 +69,7 @@ public RegisterResult register(final String registerType, final AccountCommands.
}

@Transactional(readOnly = true)
public void checkRegisterdAccount(AccountCommands.Register command) {
public void checkRegisteredAccount(AccountCommands.Register command) {
loadAccountPort.currentAccountInfo(command.username()).ifPresent(accountInfo -> {
throw new CommonApplicationException(USER_POLICY_ACCOUNT_REGISTERED);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tune_fun.v1.common.aspect;

import com.tune_fun.v1.common.constant.Constants;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
Expand Down Expand Up @@ -50,7 +51,7 @@ public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
Object proceed = joinPoint.proceed();
stopWatch.stop();

String msg = joinPoint.getSignature().getDeclaringType() + "." +
String msg = joinPoint.getSignature().getDeclaringType() + Constants.DOT +
joinPoint.getSignature().getName() + " : " +
"running time = " +
stopWatch.getTotalTimeMillis() + "ms";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.tune_fun.v1.common.exception.CommonApplicationException;
import com.tune_fun.v1.vote.application.port.output.LoadVotePaperPort;
import com.tune_fun.v1.vote.application.port.output.LoadVotePort;
import com.tune_fun.v1.vote.domain.value.RegisteredVotePaper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand All @@ -12,15 +13,15 @@

import java.io.Serializable;

import static com.tune_fun.v1.common.response.MessageCode.VOTE_PAPER_NOT_FOUND;
import static com.tune_fun.v1.common.response.MessageCode.VOTE_POLICY_ONLY_AUTHOR_CAN_UPDATE_DELIVERY_DATE;
import static com.tune_fun.v1.common.response.MessageCode.*;

@Slf4j
@Component
@RequiredArgsConstructor
public class PermissionPolicyEvaluator implements PermissionEvaluator {

private final LoadVotePaperPort loadVotePaperPort;
private final LoadVotePort loadVotePort;

@Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
Expand All @@ -33,6 +34,7 @@ public boolean hasPermission(Authentication authentication, Serializable targetI

return switch (TargetType.valueOf(targetType)) {
case VOTE_PAPER -> hasPermissionForVotePaper(principal, targetId);
case VOTE -> hasPermissionForVote(principal, targetId);
};
}

Expand All @@ -45,7 +47,15 @@ public boolean hasPermissionForVotePaper(User principal, Serializable targetId)
throw new CommonApplicationException(VOTE_PAPER_NOT_FOUND);
}

private boolean hasPermissionForVote(User principal, Serializable targetId) {
if (loadVotePort.loadVoteByVoterAndVotePaperId(principal.getUsername(), (Long) targetId).isPresent())
throw new CommonApplicationException(VOTE_POLICY_ONE_VOTE_PER_USER);

return true;
}

private enum TargetType {
VOTE_PAPER,
VOTE
}
}
13 changes: 6 additions & 7 deletions src/main/java/com/tune_fun/v1/common/config/SecurityConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
Expand Down Expand Up @@ -85,12 +84,12 @@ public SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospe
http
.sessionManagement(config -> config.sessionCreationPolicy(STATELESS))
.authorizeHttpRequests(registry -> registry
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.requestMatchers(mvc(introspector, "/static/**", "/favicon.ico")).permitAll()
.requestMatchers(mvc(introspector, Uris.PERMIT_ALL_URIS)).permitAll()
.requestMatchers(mvc(introspector, Uris.ARTIST_URIS)).hasRole("ARTIST")
.requestMatchers(mvc(introspector, Uris.ADMIN_URIS)).hasRole("ADMIN")
.anyRequest().authenticated()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.requestMatchers(mvc(introspector, "/static/**", "/favicon.ico")).permitAll()
.requestMatchers(mvc(introspector, Uris.PERMIT_ALL_URIS)).permitAll()
// .requestMatchers(mvc(introspector, Uris.ARTIST_URIS)).hasRole("ARTIST")
// .requestMatchers(mvc(introspector, Uris.ADMIN_URIS)).hasRole("ADMIN")
.anyRequest().authenticated()
)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.oauth2Login(configure ->
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/tune_fun/v1/common/config/Uris.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ private Uris() {
public static final String RESEND_OTP = API_V1_ROOT + "/otp/resend";

public static final String VOTE_ROOT = API_V1_ROOT + "/votes";
public static final String VOTE_PAPER_ROOT = VOTE_ROOT + "/paper";

public static final String REGISTER_VOTE_PAPER = VOTE_ROOT + "/paper";
public static final String SET_VOTE_PAPER_DELIVERY_DATE = VOTE_ROOT + "/paper/delivery-date";
public static final String UPDATE_VOTE_PAPER_DELIVERY_DATE = VOTE_PAPER_ROOT + "/{votePaperId}/delivery-date";

public static final String REGISTER_VOTE = VOTE_ROOT + "/{votePaperId}" + "/register" + "/{voteChoiceId}";

Expand Down Expand Up @@ -143,7 +143,7 @@ private Uris() {
};

public static final String[] ARTIST_URIS = {
REGISTER_VOTE_PAPER
UPDATE_VOTE_PAPER_DELIVERY_DATE
};

public static final String[] ADMIN_URIS = {
Expand Down
50 changes: 50 additions & 0 deletions src/main/java/com/tune_fun/v1/common/constant/Constants.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.tune_fun.v1.common.constant;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

public final class Constants {

public static final Object NULL_OBJECT = null;

public static final Number NULL_NUMBER = null;

public static final String NULL_STRING = null;

public static final String EMPTY_STRING = "";

public static final String SPACE = " ";

public static final String COMMA = ",";

public static final String COLON = ":";

public static final String SEMICOLON = ";";

public static final String DOT = ".";

public static final LocalDateTime LOCAL_DATE_TIME_MIN = LocalDateTime.of(
LocalDate.of(1970, 1, 1), LocalTime.of(0, 0, 10)
);

public static final class NicknameFragment {

public static final String[] PREFIX_NAMES = {
"행복한", "멋진", "멋있는", "귀여운", "예쁜", "잘생긴", "똑똑한", "졸린", "피곤한", "배고픈", "궁금한", "친절한", "평범한",
"활발한", "조용한", "빠른", "느린", "재빠른", "강한", "영리한", "우아한", "독특한", "재밌는", "발랄한", "따뜻한", "눈부신",
"명랑한", "빛나는", "깜찍한", "차분한", "이상한", "행운의"
};

public static final String[] ANIMAL_NAMES = {
"사자", "호랑이", "표범", "기린", "코끼리", "코뿔소", "하마", "펭귄", "독수리", "타조", "캥거루", "고래", "칠면조", "직박구리",
"청설모", "메추라기", "앵무새", "스라소니", "판다", "오소리", "오리", "거위", "백조", "두루미", "고슴도치", "두더지", "우파루파",
"너구리", "카멜레온", "이구아나", "노루", "제비", "까치", "고라니", "수달", "당나귀", "순록", "염소", "공작", "바다표범", "들소",
"참새", "물개", "바다사자", "얼룩말", "산양", "카피바라", "북극곰", "퓨마", "코요테", "라마", "딱따구리", "돌고래", "까마귀",
"낙타", "여우", "사슴", "늑대", "재규어", "알파카", "다람쥐", "담비", "사막여우", "북극여우", "꽃사슴", "해달", "강아지",
"고양이", "햄스터", "기니피그", "왈라비", "마못", "물범", "토끼", "미어캣", "북극곰", "코알라", "디프만"
};

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import static com.google.common.base.CaseFormat.LOWER_CAMEL;
import static com.google.common.base.CaseFormat.LOWER_UNDERSCORE;
import static com.tune_fun.v1.common.constant.Constants.DOT;
import static com.tune_fun.v1.common.response.MessageCode.ERROR;
import static com.tune_fun.v1.common.response.MessageCode.EXCEPTION_ILLEGAL_ARGUMENT;
import static java.util.stream.Collectors.toMap;
Expand All @@ -31,7 +32,7 @@ public class GlobalExceptionHandler {
private final ResponseMapper responseMapper;

protected static String getPropertyName(String propertyPath) {
return propertyPath.substring(propertyPath.lastIndexOf('.') + 1);
return propertyPath.substring(propertyPath.lastIndexOf(DOT) + 1);
}

@ExceptionHandler(CommonApplicationException.class)
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/com/tune_fun/v1/common/hexagon/UseCase.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.tune_fun.v1.common.hexagon;

import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.lang.annotation.*;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
@Service
public @interface UseCase {

/**
Expand All @@ -17,7 +17,7 @@
*
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
@AliasFor(annotation = Service.class)
String value() default "";

}
6 changes: 3 additions & 3 deletions src/main/java/com/tune_fun/v1/common/hexagon/WebAdapter.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package com.tune_fun.v1.common.hexagon;

import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RestController;

import java.lang.annotation.*;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
@RestController
public @interface WebAdapter {

/**
Expand All @@ -17,7 +17,7 @@
*
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
@AliasFor(annotation = RestController.class)
String value() default "";

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
@AllArgsConstructor
@Getter
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class ValidationErrorData implements BasePayload {
public final class ValidationErrorData implements BasePayload {

@JsonIgnore
private Map<String, String> errors = new HashMap<>();
Expand Down
Loading

0 comments on commit e34094b

Please sign in to comment.