Skip to content
Snippets Groups Projects
Commit ec72fbee authored by Hamza Remmal's avatar Hamza Remmal
Browse files

Unify ping endpoints and have a single one

parent ba2080a1
No related branches found
No related tags found
1 merge request!304Unify ping endpoints and have a single one
......@@ -49,7 +49,7 @@ public final class ShareSecretAuthentication implements Authentication {
@Override
public Object getPrincipal() {
return null;
return this;
}
@Override
......
......@@ -59,10 +59,10 @@ public class SecurityConfig {
.requestCache(RequestCacheConfigurer::disable)
.rememberMe(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> {
auth.requestMatchers("/api/v1/ping/no-auth").permitAll();
auth.requestMatchers("/api/v1/ping/auth").authenticated();
// By default, request authentication to access any end point
auth.anyRequest().authenticated();
// Do not enforce authentication for ping
auth.requestMatchers("/api/v1/ping").permitAll();
// By default, request authentication to access any end point
auth.anyRequest().authenticated();
})
.build();
}
......
......@@ -4,6 +4,8 @@ import ch.epfl.autograde.model.response.PingResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
......@@ -11,13 +13,13 @@ import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import static java.time.Instant.now;
import static java.util.Objects.nonNull;
/**
* REST Controller to ping the service
*
* @author Hamza REMMAL (hamza.remmal@epfl.ch)
* @since 1.0.0
* @version 1.0.0
*/
@Slf4j
@RestController
......@@ -26,36 +28,19 @@ import static java.time.Instant.now;
public final class PingController {
/**
* REST Endpoint to ping the service without authenticated
* @since 1.0.0
* REST Endpoint to ping the service
* @since 1.3.0
* @return
* <ul>
* <li>{@link HttpStatus.OK} if the request is successful</li>
* </ul>
*/
@GetMapping("/no-auth")
public PingResponse ping_without_auth() {
log.info("Received a ping from an unauthenticated source");
@GetMapping(consumes = MediaType.ALL_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public PingResponse ping(Authentication authentication) {
log.info("API Service received a ping");
return new PingResponse(
Date.from(now()),
false
);
}
/**
* REST Endpoint to ping the service when authenticated
* @since 1.0.0
* @return
* <ul>
* <li>{@link HttpStatus.OK} if the request is successful</li>
* </ul>
*/
@GetMapping("/auth")
public PingResponse ping_with_auth() {
log.info("Received a ping from an authenticated source");
return new PingResponse(
Date.from(now()),
true
nonNull(authentication) && authentication.isAuthenticated()
);
}
......
......@@ -5,6 +5,8 @@ import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
......@@ -13,10 +15,9 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
/**
* Test class for the {@link PingController} API.
* <p>
* This class verifies the behaviour of the ping endpoints provided by the API:
* This class verifies the behaviour of the ping endpoint provided by the API:
* <ul>
* <li>{@code /api/v1/ping/no-auth} - A public endpoint accessible without authentication.</li>
* <li>{@code /api/v1/ping/auth} - A protected endpoint requiring shared secret authentication.</li>
* <li>{@code /api/v1/ping} - An endpoint accessible without authentication.</li>
* </ul>
* It uses Spring Boot's {@link MockMvc} for testing HTTP requests and responses,
* and the {@link WithSharedSecretAuthentication} annotation to simulate requests
......@@ -32,78 +33,59 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
@SpringBootTest
public final class PingControllerTest {
/** The endpoint to perform a non-authenticated ping */
private final static String NO_AUTH_END_POINT = "/api/v1/ping/no-auth";
/** The endpoint to perform a ping */
private final static String PING_END_POINT = "/api/v1/ping";
/** The endpoint to perform an authenticated ping */
private final static String AUTH_END_POINT = "/api/v1/ping/auth";
@Autowired
private MockMvc mockMvc;
@Autowired
private MockMvc mockMvc;
/**
* If <b>not</b> authenticated with the shared secret, the request to `/api/v1/ping`
* should be <b>successful</b>
* <p>
* The following test will verify that:
* <ul>
* <li>The HTTP Status is {@link org.springframework.http.HttpStatus.OK}</li>
* <li>The {@link HttpHeaders.CONTENT_TYPE} is {@link MediaType.APPLICATION_JSON}</li>
* <li>The request will not generate cookies</li>
* <li>The {@code $.auth} field in the response's body is {@code false}</li>
* </ul>
*/
@Test
void successPingWithoutKey() throws Exception {
mockMvc.perform(get(PING_END_POINT))
.andExpectAll(
status().isOk(),
content().contentType(MediaType.APPLICATION_JSON),
header().doesNotExist(HttpHeaders.SET_COOKIE),
jsonPath("$.auth").value(false)
);
}
/**
* If <b>not</b> authenticated with the shared secret, the request to `/api/v1/ping/no-auth`
* should be <b>successful</b>
* <p>
* The following test will verify that:
* <ul>
* <li>The HTTP Status is {@link org.springframework.http.HttpStatus.OK}</li>
* </ul>
*/
@Test
void successPingNoAuthWithoutKey() throws Exception {
mockMvc.perform(get(NO_AUTH_END_POINT))
.andExpect(status().isOk());
}
/**
* If authenticated with the shared secret, the request to `/api/v1/ping`
* should be <b>successful</b>
* <p>
* The following test will verify that:
* <ul>
* <li>The HTTP Status is {@link org.springframework.http.HttpStatus.OK}</li>
* <li>The {@link HttpHeaders.CONTENT_TYPE} is {@link MediaType.APPLICATION_JSON}</li>
* <li>The request will not generate cookies</li>
* <li>The {@code $.auth} field in the response's body is {@code true}</li>
* </ul>
*/
@Test
@WithSharedSecretAuthentication
void successPingWithKey() throws Exception {
mockMvc.perform(get(PING_END_POINT))
.andExpectAll(
status().isOk(),
content().contentType(MediaType.APPLICATION_JSON),
header().doesNotExist(HttpHeaders.SET_COOKIE),
jsonPath("$.auth").value(true)
);
}
/**
* If authenticated with the shared secret, the request to `/api/v1/ping/no-auth`
* should be <b>successful</b>
* <p>
* The following test will verify that:
* <ul>
* <li>The HTTP Status is {@link org.springframework.http.HttpStatus.OK}</li>
* </ul>
*/
@Test
@WithSharedSecretAuthentication
void successPingNoAuthWithKey() throws Exception {
mockMvc.perform(get(NO_AUTH_END_POINT))
.andExpect(status().isOk());
}
/**
* If <b>not</b> authenticated with the shared secret, the request to `/api/v1/ping/auth`
* should be <b>fail</b>
* <p>
* The following test will verify that:
* <ul>
* <li>The HTTP Status is {@link org.springframework.http.HttpStatus.UNAUTHORIZED}</li>
* </ul>
*/
@Test
void failPingAuthWithoutKey() throws Exception {
mockMvc.perform(get(AUTH_END_POINT))
.andExpect(status().isUnauthorized())
;
}
/**
* If authenticated with the shared secret, the request to `/api/v1/ping/auth`
* should be <b>successful</b>
* <p>
* The following test will verify that:
* <ul>
* <li>The HTTP Status is {@link org.springframework.http.HttpStatus.OK}</li>
* </ul>
*/
@Test
@WithSharedSecretAuthentication
void successPingAuthWithKey() throws Exception {
mockMvc.perform(get(AUTH_END_POINT))
.andExpect(status().isOk());
}
// TODO: We need to test authorization here when we implement it
// TODO: We need to test authorization here when we implement it
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment