-
Notifications
You must be signed in to change notification settings - Fork 29
/
Copy pathChallongeController.java
83 lines (71 loc) · 3.69 KB
/
ChallongeController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package com.faforever.api.challonge;
import com.faforever.api.config.FafApiProperties;
import com.faforever.api.config.FafApiProperties.Challonge;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.access.annotation.Secured;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriBuilder;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import static org.springframework.web.bind.annotation.RequestMethod.DELETE;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;
import static org.springframework.web.bind.annotation.RequestMethod.PUT;
/**
* Forwards all requests to the Challonge API, using the configured API key. GET requests are allowed by anyone, all
* other requests require the role {@code ROLE_TOURNAMENT_DIRECTOR}. <p><strong>CAVEAT</strong>: This controller is
* only loaded if a Challonge API key is specified.</p>
*/
@RestController
@RequestMapping(path = ChallongeController.CHALLONGE_ROUTE)
@ConditionalOnProperty("faf-api.challonge.key")
public class ChallongeController {
public static final String CHALLONGE_READ_CACHE_NAME = "ChallongeController.challongeRead";
static final String CHALLONGE_ROUTE = "/challonge";
private final RestTemplate restTemplate;
public ChallongeController(FafApiProperties properties) {
Challonge challonge = properties.getChallonge();
restTemplate = new RestTemplateBuilder()
.rootUri(challonge.getBaseUrl())
.uriTemplateHandler(new ChallongeUriTemplateHandler(challonge.getKey()))
.build();
}
private static String translateRoute(HttpServletRequest request) {
return ((String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE))
.replace(CHALLONGE_ROUTE, "");
}
@Async
@Cacheable(cacheNames = CHALLONGE_READ_CACHE_NAME)
@RequestMapping(path = "/**", method = GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public CompletableFuture<ResponseEntity<String>> get(HttpServletRequest request) {
return CompletableFuture.completedFuture(restTemplate.getForEntity(translateRoute(request), String.class, Map.of()));
}
@Async
@Secured("ROLE_TOURNAMENT_DIRECTOR")
@RequestMapping(path = "/**", method = {POST, PUT, DELETE}, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public CompletableFuture<ResponseEntity<String>> write(@RequestBody(required = false) Object body, HttpMethod method, HttpServletRequest request) {
return CompletableFuture.completedFuture(restTemplate.exchange(translateRoute(request), method, new HttpEntity<>(body), String.class));
}
@RequiredArgsConstructor
private static class ChallongeUriTemplateHandler extends DefaultUriBuilderFactory {
private final String apiKey;
@Override
public UriBuilder uriString(String uriTemplate) {
return super.uriString(uriTemplate).queryParam("api_key", apiKey);
}
}
}