Skip to content

Commit 3be6fb1

Browse files
authored
Merge pull request #309 from DevKor-github/dev
[codex] Add public privacy policy page
2 parents 0b7bf3a + 503dd42 commit 3be6fb1

8 files changed

Lines changed: 352 additions & 11 deletions

File tree

ontime-back/src/main/java/devkor/ontime_back/config/SecurityConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
7272
.headers(headers -> headers
7373
.frameOptions(frameOptions -> frameOptions.disable()))
7474
.authorizeHttpRequests(auth -> auth
75-
.requestMatchers("/", "/account-deletion", "/css/**", "/images/**", "/js/**", "/favicon.ico", "/h2-console/**").permitAll()
75+
.requestMatchers("/", "/account-deletion", "/privacy-policy", "/css/**", "/images/**", "/js/**", "/favicon.ico", "/h2-console/**").permitAll()
7676
.requestMatchers("/health", "/actuator/health/**", "/oauth2/sign-up", "oauth2/success", "login/success", "/oauth2/google/login", "/oauth2/kakao/login", "/oauth2/apple/login", "/sign-up", "/*/additional-info").permitAll()
7777
.requestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-resources/**", "/webjars/**", "/swagger-ui.html").permitAll()
7878
.requestMatchers("/error").permitAll()

ontime-back/src/main/java/devkor/ontime_back/controller/AccountDeletionPageController.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,9 @@ public ResponseEntity<String> getAccountDeletionPage() {
133133
134134
<h2>Privacy Policy</h2>
135135
<p>
136-
Once the public OnTime privacy policy is hosted, it should be linked from this page and listed in
137-
Google Play Console together with this account deletion request URL.
136+
The public OnTime privacy policy is available at
137+
<a href="https://ontime-back.duckdns.org/privacy-policy">https://ontime-back.duckdns.org/privacy-policy</a>.
138+
It can be listed in Google Play Console together with this account deletion request URL.
138139
</p>
139140
</section>
140141
</main>

ontime-back/src/main/java/devkor/ontime_back/controller/PrivacyPolicyController.java

Lines changed: 295 additions & 0 deletions
Large diffs are not rendered by default.

ontime-back/src/main/java/devkor/ontime_back/global/jwt/JwtAuthenticationFilter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
@Slf4j
3333
public class JwtAuthenticationFilter extends OncePerRequestFilter {
3434

35-
private static final List<String> NO_CHECK_URLS = List.of("/login", "/health", "/actuator/health", "/swagger-ui", "/sign-up", "/account-deletion", "/v3/api-docs", "/oauth2/google/login", "/oauth2/kakao/login", "/oauth2/apple/login");
35+
private static final List<String> NO_CHECK_URLS = List.of("/login", "/health", "/actuator/health", "/swagger-ui", "/sign-up", "/account-deletion", "/privacy-policy", "/v3/api-docs", "/oauth2/google/login", "/oauth2/kakao/login", "/oauth2/apple/login");
3636

3737
private final JwtTokenProvider jwtTokenProvider;
3838
private final UserRepository userRepository;

ontime-back/src/test/java/devkor/ontime_back/ControllerTestSupport.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
FirebaseTokenController.class,
2727
AlarmController.class,
2828
SocialAuthController.class,
29-
AccountDeletionPageController.class
29+
AccountDeletionPageController.class,
30+
PrivacyPolicyController.class
3031
}
3132
)
3233
public abstract class ControllerTestSupport {

ontime-back/src/test/java/devkor/ontime_back/controller/AccountDeletionPageControllerTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@ void getAccountDeletionPage() throws Exception {
3131
.andExpect(content().string(containsString("retain that feedback for up to")))
3232
.andExpect(content().string(containsString("Operational logs, monitoring records, and security records may be retained for up to 90 days")))
3333
.andExpect(content().string(containsString("retained for no longer than 30 days")))
34-
.andExpect(content().string(containsString("privacy policy")));
34+
.andExpect(content().string(containsString("https://ontime-back.duckdns.org/privacy-policy")));
3535
}
3636
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package devkor.ontime_back.controller;
2+
3+
import devkor.ontime_back.ControllerTestSupport;
4+
import devkor.ontime_back.TestSecurityConfig;
5+
import org.junit.jupiter.api.DisplayName;
6+
import org.junit.jupiter.api.Test;
7+
import org.springframework.context.annotation.Import;
8+
9+
import static org.hamcrest.Matchers.containsString;
10+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
11+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
12+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
13+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
14+
15+
@Import(TestSecurityConfig.class)
16+
class PrivacyPolicyControllerTest extends ControllerTestSupport {
17+
18+
@DisplayName("개인정보 처리방침 페이지를 로그인 없이 HTML로 조회한다.")
19+
@Test
20+
void getPrivacyPolicy() throws Exception {
21+
mockMvc.perform(get("/privacy-policy"))
22+
.andExpect(status().isOk())
23+
.andExpect(header().string("Cache-Control", containsString("max-age=3600")))
24+
.andExpect(content().contentTypeCompatibleWith("text/html"))
25+
.andExpect(content().string(containsString("OnTime Privacy Policy")))
26+
.andExpect(content().string(containsString("App name: OnTime")))
27+
.andExpect(content().string(containsString("Developer/entity: ejun")))
28+
.andExpect(content().string(containsString("jjoonleo@gmail.com")))
29+
.andExpect(content().string(containsString("Effective date: May 10, 2026")))
30+
.andExpect(content().string(containsString("https://ontime-back.duckdns.org/account-deletion")))
31+
.andExpect(content().string(containsString("Account data")))
32+
.andExpect(content().string(containsString("Schedule/preparation data")))
33+
.andExpect(content().string(containsString("Alarm/notification data")))
34+
.andExpect(content().string(containsString("Feedback")))
35+
.andExpect(content().string(containsString("Local app data")))
36+
.andExpect(content().string(containsString("Technical/diagnostic data")))
37+
.andExpect(content().string(containsString("account data and user-owned app data are deleted")))
38+
.andExpect(content().string(containsString("for up to 1 year")))
39+
.andExpect(content().string(containsString("for up to 90")))
40+
.andExpect(content().string(containsString("retained for no longer than 30 days")));
41+
}
42+
}

ontime-back/src/test/java/devkor/ontime_back/global/jwt/JwtAuthenticationFilterTest.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import devkor.ontime_back.repository.UserRepository;
44
import jakarta.servlet.FilterChain;
55
import org.junit.jupiter.api.DisplayName;
6-
import org.junit.jupiter.api.Test;
6+
import org.junit.jupiter.params.ParameterizedTest;
7+
import org.junit.jupiter.params.provider.ValueSource;
78
import org.springframework.mock.web.MockHttpServletRequest;
89
import org.springframework.mock.web.MockHttpServletResponse;
910

@@ -13,14 +14,15 @@
1314

1415
class JwtAuthenticationFilterTest {
1516

16-
@DisplayName("계정 삭제 요청 페이지는 액세스 토큰 없이 JWT 필터를 통과한다.")
17-
@Test
18-
void skipsAccountDeletionPage() throws Exception {
17+
@DisplayName("공개 HTML 페이지는 액세스 토큰 없이 JWT 필터를 통과한다.")
18+
@ParameterizedTest
19+
@ValueSource(strings = {"/account-deletion", "/privacy-policy"})
20+
void skipsPublicHtmlPages(String path) throws Exception {
1921
JwtTokenProvider jwtTokenProvider = mock(JwtTokenProvider.class);
2022
UserRepository userRepository = mock(UserRepository.class);
2123
FilterChain filterChain = mock(FilterChain.class);
2224
JwtAuthenticationFilter filter = new JwtAuthenticationFilter(jwtTokenProvider, userRepository);
23-
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/account-deletion");
25+
MockHttpServletRequest request = new MockHttpServletRequest("GET", path);
2426
MockHttpServletResponse response = new MockHttpServletResponse();
2527

2628
filter.doFilter(request, response, filterChain);

0 commit comments

Comments
 (0)