Skip to content

Commit

Permalink
[SAMBAD-269] 온보딩 완료 API 추가 및 온보딩 페이지 리다이렉트 로직 구현 (#115)
Browse files Browse the repository at this point in the history
  • Loading branch information
kkjsw17 authored and nahyeon99 committed Aug 24, 2024
1 parent 610343a commit a979e2c
Show file tree
Hide file tree
Showing 12 changed files with 85 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ private LoginResult generateLoginResult(User user, boolean firstLogin) {
refreshTokenEntity.rotate(refreshToken);
refreshTokenRepository.save(refreshTokenEntity);

return new LoginResult(accessToken, refreshToken, firstLogin, user.getId());
return new LoginResult(accessToken, refreshToken, firstLogin, !user.getOnboardingCompleted(), user.getId());
}

private User saveNewUser(AuthAttributes attributes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ private String determineRedirectUrl(LoginResult result, String redirectCookie) {
return redirectCookie;
}

if (result.isNotCompletedOnboarding()) {
return securityProperties.onboardingRedirectUrl();
}

if (meetingMemberService.isNotEnterAnyMeeting(result.userId())) {
return result.isNewUser()
? securityProperties.newUserRedirectUrl() + "?newUser=true"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ private LoginResult getReissuedTokenResult(HttpServletResponse response, Refresh
String reissuedAccessToken = tokenGenerator.generateAccessToken(userId);
String rotatedRefreshToken = this.rotate(savedRefreshToken);

LoginResult loginResult = new LoginResult(reissuedAccessToken, rotatedRefreshToken, false, userId);
LoginResult loginResult = new LoginResult(
reissuedAccessToken, rotatedRefreshToken, false, false, userId);
tokenInjector.injectTokensToCookie(loginResult, response);

return loginResult;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ public record LoginResult(
String accessToken,
String refreshToken,
boolean isNewUser,
boolean isNotCompletedOnboarding,
Long userId
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public record SecurityProperties(
String loginUrl,
String redirectUrl,
String newUserRedirectUrl,
String onboardingRedirectUrl,
@NestedConfigurationProperty
Cookie cookie
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.depromeet.sambad.moring.common.domain;

import java.time.LocalDateTime;
import java.time.ZoneId;

import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
Expand All @@ -23,5 +24,13 @@ public abstract class BaseTimeEntity {
@UpdateTimestamp
@Column(nullable = false)
protected LocalDateTime updatedAt;

public Long getCreatedAtWithEpochMilli() {
return this.createdAt.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}

public Long getUpdatedAtWithEpochMilli() {
return this.updatedAt.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
}
}

Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package org.depromeet.sambad.moring.user.application;

import org.depromeet.sambad.moring.user.domain.User;
import org.depromeet.sambad.moring.user.domain.UserRepository;
import org.depromeet.sambad.moring.user.presentation.exception.NotFoundUserException;
import org.depromeet.sambad.moring.user.presentation.response.OnboardingResponse;
import org.depromeet.sambad.moring.user.presentation.response.UserResponse;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class UserService {

Expand All @@ -18,4 +22,14 @@ public UserResponse findByUserId(Long userId) {
.map(UserResponse::from)
.orElseThrow(NotFoundUserException::new);
}

@Transactional
public OnboardingResponse completeOnboarding(Long userId) {
User user = userRepository.findById(userId)
.orElseThrow(NotFoundUserException::new);

user.completeOnboarding();

return OnboardingResponse.from(user);
}
}
25 changes: 19 additions & 6 deletions src/main/java/org/depromeet/sambad/moring/user/domain/User.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.depromeet.sambad.moring.user.domain;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -50,22 +48,29 @@ public class User extends BaseTimeEntity {

private String externalId;

@Column(columnDefinition = "TINYINT")
private Boolean onboardingCompleted;

@OneToMany(mappedBy = "user")
private List<MeetingMember> meetingMember = new ArrayList<>();

private User(FileEntity imageFile, String name, String email, LoginProvider loginProvider, String externalId) {
private User(
FileEntity imageFile, String name, String email, LoginProvider loginProvider, String externalId,
boolean onboardingCompleted
) {
this.profileImageFile = imageFile;
this.name = name;
this.email = email;
this.loginProvider = loginProvider;
this.externalId = externalId;
this.onboardingCompleted = onboardingCompleted;
}

public static User from(
FileEntity imageFile, AuthAttributes authAttributes
) {
return new User(imageFile, authAttributes.getName(), authAttributes.getEmail(), authAttributes.getProvider(),
authAttributes.getExternalId());
authAttributes.getExternalId(), false);
}

public String getProfileImageFileUrl() {
Expand All @@ -81,7 +86,15 @@ public boolean hasDifferentProviderWithEmail(String email, String externalId) {
return Objects.equals(this.email, email) && !Objects.equals(this.externalId, externalId);
}

public Long toEpochMilli(LocalDateTime localDateTime) {
return getCreatedAt().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
public void updateProfileImage(FileEntity fileEntity) {
this.profileImageFile = fileEntity;
}

public void completeOnboarding() {
this.onboardingCompleted = true;
}

public boolean isNotEnteredAnyMeeting() {
return meetingMember.isEmpty();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package org.depromeet.sambad.moring.user.presentation;

import org.depromeet.sambad.moring.user.application.UserService;
import org.depromeet.sambad.moring.user.domain.User;
import org.depromeet.sambad.moring.user.presentation.resolver.UserId;
import org.depromeet.sambad.moring.user.presentation.response.OnboardingResponse;
import org.depromeet.sambad.moring.user.presentation.response.UserResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

Expand All @@ -31,4 +34,15 @@ public ResponseEntity<UserResponse> getUser(@UserId Long userId) {
UserResponse response = userService.findByUserId(userId);
return ResponseEntity.ok(response);
}

@Operation(
summary = "온보딩 완료",
description = "온보딩을 완료함으로써, 더 이상 온보딩 페이지로 이동하지 않도록 수정합니다."
)
@ApiResponse(responseCode = "200", description = "성공")
@PatchMapping("/onboarding/complete")
public ResponseEntity<OnboardingResponse> completeOnboarding(@UserId Long userId) {
OnboardingResponse response = userService.completeOnboarding(userId);
return ResponseEntity.ok(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package org.depromeet.sambad.moring.user.presentation.response;

import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.*;

import org.depromeet.sambad.moring.user.domain.User;

import io.swagger.v3.oas.annotations.media.Schema;

public record OnboardingResponse(
@Schema(description = "모임에 하나도 가입되어 있지 않다면 true", example = "false", requiredMode = REQUIRED)
boolean isNotEnteredAnyMeeting
) {

public static OnboardingResponse from(User user) {
return new OnboardingResponse(user.isNotEnteredAnyMeeting());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public static UserResponse from(User user) {
user.getName(),
user.getEmail(),
user.getProfileImageFileUrl(),
user.toEpochMilli(user.getCreatedAt()),
user.toEpochMilli(user.getUpdatedAt())
user.getCreatedAtWithEpochMilli(),
user.getUpdatedAtWithEpochMilli()
);
}
}
1 change: 1 addition & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ spring:
login-url: ${LOGIN_URL:/login}
redirect-url: ${REDIRECT_URL:/}
new-user-redirect-url: ${NEW_USER_REDIRECT_URL:/}
onboarding-redirect-url: ${ONBOARDING_REDIRECT_URL:/onboarding}
cookie:
domain: ${COOKIE_DOMAIN:moring.one}
secure: ${COOKIE_SECURE:true}
Expand Down

0 comments on commit a979e2c

Please sign in to comment.