diff --git a/app/common/src/main/java/stirling/software/common/service/UserServiceInterface.java b/app/common/src/main/java/stirling/software/common/service/UserServiceInterface.java index a833d4c84..074f42200 100644 --- a/app/common/src/main/java/stirling/software/common/service/UserServiceInterface.java +++ b/app/common/src/main/java/stirling/software/common/service/UserServiceInterface.java @@ -8,4 +8,6 @@ public interface UserServiceInterface { long getTotalUsersCount(); boolean isCurrentUserAdmin(); + + boolean isCurrentUserFirstLogin(); } diff --git a/app/core/src/main/java/stirling/software/SPDF/config/InitialSetup.java b/app/core/src/main/java/stirling/software/SPDF/config/InitialSetup.java index 2d261c660..0a63a6f48 100644 --- a/app/core/src/main/java/stirling/software/SPDF/config/InitialSetup.java +++ b/app/core/src/main/java/stirling/software/SPDF/config/InitialSetup.java @@ -28,6 +28,8 @@ public class InitialSetup { private final ApplicationProperties applicationProperties; + private static boolean isNewServer = false; + @PostConstruct public void init() throws IOException { initUUIDKey(); @@ -88,6 +90,13 @@ public class InitialSetup { } public void initSetAppVersion() throws IOException { + // Check if this is a new server before setting the version + String existingVersion = applicationProperties.getAutomaticallyGenerated().getAppVersion(); + isNewServer = + existingVersion == null + || existingVersion.isEmpty() + || existingVersion.equals("0.0.0"); + String appVersion = "0.0.0"; Resource resource = new ClassPathResource("version.properties"); Properties props = new Properties(); @@ -99,4 +108,8 @@ public class InitialSetup { GeneralUtils.saveKeyToSettings("AutomaticallyGenerated.appVersion", appVersion); applicationProperties.getAutomaticallyGenerated().setAppVersion(appVersion); } + + public static boolean isNewServer() { + return isNewServer; + } } diff --git a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java index b578d7c42..02b5233b8 100644 --- a/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java +++ b/app/core/src/main/java/stirling/software/SPDF/controller/api/misc/ConfigController.java @@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.RequestParam; import io.swagger.v3.oas.annotations.Hidden; import stirling.software.SPDF.config.EndpointConfiguration; +import stirling.software.SPDF.config.InitialSetup; import stirling.software.common.annotations.api.ConfigApi; import stirling.software.common.configuration.AppConfig; import stirling.software.common.model.ApplicationProperties; @@ -78,6 +79,22 @@ public class ConfigController { } configData.put("isAdmin", isAdmin); + // Check if this is a new server (version was 0.0.0 before initialization) + configData.put("isNewServer", InitialSetup.isNewServer()); + + // Check if the current user is a first-time user + boolean isNewUser = + false; // Default to false when security is disabled or user not found + if (userService != null) { + try { + isNewUser = userService.isCurrentUserFirstLogin(); + } catch (Exception e) { + // If there's an error, assume not new user for safety + isNewUser = false; + } + } + configData.put("isNewUser", isNewUser); + // System settings configData.put( "enableAlphaFunctionality", diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java index 92a1f82ac..9f2ce9456 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/controller/api/UserController.java @@ -742,4 +742,31 @@ public class UserController { return errorMessage; } } + + @PostMapping("/complete-initial-setup") + public ResponseEntity completeInitialSetup() { + try { + String username = userService.getCurrentUsername(); + if (username == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .body("User not authenticated"); + } + + Optional userOpt = userService.findByUsernameIgnoreCase(username); + if (userOpt.isEmpty()) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body("User not found"); + } + + User user = userOpt.get(); + user.setHasCompletedInitialSetup(true); + userRepository.save(user); + + log.info("User {} completed initial setup", username); + return ResponseEntity.ok().body(Map.of("success", true)); + } catch (Exception e) { + log.error("Error completing initial setup", e); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .body("Failed to complete initial setup"); + } + } } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java index 02bd08a5b..8f64d3187 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/model/User.java @@ -56,6 +56,9 @@ public class User implements UserDetails, Serializable { @Column(name = "isFirstLogin") private Boolean isFirstLogin = false; + @Column(name = "hasCompletedInitialSetup") + private Boolean hasCompletedInitialSetup = false; + @Column(name = "roleName") private String roleName; @@ -103,6 +106,14 @@ public class User implements UserDetails, Serializable { this.isFirstLogin = isFirstLogin; } + public boolean hasCompletedInitialSetup() { + return hasCompletedInitialSetup != null && hasCompletedInitialSetup; + } + + public void setHasCompletedInitialSetup(boolean hasCompletedInitialSetup) { + this.hasCompletedInitialSetup = hasCompletedInitialSetup; + } + public void setAuthenticationType(AuthenticationType authenticationType) { this.authenticationType = authenticationType.toString().toLowerCase(); } diff --git a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java index d13fcc0cd..4772368f8 100644 --- a/app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java +++ b/app/proprietary/src/main/java/stirling/software/proprietary/security/service/UserService.java @@ -663,6 +663,21 @@ public class UserService implements UserServiceInterface { return false; } + public boolean isCurrentUserFirstLogin() { + try { + String username = getCurrentUsername(); + if (username != null) { + Optional userOpt = findByUsernameIgnoreCase(username); + if (userOpt.isPresent()) { + return !userOpt.get().hasCompletedInitialSetup(); + } + } + } catch (Exception e) { + log.debug("Error checking first login status", e); + } + return false; + } + @Transactional public void syncCustomApiUser(String customApiKey) { if (customApiKey == null || customApiKey.trim().isBlank()) {