Skip to content

Commit

Permalink
Merge pull request #93 from playkuround/feat/appVersion
Browse files Browse the repository at this point in the history
Supports app version check for each OS
  • Loading branch information
redcarrot1 authored Mar 23, 2024
2 parents 63b8c77 + d6c5b2b commit 7bb07a0
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,38 @@
package com.playkuround.playkuroundserver.domain.common;

public abstract class AppVersion {
import java.util.Map;
import java.util.stream.Stream;

private AppVersion() {
}
import static java.util.stream.Collectors.toMap;

public enum AppVersion {

ANDROID("2.0.2"),
IOS("2.0.0");

private static String CURRENT_VERSION = "2.0.2";
private static final Map<String, AppVersion> stringToEnum =
Stream.of(values())
.collect(toMap(Object::toString, e -> e));
private String latest_updated_version;

AppVersion(String latest_updated_version) {
this.latest_updated_version = latest_updated_version;
}

public static boolean isCurrentVersion(String version) {
return CURRENT_VERSION.equals(version);
public static boolean isLatestUpdatedVersion(String os, String version) {
AppVersion appVersion = stringToEnum.get(os.toUpperCase());
if (appVersion == null) {
throw new NotSupportOSException();
}
return appVersion.latest_updated_version.equals(version);
}

public static void changeAppVersion(String version) {
CURRENT_VERSION = version;
public static void changeLatestUpdatedVersion(String os, String version) {
AppVersion appVersion = stringToEnum.get(os.toUpperCase());
if (appVersion == null) {
throw new NotSupportOSException();
}
appVersion.latest_updated_version = version;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.playkuround.playkuroundserver.domain.common;

import com.playkuround.playkuroundserver.global.error.ErrorCode;
import com.playkuround.playkuroundserver.global.error.exception.BusinessException;

public class NotSupportOSException extends BusinessException {

public NotSupportOSException() {
super(ErrorCode.NOT_SUPPORT_OS);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.playkuround.playkuroundserver.global.common.response.ApiResponse;
import com.playkuround.playkuroundserver.global.util.ApiUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
Expand All @@ -23,9 +24,15 @@ public class AdminApi {
private final BadgeService badgeService;

@PostMapping("/app-version")
@Operation(summary = "앱 버전 올리기(관리자모드)", description = "앱 버전을 올립니다. 이전버전 사용자에게 공지 메시지를 보냅니다.")
public ApiResponse<Void> updateAppVersion(@RequestParam("version") String appVersion) {
AppVersion.changeAppVersion(appVersion);
@Operation(summary = "앱 버전 올리기(관리자모드)", description = "앱 버전을 올립니다. 이전버전 사용자에게 공지 메시지를 보냅니다.",
parameters = {
@Parameter(name = "version", description = "최신 앱 버전", example = "2.0.2", required = true),
@Parameter(name = "os", description = "모바일 운영체제(android 또는 ios)", example = "android", required = true)
}
)
public ApiResponse<Void> updateAppVersion(@RequestParam("version") String appVersion,
@RequestParam("os") String os) {
AppVersion.changeLatestUpdatedVersion(os, appVersion);
return ApiUtils.success(null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.playkuround.playkuroundserver.global.security.UserDetailsImpl;
import com.playkuround.playkuroundserver.global.util.ApiUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
Expand Down Expand Up @@ -51,14 +52,26 @@ public ApiResponse<Boolean> isAvailableNickname(@RequestParam("nickname") String
}

@GetMapping("/notification")
@Operation(summary = "유저 알림 얻기", description = "유저 개인 알림을 얻습니다. 저장된 메시지는 (정상적인) 호출 이후 삭제됩니다.")
@Operation(summary = "유저 알림 얻기",
description = "유저 개인 알림을 얻습니다. 저장된 메시지는 (정상적인) 호출 이후 삭제됩니다.<br>" +
"=== name 명 리스트 ===<br>" +
"1. 시스템 점검 중일 때(단독으로만 반환): system_check<br>" +
"2. 앱 버전 업데이트가 필요할 때(단독으로만 반환): update<br>" +
"3. 새로운 뱃지 획득: new_badge<br>" +
"4. 개인 알림: alarm",
parameters = {
@Parameter(name = "version", description = "현재 앱 버전", example = "2.0.2", required = true),
@Parameter(name = "os", description = "모바일 운영체제(android 또는 ios)", example = "android")
}
)
public ApiResponse<List<UserNotificationResponse>> getNotification(@AuthenticationPrincipal UserDetailsImpl userDetails,
@RequestParam("version") String appVersion) {
@RequestParam("version") String appVersion,
@RequestParam(name = "os", required = false, defaultValue = "android") String os) {
List<UserNotificationResponse> response;
if (!SystemCheck.isSystemAvailable()) {
response = UserNotificationResponse.from(UserNotificationResponse.NotificationEnum.SYSTEM_CHECK);
}
else if (!AppVersion.isCurrentVersion(appVersion)) {
else if (!AppVersion.isLatestUpdatedVersion(os, appVersion)) {
response = UserNotificationResponse.from(UserNotificationResponse.NotificationEnum.UPDATE);
}
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public enum ErrorCode {
ACCESS_DENIED(HttpStatus.FORBIDDEN, "C004", "권한이 없습니다."),
INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "C005", "서버 내부에서 에러가 발생하였습니다."),
BAD_REQUEST(HttpStatus.BAD_REQUEST, "C006", "Bad Request"),
NOT_SUPPORT_OS(HttpStatus.BAD_REQUEST, "C007", "지원하지 않는 OS입니다."),

// User
EMAIL_DUPLICATION(HttpStatus.BAD_REQUEST, "U001", "이미 존재하는 이메일입니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,50 @@ class updateAppVersion {
void success_1(String version) throws Exception {
// expect
mockMvc.perform(post("/api/admin/app-version")
.queryParam("version", version))
.queryParam("version", version)
.queryParam("os", "android"))
.andExpect(status().isOk())
.andDo(print());

assertThat(AppVersion.isCurrentVersion(version)).isTrue();
assertThat(AppVersion.isLatestUpdatedVersion("android", version)).isTrue();
}

@ParameterizedTest
@ValueSource(strings = {"android", "ios"})
@WithMockCustomUser(role = Role.ROLE_ADMIN)
@DisplayName("OS 별로 앱 버전을 별도로 관리한다.")
void success_2(String os) throws Exception {
String appVersion = "12.0.0";
// expect
mockMvc.perform(post("/api/admin/app-version")
.queryParam("version", appVersion)
.queryParam("os", os))
.andExpect(status().isOk())
.andDo(print());

assertThat(AppVersion.isLatestUpdatedVersion(os, appVersion)).isTrue();
}

@Test
@WithMockCustomUser(role = Role.ROLE_ADMIN)
@DisplayName("존재하지 않는 OS이면 에러가 발생한다.")
void fail_1() throws Exception {
mockMvc.perform(post("/api/admin/app-version")
.queryParam("version", "12.0.0")
.queryParam("os", "notFound"))
.andExpect(status().isBadRequest())
.andDo(print());
}

@Test
@WithMockCustomUser(role = Role.ROLE_USER)
@DisplayName("ROLE_ADMIN이 아니면 권한 에러가 발생한다.")
void fail_2() throws Exception {
mockMvc.perform(post("/api/admin/app-version")
.queryParam("version", "12.0.0")
.queryParam("os", "android"))
.andExpect(status().isForbidden())
.andDo(print());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.playkuround.playkuroundserver.domain.user.api;

import com.playkuround.playkuroundserver.TestUtil;
import com.playkuround.playkuroundserver.domain.common.AppVersion;
import com.playkuround.playkuroundserver.domain.common.SystemCheck;
import com.playkuround.playkuroundserver.domain.user.dao.UserRepository;
import com.playkuround.playkuroundserver.domain.user.domain.Major;
import com.playkuround.playkuroundserver.domain.user.domain.User;
import com.playkuround.playkuroundserver.securityConfig.WithMockCustomUser;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
Expand Down Expand Up @@ -81,5 +84,49 @@ void checkDuplicateWhenNotDuplication() throws Exception {
.andExpect(jsonPath("$.response").value(true))
.andDo(print());
}

@Nested
@WithMockCustomUser
@DisplayName("유저 알림 얻기")
class getNotification {

@Test
@DisplayName("시스템이 사용 불가능할 때: name=system_check")
void success_1() throws Exception {
// given
SystemCheck.changeSystemAvailable(false);
String os = "android";
String version = "2.0.0";
AppVersion.changeLatestUpdatedVersion(os, version);

// expect
mockMvc.perform(get("/api/users/notification")
.queryParam("version", version)
.queryParam("os", os))
.andExpect(status().isOk())
.andExpect(jsonPath("$.isSuccess").value(true))
.andExpect(jsonPath("$.response[0].name").value("system_check"))
.andDo(print());
}

@Test
@DisplayName("앱 버전을 지원하지 않을 때: name=update")
void success_2() throws Exception {
// given
SystemCheck.changeSystemAvailable(true);
String os = "android";
String version = "2.0.0";
AppVersion.changeLatestUpdatedVersion(os, version);

// expect
mockMvc.perform(get("/api/users/notification")
.queryParam("version", "notSupport")
.queryParam("os", os))
.andExpect(status().isOk())
.andExpect(jsonPath("$.isSuccess").value(true))
.andExpect(jsonPath("$.response[0].name").value("update"))
.andDo(print());
}
}
}

0 comments on commit 7bb07a0

Please sign in to comment.