Skip to content

Commit

Permalink
Preparation for Switching to a New Database Version (#1521)
Browse files Browse the repository at this point in the history
* preparing to switch to a new database version

* add PreAuthorize

---------

Co-authored-by: Anthony Stirling <[email protected]>
  • Loading branch information
Ludy87 and Frooodle committed Jul 5, 2024
1 parent 7992741 commit be05db2
Show file tree
Hide file tree
Showing 44 changed files with 1,145 additions and 29 deletions.
3 changes: 3 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ sourceSets {
if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") {
exclude "stirling/software/SPDF/config/security/**"
exclude "stirling/software/SPDF/controller/api/UserController.java"
exclude "stirling/software/SPDF/controller/api/DatabaseController.java"
exclude "stirling/software/SPDF/controller/web/AccountWebController.java"
exclude "stirling/software/SPDF/controller/web/DatabaseWebController.java"
exclude "stirling/software/SPDF/model/ApiKeyAuthenticationToken.java"
exclude "stirling/software/SPDF/model/Authority.java"
exclude "stirling/software/SPDF/model/PersistentLogin.java"
Expand Down Expand Up @@ -120,6 +122,7 @@ dependencies {

//2.2.x requires rebuild of DB file.. need migration path
implementation "com.h2database:h2:2.1.214"
// implementation "com.h2database:h2:2.2.224"
}

testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public class CleanUrlInterceptor implements HandlerInterceptor {
"error",
"erroroauth",
"file",
"messageType");
"messageType",
"infoMessage");

@Override
public boolean preHandle(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package stirling.software.SPDF.config;

import java.io.IOException;
import java.util.List;

import stirling.software.SPDF.utils.FileInfo;

public interface DatabaseBackupInterface {
void exportDatabase() throws IOException;

boolean importDatabase();

boolean hasBackup();

List<FileInfo> getBackupList();
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,33 @@
import java.util.UUID;

import org.simpleyaml.configuration.file.YamlFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import stirling.software.SPDF.config.DatabaseBackupInterface;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.Role;

@Component
@Slf4j
public class InitialSecuritySetup {

@Autowired private UserService userService;

@Autowired private ApplicationProperties applicationProperties;

private static final Logger logger = LoggerFactory.getLogger(InitialSecuritySetup.class);
@Autowired private DatabaseBackupInterface databaseBackupHelper;

@PostConstruct
public void init() {
if (!userService.hasUsers()) {
public void init() throws IllegalArgumentException, IOException {
if (databaseBackupHelper.hasBackup() && !userService.hasUsers()) {
databaseBackupHelper.importDatabase();
} else if (!userService.hasUsers()) {
initializeAdminUser();
} else {
databaseBackupHelper.exportDatabase();
}
initializeInternalApiUser();
}
Expand All @@ -41,46 +46,45 @@ public void initSecretKey() throws IOException {
}
}

private void initializeAdminUser() {
private void initializeAdminUser() throws IOException {
String initialUsername =
applicationProperties.getSecurity().getInitialLogin().getUsername();
String initialPassword =
applicationProperties.getSecurity().getInitialLogin().getPassword();

if (initialUsername != null
&& !initialUsername.isEmpty()
&& initialPassword != null
&& !initialPassword.isEmpty()
&& !userService.findByUsernameIgnoreCase(initialUsername).isPresent()) {
try {
userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId());
logger.info("Admin user created: " + initialUsername);
log.info("Admin user created: " + initialUsername);
} catch (IllegalArgumentException e) {
logger.error("Failed to initialize security setup", e);
log.error("Failed to initialize security setup", e);
System.exit(1);
}
} else {
createDefaultAdminUser();
}
}

private void createDefaultAdminUser() {
private void createDefaultAdminUser() throws IllegalArgumentException, IOException {
String defaultUsername = "admin";
String defaultPassword = "stirling";
if (!userService.findByUsernameIgnoreCase(defaultUsername).isPresent()) {
userService.saveUser(defaultUsername, defaultPassword, Role.ADMIN.getRoleId(), true);
logger.info("Default admin user created: " + defaultUsername);
log.info("Default admin user created: " + defaultUsername);
}
}

private void initializeInternalApiUser() {
private void initializeInternalApiUser() throws IllegalArgumentException, IOException {
if (!userService.usernameExistsIgnoreCase(Role.INTERNAL_API_USER.getRoleId())) {
userService.saveUser(
Role.INTERNAL_API_USER.getRoleId(),
UUID.randomUUID().toString(),
Role.INTERNAL_API_USER.getRoleId());
userService.addApiKeyToUser(Role.INTERNAL_API_USER.getRoleId());
logger.info("Internal API user created: " + Role.INTERNAL_API_USER.getRoleId());
log.info("Internal API user created: " + Role.INTERNAL_API_USER.getRoleId());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package stirling.software.SPDF.config.security;

import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
Expand All @@ -19,6 +20,7 @@
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import stirling.software.SPDF.config.DatabaseBackupInterface;
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
import stirling.software.SPDF.model.AuthenticationType;
import stirling.software.SPDF.model.Authority;
Expand All @@ -38,8 +40,11 @@ public class UserService implements UserServiceInterface {

@Autowired private MessageSource messageSource;

@Autowired DatabaseBackupInterface databaseBackupHelper;

// Handle OAUTH2 login and user auto creation.
public boolean processOAuth2PostLogin(String username, boolean autoCreateUser) {
public boolean processOAuth2PostLogin(String username, boolean autoCreateUser)
throws IllegalArgumentException, IOException {
if (!isUsernameValid(username)) {
return false;
}
Expand Down Expand Up @@ -131,7 +136,7 @@ public boolean validateApiKeyForUser(String username, String apiKey) {
}

public void saveUser(String username, AuthenticationType authenticationType)
throws IllegalArgumentException {
throws IllegalArgumentException, IOException {
if (!isUsernameValid(username)) {
throw new IllegalArgumentException(getInvalidUsernameMessage());
}
Expand All @@ -142,9 +147,11 @@ public void saveUser(String username, AuthenticationType authenticationType)
user.addAuthority(new Authority(Role.USER.getRoleId(), user));
user.setAuthenticationType(authenticationType);
userRepository.save(user);
databaseBackupHelper.exportDatabase();
}

public void saveUser(String username, String password) throws IllegalArgumentException {
public void saveUser(String username, String password)
throws IllegalArgumentException, IOException {
if (!isUsernameValid(username)) {
throw new IllegalArgumentException(getInvalidUsernameMessage());
}
Expand All @@ -154,10 +161,11 @@ public void saveUser(String username, String password) throws IllegalArgumentExc
user.setEnabled(true);
user.setAuthenticationType(AuthenticationType.WEB);
userRepository.save(user);
databaseBackupHelper.exportDatabase();
}

public void saveUser(String username, String password, String role, boolean firstLogin)
throws IllegalArgumentException {
throws IllegalArgumentException, IOException {
if (!isUsernameValid(username)) {
throw new IllegalArgumentException(getInvalidUsernameMessage());
}
Expand All @@ -169,10 +177,11 @@ public void saveUser(String username, String password, String role, boolean firs
user.setAuthenticationType(AuthenticationType.WEB);
user.setFirstLogin(firstLogin);
userRepository.save(user);
databaseBackupHelper.exportDatabase();
}

public void saveUser(String username, String password, String role)
throws IllegalArgumentException {
throws IllegalArgumentException, IOException {
saveUser(username, password, role, false);
}

Expand Down Expand Up @@ -206,7 +215,8 @@ public boolean hasUsers() {
return userCount > 0;
}

public void updateUserSettings(String username, Map<String, String> updates) {
public void updateUserSettings(String username, Map<String, String> updates)
throws IOException {
Optional<User> userOpt = userRepository.findByUsernameIgnoreCase(username);
if (userOpt.isPresent()) {
User user = userOpt.get();
Expand All @@ -220,6 +230,7 @@ public void updateUserSettings(String username, Map<String, String> updates) {
user.setSettings(settingsMap);

userRepository.save(user);
databaseBackupHelper.exportDatabase();
}
}

Expand All @@ -235,22 +246,26 @@ public Authority findRole(User user) {
return authorityRepository.findByUserId(user.getId());
}

public void changeUsername(User user, String newUsername) throws IllegalArgumentException {
public void changeUsername(User user, String newUsername)
throws IllegalArgumentException, IOException {
if (!isUsernameValid(newUsername)) {
throw new IllegalArgumentException(getInvalidUsernameMessage());
}
user.setUsername(newUsername);
userRepository.save(user);
databaseBackupHelper.exportDatabase();
}

public void changePassword(User user, String newPassword) {
public void changePassword(User user, String newPassword) throws IOException {
user.setPassword(passwordEncoder.encode(newPassword));
userRepository.save(user);
databaseBackupHelper.exportDatabase();
}

public void changeFirstUse(User user, boolean firstUse) {
public void changeFirstUse(User user, boolean firstUse) throws IOException {
user.setFirstLogin(firstUse);
userRepository.save(user);
databaseBackupHelper.exportDatabase();
}

public void changeRole(User user, String newRole) {
Expand Down
Loading

0 comments on commit be05db2

Please sign in to comment.