package api; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn; import java.util.Comparator; import java.util.List; import java.util.regex.Pattern; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.hateoas.Link; import org.springframework.hateoas.server.LinkRelationProvider; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.google.common.collect.ImmutableList; import resources.IndexResource; import util.SuppressFBWarnings; @RestController @RequestMapping(value = ApiRestController.API_MAPPING) public class ApiRestController { protected final Logger logger = LoggerFactory.getLogger(getClass()); public static final String API_MAPPING = "/api"; private static final Pattern ADMIN_REL_PREFIX_PATTERN = Pattern.compile("admin:", Pattern.LITERAL); private static final Pattern ADMIN_REL_QUERY_BUILDER_FORM_PATTERN = Pattern.compile("query-builder-form", Pattern.LITERAL); protected static final Comparator ADMIN_LINK_REL_COMPARATOR = Comparator.comparing(link -> link.getRel().value(), (rel1, rel2) -> { rel1 = ADMIN_REL_PREFIX_PATTERN.matcher(rel1).replaceFirst(""); rel1 = ADMIN_REL_QUERY_BUILDER_FORM_PATTERN.matcher(rel1).replaceFirst(""); rel2 = ADMIN_REL_PREFIX_PATTERN.matcher(rel2).replaceFirst(""); rel2 = ADMIN_REL_QUERY_BUILDER_FORM_PATTERN.matcher(rel2).replaceFirst(""); return rel1.compareTo(rel2); }); private final WebInvocationPrivilegeEvaluator webPrivilegeEvaluator; private final List adminRestControllers; @Autowired public ApiRestController(LinkRelationProvider rels, WebInvocationPrivilegeEvaluator webPrivilegeEvaluator, List adminRestControllers) { this.webPrivilegeEvaluator = webPrivilegeEvaluator; this.adminRestControllers = adminRestControllers; } @RequestMapping(value = "", method = RequestMethod.GET, produces = {"application/hal+json", "application/json"}) public ResponseEntity api() { IndexResource resource = new IndexResource("index", null); resource.add(linkTo(ApiRestController.class).withSelfRel()); Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); ImmutableList.Builder adminResourceLinks = ImmutableList.builder(); for (ApiRootAdminRestController adminRestController : adminRestControllers) { if (webPrivilegeEvaluator.isAllowed(adminRestController.apiRootMapping(), authentication)) { adminRestController.queryBuilderFormLink().ifPresent(link -> adminResourceLinks.add(link)); adminRestController.templatedLinkToItemPermalink().ifPresent(link -> adminResourceLinks.add(link)); adminResourceLinks.addAll(adminRestController.miscRootLinks()); } } adminResourceLinks.add(linkToTranslations()); resource.add(ImmutableList.sortedCopyOf( ADMIN_LINK_REL_COMPARATOR, adminResourceLinks.build()) ); return new ResponseEntity<>(resource, HttpStatus.OK); } @SuppressWarnings("null") @SuppressFBWarnings(value = "NP_NONNULL_PARAM_VIOLATION", justification = "Not a real method call") private Link linkToTranslations() { return linkTo(methodOn(JsonTranslationController.class).get(null, null, null)).withRel(LinkRelation.of("translate")); } }