diff --git a/src/main/java/net/javahippie/fitpub/config/KomootSupport.java b/src/main/java/net/javahippie/fitpub/config/KomootSupport.java new file mode 100644 index 0000000..db43c34 --- /dev/null +++ b/src/main/java/net/javahippie/fitpub/config/KomootSupport.java @@ -0,0 +1,21 @@ +package net.javahippie.fitpub.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * Central support flag for Komoot integration availability. + */ +@Component +public class KomootSupport { + + private final boolean enabled; + + public KomootSupport(@Value("${fitpub.komoot.enabled:false}") boolean enabled) { + this.enabled = enabled; + } + + public boolean isEnabled() { + return enabled; + } +} diff --git a/src/main/java/net/javahippie/fitpub/controller/GlobalModelAttributes.java b/src/main/java/net/javahippie/fitpub/controller/GlobalModelAttributes.java new file mode 100644 index 0000000..38f631a --- /dev/null +++ b/src/main/java/net/javahippie/fitpub/controller/GlobalModelAttributes.java @@ -0,0 +1,21 @@ +package net.javahippie.fitpub.controller; + +import lombok.RequiredArgsConstructor; +import net.javahippie.fitpub.config.KomootSupport; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ModelAttribute; + +/** + * Exposes global model attributes required by shared layouts. + */ +@ControllerAdvice +@RequiredArgsConstructor +public class GlobalModelAttributes { + + private final KomootSupport komootSupport; + + @ModelAttribute("komootSupportEnabled") + public boolean komootSupportEnabled() { + return komootSupport.isEnabled(); + } +} diff --git a/src/main/java/net/javahippie/fitpub/controller/KomootImportController.java b/src/main/java/net/javahippie/fitpub/controller/KomootImportController.java index 146ebe3..08e0928 100644 --- a/src/main/java/net/javahippie/fitpub/controller/KomootImportController.java +++ b/src/main/java/net/javahippie/fitpub/controller/KomootImportController.java @@ -3,6 +3,7 @@ package net.javahippie.fitpub.controller; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import net.javahippie.fitpub.config.KomootSupport; import net.javahippie.fitpub.model.dto.KomootActivityImportRequest; import net.javahippie.fitpub.model.dto.KomootActivitiesResponse; import net.javahippie.fitpub.model.dto.KomootImportExecutionResponse; @@ -30,6 +31,7 @@ import java.util.UUID; @Slf4j public class KomootImportController { + private final KomootSupport komootSupport; private final KomootImportService komootImportService; private final UserRepository userRepository; @@ -38,6 +40,8 @@ public class KomootImportController { @Valid @RequestBody KomootImportRequest request, Authentication authentication ) { + ensureKomootSupportEnabled(); + UUID fitPubUserId = userRepository.findByUsername(authentication.getName()) .orElseThrow(() -> new IllegalArgumentException("Authenticated user not found")) .getId(); @@ -53,6 +57,8 @@ public class KomootImportController { @Valid @RequestBody KomootActivityImportRequest request, Authentication authentication ) { + ensureKomootSupportEnabled(); + UUID fitPubUserId = userRepository.findByUsername(authentication.getName()) .orElseThrow(() -> new IllegalArgumentException("Authenticated user not found")) .getId(); @@ -67,6 +73,12 @@ public class KomootImportController { return ResponseEntity.ok(response); } + private void ensureKomootSupportEnabled() { + if (!komootSupport.isEnabled()) { + throw new KomootSupportDisabledException(); + } + } + @ExceptionHandler(IllegalArgumentException.class) public ResponseEntity handleIllegalArgument(IllegalArgumentException e) { return ResponseEntity.badRequest().body(new ErrorResponse(e.getMessage())); @@ -86,5 +98,13 @@ public class KomootImportController { return ResponseEntity.status(HttpStatus.BAD_GATEWAY).body(new ErrorResponse(e.getMessage())); } + @ExceptionHandler(KomootSupportDisabledException.class) + public ResponseEntity handleKomootSupportDisabled(KomootSupportDisabledException e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse("Komoot support is disabled.")); + } + record ErrorResponse(String error) {} + + static class KomootSupportDisabledException extends RuntimeException { + } } diff --git a/src/main/java/net/javahippie/fitpub/controller/KomootImportViewController.java b/src/main/java/net/javahippie/fitpub/controller/KomootImportViewController.java index 8ac7e7d..c5922b8 100644 --- a/src/main/java/net/javahippie/fitpub/controller/KomootImportViewController.java +++ b/src/main/java/net/javahippie/fitpub/controller/KomootImportViewController.java @@ -1,5 +1,7 @@ package net.javahippie.fitpub.controller; +import lombok.RequiredArgsConstructor; +import net.javahippie.fitpub.config.KomootSupport; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @@ -10,10 +12,21 @@ import java.time.LocalDate; * Serves the Komoot import preview page. */ @Controller +@RequiredArgsConstructor public class KomootImportViewController { + private final KomootSupport komootSupport; + @GetMapping("/komoot-import") public String komootImportPage(Model model) { + if (!komootSupport.isEnabled()) { + model.addAttribute("pageTitle", "Komoot Import Unavailable"); + model.addAttribute("featureName", "Komoot Import"); + model.addAttribute("featureMessage", "Komoot support is currently disabled on this instance."); + model.addAttribute("featureIcon", "bi bi-signpost-split text-secondary"); + return "feature-disabled"; + } + LocalDate today = LocalDate.now(); model.addAttribute("pageTitle", "Komoot Import"); model.addAttribute("defaultStartDate", today.withDayOfYear(1)); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 572481a..59e175e 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -104,7 +104,9 @@ fitpub: enabled: ${WEATHER_ENABLED:false} api-key: ${OPENWEATHERMAP_API_KEY:} +# Komoot settings komoot: + enabled: ${KOMOOT_ENABLED:false} base-url: ${KOMOOT_BASE_URL:https://www.komoot.com} paginated-request-delay-ms: ${KOMOOT_PAGINATED_REQUEST_DELAY_MS:1000} detail-to-gpx-delay-ms: ${KOMOOT_DETAIL_TO_GPX_DELAY_MS:500} diff --git a/src/main/resources/templates/feature-disabled.html b/src/main/resources/templates/feature-disabled.html new file mode 100644 index 0000000..d2ba933 --- /dev/null +++ b/src/main/resources/templates/feature-disabled.html @@ -0,0 +1,29 @@ + + + + + Feature Unavailable + + + +
+
+
+
+

+ + Feature +

+

+ This feature is currently unavailable on this FitPub instance. +

+
+
+
+
+ + diff --git a/src/main/resources/templates/layout.html b/src/main/resources/templates/layout.html index f78e5d6..93d3d0e 100644 --- a/src/main/resources/templates/layout.html +++ b/src/main/resources/templates/layout.html @@ -97,7 +97,7 @@ Batch Import -
  • +
  • Komoot Import