diff --git a/module-api/src/main/java/com/mile/common/auth/JwtTokenProvider.java b/module-api/src/main/java/com/mile/common/auth/JwtTokenProvider.java index f981dc52..db14b227 100644 --- a/module-api/src/main/java/com/mile/common/auth/JwtTokenProvider.java +++ b/module-api/src/main/java/com/mile/common/auth/JwtTokenProvider.java @@ -1,8 +1,12 @@ package com.mile.common.auth; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import com.mile.exception.message.ErrorMessage; import com.mile.exception.model.BadRequestException; import com.mile.exception.model.UnauthorizedException; +import com.mile.writername.domain.MoimRole; +import com.mile.writername.service.vo.WriterNameInfo; import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.Header; @@ -11,19 +15,26 @@ import io.jsonwebtoken.UnsupportedJwtException; import io.jsonwebtoken.security.Keys; import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import org.redisson.misc.Hash; import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; +import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import javax.crypto.SecretKey; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.Date; +import java.util.HashMap; +import java.util.Map; -@Service +@Component +@RequiredArgsConstructor public class JwtTokenProvider { + private final ObjectMapper objectMapper; private static final String MEMBER_ID = "memberId"; + private static final String JOINED_ROLE = "joinedRole"; private static final Long ACCESS_TOKEN_EXPIRATION_TIME = 4 * 60 * 60 * 1000L; private static final Long REFRESH_TOKEN_EXPIRATION_TIME = 60 * 60 * 24 * 1000L * 14; @@ -32,7 +43,6 @@ public class JwtTokenProvider { @PostConstruct protected void init() { - //base64 라이브러리에서 encodeToString을 이용해서 byte[] 형식을 String 형식으로 변환 JWT_SECRET = Base64.getEncoder().encodeToString(JWT_SECRET.getBytes(StandardCharsets.UTF_8)); } @@ -45,36 +55,39 @@ private String getTokenFromHeader(final String token) { return token.substring("Bearer ".length()); } - public String issueAccessToken(final Long userId) { - return issueToken(userId, ACCESS_TOKEN_EXPIRATION_TIME); + public String issueAccessToken(final Long userId, final Map joinedRole) { + return issueToken(userId, joinedRole, ACCESS_TOKEN_EXPIRATION_TIME); } - public String issueRefreshToken(final Long userId) { - return issueToken(userId, REFRESH_TOKEN_EXPIRATION_TIME); + public String issueRefreshToken(final Long userId, final Map joinedRole) { + return issueToken(userId, joinedRole, REFRESH_TOKEN_EXPIRATION_TIME); } private String issueToken( final Long userId, + final Map role, final Long expiredTime ) { final Date now = new Date(); final Claims claims = Jwts.claims() .setIssuedAt(now) - .setExpiration(new Date(now.getTime() + expiredTime)); // 만료 시간 설정 + .setExpiration(new Date(now.getTime() + expiredTime)); claims.put(MEMBER_ID, userId); + claims.put(JOINED_ROLE, role); + return Jwts.builder() - .setHeaderParam(Header.TYPE, Header.JWT_TYPE) // Header - .setClaims(claims) // Claim - .signWith(getSigningKey()) // Signature + .setHeaderParam(Header.TYPE, Header.JWT_TYPE) + .setClaims(claims) + .signWith(getSigningKey()) .compact(); } private SecretKey getSigningKey() { - String encodedKey = Base64.getEncoder().encodeToString(JWT_SECRET.getBytes()); //SecretKey 통해 서명 생성 - return Keys.hmacShaKeyFor(encodedKey.getBytes()); //일반적으로 HMAC (Hash-based Message Authentication Code) 알고리즘 사용 + String encodedKey = Base64.getEncoder().encodeToString(JWT_SECRET.getBytes()); + return Keys.hmacShaKeyFor(encodedKey.getBytes()); } public JwtValidationType validateToken(final String token) { @@ -100,8 +113,19 @@ private Claims getBody(final String token) { .getBody(); } - public Long getUserFromJwt(final String token) { + public Long getUserFromAuthHeader(final String token) { Claims claims = getBody(getTokenFromHeader(token)); return Long.valueOf(claims.get(MEMBER_ID).toString()); } + + public HashMap getJoinedRoleFromHeader(final String token) { + return getJoinedRoleFromJwt(getTokenFromHeader(token)); + } + + public HashMap getJoinedRoleFromJwt(final String token) { + Claims claims = getBody(token); + Object joinedRole = claims.get(JOINED_ROLE); + HashMap roleMap = objectMapper.convertValue(joinedRole, new TypeReference>() {}); + return roleMap; + } } diff --git a/module-api/src/main/java/com/mile/common/auth/JwtTokenUpdater.java b/module-api/src/main/java/com/mile/common/auth/JwtTokenUpdater.java new file mode 100644 index 00000000..63526173 --- /dev/null +++ b/module-api/src/main/java/com/mile/common/auth/JwtTokenUpdater.java @@ -0,0 +1,36 @@ +package com.mile.common.auth; + +import com.mile.writername.service.vo.WriterNameInfo; +import com.mile.jwt.service.TokenService; +import com.mile.writername.domain.MoimRole; +import com.mile.writername.service.WriterNameRetriever; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import java.util.Map; + +@Component +@RequiredArgsConstructor +public class JwtTokenUpdater { + + private final JwtTokenProvider jwtTokenProvider; + private final TokenService tokenService; + private final WriterNameRetriever writerNameRetriever; + + public String setAccessToken(final Long userId, final Long moimId, final Long writerNameId, final MoimRole moimRole) { + + Map moimRoleMap = writerNameRetriever.getJoinedRoleFromUserId(userId); + + tokenService.deleteRefreshToken(userId); + + moimRoleMap.put(moimId, WriterNameInfo.of(writerNameId, moimRole)); + + String newAccessToken = jwtTokenProvider.issueAccessToken(userId, moimRoleMap); + String newRefreshToken = jwtTokenProvider.issueRefreshToken(userId, moimRoleMap); + + tokenService.saveRefreshToken(userId, newRefreshToken); + + return newAccessToken; + } + +} diff --git a/module-api/src/main/java/com/mile/common/auth/annotation/UserAuthAnnotation.java b/module-api/src/main/java/com/mile/common/auth/annotation/UserAuthAnnotation.java new file mode 100644 index 00000000..76622296 --- /dev/null +++ b/module-api/src/main/java/com/mile/common/auth/annotation/UserAuthAnnotation.java @@ -0,0 +1,14 @@ +package com.mile.common.auth.annotation; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD}) +@Documented +public @interface UserAuthAnnotation { + UserAuthenticationType value() default UserAuthenticationType.USER; +} diff --git a/module-api/src/main/java/com/mile/common/auth/annotation/UserAuthenticationType.java b/module-api/src/main/java/com/mile/common/auth/annotation/UserAuthenticationType.java new file mode 100644 index 00000000..9d85b8d6 --- /dev/null +++ b/module-api/src/main/java/com/mile/common/auth/annotation/UserAuthenticationType.java @@ -0,0 +1,7 @@ +package com.mile.common.auth.annotation; + +public enum UserAuthenticationType { + OWNER, + WRITER_NAME, + USER +} diff --git a/module-api/src/main/java/com/mile/common/auth/dto/AccessTokenDto.java b/module-api/src/main/java/com/mile/common/auth/dto/AccessTokenDto.java new file mode 100644 index 00000000..8295490f --- /dev/null +++ b/module-api/src/main/java/com/mile/common/auth/dto/AccessTokenDto.java @@ -0,0 +1,13 @@ +package com.mile.common.auth.dto; + +public record AccessTokenDto( + String accessToken, + T response +) { + public static AccessTokenDto of(final T data, final String accessToken) { + return new AccessTokenDto<>(accessToken, data); + } + public static AccessTokenDto of(final String accessToken) { + return new AccessTokenDto(accessToken, null); + } +} diff --git a/module-api/src/main/java/com/mile/common/interceptor/MoimAuthInterceptor.java b/module-api/src/main/java/com/mile/common/interceptor/MoimAuthInterceptor.java new file mode 100644 index 00000000..a8b66747 --- /dev/null +++ b/module-api/src/main/java/com/mile/common/interceptor/MoimAuthInterceptor.java @@ -0,0 +1,94 @@ +package com.mile.common.interceptor; + +import com.mile.common.auth.JwtTokenProvider; +import com.mile.common.auth.annotation.UserAuthAnnotation; +import com.mile.common.utils.thread.WriterNameContextUtil; +import com.mile.common.utils.SecureUrlUtil; +import com.mile.exception.message.ErrorMessage; +import com.mile.exception.model.ForbiddenException; +import com.mile.exception.model.UnauthorizedException; +import com.mile.writername.domain.MoimRole; +import com.mile.writername.service.vo.WriterNameInfo; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import org.springframework.web.servlet.resource.ResourceHttpRequestHandler; + +import java.util.HashMap; +import java.util.Map; + +import static org.springframework.web.servlet.HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE; + +@Component +@RequiredArgsConstructor +public class MoimAuthInterceptor implements HandlerInterceptor { + + private static final String MOIM_ID = "moimId"; + private final JwtTokenProvider jwtTokenProvider; + private final SecureUrlUtil secureUrlUtil; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + if (handler instanceof ResourceHttpRequestHandler) { + return true; + } + HandlerMethod method = (HandlerMethod) handler; + + UserAuthAnnotation annotation = method.getMethodAnnotation(UserAuthAnnotation.class); + + if (annotation != null) { + final String userToken = getUserTokenFromHeader(request); + + final HashMap roleFromUser = jwtTokenProvider.getJoinedRoleFromHeader(userToken); + final Map pathVariables = (Map) request.getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE); + + return authenticateUserFromMap(annotation, roleFromUser, pathVariables); + } + return true; + } + + private String getUserTokenFromHeader(final HttpServletRequest request) { + final String userToken = request.getHeader("Authorization"); + + if (userToken == null) { + throw new UnauthorizedException(ErrorMessage.UN_LOGIN_EXCEPTION); + } + + return userToken; + } + + private boolean authenticateUserFromMap(final UserAuthAnnotation annotation, + final Map userRoles, + final Map pathVariables) { + switch (annotation.value()) { + case OWNER -> { + final Long requestMoimId = secureUrlUtil.decodeUrl(pathVariables.get(MOIM_ID)); + if (!userRoles.containsKey(requestMoimId) || !userRoles.get(requestMoimId).moimRole().equals(MoimRole.OWNER)) { + throw new ForbiddenException(ErrorMessage.MOIM_OWNER_AUTHENTICATION_ERROR); + } + WriterNameContextUtil.setWriterNameContext(userRoles.get(requestMoimId).writerNameId()); + return true; + } + case WRITER_NAME -> { + final Long requestMoimId = secureUrlUtil.decodeUrl(pathVariables.get(MOIM_ID)); + if (!userRoles.containsKey(requestMoimId)) { + throw new ForbiddenException(ErrorMessage.USER_MOIM_AUTHENTICATE_ERROR); + } + WriterNameContextUtil.setWriterNameContext(userRoles.get(requestMoimId).writerNameId()); + return true; + } + case USER -> { + return true; + } + } + return true; + } + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { + WriterNameContextUtil.clear(); + } +} diff --git a/module-api/src/main/java/com/mile/common/resolver/user/UserIdHeaderResolver.java b/module-api/src/main/java/com/mile/common/resolver/user/UserIdHeaderResolver.java index 4f8bec0c..b6e91976 100644 --- a/module-api/src/main/java/com/mile/common/resolver/user/UserIdHeaderResolver.java +++ b/module-api/src/main/java/com/mile/common/resolver/user/UserIdHeaderResolver.java @@ -39,7 +39,7 @@ public Long resolveArgument(@NotNull MethodParameter parameter, ModelAndViewCont throw new UnauthorizedException(ErrorMessage.TOKEN_VALIDATION_ERROR); } - return jwtTokenProvider.getUserFromJwt(token); + return jwtTokenProvider.getUserFromAuthHeader(token); } } \ No newline at end of file diff --git a/module-api/src/main/java/com/mile/common/utils/ContextHolderUtil.java b/module-api/src/main/java/com/mile/common/utils/ContextHolderUtil.java index 8033880d..a9a4dabf 100644 --- a/module-api/src/main/java/com/mile/common/utils/ContextHolderUtil.java +++ b/module-api/src/main/java/com/mile/common/utils/ContextHolderUtil.java @@ -32,7 +32,7 @@ public String getUserIdFromContextHolder() { throw new UnauthorizedException(ErrorMessage.TOKEN_VALIDATION_ERROR); } - return jwtTokenProvider.getUserFromJwt(token).toString(); + return jwtTokenProvider.getUserFromAuthHeader(token).toString(); } } diff --git a/module-api/src/main/java/com/mile/common/utils/thread/WriterNameContextUtil.java b/module-api/src/main/java/com/mile/common/utils/thread/WriterNameContextUtil.java new file mode 100644 index 00000000..2827a723 --- /dev/null +++ b/module-api/src/main/java/com/mile/common/utils/thread/WriterNameContextUtil.java @@ -0,0 +1,17 @@ +package com.mile.common.utils.thread; + +public class WriterNameContextUtil { + private static final ThreadLocal writerNameContext = new ThreadLocal<>(); + + public static void setWriterNameContext(Long writerNameId) { + writerNameContext.set(writerNameId); + } + + public static Long getWriterNameContext() { + return writerNameContext.get(); + } + + public static void clear() { + writerNameContext.remove(); + } +} diff --git a/module-api/src/main/java/com/mile/config/WebConfig.java b/module-api/src/main/java/com/mile/config/WebConfig.java index 2dce679e..110e5685 100644 --- a/module-api/src/main/java/com/mile/config/WebConfig.java +++ b/module-api/src/main/java/com/mile/config/WebConfig.java @@ -2,6 +2,7 @@ import com.mile.common.interceptor.DuplicatedInterceptor; +import com.mile.common.interceptor.MoimAuthInterceptor; import com.mile.common.resolver.comment.CommentVariableResolver; import com.mile.common.resolver.moim.MoimVariableResolver; import com.mile.common.resolver.post.PostVariableResolver; @@ -27,6 +28,7 @@ public class WebConfig implements WebMvcConfigurer { private final CommentVariableResolver commentVariableResolver; private final ReplyVariableResolver replyVariableResolver; private final DuplicatedInterceptor duplicatedInterceptor; + private final MoimAuthInterceptor moimAuthInterceptor; private final UserIdHeaderResolver userIdHeaderResolver; @Value("${client.local}") @@ -59,7 +61,8 @@ public void addCorsMappings(CorsRegistry registry) { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(duplicatedInterceptor) - .addPathPatterns("/api/post/temporary", "/api/post", "/api/post/{postId}/comment","/api/comment/{commentId}", "/api/moim/{moimId}/topic"); + .addPathPatterns("/api/post/temporary", "/api/post", "/api/post/{postId}/comment", "/api/comment/{commentId}", "/api/moim/{moimId}/topic"); + registry.addInterceptor(moimAuthInterceptor); } @Override diff --git a/module-api/src/main/java/com/mile/controller/moim/MoimController.java b/module-api/src/main/java/com/mile/controller/moim/MoimController.java index 27553d82..5e5a439a 100644 --- a/module-api/src/main/java/com/mile/controller/moim/MoimController.java +++ b/module-api/src/main/java/com/mile/controller/moim/MoimController.java @@ -1,32 +1,37 @@ package com.mile.controller.moim; +import com.mile.common.auth.JwtTokenUpdater; +import com.mile.common.auth.annotation.UserAuthAnnotation; +import com.mile.common.auth.annotation.UserAuthenticationType; +import com.mile.common.auth.dto.AccessTokenDto; import com.mile.common.resolver.moim.MoimIdPathVariable; import com.mile.common.resolver.user.UserId; import com.mile.dto.SuccessResponse; import com.mile.exception.message.SuccessMessage; import com.mile.moim.service.MoimService; +import com.mile.moim.service.dto.MoimIdValueDto; +import com.mile.moim.service.dto.request.MoimCreateRequest; +import com.mile.moim.service.dto.request.MoimInfoModifyRequest; +import com.mile.moim.service.dto.request.TopicCreateRequest; +import com.mile.moim.service.dto.request.WriterMemberJoinRequest; import com.mile.moim.service.dto.response.BestMoimListResponse; import com.mile.moim.service.dto.response.ContentListResponse; import com.mile.moim.service.dto.response.InvitationCodeGetResponse; import com.mile.moim.service.dto.response.MoimAuthenticateResponse; -import com.mile.moim.service.dto.request.MoimCreateRequest; -import com.mile.moim.service.dto.response.MoimCreateResponse; import com.mile.moim.service.dto.response.MoimCuriousPostListResponse; -import com.mile.moim.service.dto.request.MoimInfoModifyRequest; import com.mile.moim.service.dto.response.MoimInfoOwnerResponse; import com.mile.moim.service.dto.response.MoimInfoResponse; import com.mile.moim.service.dto.response.MoimInvitationInfoResponse; +import com.mile.moim.service.dto.response.MoimMostCuriousWriterResponse; import com.mile.moim.service.dto.response.MoimNameConflictCheckResponse; import com.mile.moim.service.dto.response.MoimPublicStatusResponse; import com.mile.moim.service.dto.response.MoimTopicInfoListResponse; import com.mile.moim.service.dto.response.MoimTopicResponse; import com.mile.moim.service.dto.response.MoimWriterNameListGetResponse; -import com.mile.moim.service.dto.response.MoimMostCuriousWriterResponse; import com.mile.moim.service.dto.response.TemporaryPostExistResponse; -import com.mile.moim.service.dto.request.TopicCreateRequest; import com.mile.moim.service.dto.response.TopicListResponse; -import com.mile.moim.service.dto.request.WriterMemberJoinRequest; import com.mile.moim.service.dto.response.WriterNameConflictCheckResponse; +import com.mile.writername.domain.MoimRole; import com.mile.writername.service.dto.response.WriterNameShortResponse; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; @@ -46,7 +51,6 @@ import org.springframework.web.bind.annotation.RestController; import java.net.URI; -import java.util.concurrent.ExecutionException; @RestController @RequiredArgsConstructor @@ -54,16 +58,18 @@ public class MoimController implements MoimControllerSwagger { private final MoimService moimService; + private final JwtTokenUpdater jwtTokenUpdater; @Override @GetMapping("/{moimId}") + @UserAuthAnnotation(UserAuthenticationType.WRITER_NAME) public SuccessResponse getTopicsFromMoim( @MoimIdPathVariable final Long moimId, @UserId final Long userId, @PathVariable("moimId") final String moimUrl ) { return SuccessResponse.of(SuccessMessage.TOPIC_SEARCH_SUCCESS, - moimService.getContentsFromMoim(moimId, userId)); + moimService.getContentsFromMoim(moimId)); } @@ -79,16 +85,18 @@ public ResponseEntity> checkCon } @Override - @PostMapping("{moimId}/user") + @PostMapping("/{moimId}/user") public ResponseEntity joinMoim( @MoimIdPathVariable final Long moimId, @RequestBody @Valid final WriterMemberJoinRequest joinRequest, @UserId final Long userId, @PathVariable("moimId") final String moimUrl ) { - return ResponseEntity.created(URI.create( - moimService.joinMoim(moimId, userId, joinRequest).toString())) - .body(SuccessResponse.of(SuccessMessage.WRITER_JOIN_SUCCESS)); + final Long writerNameId = moimService.joinMoim(moimId, userId, joinRequest); + return ResponseEntity + .ok(SuccessResponse.of(SuccessMessage.WRITER_JOIN_SUCCESS, + AccessTokenDto.of(jwtTokenUpdater.setAccessToken(userId, moimId, writerNameId, MoimRole.WRITER) + ))); } @Override @@ -167,12 +175,13 @@ public SuccessResponse getMostCuriousPostByMoim( @Override @GetMapping("/{moimId}/info/owner") + @UserAuthAnnotation(UserAuthenticationType.OWNER) public ResponseEntity> getMoimInfoForOwner( @MoimIdPathVariable final Long moimId, @UserId final Long userId, @PathVariable("moimId") final String moimUrl ) { - return ResponseEntity.ok(SuccessResponse.of(SuccessMessage.MOIM_INFO_FOR_OWNER_GET_SUCCESS, moimService.getMoimInfoForOwner(moimId, userId))); + return ResponseEntity.ok(SuccessResponse.of(SuccessMessage.MOIM_INFO_FOR_OWNER_GET_SUCCESS, moimService.getMoimInfoForOwner(moimId))); } @Override @@ -238,11 +247,19 @@ public ResponseEntity> validateMo @PostMapping @Override - public ResponseEntity> createMoim( + public ResponseEntity> createMoim( @RequestBody @Valid final MoimCreateRequest creatRequest, @UserId final Long userId ) { - return ResponseEntity.ok(SuccessResponse.of(SuccessMessage.MOIM_CREATE_SUCCESS, moimService.createMoim(userId, creatRequest))); + MoimIdValueDto moimIdValueDto = moimService.createMoim(userId, creatRequest); + return ResponseEntity.ok( + SuccessResponse.of( + SuccessMessage.MOIM_CREATE_SUCCESS, + AccessTokenDto.of( + moimIdValueDto.data(), + jwtTokenUpdater.setAccessToken(userId, moimIdValueDto.moimId(), moimIdValueDto.writerNameId(), MoimRole.OWNER)) + ) + ); } @GetMapping("/{moimId}/invitation-code") diff --git a/module-api/src/main/java/com/mile/controller/moim/MoimControllerSwagger.java b/module-api/src/main/java/com/mile/controller/moim/MoimControllerSwagger.java index 8a566fd1..ef12ccb9 100644 --- a/module-api/src/main/java/com/mile/controller/moim/MoimControllerSwagger.java +++ b/module-api/src/main/java/com/mile/controller/moim/MoimControllerSwagger.java @@ -1,5 +1,6 @@ package com.mile.controller.moim; +import com.mile.common.auth.dto.AccessTokenDto; import com.mile.common.resolver.moim.MoimIdPathVariable; import com.mile.common.resolver.user.UserId; import com.mile.dto.ErrorResponse; @@ -309,7 +310,7 @@ ResponseEntity> getInvitationCode( content = @Content(schema = @Schema(implementation = ErrorResponse.class))) } ) - ResponseEntity> createMoim( + ResponseEntity> createMoim( @RequestBody final MoimCreateRequest creatRequest, @Parameter(schema = @Schema(implementation = String.class), in = ParameterIn.PATH) final @UserId Long userId ); diff --git a/module-api/src/main/java/com/mile/controller/user/UserController.java b/module-api/src/main/java/com/mile/controller/user/UserController.java index acccb26c..be29f4e5 100644 --- a/module-api/src/main/java/com/mile/controller/user/UserController.java +++ b/module-api/src/main/java/com/mile/controller/user/UserController.java @@ -1,6 +1,8 @@ package com.mile.controller.user; import com.mile.client.dto.UserLoginRequest; +import com.mile.common.auth.annotation.UserAuthAnnotation; +import com.mile.common.auth.annotation.UserAuthenticationType; import com.mile.common.resolver.user.UserId; import com.mile.controller.user.facade.AuthFacade; import com.mile.dto.SuccessResponse; @@ -55,6 +57,7 @@ public ResponseEntity> login( @GetMapping("/refresh-token") @Override + @UserAuthAnnotation(UserAuthenticationType.USER) public SuccessResponse refreshToken( @CookieValue(name = REFRESH_TOKEN) Cookie cookie ) { diff --git a/module-api/src/main/java/com/mile/controller/user/facade/AuthFacade.java b/module-api/src/main/java/com/mile/controller/user/facade/AuthFacade.java index 7101f737..bcdfe959 100644 --- a/module-api/src/main/java/com/mile/controller/user/facade/AuthFacade.java +++ b/module-api/src/main/java/com/mile/controller/user/facade/AuthFacade.java @@ -4,6 +4,7 @@ import com.mile.client.SocialType; import com.mile.client.dto.UserLoginRequest; import com.mile.common.auth.JwtTokenProvider; +import com.mile.writername.domain.MoimRole; import com.mile.jwt.service.TokenService; import com.mile.moim.service.dto.response.MoimListOfUserResponse; import com.mile.strategy.LoginStrategyManager; @@ -11,11 +12,15 @@ import com.mile.user.service.UserService; import com.mile.user.service.dto.AccessTokenGetSuccess; import com.mile.user.service.dto.LoginSuccessResponse; +import com.mile.writername.service.vo.WriterNameInfo; import lombok.AccessLevel; import lombok.RequiredArgsConstructor; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.stereotype.Component; +import java.util.HashMap; +import java.util.Map; + @Component @RequiredArgsConstructor(access = AccessLevel.PROTECTED) public class AuthFacade { @@ -29,9 +34,10 @@ public AccessTokenGetSuccess refreshToken( final String refreshToken ) { final Long userId = tokenService.findIdByRefreshToken(refreshToken); + final Map role = jwtTokenProvider.getJoinedRoleFromJwt(refreshToken); return AccessTokenGetSuccess.of( - jwtTokenProvider.issueAccessToken(userId) + jwtTokenProvider.issueAccessToken(userId, role) ); } @@ -59,13 +65,15 @@ private LoginSuccessResponse getTokenDto( ) { try { if (userService.isExistingUser(userResponse.socialId(), userResponse.socialType())) { - return getTokenByUserId(userService.getBySocialId(userResponse.socialId(), userResponse.socialType()).getId()); + Long userId = userService.getBySocialId(userResponse.socialId(), userResponse.socialType()).getId(); + return getTokenByUserId(userId, userService.getJoinedRoleFromUser(userId)); } else { Long id = userService.createUser(userResponse.socialId(), userResponse.socialType(), userResponse.email()); - return getTokenByUserId(id); + return getTokenByUserId(id, new HashMap<>()); } } catch (DataIntegrityViolationException e) { - return getTokenByUserId(userService.getBySocialId(userResponse.socialId(), userResponse.socialType()).getId()); + Long userId = userService.getBySocialId(userResponse.socialId(), userResponse.socialType()).getId(); + return getTokenByUserId(userId, userService.getJoinedRoleFromUser(userId)); } } @@ -92,12 +100,13 @@ public UserInfoResponse getUserInfoResponse( public LoginSuccessResponse getTokenByUserId( - final Long id + final Long id, + final Map role ) { - String refreshToken = jwtTokenProvider.issueRefreshToken(id); + String refreshToken = jwtTokenProvider.issueRefreshToken(id, role); tokenService.saveRefreshToken(id, refreshToken); return LoginSuccessResponse.of( - jwtTokenProvider.issueAccessToken(id), + jwtTokenProvider.issueAccessToken(id, role), refreshToken ); } diff --git a/module-api/src/test/java/com/mile/cocurrency/DuplicatedInterceptorTest.java b/module-api/src/test/java/com/mile/cocurrency/DuplicatedInterceptorTest.java index 3112526b..811b0179 100644 --- a/module-api/src/test/java/com/mile/cocurrency/DuplicatedInterceptorTest.java +++ b/module-api/src/test/java/com/mile/cocurrency/DuplicatedInterceptorTest.java @@ -14,8 +14,10 @@ import com.mile.user.domain.User; import com.mile.user.repository.UserRepository; import com.mile.common.utils.SecureUrlUtil; +import com.mile.writername.domain.MoimRole; import com.mile.writername.domain.WriterName; import com.mile.writername.repository.WriterNameRepository; +import com.mile.writername.service.vo.WriterNameInfo; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -29,7 +31,9 @@ import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; @@ -62,6 +66,7 @@ public class DuplicatedInterceptorTest { private static Long USER_ID; private static String MOIM_ID; private static String TOPIC_ID; + private static Map joinedRole = new HashMap<>(); @BeforeEach @Transactional @@ -91,6 +96,7 @@ public void setUp() { MOIM_ID = secureUrlUtil.encodeUrl(moim.getId()); TOPIC_ID = secureUrlUtil.encodeUrl(topic.getId()); + joinedRole.put(moim.getId(), WriterNameInfo.of(writerName.getId(), MoimRole.OWNER)); } @Test @@ -101,7 +107,7 @@ public void multipleRequestTest() throws Exception { int numberOfThread = 4; ExecutorService executorService = Executors.newFixedThreadPool(numberOfThread); CountDownLatch latch = new CountDownLatch(numberOfThread); - String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID); + String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID, joinedRole); PostCreateRequest bodyDto = new PostCreateRequest( MOIM_ID, diff --git a/module-api/src/test/java/com/mile/cocurrency/UniqueNameLockTest.java b/module-api/src/test/java/com/mile/cocurrency/UniqueNameLockTest.java index 65f7efe1..d258dff2 100644 --- a/module-api/src/test/java/com/mile/cocurrency/UniqueNameLockTest.java +++ b/module-api/src/test/java/com/mile/cocurrency/UniqueNameLockTest.java @@ -6,6 +6,7 @@ import com.mile.moim.service.dto.request.MoimCreateRequest; import com.mile.user.domain.User; import com.mile.user.repository.UserRepository; +import com.mile.writername.domain.MoimRole; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; @@ -19,6 +20,7 @@ import org.springframework.test.web.servlet.MvcResult; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.UUID; import java.util.concurrent.CountDownLatch; @@ -68,7 +70,7 @@ public void uniqueMoimNameTest() throws Exception { MoimCreateRequest(randomName, "string", false, "string", "string", "string", "string", "str", "string"); String body = objectMapper.writeValueAsString(bodyDto); - String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID); + String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID, new HashMap<>()); // when diff --git a/module-api/src/test/java/com/mile/controller/MoimControllerTest.java b/module-api/src/test/java/com/mile/controller/MoimControllerTest.java index c45ae6a2..5858d423 100644 --- a/module-api/src/test/java/com/mile/controller/MoimControllerTest.java +++ b/module-api/src/test/java/com/mile/controller/MoimControllerTest.java @@ -16,8 +16,10 @@ import com.mile.user.domain.User; import com.mile.user.repository.UserRepository; import com.mile.common.utils.SecureUrlUtil; +import com.mile.writername.domain.MoimRole; import com.mile.writername.domain.WriterName; import com.mile.writername.repository.WriterNameRepository; +import com.mile.writername.service.vo.WriterNameInfo; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -29,6 +31,7 @@ import org.springframework.test.web.servlet.MvcResult; import org.springframework.transaction.annotation.Transactional; +import java.util.HashMap; import java.util.UUID; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @@ -69,7 +72,8 @@ public class MoimControllerTest { private static Long USER_ID; private static String MOIM_ID; private static String randomString; - + private static HashMap joinedRole = new HashMap<>(); + private static HashMap newJoinedRole = new HashMap<>(); @BeforeEach @Transactional @@ -95,8 +99,9 @@ public void setUp() { moim.setOwner(writerName); moimRepository.saveAndFlush(moim); - Topic topic = topicRepository.saveAndFlush(Topic.create(moim, new TopicCreateRequest(randomString, randomString.substring(0,4), randomString))); + Topic topic = topicRepository.saveAndFlush(Topic.create(moim, new TopicCreateRequest(randomString, randomString.substring(0, 4), randomString))); MOIM_ID = secureUrlUtil.encodeUrl(moim.getId()); + joinedRole.put(moim.getId(), WriterNameInfo.of(writerName.getId(), MoimRole.OWNER)); } /* @@ -123,7 +128,7 @@ public void getBestMoim() throws Exception { public void parameterErrorTest() throws Exception { //given String variable = UUID.randomUUID().toString(); - String requestUri = "/api/moim/" + variable; + String requestUri = "/api/moim/" + variable + "/information"; //when MvcResult result = mockMvc.perform( @@ -159,7 +164,7 @@ public void getBestPostOfMoim() throws Exception { @DisplayName("모임 초대 코드가 정상적으로 조회된다.") public void getMoimInvitationCodeTest() throws Exception { //given - String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID); + String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID, joinedRole); String requestUri = "/api/moim/" + MOIM_ID + "/invitation-code"; //when @@ -177,7 +182,7 @@ public void getMoimInvitationCodeTest() throws Exception { @DisplayName("글모임의 주제들이 정상적으로 조회된다.") public void getTopicFromMoimTest() throws Exception { //given - String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID); + String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID, joinedRole); String requestUri = "/api/moim/" + MOIM_ID; //when @@ -196,8 +201,10 @@ public void getTopicFromMoimTest() throws Exception { @DisplayName("글모임에 정상적으로 가입된다.") public void joinMoimTest() throws Exception { //given + randomString = UUID.randomUUID().toString().substring(0, 6); + User user = userRepository.saveAndFlush(User.of(randomString, randomString, SocialType.GOOGLE)); String randomShortString = UUID.randomUUID().toString().substring(0, 6); - String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID); + String token = "Bearer " + jwtTokenProvider.issueAccessToken(user.getId(), newJoinedRole); String requestUri = "/api/moim/" + MOIM_ID + "/user"; String requestBody = objectMapper.writeValueAsString( WriterMemberJoinRequest.of( @@ -216,7 +223,7 @@ public void joinMoimTest() throws Exception { .andReturn(); //then - assertThat(result.getResponse().getStatus()).isEqualTo(CREATED); + assertThat(result.getResponse().getStatus()).isEqualTo(OK); } @Test @@ -275,7 +282,7 @@ public void getPublicStatusTest() throws Exception { public void getTemporaryPostOfMoim() throws Exception { //given String requestUri = "/api/moim/" + MOIM_ID + "/temporary"; - String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID); + String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID, joinedRole); //when MvcResult result = mockMvc.perform( @@ -293,7 +300,7 @@ public void getTemporaryPostOfMoim() throws Exception { @DisplayName("글 모임 뷰의 본인 필명이 정상적으로 반환된다.") public void getWriterNameForUserTest() throws Exception { //given - String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID); + String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID, joinedRole); String requestUri = "/api/moim/" + MOIM_ID + "/writername"; //when @@ -318,7 +325,7 @@ public void postMoimTest() throws Exception { String randomString = UUID.randomUUID().toString().substring(0, 7); String randemTagString = UUID.randomUUID().toString().substring(0, 3); User user = userRepository.save(User.of(randomString, randomString, SocialType.GOOGLE)); - String token = "Bearer " + jwtTokenProvider.issueAccessToken(user.getId()); + String token = "Bearer " + jwtTokenProvider.issueAccessToken(user.getId(), new HashMap<>()); String createRequest = objectMapper.writeValueAsString( new MoimCreateRequest( randomString, @@ -350,7 +357,7 @@ public void postMoimTest() throws Exception { @DisplayName("관리자 페이지 글감 조회가 정상적으로 반환된다.") public void getTopicForOwnerTest() throws Exception { //given - String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID); + String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID, joinedRole); String requestUri = "/api/moim/" + MOIM_ID + "/admin/topics"; @@ -372,7 +379,7 @@ public void getTopicForOwnerTest() throws Exception { @Transactional public void getWriterNamesForOwnerTest() throws Exception { //given - String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID); + String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID, joinedRole); String requestUri = "/api/moim/" + MOIM_ID + "/writernames"; //when @@ -395,7 +402,7 @@ public void putMoimInfoTest() throws Exception { //given String randomTagString = UUID.randomUUID().toString().substring(0, 3); String requestUri = "/api/moim/" + MOIM_ID + "/info"; - String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID); + String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID, joinedRole); String request = objectMapper.writeValueAsString(new MoimInfoModifyRequest( randomString, @@ -420,7 +427,7 @@ public void putMoimInfoTest() throws Exception { @DisplayName("글감을 정상적으로 등록한다.") public void createTopicTest() throws Exception { //given - String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID); + String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID, joinedRole); String requestUri = "/api/moim/" + MOIM_ID + "/topic"; String request = objectMapper.writeValueAsString( TopicCreateRequest.of(randomString, "---", randomString)); @@ -440,7 +447,7 @@ public void createTopicTest() throws Exception { @DisplayName("글모임이 정상적으로 삭제된다.") public void deleteMoimTest() throws Exception { //given - String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID); + String token = "Bearer " + jwtTokenProvider.issueAccessToken(USER_ID, joinedRole); String requestUri = "/api/moim/" + MOIM_ID; //when diff --git a/module-auth/src/main/java/com/mile/jwt/repository/TokenRepository.java b/module-auth/src/main/java/com/mile/jwt/repository/TokenRepository.java index e43d6c6b..92c27b36 100644 --- a/module-auth/src/main/java/com/mile/jwt/repository/TokenRepository.java +++ b/module-auth/src/main/java/com/mile/jwt/repository/TokenRepository.java @@ -9,4 +9,5 @@ public interface TokenRepository extends CrudRepository { Optional findByRefreshToken(final String refreshToken); Optional findById(final Long id); + void deleteById(final long id); } \ No newline at end of file diff --git a/module-auth/src/main/java/com/mile/jwt/service/TokenService.java b/module-auth/src/main/java/com/mile/jwt/service/TokenService.java index cf241df0..4f837570 100644 --- a/module-auth/src/main/java/com/mile/jwt/service/TokenService.java +++ b/module-auth/src/main/java/com/mile/jwt/service/TokenService.java @@ -41,9 +41,6 @@ public Long findIdByRefreshToken( public void deleteRefreshToken( final Long userId ) { - Token token = tokenRepository.findById(userId).orElseThrow( - () -> new NotFoundException(ErrorMessage.REFRESH_TOKEN_NOT_FOUND) - ); - tokenRepository.delete(token); + tokenRepository.deleteById(userId); } } \ No newline at end of file diff --git a/module-domain/src/main/java/com/mile/moim/service/MoimService.java b/module-domain/src/main/java/com/mile/moim/service/MoimService.java index 45dcae60..d5f0e7cb 100644 --- a/module-domain/src/main/java/com/mile/moim/service/MoimService.java +++ b/module-domain/src/main/java/com/mile/moim/service/MoimService.java @@ -9,6 +9,7 @@ import com.mile.moim.domain.Moim; import com.mile.moim.domain.popular.MoimCuriousWriter; import com.mile.moim.domain.popular.MoimPopularInfo; +import com.mile.moim.service.dto.MoimIdValueDto; import com.mile.moim.service.dto.request.MoimCreateRequest; import com.mile.moim.service.dto.request.MoimInfoModifyRequest; import com.mile.moim.service.dto.request.TopicCreateRequest; @@ -78,10 +79,8 @@ public class MoimService { private static final int BEST_MOIM_DEFAULT_NUMBER = 3; public ContentListResponse getContentsFromMoim( - final Long moimId, - final Long userId + final Long moimId ) { - postRetriever.authenticateUserOfMoim(writerNameRetriever.isUserInMoim(moimId, userId)); return ContentListResponse.of(topicRetriever.getContentsFromMoim(moimId)); } @@ -298,7 +297,7 @@ public String createTopic( } @AtomicValidateUniqueMoimName - public MoimCreateResponse createMoim( + public MoimIdValueDto createMoim( final Long userId, final MoimCreateRequest createRequest ) { @@ -306,13 +305,13 @@ public MoimCreateResponse createMoim( Moim moim = moimCreator.createMoim(createRequest); User user = userRetriever.findById(userId); - setMoimOwner(moim, user, createRequest); + final Long writerNameId = setMoimOwner(moim, user, createRequest); setFirstTopic(moim, userId, createRequest); - return MoimCreateResponse.of(moim.getIdUrl(), moim.getIdUrl()); + return MoimIdValueDto.of(moim.getId(), writerNameId, MoimCreateResponse.of(moim.getIdUrl(), moim.getIdUrl())); } - private void setMoimOwner( + private Long setMoimOwner( final Moim moim, final User user, final MoimCreateRequest createRequest @@ -321,6 +320,7 @@ private void setMoimOwner( WriterName owner = writerNameRetriever.findById(writerNameService.createWriterName(user, moim, joinRequest)); moim.setOwner(owner); moim.setIdUrl(secureUrlUtil.encodeUrl(moim.getId())); + return owner.getId(); } @@ -335,11 +335,9 @@ private void setFirstTopic( } public MoimInfoOwnerResponse getMoimInfoForOwner( - final Long moimId, - final Long userId + final Long moimId ) { Moim moim = moimRetriever.findById(moimId); - moimRetriever.authenticateOwnerOfMoim(moim, userRetriever.findById(userId)); return MoimInfoOwnerResponse.of(moim); } diff --git a/module-domain/src/main/java/com/mile/moim/service/dto/MoimIdValueDto.java b/module-domain/src/main/java/com/mile/moim/service/dto/MoimIdValueDto.java new file mode 100644 index 00000000..f1fade00 --- /dev/null +++ b/module-domain/src/main/java/com/mile/moim/service/dto/MoimIdValueDto.java @@ -0,0 +1,15 @@ +package com.mile.moim.service.dto; + +public record MoimIdValueDto( + Long moimId, + Long writerNameId, + T data +) { + public static MoimIdValueDto of( + final Long moimId, + final Long writerNameId, + final T data + ) { + return new MoimIdValueDto<>(moimId, writerNameId, data); + } +} diff --git a/module-domain/src/main/java/com/mile/moim/service/dto/response/MoimCreateResponse.java b/module-domain/src/main/java/com/mile/moim/service/dto/response/MoimCreateResponse.java index 5fc3746b..5214c6b8 100644 --- a/module-domain/src/main/java/com/mile/moim/service/dto/response/MoimCreateResponse.java +++ b/module-domain/src/main/java/com/mile/moim/service/dto/response/MoimCreateResponse.java @@ -5,9 +5,10 @@ public record MoimCreateResponse( String inviteCode ) { public static MoimCreateResponse of( - String moimId, - String inviteCode + final String moimId, + final String inviteCode ) { return new MoimCreateResponse(moimId, inviteCode); } + } diff --git a/module-domain/src/main/java/com/mile/user/service/UserService.java b/module-domain/src/main/java/com/mile/user/service/UserService.java index eae62fe2..64b59004 100644 --- a/module-domain/src/main/java/com/mile/user/service/UserService.java +++ b/module-domain/src/main/java/com/mile/user/service/UserService.java @@ -4,11 +4,14 @@ import com.mile.moim.service.dto.response.MoimListOfUserResponse; import com.mile.moim.service.dto.response.MoimOfUserResponse; import com.mile.user.domain.User; +import com.mile.writername.domain.MoimRole; import com.mile.writername.service.WriterNameRetriever; import com.mile.writername.service.WriterNameService; +import com.mile.writername.service.vo.WriterNameInfo; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.Map; import java.util.stream.Collectors; @Service @@ -48,4 +51,8 @@ public MoimListOfUserResponse getMoimOfUserList(final Long userId) { .map(MoimOfUserResponse::of) .collect(Collectors.toList())); } + + public Map getJoinedRoleFromUser(final Long userId) { + return writerNameRetriever.getJoinedRoleFromUserId(userId); + } } diff --git a/module-domain/src/main/java/com/mile/writername/domain/MoimRole.java b/module-domain/src/main/java/com/mile/writername/domain/MoimRole.java new file mode 100644 index 00000000..fb0f3f07 --- /dev/null +++ b/module-domain/src/main/java/com/mile/writername/domain/MoimRole.java @@ -0,0 +1,14 @@ +package com.mile.writername.domain; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor +@Getter +public enum MoimRole { + + WRITER("WRITER"), + OWNER("OWNER"); + + private final String role; +} diff --git a/module-domain/src/main/java/com/mile/writername/repository/WriterNameRepository.java b/module-domain/src/main/java/com/mile/writername/repository/WriterNameRepository.java index b07b187b..9cd120ed 100644 --- a/module-domain/src/main/java/com/mile/writername/repository/WriterNameRepository.java +++ b/module-domain/src/main/java/com/mile/writername/repository/WriterNameRepository.java @@ -37,7 +37,7 @@ public interface WriterNameRepository extends JpaRepository { Optional findById(final Long id); @Query("select w from WriterName w join fetch w.moim where w.writer.id = :writerId") - List findAllByWriterId(final Long writerId); + List findAllByWriterId(final long writerId); Integer countAllByWriter(final User user); diff --git a/module-domain/src/main/java/com/mile/writername/service/WriterNameRetriever.java b/module-domain/src/main/java/com/mile/writername/service/WriterNameRetriever.java index 248554d2..e4e1ff51 100644 --- a/module-domain/src/main/java/com/mile/writername/service/WriterNameRetriever.java +++ b/module-domain/src/main/java/com/mile/writername/service/WriterNameRetriever.java @@ -5,15 +5,18 @@ import com.mile.exception.model.NotFoundException; import com.mile.moim.domain.Moim; import com.mile.user.domain.User; +import com.mile.writername.domain.MoimRole; import com.mile.writername.domain.WriterName; import com.mile.writername.repository.WriterNameRepository; import com.mile.writername.service.dto.response.WriterNameShortResponse; +import com.mile.writername.service.vo.WriterNameInfo; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Component; import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; @@ -74,7 +77,7 @@ public WriterName findByMoimAndUserWithNotExceptionCase( final Long writerId ) { return writerNameRepository.findByMoimIdAndWriterId(moimId, writerId) - .orElseThrow( () -> new ForbiddenException(ErrorMessage.WRITER_NAME_NON_AUTHENTICATE) + .orElseThrow(() -> new ForbiddenException(ErrorMessage.WRITER_NAME_NON_AUTHENTICATE) ); } @@ -120,6 +123,16 @@ public int findNumbersOfWritersByMoim( return writerNameRepository.countByMoim(moim); } + public Map getJoinedRoleFromUserId(final Long userId) { + return writerNameRepository.findAllByWriterId(userId).stream().collect( + Collectors.toMap(writerName -> writerName.getMoim().getId(), this::getWriterNameMoimRole) + ); + } + + private WriterNameInfo getWriterNameMoimRole(final WriterName writerName) { + return WriterNameInfo.of(writerName.getId(), writerName.getMoim().getOwner().equals(writerName) ? MoimRole.OWNER : MoimRole.WRITER); + } + public List findTop2ByCuriousCount(final Moim moim) { return writerNameRepository.findTop2ByMoimAndTotalCuriousCountGreaterThanOrderByTotalCuriousCountDesc(moim, MIN_TOTAL_CURIOUS_COUNT); } diff --git a/module-domain/src/main/java/com/mile/writername/service/vo/WriterNameInfo.java b/module-domain/src/main/java/com/mile/writername/service/vo/WriterNameInfo.java new file mode 100644 index 00000000..8e455f58 --- /dev/null +++ b/module-domain/src/main/java/com/mile/writername/service/vo/WriterNameInfo.java @@ -0,0 +1,12 @@ +package com.mile.writername.service.vo; + +import com.mile.writername.domain.MoimRole; + +public record WriterNameInfo( + Long writerNameId, + MoimRole moimRole +) { + public static WriterNameInfo of(final Long writerNameId, final MoimRole moimRole) { + return new WriterNameInfo(writerNameId, moimRole); + } +} \ No newline at end of file