mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-15 19:10:47 +02:00
refactor: move modules under app/ directory and update file paths (#3938)
# Description of Changes - **What was changed:** - Renamed top-level directories: `stirling-pdf` → `app/core`, `common` → `app/common`, `proprietary` → `app/proprietary`. - Updated all path references in `.gitattributes`, GitHub workflows (`.github/workflows/*`), scripts (`.github/scripts/*`), `.gitignore`, Dockerfiles, license files, and template settings to reflect the new structure. - Added a new CI job `check-generateOpenApiDocs` to generate and upload OpenAPI documentation. - Removed redundant `@Autowired` annotations from `TempFileShutdownHook` and `UnlockPDFFormsController`. - Minor formatting and comment adjustments in YAML templates and resource files. - **Why the change was made:** - To introduce a clear `app/` directory hierarchy for core, common, and proprietary modules, improving organization and maintainability. - To ensure continuous integration and Docker builds continue to work seamlessly with the reorganized structure. - To automate OpenAPI documentation generation as part of the CI pipeline. --- ## Checklist ### General - [x] I have read the [Contribution Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md) - [x] I have read the [Stirling-PDF Developer Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md) (if applicable) - [ ] I have read the [How to add new languages to Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md) (if applicable) - [x] I have performed a self-review of my own code - [x] My changes generate no new warnings ### Documentation - [ ] I have updated relevant docs on [Stirling-PDF's doc repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/) (if functionality has heavily changed) - [ ] I have read the section [Add New Translation Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags) (for new translation tags only) ### UI Changes (if applicable) - [ ] Screenshots or videos demonstrating the UI changes are attached (e.g., as comments or direct attachments in the PR) ### Testing (if applicable) - [ ] I have tested my changes locally. Refer to the [Testing Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/DeveloperGuide.md#6-testing) for more details.
This commit is contained in:
+267
@@ -0,0 +1,267 @@
|
||||
package stirling.software.proprietary.security;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class CustomLogoutSuccessHandlerTest {
|
||||
|
||||
@Mock private ApplicationProperties applicationProperties;
|
||||
|
||||
@InjectMocks private CustomLogoutSuccessHandler customLogoutSuccessHandler;
|
||||
|
||||
@Test
|
||||
void testSuccessfulLogout() throws IOException {
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
String logoutPath = "logout=true";
|
||||
|
||||
when(response.isCommitted()).thenReturn(false);
|
||||
when(request.getContextPath()).thenReturn("");
|
||||
when(response.encodeRedirectURL(logoutPath)).thenReturn(logoutPath);
|
||||
|
||||
customLogoutSuccessHandler.onLogoutSuccess(request, response, null);
|
||||
|
||||
verify(response).sendRedirect(logoutPath);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSuccessfulLogoutViaOAuth2() throws IOException {
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
OAuth2AuthenticationToken oAuth2AuthenticationToken = mock(OAuth2AuthenticationToken.class);
|
||||
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
|
||||
ApplicationProperties.Security.OAUTH2 oauth =
|
||||
mock(ApplicationProperties.Security.OAUTH2.class);
|
||||
|
||||
when(response.isCommitted()).thenReturn(false);
|
||||
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
|
||||
when(request.getParameter("errorOAuth")).thenReturn(null);
|
||||
when(request.getScheme()).thenReturn("http");
|
||||
when(request.getServerName()).thenReturn("localhost");
|
||||
when(request.getServerPort()).thenReturn(8080);
|
||||
when(request.getContextPath()).thenReturn("");
|
||||
when(applicationProperties.getSecurity()).thenReturn(security);
|
||||
when(security.getOauth2()).thenReturn(oauth);
|
||||
when(oAuth2AuthenticationToken.getAuthorizedClientRegistrationId()).thenReturn("test");
|
||||
|
||||
customLogoutSuccessHandler.onLogoutSuccess(request, response, oAuth2AuthenticationToken);
|
||||
|
||||
verify(response).sendRedirect("http://localhost:8080/login?logout=true");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUserIsDisabledRedirect() throws IOException {
|
||||
String error = "userIsDisabled";
|
||||
String url = "http://localhost:8080";
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
|
||||
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
|
||||
ApplicationProperties.Security.OAUTH2 oauth =
|
||||
mock(ApplicationProperties.Security.OAUTH2.class);
|
||||
|
||||
when(response.isCommitted()).thenReturn(false);
|
||||
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
|
||||
when(request.getParameter("errorOAuth")).thenReturn(null);
|
||||
when(request.getParameter("oAuth2AutoCreateDisabled")).thenReturn(null);
|
||||
when(request.getParameter("oAuth2AdminBlockedUser")).thenReturn(null);
|
||||
when(request.getParameter(error)).thenReturn("true");
|
||||
when(request.getScheme()).thenReturn("http");
|
||||
when(request.getServerName()).thenReturn("localhost");
|
||||
when(request.getServerPort()).thenReturn(8080);
|
||||
when(request.getContextPath()).thenReturn("");
|
||||
when(applicationProperties.getSecurity()).thenReturn(security);
|
||||
when(security.getOauth2()).thenReturn(oauth);
|
||||
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
|
||||
|
||||
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
|
||||
|
||||
verify(response).sendRedirect(url + "/login?errorOAuth=" + error);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUserAlreadyExistsWebRedirect() throws IOException {
|
||||
String error = "oAuth2AuthenticationErrorWeb";
|
||||
String errorPath = "userAlreadyExistsWeb";
|
||||
String url = "http://localhost:8080";
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
|
||||
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
|
||||
ApplicationProperties.Security.OAUTH2 oauth =
|
||||
mock(ApplicationProperties.Security.OAUTH2.class);
|
||||
|
||||
when(response.isCommitted()).thenReturn(false);
|
||||
when(request.getParameter(error)).thenReturn("true");
|
||||
when(request.getScheme()).thenReturn("http");
|
||||
when(request.getServerName()).thenReturn("localhost");
|
||||
when(request.getServerPort()).thenReturn(8080);
|
||||
when(request.getContextPath()).thenReturn("");
|
||||
when(applicationProperties.getSecurity()).thenReturn(security);
|
||||
when(security.getOauth2()).thenReturn(oauth);
|
||||
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
|
||||
|
||||
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
|
||||
|
||||
verify(response).sendRedirect(url + "/login?errorOAuth=" + errorPath);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testErrorOAuthRedirect() throws IOException {
|
||||
String error = "testError";
|
||||
String url = "http://localhost:8080";
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
|
||||
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
|
||||
ApplicationProperties.Security.OAUTH2 oauth =
|
||||
mock(ApplicationProperties.Security.OAUTH2.class);
|
||||
|
||||
when(response.isCommitted()).thenReturn(false);
|
||||
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
|
||||
when(request.getParameter("errorOAuth")).thenReturn("!!!" + error + "!!!");
|
||||
when(request.getScheme()).thenReturn("http");
|
||||
when(request.getServerName()).thenReturn("localhost");
|
||||
when(request.getServerPort()).thenReturn(8080);
|
||||
when(request.getContextPath()).thenReturn("");
|
||||
when(applicationProperties.getSecurity()).thenReturn(security);
|
||||
when(security.getOauth2()).thenReturn(oauth);
|
||||
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
|
||||
|
||||
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
|
||||
|
||||
verify(response).sendRedirect(url + "/login?errorOAuth=" + error);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOAuth2AutoCreateDisabled() throws IOException {
|
||||
String error = "oAuth2AutoCreateDisabled";
|
||||
String url = "http://localhost:8080";
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
|
||||
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
|
||||
ApplicationProperties.Security.OAUTH2 oauth =
|
||||
mock(ApplicationProperties.Security.OAUTH2.class);
|
||||
|
||||
when(response.isCommitted()).thenReturn(false);
|
||||
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
|
||||
when(request.getParameter("errorOAuth")).thenReturn(null);
|
||||
when(request.getParameter(error)).thenReturn("true");
|
||||
when(request.getContextPath()).thenReturn(url);
|
||||
when(request.getScheme()).thenReturn("http");
|
||||
when(request.getServerName()).thenReturn("localhost");
|
||||
when(request.getServerPort()).thenReturn(8080);
|
||||
when(request.getContextPath()).thenReturn("");
|
||||
when(applicationProperties.getSecurity()).thenReturn(security);
|
||||
when(security.getOauth2()).thenReturn(oauth);
|
||||
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
|
||||
|
||||
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
|
||||
|
||||
verify(response).sendRedirect(url + "/login?errorOAuth=" + error);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOAuth2Error() throws IOException {
|
||||
String error = "test";
|
||||
String url = "http://localhost:8080";
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
|
||||
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
|
||||
ApplicationProperties.Security.OAUTH2 oauth =
|
||||
mock(ApplicationProperties.Security.OAUTH2.class);
|
||||
|
||||
when(response.isCommitted()).thenReturn(false);
|
||||
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
|
||||
when(request.getParameter("errorOAuth")).thenReturn(null);
|
||||
when(request.getParameter("oAuth2AutoCreateDisabled")).thenReturn(null);
|
||||
when(request.getParameter("oAuth2AdminBlockedUser")).thenReturn(null);
|
||||
when(request.getParameter("userIsDisabled")).thenReturn(null);
|
||||
when(request.getParameter("error")).thenReturn("!@$!@£" + error + "£$%^*$");
|
||||
when(request.getScheme()).thenReturn("http");
|
||||
when(request.getServerName()).thenReturn("localhost");
|
||||
when(request.getServerPort()).thenReturn(8080);
|
||||
when(request.getContextPath()).thenReturn("");
|
||||
when(applicationProperties.getSecurity()).thenReturn(security);
|
||||
when(security.getOauth2()).thenReturn(oauth);
|
||||
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
|
||||
|
||||
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
|
||||
|
||||
verify(response).sendRedirect(url + "/login?errorOAuth=" + error);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOAuth2BadCredentialsError() throws IOException {
|
||||
String error = "badCredentials";
|
||||
String url = "http://localhost:8080";
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
|
||||
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
|
||||
ApplicationProperties.Security.OAUTH2 oauth =
|
||||
mock(ApplicationProperties.Security.OAUTH2.class);
|
||||
|
||||
when(response.isCommitted()).thenReturn(false);
|
||||
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
|
||||
when(request.getParameter("errorOAuth")).thenReturn(null);
|
||||
when(request.getParameter("oAuth2AutoCreateDisabled")).thenReturn(null);
|
||||
when(request.getParameter("oAuth2AdminBlockedUser")).thenReturn(null);
|
||||
when(request.getParameter("userIsDisabled")).thenReturn(null);
|
||||
when(request.getParameter("error")).thenReturn(null);
|
||||
when(request.getParameter(error)).thenReturn("true");
|
||||
when(request.getScheme()).thenReturn("http");
|
||||
when(request.getServerName()).thenReturn("localhost");
|
||||
when(request.getServerPort()).thenReturn(8080);
|
||||
when(request.getContextPath()).thenReturn("");
|
||||
when(applicationProperties.getSecurity()).thenReturn(security);
|
||||
when(security.getOauth2()).thenReturn(oauth);
|
||||
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
|
||||
|
||||
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
|
||||
|
||||
verify(response).sendRedirect(url + "/login?errorOAuth=" + error);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOAuth2AdminBlockedUser() throws IOException {
|
||||
String error = "oAuth2AdminBlockedUser";
|
||||
String url = "http://localhost:8080";
|
||||
HttpServletRequest request = mock(HttpServletRequest.class);
|
||||
HttpServletResponse response = mock(HttpServletResponse.class);
|
||||
OAuth2AuthenticationToken authentication = mock(OAuth2AuthenticationToken.class);
|
||||
ApplicationProperties.Security security = mock(ApplicationProperties.Security.class);
|
||||
ApplicationProperties.Security.OAUTH2 oauth =
|
||||
mock(ApplicationProperties.Security.OAUTH2.class);
|
||||
|
||||
when(response.isCommitted()).thenReturn(false);
|
||||
when(request.getParameter("oAuth2AuthenticationErrorWeb")).thenReturn(null);
|
||||
when(request.getParameter("errorOAuth")).thenReturn(null);
|
||||
when(request.getParameter("oAuth2AutoCreateDisabled")).thenReturn(null);
|
||||
when(request.getParameter(error)).thenReturn("true");
|
||||
when(request.getScheme()).thenReturn("http");
|
||||
when(request.getServerName()).thenReturn("localhost");
|
||||
when(request.getServerPort()).thenReturn(8080);
|
||||
when(request.getContextPath()).thenReturn("");
|
||||
when(applicationProperties.getSecurity()).thenReturn(security);
|
||||
when(security.getOauth2()).thenReturn(oauth);
|
||||
when(authentication.getAuthorizedClientRegistrationId()).thenReturn("test");
|
||||
|
||||
customLogoutSuccessHandler.onLogoutSuccess(request, response, authentication);
|
||||
|
||||
verify(response).sendRedirect(url + "/login?errorOAuth=" + error);
|
||||
}
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package stirling.software.proprietary.security.configuration;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.common.model.exception.UnsupportedProviderException;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class DatabaseConfigTest {
|
||||
|
||||
@Mock private ApplicationProperties.Datasource datasource;
|
||||
|
||||
private DatabaseConfig databaseConfig;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
databaseConfig = new DatabaseConfig(datasource, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDataSource_whenRunningEEIsFalse() throws UnsupportedProviderException {
|
||||
databaseConfig = new DatabaseConfig(datasource, false);
|
||||
|
||||
var result = databaseConfig.dataSource();
|
||||
|
||||
assertInstanceOf(DataSource.class, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultConfigurationForDataSource() throws UnsupportedProviderException {
|
||||
when(datasource.isEnableCustomDatabase()).thenReturn(false);
|
||||
|
||||
var result = databaseConfig.dataSource();
|
||||
|
||||
assertInstanceOf(DataSource.class, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomUrlForDataSource() throws UnsupportedProviderException {
|
||||
when(datasource.isEnableCustomDatabase()).thenReturn(true);
|
||||
when(datasource.getCustomDatabaseUrl()).thenReturn("jdbc:postgresql://mockUrl");
|
||||
when(datasource.getUsername()).thenReturn("test");
|
||||
when(datasource.getPassword()).thenReturn("pass");
|
||||
|
||||
var result = databaseConfig.dataSource();
|
||||
|
||||
assertInstanceOf(DataSource.class, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCustomConfigurationForDataSource() throws UnsupportedProviderException {
|
||||
when(datasource.isEnableCustomDatabase()).thenReturn(true);
|
||||
when(datasource.getCustomDatabaseUrl()).thenReturn("");
|
||||
when(datasource.getType()).thenReturn("postgresql");
|
||||
when(datasource.getHostName()).thenReturn("test");
|
||||
when(datasource.getPort()).thenReturn(1234);
|
||||
when(datasource.getName()).thenReturn("test_db");
|
||||
when(datasource.getUsername()).thenReturn("test");
|
||||
when(datasource.getPassword()).thenReturn("pass");
|
||||
|
||||
var result = databaseConfig.dataSource();
|
||||
|
||||
assertInstanceOf(DataSource.class, result);
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "Exception thrown when the DB type [{arguments}] is not supported")
|
||||
@ValueSource(strings = {"oracle", "mysql", "mongoDb"})
|
||||
void exceptionThrown_whenDBTypeIsUnsupported(String datasourceType) {
|
||||
when(datasource.isEnableCustomDatabase()).thenReturn(true);
|
||||
when(datasource.getCustomDatabaseUrl()).thenReturn("");
|
||||
when(datasource.getType()).thenReturn(datasourceType);
|
||||
|
||||
assertThrows(UnsupportedProviderException.class, () -> databaseConfig.dataSource());
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
package stirling.software.proprietary.security.configuration.ee;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static stirling.software.proprietary.security.configuration.ee.KeygenLicenseVerifier.License;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class LicenseKeyCheckerTest {
|
||||
|
||||
@Mock private KeygenLicenseVerifier verifier;
|
||||
|
||||
@Test
|
||||
void premiumDisabled_skipsVerification() {
|
||||
ApplicationProperties props = new ApplicationProperties();
|
||||
props.getPremium().setEnabled(false);
|
||||
props.getPremium().setKey("dummy");
|
||||
|
||||
LicenseKeyChecker checker = new LicenseKeyChecker(verifier, props);
|
||||
|
||||
assertEquals(License.NORMAL, checker.getPremiumLicenseEnabledResult());
|
||||
verifyNoInteractions(verifier);
|
||||
}
|
||||
|
||||
@Test
|
||||
void directKey_verified() {
|
||||
ApplicationProperties props = new ApplicationProperties();
|
||||
props.getPremium().setEnabled(true);
|
||||
props.getPremium().setKey("abc");
|
||||
when(verifier.verifyLicense("abc")).thenReturn(License.PRO);
|
||||
|
||||
LicenseKeyChecker checker = new LicenseKeyChecker(verifier, props);
|
||||
|
||||
assertEquals(License.PRO, checker.getPremiumLicenseEnabledResult());
|
||||
verify(verifier).verifyLicense("abc");
|
||||
}
|
||||
|
||||
@Test
|
||||
void fileKey_verified(@TempDir Path temp) throws IOException {
|
||||
Path file = temp.resolve("license.txt");
|
||||
Files.writeString(file, "filekey");
|
||||
|
||||
ApplicationProperties props = new ApplicationProperties();
|
||||
props.getPremium().setEnabled(true);
|
||||
props.getPremium().setKey("file:" + file.toString());
|
||||
when(verifier.verifyLicense("filekey")).thenReturn(License.ENTERPRISE);
|
||||
|
||||
LicenseKeyChecker checker = new LicenseKeyChecker(verifier, props);
|
||||
|
||||
assertEquals(License.ENTERPRISE, checker.getPremiumLicenseEnabledResult());
|
||||
verify(verifier).verifyLicense("filekey");
|
||||
}
|
||||
|
||||
@Test
|
||||
void missingFile_resultsNormal(@TempDir Path temp) {
|
||||
Path file = temp.resolve("missing.txt");
|
||||
ApplicationProperties props = new ApplicationProperties();
|
||||
props.getPremium().setEnabled(true);
|
||||
props.getPremium().setKey("file:" + file.toString());
|
||||
|
||||
LicenseKeyChecker checker = new LicenseKeyChecker(verifier, props);
|
||||
|
||||
assertEquals(License.NORMAL, checker.getPremiumLicenseEnabledResult());
|
||||
verifyNoInteractions(verifier);
|
||||
}
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package stirling.software.proprietary.security.controller.api;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.mail.MailSendException;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
|
||||
import jakarta.mail.MessagingException;
|
||||
|
||||
import stirling.software.proprietary.security.model.api.Email;
|
||||
import stirling.software.proprietary.security.service.EmailService;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class EmailControllerTest {
|
||||
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Mock private EmailService emailService;
|
||||
|
||||
@InjectMocks private EmailController emailController;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
mockMvc = MockMvcBuilders.standaloneSetup(emailController).build();
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "Case {index}: exception={0}, includeTo={1}")
|
||||
@MethodSource("emailParams")
|
||||
void shouldHandleEmailRequests(
|
||||
Exception serviceException,
|
||||
boolean includeTo,
|
||||
int expectedStatus,
|
||||
String expectedContent)
|
||||
throws Exception {
|
||||
if (serviceException == null) {
|
||||
doNothing().when(emailService).sendEmailWithAttachment(any(Email.class));
|
||||
} else {
|
||||
doThrow(serviceException).when(emailService).sendEmailWithAttachment(any(Email.class));
|
||||
}
|
||||
|
||||
var request =
|
||||
multipart("/api/v1/general/send-email")
|
||||
.file("fileInput", "dummy-content".getBytes())
|
||||
.param("subject", "Test Email")
|
||||
.param("body", "This is a test email.");
|
||||
|
||||
if (includeTo) {
|
||||
request = request.param("to", "[email protected]");
|
||||
}
|
||||
|
||||
mockMvc.perform(request)
|
||||
.andExpect(status().is(expectedStatus))
|
||||
.andExpect(content().string(expectedContent));
|
||||
}
|
||||
|
||||
static Stream<Arguments> emailParams() {
|
||||
return Stream.of(
|
||||
// success case
|
||||
Arguments.of(null, true, 200, "Email sent successfully"),
|
||||
// generic messaging error
|
||||
Arguments.of(
|
||||
new MessagingException("Failed to send email"),
|
||||
true,
|
||||
500,
|
||||
"Failed to send email: Failed to send email"),
|
||||
// missing 'to' results in MailSendException
|
||||
Arguments.of(
|
||||
new MailSendException("Invalid Addresses"),
|
||||
false,
|
||||
500,
|
||||
"Invalid Addresses"),
|
||||
// invalid email address formatting
|
||||
Arguments.of(
|
||||
new MessagingException("Invalid Addresses"),
|
||||
true,
|
||||
500,
|
||||
"Failed to send email: Invalid Addresses"));
|
||||
}
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
package stirling.software.proprietary.security.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import jakarta.mail.MessagingException;
|
||||
import jakarta.mail.internet.MimeMessage;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import jakarta.mail.MessagingException;
|
||||
import jakarta.mail.internet.MimeMessage;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.proprietary.security.model.api.Email;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public class EmailServiceTest {
|
||||
|
||||
@Mock private JavaMailSender mailSender;
|
||||
|
||||
@Mock private ApplicationProperties applicationProperties;
|
||||
|
||||
@Mock private ApplicationProperties.Mail mailProperties;
|
||||
|
||||
@Mock private MultipartFile fileInput;
|
||||
|
||||
@InjectMocks private EmailService emailService;
|
||||
|
||||
@Test
|
||||
void testSendEmailWithAttachment() throws MessagingException {
|
||||
// Mock the values returned by ApplicationProperties
|
||||
when(applicationProperties.getMail()).thenReturn(mailProperties);
|
||||
when(mailProperties.getFrom()).thenReturn("[email protected]");
|
||||
|
||||
// Create a mock Email object
|
||||
Email email = new Email();
|
||||
email.setTo("[email protected]");
|
||||
email.setSubject("Test Email");
|
||||
email.setBody("This is a test email.");
|
||||
email.setFileInput(fileInput);
|
||||
|
||||
// Mock MultipartFile behavior
|
||||
when(fileInput.getOriginalFilename()).thenReturn("testFile.txt");
|
||||
|
||||
// Mock MimeMessage
|
||||
MimeMessage mimeMessage = mock(MimeMessage.class);
|
||||
|
||||
// Configure mailSender to return the mocked MimeMessage
|
||||
when(mailSender.createMimeMessage()).thenReturn(mimeMessage);
|
||||
|
||||
// Call the service method
|
||||
emailService.sendEmailWithAttachment(email);
|
||||
|
||||
// Verify that the email was sent using mailSender
|
||||
verify(mailSender).send(mimeMessage);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendEmailWithAttachmentThrowsExceptionForMissingFilename() throws MessagingException {
|
||||
Email email = new Email();
|
||||
email.setTo("[email protected]");
|
||||
email.setSubject("Test Email");
|
||||
email.setBody("This is a test email.");
|
||||
email.setFileInput(fileInput);
|
||||
|
||||
when(fileInput.isEmpty()).thenReturn(false);
|
||||
when(fileInput.getOriginalFilename()).thenReturn("");
|
||||
|
||||
try {
|
||||
emailService.sendEmailWithAttachment(email);
|
||||
fail("Expected MessagingException to be thrown");
|
||||
} catch (MessagingException e) {
|
||||
assertEquals("An attachment is required to send the email.", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendEmailWithAttachmentThrowsExceptionForMissingFilenameNull()
|
||||
throws MessagingException {
|
||||
Email email = new Email();
|
||||
email.setTo("[email protected]");
|
||||
email.setSubject("Test Email");
|
||||
email.setBody("This is a test email.");
|
||||
email.setFileInput(fileInput);
|
||||
|
||||
when(fileInput.isEmpty()).thenReturn(false);
|
||||
when(fileInput.getOriginalFilename()).thenReturn(null);
|
||||
|
||||
try {
|
||||
emailService.sendEmailWithAttachment(email);
|
||||
fail("Expected MessagingException to be thrown");
|
||||
} catch (MessagingException e) {
|
||||
assertEquals("An attachment is required to send the email.", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendEmailWithAttachmentThrowsExceptionForMissingFile() throws MessagingException {
|
||||
Email email = new Email();
|
||||
email.setTo("[email protected]");
|
||||
email.setSubject("Test Email");
|
||||
email.setBody("This is a test email.");
|
||||
email.setFileInput(fileInput);
|
||||
|
||||
when(fileInput.isEmpty()).thenReturn(true);
|
||||
|
||||
try {
|
||||
emailService.sendEmailWithAttachment(email);
|
||||
fail("Expected MessagingException to be thrown");
|
||||
} catch (MessagingException e) {
|
||||
assertEquals("An attachment is required to send the email.", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendEmailWithAttachmentThrowsExceptionForMissingFileNull() throws MessagingException {
|
||||
Email email = new Email();
|
||||
email.setTo("[email protected]");
|
||||
email.setSubject("Test Email");
|
||||
email.setBody("This is a test email.");
|
||||
email.setFileInput(null); // Missing file
|
||||
|
||||
try {
|
||||
emailService.sendEmailWithAttachment(email);
|
||||
fail("Expected MessagingException to be thrown");
|
||||
} catch (MessagingException e) {
|
||||
assertEquals("An attachment is required to send the email.", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendEmailWithAttachmentThrowsExceptionForInvalidAddressNull()
|
||||
throws MessagingException {
|
||||
Email email = new Email();
|
||||
email.setTo(null); // Invalid address
|
||||
email.setSubject("Test Email");
|
||||
email.setBody("This is a test email.");
|
||||
email.setFileInput(fileInput);
|
||||
|
||||
try {
|
||||
emailService.sendEmailWithAttachment(email);
|
||||
fail("Expected MailSendException to be thrown");
|
||||
} catch (MessagingException e) {
|
||||
assertEquals("Invalid Addresses", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendEmailWithAttachmentThrowsExceptionForInvalidAddressEmpty()
|
||||
throws MessagingException {
|
||||
Email email = new Email();
|
||||
email.setTo(""); // Invalid address
|
||||
email.setSubject("Test Email");
|
||||
email.setBody("This is a test email.");
|
||||
email.setFileInput(fileInput);
|
||||
|
||||
try {
|
||||
emailService.sendEmailWithAttachment(email);
|
||||
fail("Expected MailSendException to be thrown");
|
||||
} catch (MessagingException e) {
|
||||
assertEquals("Invalid Addresses", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package stirling.software.proprietary.security.service;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertAll;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.proprietary.security.configuration.MailConfig;
|
||||
|
||||
class MailConfigTest {
|
||||
|
||||
private ApplicationProperties.Mail mailProps;
|
||||
|
||||
@BeforeEach
|
||||
void initMailProperties() {
|
||||
mailProps = mock(ApplicationProperties.Mail.class);
|
||||
when(mailProps.getHost()).thenReturn("smtp.example.com");
|
||||
when(mailProps.getPort()).thenReturn(587);
|
||||
when(mailProps.getUsername()).thenReturn("[email protected]");
|
||||
when(mailProps.getPassword()).thenReturn("password");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldConfigureJavaMailSenderWithCorrectProperties() {
|
||||
ApplicationProperties appProps = mock(ApplicationProperties.class);
|
||||
when(appProps.getMail()).thenReturn(mailProps);
|
||||
|
||||
MailConfig config = new MailConfig(appProps);
|
||||
JavaMailSender sender = config.javaMailSender();
|
||||
|
||||
assertInstanceOf(JavaMailSenderImpl.class, sender);
|
||||
JavaMailSenderImpl impl = (JavaMailSenderImpl) sender;
|
||||
|
||||
Properties props = impl.getJavaMailProperties();
|
||||
|
||||
assertAll(
|
||||
"SMTP configuration",
|
||||
() -> assertEquals("smtp.example.com", impl.getHost()),
|
||||
() -> assertEquals(587, impl.getPort()),
|
||||
() -> assertEquals("[email protected]", impl.getUsername()),
|
||||
() -> assertEquals("password", impl.getPassword()),
|
||||
() -> assertEquals("UTF-8", impl.getDefaultEncoding()),
|
||||
() -> assertEquals("true", props.getProperty("mail.smtp.auth")),
|
||||
() -> assertEquals("true", props.getProperty("mail.smtp.starttls.enable")));
|
||||
}
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package stirling.software.proprietary.security.service;
|
||||
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import stirling.software.proprietary.model.Team;
|
||||
import stirling.software.proprietary.security.repository.TeamRepository;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class TeamServiceTest {
|
||||
|
||||
@Mock
|
||||
private TeamRepository teamRepository;
|
||||
|
||||
@InjectMocks
|
||||
private TeamService teamService;
|
||||
|
||||
@Test
|
||||
void getDefaultTeam() {
|
||||
var team = new Team();
|
||||
team.setName("Marleyans");
|
||||
|
||||
when(teamRepository.findByName(TeamService.DEFAULT_TEAM_NAME))
|
||||
.thenReturn(Optional.of(team));
|
||||
|
||||
Team result = teamService.getOrCreateDefaultTeam();
|
||||
|
||||
assertEquals(team, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createDefaultTeam_whenRepositoryIsEmpty() {
|
||||
String teamName = "Default";
|
||||
var defaultTeam = new Team();
|
||||
defaultTeam.setId(1L);
|
||||
defaultTeam.setName(teamName);
|
||||
|
||||
when(teamRepository.findByName(teamName))
|
||||
.thenReturn(Optional.empty());
|
||||
when(teamRepository.save(any(Team.class))).thenReturn(defaultTeam);
|
||||
|
||||
Team result = teamService.getOrCreateDefaultTeam();
|
||||
|
||||
assertEquals(TeamService.DEFAULT_TEAM_NAME, result.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void getInternalTeam() {
|
||||
var team = new Team();
|
||||
team.setName("Eldians");
|
||||
|
||||
when(teamRepository.findByName(TeamService.INTERNAL_TEAM_NAME))
|
||||
.thenReturn(Optional.of(team));
|
||||
|
||||
Team result = teamService.getOrCreateInternalTeam();
|
||||
|
||||
assertEquals(team, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void createInternalTeam_whenRepositoryIsEmpty() {
|
||||
String teamName = "Internal";
|
||||
Team internalTeam = new Team();
|
||||
internalTeam.setId(2L);
|
||||
internalTeam.setName(teamName);
|
||||
|
||||
when(teamRepository.findByName(teamName))
|
||||
.thenReturn(Optional.empty());
|
||||
when(teamRepository.save(any(Team.class))).thenReturn(internalTeam);
|
||||
when(teamRepository.findByName(TeamService.INTERNAL_TEAM_NAME))
|
||||
.thenReturn(Optional.empty());
|
||||
|
||||
Team result = teamService.getOrCreateInternalTeam();
|
||||
|
||||
assertEquals(internalTeam, result);
|
||||
}
|
||||
}
|
||||
+317
@@ -0,0 +1,317 @@
|
||||
package stirling.software.proprietary.security.service;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
import stirling.software.common.model.ApplicationProperties;
|
||||
import stirling.software.common.model.enumeration.Role;
|
||||
import stirling.software.common.model.exception.UnsupportedProviderException;
|
||||
import stirling.software.proprietary.model.Team;
|
||||
import stirling.software.proprietary.security.database.repository.AuthorityRepository;
|
||||
import stirling.software.proprietary.security.database.repository.UserRepository;
|
||||
import stirling.software.proprietary.security.model.AuthenticationType;
|
||||
import stirling.software.proprietary.security.model.User;
|
||||
import stirling.software.proprietary.security.repository.TeamRepository;
|
||||
import stirling.software.proprietary.security.session.SessionPersistentRegistry;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UserServiceTest {
|
||||
|
||||
@Mock
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Mock
|
||||
private TeamRepository teamRepository;
|
||||
|
||||
@Mock
|
||||
private AuthorityRepository authorityRepository;
|
||||
|
||||
@Mock
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Mock
|
||||
private MessageSource messageSource;
|
||||
|
||||
@Mock
|
||||
private SessionPersistentRegistry sessionPersistentRegistry;
|
||||
|
||||
@Mock
|
||||
private DatabaseServiceInterface databaseService;
|
||||
|
||||
@Mock
|
||||
private ApplicationProperties.Security.OAUTH2 oauth2Properties;
|
||||
|
||||
@InjectMocks
|
||||
private UserService userService;
|
||||
|
||||
private Team mockTeam;
|
||||
private User mockUser;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
mockTeam = new Team();
|
||||
mockTeam.setId(1L);
|
||||
mockTeam.setName("Test Team");
|
||||
|
||||
mockUser = new User();
|
||||
mockUser.setId(1L);
|
||||
mockUser.setUsername("testuser");
|
||||
mockUser.setEnabled(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveUser_WithUsernameAndAuthenticationType_Success() throws Exception {
|
||||
// Given
|
||||
String username = "testuser";
|
||||
AuthenticationType authType = AuthenticationType.WEB;
|
||||
|
||||
when(teamRepository.findByName("Default")).thenReturn(Optional.of(mockTeam));
|
||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
||||
doNothing().when(databaseService).exportDatabase();
|
||||
|
||||
// When
|
||||
userService.saveUser(username, authType);
|
||||
|
||||
// Then
|
||||
verify(userRepository).save(any(User.class));
|
||||
verify(databaseService).exportDatabase();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveUser_WithUsernamePasswordAndTeamId_Success() throws Exception {
|
||||
// Given
|
||||
String username = "testuser";
|
||||
String password = "password123";
|
||||
Long teamId = 1L;
|
||||
String encodedPassword = "encodedPassword123";
|
||||
|
||||
when(passwordEncoder.encode(password)).thenReturn(encodedPassword);
|
||||
when(teamRepository.findById(teamId)).thenReturn(Optional.of(mockTeam));
|
||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
||||
doNothing().when(databaseService).exportDatabase();
|
||||
|
||||
// When
|
||||
User result = userService.saveUser(username, password, teamId);
|
||||
|
||||
// Then
|
||||
assertNotNull(result);
|
||||
verify(passwordEncoder).encode(password);
|
||||
verify(teamRepository).findById(teamId);
|
||||
verify(userRepository).save(any(User.class));
|
||||
verify(databaseService).exportDatabase();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveUser_WithTeamAndRole_Success() throws Exception {
|
||||
// Given
|
||||
String username = "testuser";
|
||||
String password = "password123";
|
||||
String role = Role.ADMIN.getRoleId();
|
||||
boolean firstLogin = true;
|
||||
String encodedPassword = "encodedPassword123";
|
||||
|
||||
when(passwordEncoder.encode(password)).thenReturn(encodedPassword);
|
||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
||||
doNothing().when(databaseService).exportDatabase();
|
||||
|
||||
// When
|
||||
User result = userService.saveUser(username, password, mockTeam, role, firstLogin);
|
||||
|
||||
// Then
|
||||
assertNotNull(result);
|
||||
verify(passwordEncoder).encode(password);
|
||||
verify(userRepository).save(any(User.class));
|
||||
verify(databaseService).exportDatabase();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveUser_WithInvalidUsername_ThrowsException() throws Exception {
|
||||
// Given
|
||||
String invalidUsername = "ab"; // Too short (less than 3 characters)
|
||||
AuthenticationType authType = AuthenticationType.WEB;
|
||||
|
||||
// When & Then
|
||||
IllegalArgumentException exception = assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> userService.saveUser(invalidUsername, authType)
|
||||
);
|
||||
|
||||
verify(userRepository, never()).save(any(User.class));
|
||||
verify(databaseService, never()).exportDatabase();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveUser_WithNullPassword_Success() throws Exception {
|
||||
// Given
|
||||
String username = "testuser";
|
||||
Long teamId = 1L;
|
||||
|
||||
when(teamRepository.findById(teamId)).thenReturn(Optional.of(mockTeam));
|
||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
||||
doNothing().when(databaseService).exportDatabase();
|
||||
|
||||
// When
|
||||
User result = userService.saveUser(username, null, teamId);
|
||||
|
||||
// Then
|
||||
assertNotNull(result);
|
||||
verify(passwordEncoder, never()).encode(anyString());
|
||||
verify(userRepository).save(any(User.class));
|
||||
verify(databaseService).exportDatabase();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveUser_WithEmptyPassword_Success() throws Exception {
|
||||
// Given
|
||||
String username = "testuser";
|
||||
String emptyPassword = "";
|
||||
Long teamId = 1L;
|
||||
|
||||
when(teamRepository.findById(teamId)).thenReturn(Optional.of(mockTeam));
|
||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
||||
doNothing().when(databaseService).exportDatabase();
|
||||
|
||||
// When
|
||||
User result = userService.saveUser(username, emptyPassword, teamId);
|
||||
|
||||
// Then
|
||||
assertNotNull(result);
|
||||
verify(passwordEncoder, never()).encode(anyString());
|
||||
verify(userRepository).save(any(User.class));
|
||||
verify(databaseService).exportDatabase();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveUser_WithValidEmail_Success() throws Exception {
|
||||
// Given
|
||||
String emailUsername = "[email protected]";
|
||||
AuthenticationType authType = AuthenticationType.SSO;
|
||||
|
||||
when(teamRepository.findByName("Default")).thenReturn(Optional.of(mockTeam));
|
||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
||||
doNothing().when(databaseService).exportDatabase();
|
||||
|
||||
// When
|
||||
userService.saveUser(emailUsername, authType);
|
||||
|
||||
// Then
|
||||
verify(userRepository).save(any(User.class));
|
||||
verify(databaseService).exportDatabase();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveUser_WithReservedUsername_ThrowsException() throws Exception {
|
||||
// Given
|
||||
String reservedUsername = "all_users";
|
||||
AuthenticationType authType = AuthenticationType.WEB;
|
||||
|
||||
// When & Then
|
||||
IllegalArgumentException exception = assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> userService.saveUser(reservedUsername, authType)
|
||||
);
|
||||
|
||||
verify(userRepository, never()).save(any(User.class));
|
||||
verify(databaseService, never()).exportDatabase();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveUser_WithAnonymousUser_ThrowsException() throws Exception {
|
||||
// Given
|
||||
String anonymousUsername = "anonymoususer";
|
||||
AuthenticationType authType = AuthenticationType.WEB;
|
||||
|
||||
// When & Then
|
||||
IllegalArgumentException exception = assertThrows(
|
||||
IllegalArgumentException.class,
|
||||
() -> userService.saveUser(anonymousUsername, authType)
|
||||
);
|
||||
|
||||
verify(userRepository, never()).save(any(User.class));
|
||||
verify(databaseService, never()).exportDatabase();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveUser_DatabaseExportThrowsException_StillSavesUser() throws Exception {
|
||||
// Given
|
||||
String username = "testuser";
|
||||
String password = "password123";
|
||||
Long teamId = 1L;
|
||||
String encodedPassword = "encodedPassword123";
|
||||
|
||||
when(passwordEncoder.encode(password)).thenReturn(encodedPassword);
|
||||
when(teamRepository.findById(teamId)).thenReturn(Optional.of(mockTeam));
|
||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
||||
doThrow(new SQLException("Database export failed")).when(databaseService).exportDatabase();
|
||||
|
||||
// When & Then
|
||||
assertThrows(SQLException.class, () -> userService.saveUser(username, password, teamId));
|
||||
|
||||
// Verify user was still saved before the exception
|
||||
verify(userRepository).save(any(User.class));
|
||||
verify(databaseService).exportDatabase();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveUser_WithFirstLoginFlag_Success() throws Exception {
|
||||
// Given
|
||||
String username = "testuser";
|
||||
String password = "password123";
|
||||
Long teamId = 1L;
|
||||
boolean firstLogin = true;
|
||||
boolean enabled = false;
|
||||
String encodedPassword = "encodedPassword123";
|
||||
|
||||
when(passwordEncoder.encode(password)).thenReturn(encodedPassword);
|
||||
when(teamRepository.findById(teamId)).thenReturn(Optional.of(mockTeam));
|
||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
||||
doNothing().when(databaseService).exportDatabase();
|
||||
|
||||
// When
|
||||
userService.saveUser(username, password, teamId, firstLogin, enabled);
|
||||
|
||||
// Then
|
||||
verify(passwordEncoder).encode(password);
|
||||
verify(userRepository).save(any(User.class));
|
||||
verify(databaseService).exportDatabase();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSaveUser_WithCustomRole_Success() throws Exception {
|
||||
// Given
|
||||
String username = "testuser";
|
||||
String password = "password123";
|
||||
Long teamId = 1L;
|
||||
String customRole = Role.LIMITED_API_USER.getRoleId();
|
||||
String encodedPassword = "encodedPassword123";
|
||||
|
||||
when(passwordEncoder.encode(password)).thenReturn(encodedPassword);
|
||||
when(teamRepository.findById(teamId)).thenReturn(Optional.of(mockTeam));
|
||||
when(userRepository.save(any(User.class))).thenReturn(mockUser);
|
||||
doNothing().when(databaseService).exportDatabase();
|
||||
|
||||
// When
|
||||
userService.saveUser(username, password, teamId, customRole);
|
||||
|
||||
// Then
|
||||
verify(passwordEncoder).encode(password);
|
||||
verify(userRepository).save(any(User.class));
|
||||
verify(databaseService).exportDatabase();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user