Skip to content
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

feat: 이미지 업로드 기능 및 토큰 재발급 기능 추가 #60

Merged
merged 9 commits into from
Jul 6, 2024
8 changes: 5 additions & 3 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ jib {

container {
jvmFlags = [
'-Duser.timezone="Asia/Seoul"',
'--enable-preview',
String.format('-Dspring.profiles.active=%s', "prod"),
'-Xms1024m',
Expand Down Expand Up @@ -75,7 +76,7 @@ dependencies {


// jwt
implementation 'org.springframework.security:spring-security-oauth2-jose:6.2.4'
implementation 'org.springframework.security:spring-security-oauth2-jose:6.2.3'

// cloud speech
implementation 'com.google.cloud:google-cloud-speech:4.38.0'
Expand All @@ -90,8 +91,9 @@ dependencies {
implementation 'org.flywaydb:flyway-mysql'

// mysql
implementation platform("com.google.cloud:spring-cloud-gcp-dependencies:5.3.0")
implementation "com.google.cloud:spring-cloud-gcp-starter-sql-mysql:5.3.0"
implementation platform("com.google.cloud:spring-cloud-gcp-dependencies:5.4.3")
implementation "com.google.cloud:spring-cloud-gcp-starter-sql-mysql"
implementation "com.google.cloud:spring-cloud-gcp-starter-storage"

compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
Expand Down
2 changes: 1 addition & 1 deletion backend/secret
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package in.backend.core.auth.application;


import in.backend.core.auth.application.payload.IssuedToken;
import in.backend.core.auth.domain.Visitor;
import in.backend.core.auth.infrastrcutrue.RefreshTokenWriter;
import in.backend.core.auth.infrastrcutrue.RefreshTokenReader;
import in.backend.global.provider.JwtProvider;
import java.time.Instant;
import lombok.RequiredArgsConstructor;
Expand All @@ -12,21 +10,16 @@
@Service
@RequiredArgsConstructor
public class TokenReissue {

private final JwtProvider jwtProvider;
private final RefreshTokenWriter refreshTokenWriter;

public IssuedToken publish(Visitor visitor) {
var now = Instant.now();
private final RefreshTokenReader refreshTokenReader;

var accessToken = jwtProvider.createAccessToken(visitor.memberId(), now);
var refreshToken = jwtProvider.createRefreshToken(visitor.memberId(), now);
public String publish(String refreshToken) {
jwtProvider.validRefreshToken(refreshToken);

refreshTokenWriter.write(visitor.memberId(), refreshToken);

return IssuedToken.builder()
.accessToken(accessToken)
.refreshToken(refreshToken)
.build();
return jwtProvider.createAccessToken(
refreshTokenReader.read(refreshToken).getId(),
Instant.now()
);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.Getter;
import lombok.NoArgsConstructor;


@Getter
@Entity
@NoArgsConstructor
@Table(name = "REFRESH_TOKENS")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package in.backend.core.auth.infrastrcutrue;


import in.backend.core.auth.entity.RefreshTokenEntity;
import in.backend.global.exception.GlobalExceptionCode;
import in.backend.global.exception.RefreshTokenException;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -14,4 +17,9 @@ public class RefreshTokenReader {
public boolean existsBy(Long memberId) {
return refreshTokenRepository.existsById(memberId);
}

public RefreshTokenEntity read(String refreshToken) {
return refreshTokenRepository.findByToken(refreshToken)
.orElseThrow(() -> new RefreshTokenException(GlobalExceptionCode.NOT_FOUND_REFRESH_TOKEN));
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package in.backend.core.auth.infrastrcutrue;

import in.backend.core.auth.entity.RefreshTokenEntity;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface RefreshTokenRepository extends JpaRepository<RefreshTokenEntity, Long> {

Optional<RefreshTokenEntity> findByToken(String refreshToken);
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
Expand Down Expand Up @@ -69,17 +70,14 @@ public OAuthProfileResponse getProfile(@ModelAttribute OAuthProfileRequest profi
return socialLoginProcessor.findProfile(profile);
}

@MemberOnly
@PostMapping("/token/reissue")
public ResponseEntity<AccessTokenResponse> reIssue(
@Auth Visitor visitor,
HttpServletResponse response
@CookieValue("refreshToken") final String refreshToken
) {
var issuedToken = tokenReissue.publish(visitor);
response.addHeader(SET_COOKIE, cookieProvider.createCookie(issuedToken.refreshToken()).toString());
var accessToken = tokenReissue.publish(refreshToken);

return ResponseEntity.status(CREATED)
.body(new AccessTokenResponse(issuedToken.accessToken()));
.body(new AccessTokenResponse(accessToken));
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package in.backend.core.question.application;

import in.backend.global.entity.ActionType;

public record QuestionSaveCommand(
ActionType action,
Long questionId,
Long questionSetId,
Integer sequence,
String question
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package in.backend.core.question.application;


import in.backend.core.question.application.QuestionWriter.QuestionInfo;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class QuestionService {
private final QuestionWriter questionWriter;

public Long save(QuestionSaveCommand command) {
return switch (command.action()) {
case CREATE -> questionWriter.write(new QuestionInfo(command));
case UPDATE -> questionWriter.write(command.questionId(), new QuestionInfo(command));
case DELETE -> throw new UnsupportedOperationException();
};
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,25 +15,31 @@ public class QuestionWriter {
private final QuestionReader questionReader;


public Long execute(QuestionInfo questionInfo) {
return questionRepository.save(questionInfo.toEntity()).getId();
public Long write(QuestionInfo questionInfo) {
return questionRepository.save(questionInfo.toEntity())
.getId();
}

public void update(Long questionId, QuestionInfo questionInfo) {
public Long write(Long questionId, QuestionInfo questionInfo) {
var question = questionReader.read(questionId);

question.update(questionInfo);

return question.getId();
}

public record QuestionInfo(
String content,
String referenceLinks,
int sequence
) {

public QuestionInfo(QuestionSaveCommand command) {
this(command.question(), command.sequence());
}

public QuestionEntity toEntity() {
return QuestionEntity.builder()
.content(content)
.referenceLinks(referenceLinks)
.sequence(sequence)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ public QuestionEntity(

public void update(QuestionInfo questionInfo) {
applyIfPresent(questionInfo.content(), value -> this.content = value);
applyIfPresent(questionInfo.referenceLinks(), value -> this.referenceLinks = value);
applyIfPresent(questionInfo.sequence(), value -> this.sequence = value);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package in.backend.core.question.presentation;


import in.backend.core.auth.domain.Visitor;
import in.backend.core.auth.domain.attributes.Auth;
import in.backend.core.question.presentation.payload.QuestionSaveRequest;
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("/api/questions")
public class QuestionApi {


@PostMapping
public void save(
@RequestBody QuestionSaveRequest questionSaveRequest,
@Auth Visitor visitor
) {

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package in.backend.core.question.presentation.payload;

public record QuestionDetailResponse(
Long questionId,
Long questionSetId,
String question,
Integer sequence
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package in.backend.core.question.presentation.payload;

import in.backend.global.entity.ActionType;

public record QuestionSaveRequest(
ActionType action,
Long questionId,
Long questionSetId,
Integer sequence,
String question
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package in.backend.core.questionset.application;

import lombok.Builder;
import org.springframework.web.multipart.MultipartFile;

@Builder
public record QuestionSetCreator(
String title,
String description,
String thumbnailUrl,
MultipartFile multipartFile,
int defaultTailQuestionDepth,
int defaultTimeToAnswer,
int defaultTimeToThink
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import static java.util.stream.Collectors.toMap;

import in.backend.core.question.application.QuestionReader;
import in.backend.core.questionset.entity.QuestionSetEntity;
import in.backend.core.questionset.infrastructure.QuestionSetReader;
import in.backend.core.questionset.infrastructure.QuestionSetWriter;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand All @@ -15,6 +17,7 @@
public class QuestionSetService {

private final QuestionSetReader questionSetReader;
private final QuestionSetWriter questionSetWriter;
private final QuestionReader questionReader;

public Page<QuestionSetInfo> find(Pageable pageable) {
Expand All @@ -29,4 +32,8 @@ public Page<QuestionSetInfo> find(Pageable pageable) {
questionSetProblemCounts.get(questionSet.getId())
));
}

public QuestionSetEntity create(QuestionSetCreator questionSetCreator, Long adminId) {
return questionSetWriter.write(questionSetCreator, adminId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,12 @@ public class QuestionSetEntity extends BaseEntity {


@Builder
public QuestionSetEntity(Long adminId, String title, String description, QuestionSetRules questionSetRules) {
public QuestionSetEntity(
Long adminId,
String title,
String description,
QuestionSetRules questionSetRules
) {
this.adminId = adminId;
this.title = title;
this.questionSetRules = questionSetRules;
Expand All @@ -90,10 +95,6 @@ public List<QuestionEntity> extractQuestions(int count) {
}


public int getQuestionSize() {
return questions.size();
}

public int getTailQuestionDepth() {
return questionSetRules.getDefaultTailQuestionDepth();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package in.backend.core.questionset.infrastructure;


import in.backend.core.questionset.application.QuestionSetCreator;
import in.backend.core.questionset.entity.QuestionSetEntity;
import in.backend.core.questionset.entity.QuestionSetRules;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
@RequiredArgsConstructor
public class QuestionSetWriter {
private final QuestionSetRepository questionSetRepository;

public QuestionSetEntity write(QuestionSetCreator questionSetCreator, Long adminId) {
var questionSet = QuestionSetEntity.builder()
.adminId(adminId)
.title(questionSetCreator.title())
.description(questionSetCreator.description())
.questionSetRules(QuestionSetRules.builder()
.defaultTimeToAnswer(questionSetCreator.defaultTimeToAnswer())
.defaultTimeToThink(questionSetCreator.defaultTimeToThink())
.defaultTailQuestionDepth(questionSetCreator.defaultTailQuestionDepth())
.build())
.build();

return questionSetRepository.save(questionSet);
}
}
Loading
Loading