Skip to content
13 changes: 13 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'

compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.mysql:mysql-connector-j'
Expand All @@ -37,10 +39,21 @@ dependencies {
// bcrypt
implementation 'at.favre.lib:bcrypt:0.10.2'

// querydsl
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"

// jwt
compileOnly group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5'


// AWS S3
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
Expand All @@ -18,7 +18,7 @@ public class AdminAccessLoggingAspect {

private final HttpServletRequest request;

@After("execution(* org.example.expert.domain.user.controller.UserController.getUser(..))")
@Before("execution(* org.example.expert.domain.user.controller.UserAdminController.changeUserRole(..))")
public void logAfterChangeUserRole(JoinPoint joinPoint) {
String userId = String.valueOf(request.getAttribute("userId"));
String requestUrl = request.getRequestURI();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ public boolean supportsParameter(MethodParameter parameter) {
boolean hasAuthAnnotation = parameter.getParameterAnnotation(Auth.class) != null;
boolean isAuthUserType = parameter.getParameterType().equals(AuthUser.class);

// @Auth 어노테이션과 AuthUser 타입이 함께 사용되지 않은 경우 예외 발생
// @AuthenticationPrincipal 어노테이션과 AuthUser 타입이 함께 사용되지 않은 경우 예외 발생
if (hasAuthAnnotation != isAuthUserType) {
throw new AuthException("@Auth와 AuthUser 타입은 함께 사용되어야 합니다.");
throw new AuthException("@AuthenticationPrincipal와 AuthUser 타입은 함께 사용되어야 합니다.");
}

return hasAuthAnnotation;
Expand All @@ -40,7 +40,7 @@ public Object resolveArgument(
Long userId = (Long) request.getAttribute("userId");
String email = (String) request.getAttribute("email");
UserRole userRole = UserRole.of((String) request.getAttribute("userRole"));

return new AuthUser(userId, email, userRole);
String nickname = (String) request.getAttribute("nickname");
return new AuthUser(userId, email, userRole, nickname);
}
}
22 changes: 0 additions & 22 deletions src/main/java/org/example/expert/config/FilterConfig.java

This file was deleted.

94 changes: 0 additions & 94 deletions src/main/java/org/example/expert/config/JwtFilter.java

This file was deleted.

3 changes: 2 additions & 1 deletion src/main/java/org/example/expert/config/JwtUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@ public void init() {
key = Keys.hmacShaKeyFor(bytes);
}

public String createToken(Long userId, String email, UserRole userRole) {
public String createToken(Long userId, String email, UserRole userRole, String nickname) {
Date date = new Date();

return BEARER_PREFIX +
Jwts.builder()
.setSubject(String.valueOf(userId))
.claim("email", email)
.claim("userRole", userRole)
.claim("nickname", nickname)
.setExpiration(new Date(date.getTime() + TOKEN_TIME))
.setIssuedAt(date) // 발급일
.signWith(key, signatureAlgorithm) // 암호화 알고리즘
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/org/example/expert/config/QueryDslConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package org.example.expert.config;

import com.querydsl.jpa.JPQLTemplates;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
class QueryDslConfig {

@PersistenceContext
private EntityManager em;

@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(JPQLTemplates.DEFAULT, em);
}
}
19 changes: 0 additions & 19 deletions src/main/java/org/example/expert/config/WebConfig.java

This file was deleted.

27 changes: 27 additions & 0 deletions src/main/java/org/example/expert/config/aws/S3Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.example.expert.config.aws;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class S3Config {
@Value("${S3_ACCESS}")
private String accessKey;
@Value("${S3_SECRET}")
private String secretKey;
@Value("${cloud.aws.region.static}")
private String region;
@Bean
public AmazonS3Client amazonS3Client() {
BasicAWSCredentials awsCredentials= new BasicAWSCredentials(accessKey, secretKey);
return (AmazonS3Client) AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.example.expert.domain.Attachment.controller;

import lombok.RequiredArgsConstructor;
import org.example.expert.domain.Attachment.dto.AttachmentResponseDto;
import org.example.expert.domain.Attachment.service.AttachmentService;
import org.example.expert.domain.common.dto.AuthUser;
import org.example.expert.domain.common.dto.ResponseDto;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.List;

@RestController
@RequestMapping("/attachments")
@RequiredArgsConstructor
public class AttachmentController {
private final AttachmentService attachmentService;
@PostMapping
public ResponseEntity<ResponseDto<List<AttachmentResponseDto>>> uploadAttachments(
@AuthenticationPrincipal AuthUser authUser,
@RequestPart List<MultipartFile> files
) throws IOException {
List<AttachmentResponseDto> responseDto = attachmentService.uploadAttachments(authUser, files);
return ResponseEntity.status(HttpStatus.CREATED)
.body(ResponseDto.of(HttpStatus.CREATED, "파일 업로드가 완료되었습니다.", responseDto));
}

@DeleteMapping("/{attachment_id}")
public ResponseEntity<ResponseDto<String>> deleteAttachment(
@AuthenticationPrincipal AuthUser authUser,
@PathVariable("attachment_id") Long attachmentId
) {
attachmentService.deleteAttachment(authUser, attachmentId);
return ResponseEntity.status(HttpStatus.OK)
.body(ResponseDto.of(200, "성공적으로 삭제되었습니다."));
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.example.expert.domain.Attachment.dto;

import lombok.Getter;
import org.example.expert.domain.Attachment.entity.Attachment;

@Getter
public class AttachmentResponseDto {
private Long id;
private String url;

public AttachmentResponseDto(Attachment attachment) {
this.id = attachment.getId();
this.url = attachment.getUrl();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.example.expert.domain.Attachment.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
@Getter
@Entity
@Table(name = "attachment")
public class Attachment {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "attach_id")
private Long id;

private String url;

public Attachment(String url) {
this.url = url;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.example.expert.domain.Attachment.repository;

import org.example.expert.domain.Attachment.entity.Attachment;
import org.springframework.data.jpa.repository.JpaRepository;

public interface AttachmentRepository extends JpaRepository<Attachment, Long> {
}
Loading