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

YEL-150 [deploy] 1.1.8v #290

Merged
merged 17 commits into from
Sep 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deploy-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: 🚀 YELL:O Deploy for staging server

on:
push:
branches: [ "develop" ]
branches: [ "staging" ]

permissions:
contents: read
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: 🚀 YELL:O Deploy
on:
push:
branches:
- staging
- main

permissions:
contents: read
Expand Down
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ dependencies {

// jwt decode
implementation 'org.bouncycastle:bcprov-jdk15on:1.69'
implementation 'io.jsonwebtoken:jjwt-api:0.11.2'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.2'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.2'

// AOP
implementation 'org.springframework.boot:spring-boot-starter-aop'
}

asciidoctor {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

import static com.yello.server.global.common.SuccessCode.DELETE_COOLDOWN_ADMIN_SUCCESS;
import static com.yello.server.global.common.SuccessCode.DELETE_USER_ADMIN_SUCCESS;
import static com.yello.server.global.common.SuccessCode.LOGIN_USER_ADMIN_SUCCESS;
import static com.yello.server.global.common.SuccessCode.READ_COOLDOWN_ADMIN_SUCCESS;
import static com.yello.server.global.common.SuccessCode.READ_USER_ADMIN_SUCCESS;

import com.yello.server.domain.admin.dto.request.AdminLoginRequest;
import com.yello.server.domain.admin.dto.response.AdminCooldownResponse;
import com.yello.server.domain.admin.dto.response.AdminLoginResponse;
import com.yello.server.domain.admin.dto.response.AdminUserResponse;
import com.yello.server.domain.admin.service.AdminService;
import com.yello.server.domain.user.entity.User;
Expand All @@ -17,6 +20,8 @@
import lombok.val;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -28,6 +33,12 @@ public class AdminController {

private final AdminService adminService;

@PostMapping("/login")
public BaseResponse<AdminLoginResponse> postAdminLogin(@RequestBody AdminLoginRequest request) {
val data = adminService.login(request);
return BaseResponse.success(LOGIN_USER_ADMIN_SUCCESS, data);
}

@GetMapping("/user")
public BaseResponse<AdminUserResponse> getUserAdmin(@AccessTokenUser User user, @RequestParam Integer page,
@Nullable @RequestParam String yelloId) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.yello.server.domain.admin.dto.request;

import lombok.Builder;

@Builder
public record AdminLoginRequest(
String password
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.yello.server.domain.admin.dto.response;

import lombok.Builder;

@Builder
public record AdminLoginResponse(
String accessToken
) {

public static AdminLoginResponse of(String accessToken) {
return AdminLoginResponse.builder()
.accessToken(accessToken)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
package com.yello.server.domain.admin.service;

import static com.yello.server.global.common.ErrorCode.USER_ADMIN_NOT_FOUND_EXCEPTION;

import com.yello.server.domain.admin.dto.request.AdminLoginRequest;
import com.yello.server.domain.admin.dto.response.AdminCooldownContentVO;
import com.yello.server.domain.admin.dto.response.AdminCooldownResponse;
import com.yello.server.domain.admin.dto.response.AdminLoginResponse;
import com.yello.server.domain.admin.dto.response.AdminUserContentVO;
import com.yello.server.domain.admin.dto.response.AdminUserResponse;
import com.yello.server.domain.admin.exception.UserAdminNotFoundException;
import com.yello.server.domain.admin.repository.UserAdminRepository;
import com.yello.server.domain.authorization.service.TokenProvider;
import com.yello.server.domain.cooldown.entity.Cooldown;
import com.yello.server.domain.cooldown.repository.CooldownRepository;
import com.yello.server.domain.user.entity.User;
import com.yello.server.domain.user.repository.UserRepository;
import com.yello.server.domain.user.service.UserManager;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
Expand All @@ -21,9 +29,28 @@
public class AdminService {

private final UserRepository userRepository;
private final UserManager userManager;
private final TokenProvider tokenProvider;
private final CooldownRepository cooldownRepository;
private final UserAdminRepository userAdminRepository;

public AdminLoginResponse login(AdminLoginRequest request) {
AtomicReference<String> accessToken = new AtomicReference<>();

userManager.getOfficialUsers()
.forEach((user) -> {
if (user.getYelloId().equals(request.password())) {
accessToken.set(tokenProvider.createAccessToken(user.getId(), user.getUuid()));
}
});

if (accessToken.get() == null || accessToken.get().isEmpty()) {
throw new UserAdminNotFoundException(USER_ADMIN_NOT_FOUND_EXCEPTION);
}

return AdminLoginResponse.of(accessToken.get());
}

public AdminUserResponse findUser(Long adminId, Pageable page) {
// exception
final User admin = userRepository.getById(adminId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.yello.server.domain.authorization.filter;

import static com.yello.server.domain.authorization.filter.JwtFilter.BEARER;
import static com.yello.server.domain.authorization.filter.JwtFilter.X_ACCESS_AUTH;
import static com.yello.server.domain.authorization.filter.JwtFilter.X_REFRESH_AUTH;
import static com.yello.server.global.common.ErrorCode.AUTHENTICATION_ERROR;
import static com.yello.server.global.common.ErrorCode.EXPIRED_TOKEN;
import static com.yello.server.global.common.ErrorCode.ILLEGAL_TOKEN;
Expand Down Expand Up @@ -43,25 +45,45 @@ protected void doFilterInternal(
if (requestPath.equals("/")
|| requestPath.startsWith("/docs")
|| requestPath.startsWith("/actuator") || requestPath.startsWith("/prometheus")
|| requestPath.startsWith("/api/v1/auth")) {
|| requestPath.startsWith("/api/v1/admin/login")
|| (requestPath.startsWith("/api/v1/auth")
&& !requestPath.startsWith("/api/v1/auth/token/issue"))) {
filterChain.doFilter(request, response);
return;
}

val accessHeader = request.getHeader(AUTHORIZATION);
log.info("Authorization : {}", accessHeader);
try {
if (requestPath.startsWith("/api/v1/auth/token/issue")) {
val accessHeader = request.getHeader(X_ACCESS_AUTH);
val refreshHeader = request.getHeader(X_REFRESH_AUTH);
log.info("Authorization-access : {}", accessHeader);
log.info("Authorization-refresh : {}", refreshHeader);

if (accessHeader==null || !accessHeader.startsWith(BEARER)) {
throw new CustomAuthenticationException(AUTHENTICATION_ERROR);
}
if (accessHeader == null || !accessHeader.startsWith(BEARER)
|| refreshHeader == null || !refreshHeader.startsWith(BEARER)) {
throw new CustomAuthenticationException(AUTHENTICATION_ERROR);
}

val token = accessHeader.substring(BEARER.length());
try {
Long userId = tokenProvider.getUserId(token);
request.setAttribute("userId", userId);
val token = accessHeader.substring(BEARER.length());
Long userId = tokenProvider.getUserId(token);
request.setAttribute("userId", userId);
} else {
val accessHeader = request.getHeader(AUTHORIZATION);
log.info("Authorization : {}", accessHeader);

if (accessHeader == null || !accessHeader.startsWith(BEARER)) {
throw new CustomAuthenticationException(AUTHENTICATION_ERROR);
}

val token = accessHeader.substring(BEARER.length());
Long userId = tokenProvider.getUserId(token);
request.setAttribute("userId", userId);
}
} catch (ExpiredJwtException e) {
log.info("토큰이 만료되었습니다. 토큰 재발급 API 호출이 필요합니다.");
throw new InvalidTokenException(EXPIRED_TOKEN);
if (!requestPath.startsWith("/api/v1/auth/token/issue")) {
log.info("토큰이 만료되었습니다. 토큰 재발급 API 호출이 필요합니다.");
throw new InvalidTokenException(EXPIRED_TOKEN);
}
} catch (MalformedJwtException e) {
log.info("토큰이 변조되었습니다.");
throw new InvalidTokenException(MALFORMED_TOKEN);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
@RequiredArgsConstructor
public class JwtFilter extends OncePerRequestFilter {

public static final String X_ACCESS_AUTH = "X-ACCESS-AUTH";
public static final String X_REFRESH_AUTH = "X-REFRESH-AUTH";
public static final String BEARER = "Bearer ";
private final UserRepository userRepository;

Expand All @@ -36,6 +38,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
if (requestPath.equals("/")
|| requestPath.startsWith("/docs")
|| requestPath.startsWith("/actuator") || requestPath.startsWith("/prometheus")
|| requestPath.startsWith("/api/v1/admin/login")
|| requestPath.startsWith("/api/v1/auth")) {
filterChain.doFilter(request, response);
return;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.yello.server.domain.authorization.service;

import static com.yello.server.global.common.ErrorCode.DEVICE_TOKEN_CONFLICT_USER_EXCEPTION;
import static com.yello.server.global.common.ErrorCode.NOT_SIGNIN_USER_EXCEPTION;
import static com.yello.server.global.common.ErrorCode.UUID_CONFLICT_USER_EXCEPTION;
import static com.yello.server.global.common.ErrorCode.YELLOID_CONFLICT_USER_EXCEPTION;
Expand Down Expand Up @@ -66,7 +67,7 @@ public ServiceTokenVO setNewAccessToken(String refreshToken) {

@Override
public void validateSignupRequest(SignUpRequest signUpRequest) {
userRepository.findByUuid(signUpRequest.uuid())
userRepository.findByUuidNotFiltered(signUpRequest.uuid())
.ifPresent(action -> {
throw new UserConflictException(UUID_CONFLICT_USER_EXCEPTION);
});
Expand All @@ -75,6 +76,11 @@ public void validateSignupRequest(SignUpRequest signUpRequest) {
.ifPresent(action -> {
throw new UserConflictException(YELLOID_CONFLICT_USER_EXCEPTION);
});

userRepository.findByDeviceTokenNotFiltered(signUpRequest.deviceToken())
.ifPresent(action -> {
throw new UserConflictException(DEVICE_TOKEN_CONFLICT_USER_EXCEPTION);
});
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public Purchase createTicket(User user, ProductType productType, Gateway gateway
@Override
public void handleAppleTransactionError(ResponseEntity<TransactionInfoResponse> response,
String transactionId) {
tokenFactory.decodeTransactionToken(response.getBody().signedTransactionInfo(),
transactionId);

if (!response.getStatusCode().is2xxSuccessful()) {
throw new AppleTokenServerErrorException(APPLE_TOKEN_SERVER_EXCEPTION);
Expand All @@ -54,4 +56,5 @@ public void handleAppleTransactionError(ResponseEntity<TransactionInfoResponse>
});
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public UserSubscribeNeededResponse getUserSubscribe(User user, LocalDateTime tim
final Optional<Purchase> mostRecentPurchase =
purchaseRepository.findTopByUserAndProductTypeOrderByCreatedAtDesc(
user, ProductType.YELLO_PLUS);
final Boolean isSubscribeNeeded = user.getSubscribe()==Subscribe.CANCELED
final Boolean isSubscribeNeeded = user.getSubscribe() == Subscribe.CANCELED
&& mostRecentPurchase.isPresent()
&& Duration.between(mostRecentPurchase.get().getCreatedAt(), time).getSeconds()
< 1 * 24 * 60 * 60;
Expand All @@ -94,7 +94,7 @@ public void verifyAppleSubscriptionTransaction(Long userId,

purchaseManager.handleAppleTransactionError(verifyReceiptResponse, request.transactionId());

if (user.getSubscribe()==Subscribe.ACTIVE) {
if (user.getSubscribe() == Subscribe.ACTIVE) {
throw new SubscriptionConflictException(SUBSCRIBE_ACTIVE_EXCEPTION);
}

Expand Down Expand Up @@ -141,7 +141,7 @@ public GoogleSubscriptionGetResponse verifyGoogleSubscriptionTransaction(Long us
User user = userRepository.getById(userId);

// exception
if (user.getSubscribe()!=Subscribe.NORMAL) {
if (user.getSubscribe() != Subscribe.NORMAL) {
throw new PurchaseConflictException(GOOGLE_SUBSCRIPTIONS_FORBIDDEN_EXCEPTION);
}

Expand Down Expand Up @@ -187,7 +187,7 @@ public GoogleSubscriptionGetResponse verifyGoogleSubscriptionTransaction(Long us
GOOGLE_SUBSCRIPTION_TRANSACTION_EXPIRED_EXCEPTION);
}
case ConstantUtil.GOOGLE_PURCHASE_SUBSCRIPTION_CANCELED -> {
if (user.getSubscribe()==Subscribe.CANCELED) {
if (user.getSubscribe() == Subscribe.CANCELED) {
throw new GoogleBadRequestException(
GOOGLE_SUBSCRIPTION_DUPLICATED_CANCEL_EXCEPTION);
} else {
Expand Down Expand Up @@ -239,8 +239,9 @@ public GoogleTicketGetResponse verifyGoogleTicketTransaction(Long userId,
if (!inAppResponse.getStatusCode().is2xxSuccessful()) {
throw new GoogleTokenServerErrorException(GOOGLE_TOKEN_SERVER_EXCEPTION);
}
System.out.println("inAppResponse = " + inAppResponse);

if (inAppResponse.getBody().purchaseState()==0) {
if (inAppResponse.getBody().purchaseState() == 0) {
purchaseRepository.findByTransactionId(inAppResponse.getBody().orderId())
.ifPresent(action -> {
throw new PurchaseConflictException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ public interface UserJpaRepository extends JpaRepository<User, Long> {
"where u.uuid = :uuid")
Optional<User> findByUuid(@Param("uuid") String uuid);

@Query("select u from User u " +
"where u.uuid = :uuid")
Optional<User> findByUuidNotFiltered(@Param("uuid") String uuid);

@Query("select case when count(u) > 0 then true else false end from User u " +
"where u.uuid = :uuid " +
"and u.deletedAt is null")
Expand Down Expand Up @@ -76,7 +80,14 @@ List<User> findAllByGroupContainingYelloId(@Param("groupName") String groupName,
List<User> findAllByOtherGroupContainingYelloId(@Param("groupName") String groupName,
@Param("keyword") String keyword, @Param("uuidList") List<String> uuidList);

Optional<User> findByDeviceToken(String deviceToken);
@Query("select u from User u "
+ "where u.deviceToken = :deviceToken "
+ "and u.deletedAt is null")
Optional<User> findByDeviceToken(@Param("deviceToken") String deviceToken);

@Query("select u from User u " +
"where u.deviceToken = :deviceToken")
Optional<User> findByDeviceTokenNotFiltered(@Param("deviceToken") String deviceToken);

Long countAllByYelloIdContaining(String yelloId);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public interface UserRepository {

Optional<User> findByUuid(String uuid);

Optional<User> findByUuidNotFiltered(String uuid);

User getByUuid(String uuid);

boolean existsByUuid(String uuid);
Expand All @@ -28,6 +30,8 @@ public interface UserRepository {

Optional<User> findByDeviceToken(String deviceToken);

Optional<User> findByDeviceTokenNotFiltered(String deviceToken);

List<User> findAllByGroupId(Long groupId);

List<User> findAllByGroupContainingName(String groupName, String keyword,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ public Optional<User> findByUuid(String uuid) {
return userJpaRepository.findByUuid(uuid);
}

@Override
public Optional<User> findByUuidNotFiltered(String uuid) {
return userJpaRepository.findByUuidNotFiltered(uuid);
}

@Override
public User getByUuid(String uuid) {
return userJpaRepository.findByUuid(uuid)
Expand Down Expand Up @@ -74,6 +79,11 @@ public Optional<User> findByDeviceToken(String deviceToken) {
return userJpaRepository.findByDeviceToken(deviceToken);
}

@Override
public Optional<User> findByDeviceTokenNotFiltered(String deviceToken) {
return userJpaRepository.findByDeviceTokenNotFiltered(deviceToken);
}

@Override
public List<User> findAllByGroupId(Long groupId) {
return userJpaRepository.findAllByGroupId(groupId);
Expand Down
Loading
Loading